Concurrency.
This commit is contained in:
+48
-34
@@ -18,38 +18,50 @@ ws_manager = WebSocketManager(game_state)
|
||||
economy_engine = EconomyEngine(game_state)
|
||||
database = Database()
|
||||
|
||||
# --- HYBRID MODEL RE-IMPLEMENTED ---
|
||||
last_economy_tick_time = time.time()
|
||||
TICK_INTERVAL = 10 # seconds
|
||||
|
||||
# --- FIX: Reverting to a simple, reliable 10-second loop ---
|
||||
async def economy_loop():
|
||||
"""A simple loop that runs the economy tick every 10 seconds."""
|
||||
while True:
|
||||
await asyncio.sleep(TICK_INTERVAL)
|
||||
|
||||
logger.info("Triggering scheduled economy tick.")
|
||||
start_time = time.perf_counter()
|
||||
async def trigger_economy_update_and_save():
|
||||
"""Triggers an economy tick, broadcasts updates concurrently, saves, and resets the timer."""
|
||||
global last_economy_tick_time
|
||||
|
||||
logger.debug("Triggering full economy update and save cycle...")
|
||||
start_time = time.perf_counter()
|
||||
|
||||
# 1. Process one economy tick
|
||||
economy_engine.tick()
|
||||
economy_engine.tick()
|
||||
|
||||
update_tasks = []
|
||||
for player_id, player in game_state.players.items():
|
||||
if player_id in ws_manager.active_connections:
|
||||
task = ws_manager.send_to_player(player_id, {
|
||||
"type": "player_stats_update",
|
||||
"player": player.to_dict()
|
||||
})
|
||||
update_tasks.append(task)
|
||||
|
||||
if update_tasks:
|
||||
await asyncio.gather(*update_tasks)
|
||||
|
||||
database.save_game_state(game_state)
|
||||
|
||||
# Reset the global tick timer after any update
|
||||
last_economy_tick_time = time.time()
|
||||
|
||||
duration = time.perf_counter() - start_time
|
||||
logger.info(f"Full economy update cycle completed in {duration:.4f} seconds.")
|
||||
|
||||
async def economy_loop():
|
||||
"""Runs periodically to check if a passive economy update is needed."""
|
||||
global last_economy_tick_time
|
||||
while True:
|
||||
# Check if 10 seconds have passed since the last tick (from any source)
|
||||
if time.time() - last_economy_tick_time > TICK_INTERVAL:
|
||||
logger.info("Triggering timed economy update for idle players.")
|
||||
await trigger_economy_update_and_save()
|
||||
|
||||
# 2. Broadcast updates concurrently
|
||||
update_tasks = []
|
||||
for player_id, player in game_state.players.items():
|
||||
if player_id in ws_manager.active_connections:
|
||||
task = ws_manager.send_to_player(player_id, {
|
||||
"type": "player_stats_update",
|
||||
"player": player.to_dict()
|
||||
})
|
||||
update_tasks.append(task)
|
||||
|
||||
if update_tasks:
|
||||
await asyncio.gather(*update_tasks)
|
||||
|
||||
# 3. Save the new state
|
||||
database.save_game_state(game_state)
|
||||
|
||||
duration = time.perf_counter() - start_time
|
||||
logger.info(f"Economy tick cycle completed in {duration:.4f} seconds.")
|
||||
# Check frequently for responsiveness
|
||||
await asyncio.sleep(1)
|
||||
|
||||
@asynccontextmanager
|
||||
async def lifespan(app: FastAPI):
|
||||
@@ -58,9 +70,9 @@ async def lifespan(app: FastAPI):
|
||||
database.init_db()
|
||||
game_state.load_state(database.load_game_state())
|
||||
|
||||
# Start the simple economy loop
|
||||
# Start the hybrid economy loop
|
||||
task = asyncio.create_task(economy_loop())
|
||||
logger.info(f"Economy loop started with a {TICK_INTERVAL}-second interval.")
|
||||
logger.info("Hybrid economy loop started.")
|
||||
|
||||
yield
|
||||
|
||||
@@ -117,8 +129,9 @@ async def handle_message(websocket: WebSocket, data: dict):
|
||||
result = game_state.place_building(player_id, data["building_type"], data["x"], data["y"])
|
||||
if result["success"]:
|
||||
await ws_manager.broadcast({"type": "building_placed", "building": result["building"]})
|
||||
# --- CHANGE: Action now only saves, economy is handled by the loop ---
|
||||
database.save_game_state(game_state)
|
||||
# --- CHANGE: Trigger an INSTANT economy update on financial action ---
|
||||
logger.info(f"Player {player_id} action triggered immediate economy update.")
|
||||
await trigger_economy_update_and_save()
|
||||
else:
|
||||
await websocket.send_json({"type": "error", "message": result["error"]})
|
||||
|
||||
@@ -126,8 +139,9 @@ async def handle_message(websocket: WebSocket, data: dict):
|
||||
result = game_state.remove_building(player_id, data["x"], data["y"])
|
||||
if result["success"]:
|
||||
await ws_manager.broadcast({"type": "building_removed", "x": data["x"], "y": data["y"]})
|
||||
# --- CHANGE: Action now only saves, economy is handled by the loop ---
|
||||
database.save_game_state(game_state)
|
||||
# --- CHANGE: Trigger an INSTANT economy update on financial action ---
|
||||
logger.info(f"Player {player_id} action triggered immediate economy update.")
|
||||
await trigger_economy_update_and_save()
|
||||
else:
|
||||
await websocket.send_json({"type": "error", "message": result["error"]})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user