update add modules

This commit is contained in:
2026-04-23 18:45:54 +03:00
parent aec99fa00d
commit 54ec9a3db6
6 changed files with 826 additions and 10 deletions

View File

@@ -1,7 +1,7 @@
// ==UserScript==
// @name Grepolis Remote Control
// @namespace http://tampermonkey.net/
// @version 3.2
// @version 3.3
// @description Polls grepo.haunter-pets.top for remote commands and executes them in-game (Multi-Player)
// @author Dimitrios
// @match https://*.grepolis.com/game/*
@@ -241,12 +241,35 @@
}
} catch (e) { log(`Failed to gather unit data: ${e}`); }
// ---- Farm town data -----------------------------------------------
let farms = [];
try {
const farmCollection = uw.MM.getOnlyCollectionByName('FarmTown');
const relCollection = uw.MM.getOnlyCollectionByName('FarmTownPlayerRelation');
if (farmCollection && relCollection) {
const ix = town.getIslandCoordinateX?.();
const iy = town.getIslandCoordinateY?.();
farmCollection.models.forEach(farm => {
if (farm.attributes.island_x !== ix || farm.attributes.island_y !== iy) return;
relCollection.models.forEach(rel => {
if (rel.attributes.farm_town_id === farm.attributes.id &&
rel.attributes.relation_status === 1) {
farms.push({
farm_town_id: farm.attributes.id,
relation_id: rel.id,
lootable_at: rel.attributes.lootable_at || 0
});
}
});
});
}
} catch (e) { }
// ---- Extra town flags -----------------------------------------------
let has_premium = false;
let bonuses = {};
let wonder_points = 0;
try {
// Proper premium check for Admin/Curator
has_premium = uw.GameDataPremium?.isAdvisorActivated?.('curator') || false;
} catch (e) { }
@@ -272,6 +295,7 @@
bonuses,
wonder_points,
alliance_name,
farms,
};
});
@@ -382,6 +406,94 @@
}, 1000);
}
// ----------------------------------------------------------------
// Execute: Farm Loot
// Claims all ready farm towns across all towns that match
// the cmd payload (town_ids list + loot_option).
// Between-claim delay: random 500ms1500ms (never below 500ms)
// Between-town-group delay: random 30s90s
// ----------------------------------------------------------------
async function executeFarmLoot(cmd) {
const { loot_option } = cmd.payload || {};
const option = parseInt(loot_option) || 1;
const now = Math.floor(Date.now() / 1000);
let farmCollection, relCollection;
try {
farmCollection = uw.MM.getOnlyCollectionByName('FarmTown');
relCollection = uw.MM.getOnlyCollectionByName('FarmTownPlayerRelation');
} catch (e) {
return { ok: false, msg: `Cannot access farm collections: ${e.message}` };
}
if (!farmCollection || !relCollection) {
return { ok: false, msg: 'Farm collections not loaded yet' };
}
const towns = uw.ITowns?.towns || {};
const islandsSeen = new Set();
const polisList = []; // one town per island
for (const town of Object.values(towns)) {
const iid = town.attributes?.island_id;
if (town.attributes?.on_small_island || !iid) continue;
if (!islandsSeen.has(iid)) {
islandsSeen.add(iid);
polisList.push(town.id);
}
}
let claimed = 0;
let skipped = 0;
let errors = 0;
for (const town_id of polisList) {
const town = uw.ITowns.towns[town_id];
if (!town) continue;
const ix = town.getIslandCoordinateX?.();
const iy = town.getIslandCoordinateY?.();
const readyFarms = [];
farmCollection.models.forEach(farm => {
if (farm.attributes.island_x !== ix || farm.attributes.island_y !== iy) return;
relCollection.models.forEach(rel => {
if (rel.attributes.farm_town_id === farm.attributes.id &&
rel.attributes.relation_status === 1 &&
(rel.attributes.lootable_at || 0) <= now) {
readyFarms.push({
farm_town_id: rel.attributes.farm_town_id,
relation_id: rel.id
});
}
});
});
if (readyFarms.length === 0) { skipped++; continue; }
for (const farm of readyFarms) {
try {
uw.gpAjax.ajaxPost('frontend_bridge', 'execute', {
model_url: `FarmTownPlayerRelation/${farm.relation_id}`,
action_name: 'claim',
arguments: { farm_town_id: farm.farm_town_id, type: 'resources', option },
town_id
});
claimed++;
} catch (e) { errors++; }
// Random per-claim delay: 500ms 1500ms
await sleep(randInt(500, 1500));
}
// Random between-town-group delay: 30s 90s
if (polisList.indexOf(town_id) < polisList.length - 1) {
const gap = randInt(30000, 90000);
log(`Farm: done with town ${town_id}. Waiting ${(gap/1000).toFixed(0)}s before next...`);
await sleep(gap);
}
}
return { ok: true, msg: `Farm done: ${claimed} claimed, ${skipped} towns skipped, ${errors} errors` };
}
// ----------------------------------------------------------------
// Execute: Build
// ----------------------------------------------------------------
@@ -517,9 +629,28 @@
}
// Build queue, Recruit queue and Market queue are independent
const buildCmd = cmdData.build;
const buildCmd = cmdData.build;
const recruitCmd = cmdData.recruit;
const marketCmd = cmdData.market;
const marketCmd = cmdData.market;
const farmCmd = cmdData.farm;
// Auto-farm: if enabled, claim all ready farms (no explicit command needed)
const farmSettings = cmdData.farm_settings || {};
if (farmSettings.enabled && !farmCmd) {
const nowTs = Math.floor(Date.now() / 1000);
// Check if any town has ready farms before triggering
const hasFarms = Object.values(uw.ITowns?.towns || {}).some(t => {
try {
const coll = uw.MM.getOnlyCollectionByName('FarmTownPlayerRelation');
return coll?.models?.some(r => r.attributes.relation_status === 1 && (r.attributes.lootable_at || 0) <= nowTs);
} catch(e) { return false; }
});
if (hasFarms) {
log('⚡ Auto-farm: ready farms detected, triggering loot...');
await executeFarmLoot({ payload: { loot_option: farmSettings.loot_option } });
pushState();
}
}
if (cmdData.sync_requested) {
log('Sync requested by server — pushing state immediately');
@@ -534,6 +665,7 @@
if (cmd.type === 'build') result = await executeBuild(cmd);
else if (cmd.type === 'recruit') result = await executeRecruit(cmd);
else if (cmd.type === 'market_offer') result = await executeMarketOffer(cmd);
else if (cmd.type === 'farm_loot') result = await executeFarmLoot(cmd);
else result = { ok: false, msg: `Unknown type: ${cmd.type}` };
} catch (e) {
result = { ok: false, msg: `Exception: ${e.message}` };
@@ -545,13 +677,14 @@
// Run concurrently — they do NOT block each other
await Promise.all([execute(buildCmd), execute(recruitCmd), execute(marketCmd)]);
if (farmCmd) await execute(farmCmd);
}
// ----------------------------------------------------------------
// Boot
// ----------------------------------------------------------------
window.addEventListener('load', () => {
log('Grepolis Remote Control v2.8 loaded');
log('Grepolis Remote Control v3.3 loaded');
// Start captcha watcher immediately
detectCaptcha();