fix for buildinds
This commit is contained in:
@@ -833,8 +833,8 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build queue, Recruit queue and Market queue are independent
|
// Build queue: one command per town (all towns build in the same poll cycle)
|
||||||
const buildCmd = cmdData.build;
|
const buildCmds = cmdData.builds || [];
|
||||||
const recruitCmd = cmdData.recruit;
|
const recruitCmd = cmdData.recruit;
|
||||||
const marketCmd = cmdData.market;
|
const marketCmd = cmdData.market;
|
||||||
const researchCmd = cmdData.research;
|
const researchCmd = cmdData.research;
|
||||||
@@ -873,8 +873,16 @@
|
|||||||
reportResult(cmd.id, finalStatus, result.msg);
|
reportResult(cmd.id, finalStatus, result.msg);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Run sequentially — humans cannot perform 3 actions simultaneously!
|
// Execute ALL town build commands (one per town, sequential with inter-town delay)
|
||||||
await execute(buildCmd);
|
for (let i = 0; i < buildCmds.length; i++) {
|
||||||
|
await execute(buildCmds[i]);
|
||||||
|
if (i < buildCmds.length - 1) {
|
||||||
|
// Random gap between towns so it doesn't look like a macro
|
||||||
|
const gap = randInt(1500, 3000);
|
||||||
|
log(`Build: town done. Waiting ${gap}ms before next town...`);
|
||||||
|
await sleep(gap);
|
||||||
|
}
|
||||||
|
}
|
||||||
await execute(recruitCmd);
|
await execute(recruitCmd);
|
||||||
await execute(marketCmd);
|
await execute(marketCmd);
|
||||||
await execute(researchCmd);
|
await execute(researchCmd);
|
||||||
|
|||||||
@@ -22,7 +22,8 @@ async function pollAndExecute() {
|
|||||||
const farmOn = features.includes('farm');
|
const farmOn = features.includes('farm');
|
||||||
const adminOn = features.includes('admin');
|
const adminOn = features.includes('admin');
|
||||||
|
|
||||||
const buildCmd = adminOn ? cmdData.build : null;
|
// Build: one command per town (server returns an array)
|
||||||
|
const buildCmds = adminOn ? (cmdData.builds || []) : [];
|
||||||
const recruitCmd = adminOn ? cmdData.recruit : null;
|
const recruitCmd = adminOn ? cmdData.recruit : null;
|
||||||
const marketCmd = adminOn ? cmdData.market : null;
|
const marketCmd = adminOn ? cmdData.market : null;
|
||||||
const researchCmd = adminOn ? cmdData.research : null;
|
const researchCmd = adminOn ? cmdData.research : null;
|
||||||
@@ -60,8 +61,16 @@ async function pollAndExecute() {
|
|||||||
reportResult(cmd.id, finalStatus, result.msg);
|
reportResult(cmd.id, finalStatus, result.msg);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Run sequentially — humans cannot perform 3 actions simultaneously!
|
// Execute one build command per town (simultaneous queue draining across all villages)
|
||||||
await execute(buildCmd);
|
for (let i = 0; i < buildCmds.length; i++) {
|
||||||
|
await execute(buildCmds[i]);
|
||||||
|
if (i < buildCmds.length - 1) {
|
||||||
|
// Random inter-town gap — avoids looking like a macro
|
||||||
|
const gap = randInt(1500, 3000);
|
||||||
|
log(`Build: town done. Waiting ${gap}ms before next town...`);
|
||||||
|
await sleep(gap);
|
||||||
|
}
|
||||||
|
}
|
||||||
await execute(recruitCmd);
|
await execute(recruitCmd);
|
||||||
await execute(marketCmd);
|
await execute(marketCmd);
|
||||||
await execute(researchCmd);
|
await execute(researchCmd);
|
||||||
|
|||||||
@@ -105,10 +105,11 @@ def receive_state():
|
|||||||
# so both queues are served in parallel without blocking each other.
|
# so both queues are served in parallel without blocking each other.
|
||||||
# ------------------------------------------------------------------
|
# ------------------------------------------------------------------
|
||||||
def _fetch_pending_of_type(c, cmd_type, player_id):
|
def _fetch_pending_of_type(c, cmd_type, player_id):
|
||||||
|
"""Fetch a single oldest pending command of a given type (recruit, market, etc.)."""
|
||||||
row = c.execute('''
|
row = c.execute('''
|
||||||
SELECT * FROM commands
|
SELECT * FROM commands
|
||||||
WHERE status = 'pending' AND type = ? AND player_id = ?
|
WHERE status = 'pending' AND type = ? AND player_id = ?
|
||||||
ORDER BY id ASC
|
ORDER BY updated_at ASC, id ASC
|
||||||
LIMIT 1
|
LIMIT 1
|
||||||
''', (cmd_type, player_id)).fetchone()
|
''', (cmd_type, player_id)).fetchone()
|
||||||
if not row:
|
if not row:
|
||||||
@@ -125,6 +126,49 @@ def _fetch_pending_of_type(c, cmd_type, player_id):
|
|||||||
'payload': json.loads(row['payload'])
|
'payload': json.loads(row['payload'])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def _fetch_pending_builds_all_towns(c, player_id):
|
||||||
|
"""
|
||||||
|
Fetch ONE pending 'build' command per distinct town_id.
|
||||||
|
This allows all towns to build in parallel within a single poll cycle.
|
||||||
|
Within each town the oldest-updated command is picked first, so requeued
|
||||||
|
commands (updated_at = now) naturally sort behind fresh ones.
|
||||||
|
"""
|
||||||
|
# Get every town that has at least one pending build, ordered by
|
||||||
|
# which town has been waiting longest (MIN updated_at across its commands).
|
||||||
|
town_rows = c.execute('''
|
||||||
|
SELECT town_id
|
||||||
|
FROM commands
|
||||||
|
WHERE status = 'pending' AND type = 'build' AND player_id = ?
|
||||||
|
GROUP BY town_id
|
||||||
|
ORDER BY MIN(updated_at) ASC
|
||||||
|
''', (player_id,)).fetchall()
|
||||||
|
|
||||||
|
results = []
|
||||||
|
now = datetime.utcnow().isoformat()
|
||||||
|
for town_row in town_rows:
|
||||||
|
town_id = town_row['town_id']
|
||||||
|
row = c.execute('''
|
||||||
|
SELECT * FROM commands
|
||||||
|
WHERE status = 'pending' AND type = 'build'
|
||||||
|
AND player_id = ? AND town_id = ?
|
||||||
|
ORDER BY updated_at ASC, id ASC
|
||||||
|
LIMIT 1
|
||||||
|
''', (player_id, town_id)).fetchone()
|
||||||
|
if not row:
|
||||||
|
continue
|
||||||
|
c.execute('''
|
||||||
|
UPDATE commands SET status = 'executing', updated_at = ?
|
||||||
|
WHERE id = ?
|
||||||
|
''', (now, row['id']))
|
||||||
|
results.append({
|
||||||
|
'id': row['id'],
|
||||||
|
'town_id': row['town_id'],
|
||||||
|
'type': row['type'],
|
||||||
|
'payload': json.loads(row['payload'])
|
||||||
|
})
|
||||||
|
return results
|
||||||
|
|
||||||
@api.route('/api/commands/pending', methods=['GET'])
|
@api.route('/api/commands/pending', methods=['GET'])
|
||||||
def get_pending_command():
|
def get_pending_command():
|
||||||
player_id = request.args.get('player_id')
|
player_id = request.args.get('player_id')
|
||||||
@@ -134,7 +178,7 @@ def get_pending_command():
|
|||||||
conn = get_db()
|
conn = get_db()
|
||||||
c = conn.cursor()
|
c = conn.cursor()
|
||||||
|
|
||||||
build_cmd = _fetch_pending_of_type(c, 'build', player_id)
|
build_cmds = _fetch_pending_builds_all_towns(c, player_id) # one per town
|
||||||
recruit_cmd = _fetch_pending_of_type(c, 'recruit', player_id)
|
recruit_cmd = _fetch_pending_of_type(c, 'recruit', player_id)
|
||||||
market_cmd = _fetch_pending_of_type(c, 'market_offer', player_id)
|
market_cmd = _fetch_pending_of_type(c, 'market_offer', player_id)
|
||||||
farm_cmd = _fetch_pending_of_type(c, 'farm_loot', player_id)
|
farm_cmd = _fetch_pending_of_type(c, 'farm_loot', player_id)
|
||||||
@@ -164,7 +208,7 @@ def get_pending_command():
|
|||||||
conn.close()
|
conn.close()
|
||||||
|
|
||||||
return jsonify({
|
return jsonify({
|
||||||
'build': build_cmd,
|
'builds': build_cmds, # list: one build command per town
|
||||||
'recruit': recruit_cmd,
|
'recruit': recruit_cmd,
|
||||||
'market': market_cmd,
|
'market': market_cmd,
|
||||||
'research': research_cmd,
|
'research': research_cmd,
|
||||||
|
|||||||
Reference in New Issue
Block a user