revert and farm fix

This commit is contained in:
2026-04-26 02:02:50 +03:00
parent b688b66275
commit 95b38b1212
3 changed files with 103 additions and 116 deletions

View File

@@ -786,105 +786,6 @@
await sleep(500);
return { ok: true, msg: `Market offer posted: ${offer} ${offer_type} => ${demand} ${demand_type}` };
}
// ----------------------------------------------------------------
// Execute: Scan Market (On-Demand)
// ----------------------------------------------------------------
async function executeScanMarket(cmd) {
const { town_id } = cmd;
await sleep(randInt(1500, 3000));
if (paused) return { ok: false, msg: 'Aborted due to pause/captcha' };
return new Promise((resolve) => {
let intercepted = false;
let timeoutId;
const origAjaxPost = uw.gpAjax.ajaxPost.bind(uw.gpAjax);
// Handle BOTH Grepolis callback styles:
// Style A: ajaxPost(ctrl, action, params, loader, {success, error})
// Style B: ajaxPost(ctrl, action, params, loader, fnSuccess, fnError)
uw.gpAjax.ajaxPost = function(controller, action, params, loader, cbSuccessOrObj, cbError) {
const handleResp = function(resp) {
log(`[Market intercept] ctrl:${controller} action:${action} has_offers:${!!(resp && resp.offers)}`);
if (!intercepted && resp && resp.offers) {
intercepted = true;
clearTimeout(timeoutId);
uw.gpAjax.ajaxPost = origAjaxPost;
fetch(`${BASE_URL}/api/market_data?player_id=${uw.Game.player_id}`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(resp)
})
.then(() => resolve({ ok: true, msg: `Market scanned: ${resp.offers.length} offers` }))
.catch(e => resolve({ ok: false, msg: 'Upload failed: ' + e }));
}
};
if (cbSuccessOrObj && typeof cbSuccessOrObj === 'object') {
// Style A — object with success/error keys
const origSuccess = cbSuccessOrObj.success;
return origAjaxPost(controller, action, params, loader, {
success: function(resp) { handleResp(resp); if (origSuccess) origSuccess(resp); },
error: cbSuccessOrObj.error
});
} else {
// Style B — separate function args
return origAjaxPost(controller, action, params, loader,
function(resp) { handleResp(resp); if (typeof cbSuccessOrObj === 'function') cbSuccessOrObj(resp); },
cbError
);
}
};
// Trigger getData through frontend_bridge
origAjaxPost('frontend_bridge', 'execute', {
model_url: 'BuildingMarket',
action_name: 'getData',
arguments: {
limit: 20, offset: 0,
demand_type: 'all_but_gold', offer_type: 'all_but_gold',
max_ratio: 3, max_delivery_time: 172800,
visibility: 2, order_by: 'ratio', order_direction: 'desc'
},
town_id: town_id,
nl_init: true
});
// Timeout after 15 seconds
timeoutId = setTimeout(() => {
if (!intercepted) {
uw.gpAjax.ajaxPost = origAjaxPost;
resolve({ ok: false, msg: 'Market scan timed out' });
}
}, 15000);
});
}
// ----------------------------------------------------------------
// Execute: Accept Market Offer
// ----------------------------------------------------------------
async function executeAcceptMarketOffer(cmd) {
const { town_id, payload } = cmd;
const { offer_id, amount } = payload;
const reactionMs = randInt(800, 2000);
log(`Waiting ${reactionMs}ms before accepting offer...`);
await sleep(reactionMs);
if (paused) return { ok: false, msg: 'Aborted due to pause/captcha' };
uw.gpAjax.ajaxPost('frontend_bridge', 'execute', {
model_url: 'BuildingMarket',
action_name: 'acceptOffer',
arguments: { offer_id, amount },
town_id: town_id,
nl_init: true
});
await sleep(500);
return { ok: true, msg: `Accepted market offer ${offer_id} for amount ${amount}` };
}
// ----------------------------------------------------------------
// Execute: Research (Academy)
@@ -935,8 +836,6 @@
// Build queue, Recruit queue and Market queue are independent
const buildCmd = cmdData.build;
const recruitCmd = cmdData.recruit;
const scanMarketCmd = cmdData.scan_market;
const acceptMarketCmd = cmdData.accept_market_offer;
const marketCmd = cmdData.market;
const researchCmd = cmdData.research;
const farmCmd = cmdData.farm;
@@ -962,8 +861,6 @@
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 === 'scan_market') result = await executeScanMarket(cmd);
else if (cmd.type === 'accept_market_offer') result = await executeAcceptMarketOffer(cmd);
else if (cmd.type === 'research') result = await executeResearch(cmd);
else if (cmd.type === 'farm_loot') result = await executeFarmLoot(cmd);
else if (cmd.type === 'farm_upgrade') result = await executeFarmUpgrade(cmd);
@@ -980,8 +877,6 @@
await execute(buildCmd);
await execute(recruitCmd);
await execute(marketCmd);
await execute(scanMarketCmd);
await execute(acceptMarketCmd);
await execute(researchCmd);
await execute(farmCmd);
await execute(farmUpgradeCmd);
@@ -990,17 +885,64 @@
const farmSettings = cmdData.farm_settings || {};
if (farmSettings.enabled && !farmCmd) {
const nowTs = Math.floor(Date.now() / 1000);
// Check if ANY farm relation is ready (no need to iterate per-town)
const hasFarms = (() => {
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();
// Check if ANY farm relation is ready
let readyFarms = [];
try {
const coll = uw.MM.getOnlyCollectionByName('FarmTownPlayerRelation');
readyFarms = coll?.models?.filter(r =>
r.attributes.relation_status === 1 &&
(r.attributes.lootable_at || 0) <= nowTs
) || [];
} catch (e) { /* silent */ }
if (readyFarms.length > 0) {
// Check if the CURRENT town's warehouse is full (>95%)
let allFull = true;
let claimedAny = false;
// Iterate over all towns that have ready farms
const towns = Object.values(uw.ITowns?.towns || {});
for (const town of towns) {
const storage = town.resources?.()?.storage || town.get?.('storage') || 0;
const wood = town.resources?.()?.wood || town.get?.('wood') || 0;
const stone = town.resources?.()?.stone || town.get?.('stone') || 0;
const iron = town.resources?.()?.iron || town.get?.('iron') || 0;
if (!storage) continue;
const maxRes = Math.max(wood, stone, iron);
const pct = maxRes / storage;
if (pct < 0.95) {
// This town has room — loot using its town_id context
allFull = false;
log(`⚡ Auto-farm: looting into town ${town.get?.('name')} (${Math.round(pct*100)}% full)`);
await executeFarmLoot({ payload: { loot_option: farmSettings.loot_option } });
claimedAny = true;
pushState();
break; // one loot pass is enough per poll cycle
}
}
if (allFull) {
log('⚠️ Auto-farm: ALL warehouses are full (>95%) — skipping loot this cycle');
// Report full status to backend so farm.html can show notice
try {
await fetch(`${BASE_URL}/api/farm_status?player_id=${uw.Game.player_id}`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ warehouse_full: true })
});
} catch(e) {}
} else if (claimedAny) {
// Clear the full flag
try {
await fetch(`${BASE_URL}/api/farm_status?player_id=${uw.Game.player_id}`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ warehouse_full: false })
});
} catch(e) {}
}
}
}
}