Add town.js

This commit is contained in:
2025-08-17 14:53:47 +00:00
parent 4324b54c2f
commit 519d48fbd4

175
town.js Normal file
View File

@@ -0,0 +1,175 @@
// ==UserScript==
// @name Grepolis Town Stats Extended Clean (with Sea, Buildings, Researches)
// @namespace http://tampermonkey.net/
// @version 1.4
// @description Sends town stats with coords, sea, full building orders, and researches
// @author Dimitrios
// @match https://*.grepolis.com/game/*
// @grant unsafeWindow
// ==/UserScript==
(function () {
'use strict';
const uw = unsafeWindow || window;
let paused = false;
console.log("🚀 Town Stats Extended Clean (with Sea, Buildings, Researches) loaded");
// -----------------------------
// Toolbar pause/resume button
// -----------------------------
const toolbarButtonHtml = `
<div class="divider"></div>
<div class="activity" id="tsbutton"
style="filter: brightness(70%) sepia(100%) hue-rotate(-50deg) saturate(1000%) contrast(0.8);">
<p id="tslabel" style="position: relative; top: -8px; font-weight: bold; z-index:6;">TownScan</p>
</div>`;
function togglePause() {
paused = !paused;
const label = document.getElementById('tslabel');
const btn = document.getElementById('tsbutton');
if (paused) {
label.textContent = 'Paused';
btn.style.filter = 'brightness(70%) sepia(100%) hue-rotate(-50deg) saturate(1000%) contrast(0.8)';
} else {
label.textContent = 'TownScan';
btn.style.filter = 'brightness(294%) sepia(100%) hue-rotate(15deg) saturate(1000%) contrast(0.8)';
}
console.log(`🔘 TownScan is now ${paused ? 'paused' : 'running'}`);
}
setTimeout(() => {
if (!document.getElementById('tsbutton')) {
uw.$('.tb_activities, .toolbar_activities').find('.middle').append(toolbarButtonHtml);
}
}, 4000);
uw.$(document).on('click', '#tsbutton', togglePause);
// -----------------------------
// Compute Sea from x,y
// -----------------------------
function computeSea(x, y) {
const seaY = Math.floor(y / 100);
const seaX = Math.floor(x / 100);
return seaY * 10 + seaX;
}
// -----------------------------
// Gather Town Stats
// -----------------------------
function gatherTownStats() {
const towns = uw.ITowns?.towns || {};
const player = uw.Game?.player_name || "unknown";
const player_id = uw.Game?.player_id || "unknown";
const townStats = Object.values(towns).map(town => {
const res = town.resources();
const buildings = town.buildings()?.attributes ?? {};
// Units fix
const unitsObj = {};
const units = town.units();
if (units) {
Object.keys(units).forEach(type => {
if (typeof units[type] === 'number') {
unitsObj[type] = units[type];
} else if (typeof units[type]?.getAmount === 'function') {
unitsObj[type] = units[type].getAmount();
} else {
unitsObj[type] = 0;
}
});
}
// Coordinates & sea
const x = town.getIslandCoordinateX ? town.getIslandCoordinateX() : null;
const y = town.getIslandCoordinateY ? town.getIslandCoordinateY() : null;
const sea = (x !== null && y !== null) ? computeSea(x, y) : null;
// Full building orders
let buildingOrder = [];
if (typeof town.buildingOrders === "function") {
const bo = town.buildingOrders();
if (bo && bo.models) {
buildingOrder = bo.models.map(m => m.attributes);
}
}
// Researches
let researches = {};
if (typeof town.researches === "function") {
researches = town.researches();
}
return {
town_id: town.id,
town_name: town.name,
x, y, sea,
wood: res.wood,
stone: res.stone,
iron: res.iron,
population: res.population,
points: town.points || 0,
buildings,
units: unitsObj,
buildingOrder,
researches,
has_premium: town.hasPremium?.() || false,
bonuses: town.getBonus ? town.getBonus() : {},
wonder_points: town.wonder_points || 0
};
});
return { player, player_id, towns: townStats };
}
// -----------------------------
// Send Data
// -----------------------------
function sendData() {
if (paused) return console.log("⏸️ TownScan is paused — skipping data send");
try {
const payload = {
type: "extended",
timestamp: new Date().toISOString(),
...gatherTownStats(),
server_received_at: new Date().toISOString()
};
console.log("📤 Sending payload:", payload);
fetch("https://grepo.haunter-pets.top/api/grepolis-data", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(payload)
})
.then(res => res.text())
.then(txt => console.log("✅ Data sent:", txt))
.catch(err => console.error("❌ Failed to send:", err));
} catch (e) {
console.error("💥 Error sending stats:", e);
}
}
// -----------------------------
// Main Loop
// -----------------------------
function startCycle() {
setInterval(() => {
console.log("🕒 TownScan cycle tick");
sendData();
}, 30000);
}
window.addEventListener("load", () => {
console.log("🚀 TownScan booting...");
startCycle();
});
})();