greekbuilding names ,live synch button ,market capacity
This commit is contained in:
@@ -157,6 +157,21 @@
|
||||
log(`storage capacity lookup failed: ${e}`);
|
||||
}
|
||||
|
||||
// ---- Market / Trade capacity -----------------------------------------
|
||||
let marketCapacity = 0;
|
||||
try {
|
||||
const marketLevel = buildings.market ?? 0;
|
||||
const gd = uw.GameData?.buildingData?.market;
|
||||
marketCapacity = gd?.capacity_per_level?.[marketLevel] || 0;
|
||||
|
||||
// Add Trade Office bonus if present
|
||||
if (buildings.trade_office && buildings.trade_office > 0) {
|
||||
marketCapacity += (uw.GameData?.buildingData?.trade_office?.capacity_extra_per_level || 500) * marketLevel;
|
||||
}
|
||||
} catch (e) {
|
||||
log(`market capacity lookup failed: ${e}`);
|
||||
}
|
||||
|
||||
// ---- Coordinates & sea zone -----------------------------------------
|
||||
let x = null, y = null, sea = null;
|
||||
try {
|
||||
@@ -234,6 +249,7 @@
|
||||
stone: res.stone,
|
||||
iron: res.iron,
|
||||
storage: storageCapacity,
|
||||
market_capacity: marketCapacity,
|
||||
population: res.population,
|
||||
points: town.getPoints?.() ?? 0,
|
||||
god: town.god?.() ?? null,
|
||||
@@ -466,6 +482,11 @@
|
||||
const recruitCmd = cmdData.recruit;
|
||||
const marketCmd = cmdData.market;
|
||||
|
||||
if (cmdData.sync_requested) {
|
||||
log('Sync requested by server — pushing state immediately');
|
||||
pushState();
|
||||
}
|
||||
|
||||
const execute = async (cmd) => {
|
||||
if (!cmd) return;
|
||||
log(`Executing command #${cmd.id} — type:${cmd.type} town:${cmd.town_id}`);
|
||||
|
||||
@@ -105,9 +105,38 @@ def get_pending_command():
|
||||
return jsonify({
|
||||
'build': build_cmd,
|
||||
'recruit': recruit_cmd,
|
||||
'market': market_cmd
|
||||
'market': market_cmd,
|
||||
'sync_requested': _check_and_reset_sync(c, player_id)
|
||||
})
|
||||
|
||||
def _check_and_reset_sync(c, player_id):
|
||||
key = f'sync_request_{player_id}'
|
||||
row = c.execute("SELECT value FROM kv_store WHERE key = ?", (key,)).fetchone()
|
||||
if row and row['value'] == '1':
|
||||
c.execute("UPDATE kv_store SET value = '0', updated_at = ? WHERE key = ?", (datetime.utcnow().isoformat(), key))
|
||||
return True
|
||||
return False
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# POST /api/sync-request
|
||||
# Dashboard requests an immediate state update from the client.
|
||||
# ------------------------------------------------------------------
|
||||
@api.route('/api/sync-request', methods=['POST'])
|
||||
def sync_request():
|
||||
player_id = request.args.get('player_id')
|
||||
if not player_id:
|
||||
return jsonify({'error': 'no player_id provided'}), 400
|
||||
|
||||
conn = get_db()
|
||||
conn.execute('''
|
||||
INSERT INTO kv_store (key, value, updated_at)
|
||||
VALUES (?, '1', ?)
|
||||
ON CONFLICT(key) DO UPDATE SET value = '1', updated_at = excluded.updated_at
|
||||
''', (f'sync_request_{player_id}', datetime.utcnow().isoformat()))
|
||||
conn.commit()
|
||||
conn.close()
|
||||
return jsonify({'ok': True})
|
||||
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# POST /api/commands/<id>/result
|
||||
|
||||
@@ -89,6 +89,7 @@ def get_towns():
|
||||
'stone': d.get('stone', 0),
|
||||
'iron': d.get('iron', 0),
|
||||
'storage': d.get('storage', 0),
|
||||
'market_capacity': d.get('market_capacity', 0),
|
||||
'population': d.get('population', 0),
|
||||
},
|
||||
'buildings': d.get('buildings', {}),
|
||||
|
||||
@@ -223,3 +223,28 @@ window.dismissCaptchaBanner = function() {
|
||||
banner.dataset.dismissed = '1';
|
||||
}
|
||||
};
|
||||
|
||||
window.requestLiveSync = async function() {
|
||||
const btn = document.getElementById('live-btn');
|
||||
const originalText = btn.textContent;
|
||||
btn.textContent = '⏳ Requesting...';
|
||||
btn.disabled = true;
|
||||
|
||||
try {
|
||||
const res = await fetch('/api/sync-request?player_id=' + window.PLAYER_ID, { method: 'POST' });
|
||||
const data = await res.json();
|
||||
if (data.ok) {
|
||||
btn.textContent = '✅ Requested!';
|
||||
setTimeout(() => {
|
||||
btn.textContent = originalText;
|
||||
btn.disabled = false;
|
||||
}, 5000);
|
||||
}
|
||||
} catch (e) {
|
||||
btn.textContent = '❌ Failed';
|
||||
setTimeout(() => {
|
||||
btn.textContent = originalText;
|
||||
btn.disabled = false;
|
||||
}, 3000);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -144,8 +144,10 @@ window.renderBuildQueuePreview = function() {
|
||||
el.innerHTML = '<span style="color:#444">Build queue: empty</span>';
|
||||
return;
|
||||
}
|
||||
const items = town.build_queue.map(o =>
|
||||
`<span>${o.building_type || o.name || JSON.stringify(o)}</span>`
|
||||
).join('');
|
||||
const items = town.build_queue.map(o => {
|
||||
const raw = o.building_type || o.name || "";
|
||||
const nameGr = window.BUILDING_NAMES_GR[raw] || raw || JSON.stringify(o);
|
||||
return `<span style="background: rgba(0,0,0,0.3); padding: 2px 6px; border-radius: 4px; margin-right: 4px; font-size: 0.8rem;">${nameGr}</span>`;
|
||||
}).join('');
|
||||
el.innerHTML = `<div style="margin-top:6px;color:#888;font-size:0.72rem;text-transform:uppercase;letter-spacing:0.5px;margin-bottom:4px;">Current queue</div>${items}`;
|
||||
};
|
||||
|
||||
@@ -160,6 +160,11 @@ window.renderTownDetails = function() {
|
||||
<div>${window.RES_ICONS.iron} Ασήμι: ${resHtml(resObj.iron || 0, reservedIron)}</div>
|
||||
<div style="margin-top: 6px;">${window.RES_ICONS.pop} Πληθυσμός: <strong style="color:#fff">${resObj.population || 0}</strong></div>
|
||||
`;
|
||||
|
||||
const mCap = resObj.market_capacity || 0;
|
||||
document.getElementById('td-market').innerHTML = `
|
||||
📦 Εμπορική Χωρητικότητα: <strong>${window.fmt(mCap)}</strong>
|
||||
`;
|
||||
|
||||
const godName = t.god ? t.god.charAt(0).toUpperCase() + t.god.slice(1) : 'Κανένας';
|
||||
const seaStr = t.sea != null ? `Θ${t.sea}` : '—';
|
||||
|
||||
@@ -27,7 +27,10 @@
|
||||
|
||||
<!-- Left: Town list -->
|
||||
<div id="town-panel">
|
||||
<h2>Towns</h2>
|
||||
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px;">
|
||||
<h2 style="margin: 0;">Towns</h2>
|
||||
<button class="btn btn-gold btn-sm" id="live-btn" onclick="window.requestLiveSync()" title="Request immediate data update from game" style="padding: 4px 8px; font-size: 0.72rem;">⚡ Live Sync</button>
|
||||
</div>
|
||||
|
||||
<div id="town-filters" style="margin-bottom: 15px; padding: 10px; background: #0f3460; border-radius: 6px; border: 1px solid #2a4a6a;">
|
||||
<input type="text" id="town-search" placeholder="Αναζήτηση Πόλης..." style="width: 100%; box-sizing: border-box; margin-bottom: 10px; padding: 6px; border-radius: 4px; border: 1px solid #3a5a7a; background: #1a1a24; color: white;" onkeyup="window.renderTowns()">
|
||||
@@ -63,6 +66,7 @@
|
||||
<div style="flex: 1; min-width: 130px;">
|
||||
<strong style="font-size: 0.75rem; color: #888; text-transform: uppercase;">Ποροι</strong>
|
||||
<div id="td-resources" style="font-size: 0.85rem; margin-top: 4px; line-height: 1.5;"></div>
|
||||
<div id="td-market" style="font-size: 0.75rem; color: #6fcfcf; margin-top: 6px; border-top: 1px solid #2a4a6a; padding-top: 4px;"></div>
|
||||
</div>
|
||||
|
||||
<div style="flex: 1; min-width: 130px;">
|
||||
|
||||
Reference in New Issue
Block a user