fix que / add auto

This commit is contained in:
2026-05-07 20:22:28 +03:00
parent 51d15118ed
commit 74b51e74ca
6 changed files with 467 additions and 54 deletions

View File

@@ -1,40 +1,52 @@
// ================================================================
// 04d_execute_culture.js — Execute Αγορά celebration commands
//
// Handles commands of type 'culture' from the poll response.
// Supported celebration_type values:
// 'party' → Γιορτή πόλης (costs wood/stone/iron)
// 'triumph' → Παρέλαση θριάμβου (costs battle points)
// Handles commands of type 'culture' from the culture_queue.
// Completely separate from the commands table — builds/recruits
// are never blocked by a stuck culture command.
//
// Uses the same fire-and-forget ajaxPost pattern as all other
// execute modules in this codebase (04a, 04b, 04c).
// Reports results to /api/culture/result/<id> (dedicated endpoint).
// ================================================================
async function executeCultureCommand(cmd) {
if (!cmd || !cmd.id || !cmd.payload) return;
async function reportCultureResult(queueId, status, msg) {
try {
await apiFetch(`${BASE_URL}/api/culture/result/${queueId}`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ status, message: msg })
});
} catch (e) {
log(`[αγορά] ⚠️ Failed to report result for queue #${queueId}: ${e}`);
}
}
// town_id lives on the command root (like build/recruit), payload has celebration_type
const town_id = cmd.town_id || cmd.payload.town_id;
async function executeCultureCommand(cmd) {
if (!cmd || !cmd.id || !cmd.payload) return { ok: false, msg: 'No payload' };
// town_id lives on the command root; payload has celebration_type
const town_id = cmd.town_id || cmd.payload.town_id;
const celebration_type = cmd.payload.celebration_type;
const source = cmd.payload.source || 'manual';
if (!celebration_type || !town_id) {
reportResult(cmd.id, 'failed', 'Invalid culture payload: missing celebration_type or town_id');
return;
await reportCultureResult(cmd.id, 'failed', 'Invalid culture payload: missing celebration_type or town_id');
return { ok: false, msg: 'Invalid payload' };
}
if (!['party', 'triumph'].includes(celebration_type)) {
reportResult(cmd.id, 'failed', `Unknown celebration_type: ${celebration_type}`);
return;
await reportCultureResult(cmd.id, 'failed', `Unknown celebration_type: ${celebration_type}`);
return { ok: false, msg: 'Unknown type' };
}
const label = celebration_type === 'party' ? 'Γιορτή πόλης' : 'Παρέλαση θριάμβου';
log(`[αγορά] Εκτέλεση ${label} για πόλη ${town_id}`);
log(`[αγορά] Εκτέλεση ${label} για πόλη ${town_id} (${source})`);
// Validate town exists in game memory
const town = uw.ITowns?.towns?.[town_id];
if (!town) {
reportResult(cmd.id, 'failed', `Η πόλη ${town_id} δεν βρέθηκε στη μνήμη του παιχνιδιού.`);
return;
const msg = `Η πόλη ${town_id} δεν βρέθηκε στη μνήμη του παιχνιδιού.`;
await reportCultureResult(cmd.id, 'failed', msg);
return { ok: false, msg };
}
// Double-check: is there already a celebration of this type running?
@@ -47,9 +59,9 @@ async function executeCultureCommand(cmd) {
if (String(a.town_id) === String(town_id)
&& a.celebration_type === celebration_type
&& (a.finished_at ?? 0) > nowTs) {
reportResult(cmd.id, 'failed',
`${label} ήδη ενεργή στην πόλη ${town_id}.`);
return;
const msg = `${label} ήδη ενεργή στην πόλη ${town_id}.`;
await reportCultureResult(cmd.id, 'failed', msg);
return { ok: false, msg };
}
}
}
@@ -61,8 +73,8 @@ async function executeCultureCommand(cmd) {
await sleep(reactionMs);
if (paused) {
reportResult(cmd.id, 'failed', 'Aborted due to pause/captcha');
return;
await reportCultureResult(cmd.id, 'failed', 'Aborted due to pause/captcha');
return { ok: false, msg: 'Paused' };
}
// Fire-and-forget — exact same 3-arg pattern used everywhere in this codebase.
@@ -74,6 +86,8 @@ async function executeCultureCommand(cmd) {
});
await sleep(500);
log(`[αγορά] ✅ ${label} εστάλη (πόλη ${town_id})`);
reportResult(cmd.id, 'done', `${label} εστάλη επιτυχώς.`);
const successMsg = `${label} εστάλη επιτυχώς (${source}).`;
log(`[αγορά] ✅ ${successMsg} (πόλη ${town_id})`);
await reportCultureResult(cmd.id, 'done', successMsg);
return { ok: true, msg: successMsg };
}

View File

@@ -97,7 +97,12 @@ async function pollAndExecute() {
else if (cmd.type === 'market_offer') result = await executeMarketOffer(cmd);
else if (cmd.type === 'research') result = await executeResearch(cmd);
else if (cmd.type === 'farm_upgrade') result = await executeFarmUpgrade(cmd);
else if (cmd.type === 'culture') result = await executeCultureCommand(cmd);
else if (cmd.type === 'culture') {
// executeCultureCommand reports to /api/culture/result directly
// — do NOT call the shared reportResult() afterwards
await executeCultureCommand(cmd);
return;
}
else if (cmd.type === 'farm_loot') {
// Guard: if auto-farm is mid-run, requeue rather than overlap
if (farmLootRunning) {