This commit is contained in:
2026-04-20 12:42:58 +03:00
parent bb7d7392a8
commit b1cb321cb0

View File

@@ -1,7 +1,7 @@
// ==UserScript== // ==UserScript==
// @name Grepolis Remote Control // @name Grepolis Remote Control
// @namespace http://tampermonkey.net/ // @namespace http://tampermonkey.net/
// @version 1.3 // @version 1.4
// @description Polls grepo.haunter-pets.top for remote commands and executes them in-game // @description Polls grepo.haunter-pets.top for remote commands and executes them in-game
// @author Dimitrios // @author Dimitrios
// @match https://*.grepolis.com/game/* // @match https://*.grepolis.com/game/*
@@ -15,7 +15,7 @@
const uw = typeof unsafeWindow !== 'undefined' ? unsafeWindow : window; const uw = typeof unsafeWindow !== 'undefined' ? unsafeWindow : window;
const BASE_URL = 'https://grepo.haunter-pets.top'; const BASE_URL = 'https://grepo.haunter-pets.top';
const POLL_INTERVAL_MS = 5000; // poll for commands const POLL_INTERVAL_MS = 5000; // poll for commands
const STATE_INTERVAL_MS = 30000; // push town state const STATE_INTERVAL_MS = 30000; // push town state
// ---------------------------------------------------------------- // ----------------------------------------------------------------
@@ -33,13 +33,13 @@
function togglePause() { function togglePause() {
paused = !paused; paused = !paused;
const label = document.getElementById('grc_label'); const label = document.getElementById('grc_label');
const btn = document.getElementById('grc_btn'); const btn = document.getElementById('grc_btn');
if (paused) { if (paused) {
label.textContent = 'Paused'; label.textContent = 'Paused';
btn.style.filter = 'brightness(70%) sepia(100%) hue-rotate(-50deg) saturate(1000%) contrast(0.8)'; btn.style.filter = 'brightness(70%) sepia(100%) hue-rotate(-50deg) saturate(1000%) contrast(0.8)';
} else { } else {
label.textContent = 'Remote'; label.textContent = 'Remote';
btn.style.filter = 'brightness(294%) sepia(100%) hue-rotate(200deg) saturate(1000%) contrast(0.8)'; btn.style.filter = 'brightness(294%) sepia(100%) hue-rotate(200deg) saturate(1000%) contrast(0.8)';
} }
log(`Remote is now ${paused ? 'PAUSED' : 'ACTIVE'}`); log(`Remote is now ${paused ? 'PAUSED' : 'ACTIVE'}`);
} }
@@ -67,16 +67,26 @@
// Push town state to relay // Push town state to relay
// ---------------------------------------------------------------- // ----------------------------------------------------------------
function gatherState() { function gatherState() {
const towns = uw.ITowns?.towns || {}; const towns = uw.ITowns?.towns || {};
const player = uw.Game?.player_name || ''; const player = uw.Game?.player_name || '';
const player_id = uw.Game?.player_id ?? null; const player_id = uw.Game?.player_id ?? null;
const alliance_id = uw.Game?.alliance_id ?? null; const alliance_id = uw.Game?.alliance_id ?? null;
const total_points = uw.Game?.player_points ?? 0; const total_points = uw.Game?.player_points ?? 0;
const world = uw.Game?.world_id || ''; const world = uw.Game?.world_id || '';
// ---- Debug: Game-level fields (logged once on first push) ---------------
if (!gatherState._debugDone) {
gatherState._debugDone = true;
console.group('[GRC Debug] Game-level fields');
console.log('player_id :', uw.Game?.player_id, '→', player_id ?? '❌ MISSING');
console.log('alliance_id :', uw.Game?.alliance_id, '→', alliance_id ?? '❌ MISSING');
console.log('player_points:', uw.Game?.player_points, '→', total_points || '❌ ZERO/MISSING');
console.log('world_id :', uw.Game?.world_id, '→', world || '❌ MISSING');
console.groupEnd();
}
const townList = Object.values(towns).map(town => { const townList = Object.values(towns).map(town => {
const res = town.resources(); const res = town.resources();
const buildings = town.buildings()?.attributes ?? {}; const buildings = town.buildings()?.attributes ?? {};
const unitsObj = {}; const unitsObj = {};
@@ -89,13 +99,13 @@
: (units[k]?.getAmount?.() ?? 0); : (units[k]?.getAmount?.() ?? 0);
}); });
} }
} catch (e) {} } catch (e) { }
let buildQueue = []; let buildQueue = [];
try { try {
const bo = town.buildingOrders?.(); const bo = town.buildingOrders?.();
if (bo?.models) buildQueue = bo.models.map(m => m.attributes); if (bo?.models) buildQueue = bo.models.map(m => m.attributes);
} catch (e) {} } catch (e) { }
let buildDataMap = {}; let buildDataMap = {};
try { try {
@@ -127,8 +137,8 @@
const storageLevel = buildings.storage ?? 0; const storageLevel = buildings.storage ?? 0;
const gd = uw.GameData?.buildingData?.storage; const gd = uw.GameData?.buildingData?.storage;
storageCapacity = gd?.max_storage?.[storageLevel] storageCapacity = gd?.max_storage?.[storageLevel]
|| gd?.storage?.[storageLevel] || gd?.storage?.[storageLevel]
|| 0; || 0;
} }
// Strategy 3: resource object fallback keys // Strategy 3: resource object fallback keys
@@ -147,38 +157,50 @@
if (typeof x === 'number' && typeof y === 'number') { if (typeof x === 'number' && typeof y === 'number') {
sea = Math.floor(x / 100) * 10 + Math.floor(y / 100); sea = Math.floor(x / 100) * 10 + Math.floor(y / 100);
} }
} catch (e) {} } catch (e) { }
// ---- Researches ----------------------------------------------------- // ---- Researches -----------------------------------------------------
let researches = {}; let researches = {};
try { try {
const r = town.researches?.(); const r = town.researches?.();
if (r) researches = r.attributes ?? (typeof r === 'object' ? r : {}); if (r) researches = r.attributes ?? (typeof r === 'object' ? r : {});
} catch (e) {} if (!Object.keys(researches).length) log(`[Debug] researches empty for town ${town.name} — raw: ${JSON.stringify(r)}`);
} catch (e) { log(`[Debug] town.researches() failed: ${e}`); }
// ---- Extra town flags ----------------------------------------------- // ---- Extra town flags -----------------------------------------------
let has_premium = false; let has_premium = false;
let bonuses = {}; let bonuses = {};
let wonder_points = 0; let wonder_points = 0;
try { has_premium = town.hasPremium?.() || false; } catch (e) {} try {
try { bonuses = town.getBonus?.() || {}; } catch (e) {} const hp = town.hasPremium?.();
try { wonder_points = town.wonder_points || 0; } catch (e) {} has_premium = hp || false;
if (hp === undefined || hp === null) log(`[Debug] town.hasPremium() = ${hp} (missing or undefined) for ${town.name}`);
} catch (e) { log(`[Debug] town.hasPremium() threw: ${e}`); }
try {
const gb = town.getBonus?.();
bonuses = gb || {};
if (!gb || !Object.keys(gb).length) log(`[Debug] town.getBonus() = ${JSON.stringify(gb)} (empty/missing) for ${town.name}`);
} catch (e) { log(`[Debug] town.getBonus() threw: ${e}`); }
try {
wonder_points = town.wonder_points || 0;
if (!town.wonder_points) log(`[Debug] town.wonder_points = ${town.wonder_points} (zero/missing) for ${town.name}`);
} catch (e) { log(`[Debug] town.wonder_points threw: ${e}`); }
return { return {
town_id: town.id, town_id: town.id,
town_name: town.name, town_name: town.name,
x, y, sea, x, y, sea,
wood: res.wood, wood: res.wood,
stone: res.stone, stone: res.stone,
iron: res.iron, iron: res.iron,
storage: storageCapacity, storage: storageCapacity,
population: res.population, population: res.population,
points: town.getPoints?.() ?? 0, points: town.getPoints?.() ?? 0,
god: town.god?.() ?? null, god: town.god?.() ?? null,
buildings, buildings,
units: unitsObj, units: unitsObj,
buildingOrder: buildQueue, buildingOrder: buildQueue,
buildData: buildDataMap, buildData: buildDataMap,
researches, researches,
has_premium, has_premium,
bonuses, bonuses,
@@ -194,12 +216,12 @@
try { try {
const payload = gatherState(); const payload = gatherState();
fetch(`${BASE_URL}/api/state`, { fetch(`${BASE_URL}/api/state`, {
method: 'POST', method: 'POST',
headers: { 'Content-Type': 'application/json' }, headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload) body: JSON.stringify(payload)
}) })
.then(() => log(`State pushed — ${payload.towns.length} towns`)) .then(() => log(`State pushed — ${payload.towns.length} towns`))
.catch(e => log(`State push failed: ${e}`)); .catch(e => log(`State push failed: ${e}`));
} catch (e) { } catch (e) {
log(`gatherState error: ${e}`); log(`gatherState error: ${e}`);
} }
@@ -210,9 +232,9 @@
// ---------------------------------------------------------------- // ----------------------------------------------------------------
function reportResult(cmdId, status, message) { function reportResult(cmdId, status, message) {
fetch(`${BASE_URL}/api/commands/${cmdId}/result`, { fetch(`${BASE_URL}/api/commands/${cmdId}/result`, {
method: 'POST', method: 'POST',
headers: { 'Content-Type': 'application/json' }, headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ status, message }) body: JSON.stringify({ status, message })
}).catch(e => log(`reportResult failed: ${e}`)); }).catch(e => log(`reportResult failed: ${e}`));
} }
@@ -256,9 +278,9 @@
// Fire the build request // Fire the build request
uw.gpAjax.ajaxPost('frontend_bridge', 'execute', { uw.gpAjax.ajaxPost('frontend_bridge', 'execute', {
model_url: 'BuildingOrder', model_url: 'BuildingOrder',
action_name: 'buildUp', action_name: 'buildUp',
arguments: { building_id }, arguments: { building_id },
town_id town_id
}); });