agoara update

This commit is contained in:
2026-05-06 23:41:52 +03:00
parent 7e98f1292e
commit b824144a6a
9 changed files with 1283 additions and 6 deletions

View File

@@ -247,11 +247,31 @@ function gatherState() {
}
} catch (e) { log(`unit speed gather failed: ${e}`); }
// Active celebrations — tracks running parties/processions per town
// finished_at is a unix timestamp (seconds). 0 means not running.
const celebrations = [];
try {
const celebModels = uw.MM.getModels()?.Celebration;
if (celebModels) {
for (const cel of Object.values(celebModels)) {
const a = cel.attributes;
if (!a || !a.town_id) continue;
celebrations.push({
town_id: String(a.town_id),
celebration_type: a.celebration_type, // 'party' | 'triumph'
finished_at: a.finished_at ?? 0
});
}
}
} catch (e) { log(`celebrations gather failed: ${e}`); }
return { player, player_id, alliance_id, total_points, battle_points, world_id: world,
world_speed, unit_speeds, towns: townList };
world_speed, unit_speeds, towns: townList, celebrations };
}
function pushState() {
if (paused) return;
try {

View File

@@ -0,0 +1,101 @@
// ================================================================
// 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)
//
// On success/failure, reports back to /api/commands/<id>/result
// so the culture_log row is updated from 'pending' to 'success'/'failed'.
// ================================================================
async function executeCultureCommand(cmd) {
if (!cmd || !cmd.id || !cmd.payload) return;
const { celebration_type, town_id } = cmd.payload;
if (!celebration_type || !town_id) {
reportResult(cmd.id, 'failed', 'Invalid culture payload: missing celebration_type or town_id');
return;
}
if (!['party', 'triumph'].includes(celebration_type)) {
reportResult(cmd.id, 'failed', `Unknown celebration_type: ${celebration_type}`);
return;
}
log(`[αγορά] Εκτέλεση ${celebration_type === 'party' ? 'Γιορτής πόλης' : 'Παρέλασης θριάμβου'} για πόλη ${town_id}`);
// Validate town still exists in game memory
const town = uw.ITowns?.towns?.[town_id];
if (!town) {
reportResult(cmd.id, 'failed', `Η πόλη ${town_id} δεν βρέθηκε στη μνήμη του παιχνιδιού.`);
return;
}
// Double-check: is there already a celebration of this type running?
try {
const celebModels = uw.MM.getModels()?.Celebration;
if (celebModels) {
const nowTs = Math.floor(Date.now() / 1000);
for (const cel of Object.values(celebModels)) {
const a = cel.attributes;
if (String(a.town_id) === String(town_id)
&& a.celebration_type === celebration_type
&& (a.finished_at ?? 0) > nowTs) {
reportResult(cmd.id, 'failed',
`${celebration_type === 'party' ? 'Γιορτή' : 'Παρέλαση'} ήδη ενεργή στην πόλη ${town_id}.`);
return;
}
}
}
} catch (e) { /* model not loaded — proceed anyway, server will error if invalid */ }
// Fire the Grepolis AJAX
let ajaxSuccess = false;
let ajaxError = null;
await new Promise(resolve => {
try {
uw.gpAjax.ajaxPost(
'building_place',
'start_celebration',
{
town_id: parseInt(town_id, 10),
celebration_type: celebration_type
},
false, // no cache-busting
// success callback
() => {
ajaxSuccess = true;
resolve();
},
// error callback
(err) => {
ajaxError = err ? JSON.stringify(err) : 'Άγνωστο σφάλμα AJAX';
resolve();
}
);
} catch (e) {
ajaxError = String(e);
resolve();
}
// Safety timeout: if neither callback fires within 12 s, treat as failed
setTimeout(() => {
if (!ajaxSuccess && !ajaxError) {
ajaxError = 'Timeout — δεν ελήφθη απάντηση από το παιχνίδι εντός 12δ.';
}
resolve();
}, 12000);
});
if (ajaxSuccess) {
const label = celebration_type === 'party' ? 'Γιορτή πόλης' : 'Παρέλαση θριάμβου';
log(`[αγορά] ✅ ${label} ξεκίνησε επιτυχώς (πόλη ${town_id})`);
reportResult(cmd.id, 'done', `${label} ξεκίνησε επιτυχώς.`);
} else {
log(`[αγορά] ❌ Αποτυχία: ${ajaxError}`);
reportResult(cmd.id, 'failed', ajaxError || 'Αποτυχία εκτέλεσης εορτής.');
}
}