update add modules
This commit is contained in:
@@ -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 500ms–1500ms (never below 500ms)
|
||||
// Between-town-group delay: random 30s–90s
|
||||
// ----------------------------------------------------------------
|
||||
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();
|
||||
|
||||
Reference in New Issue
Block a user