Add game event support to the admin client
Everything on the admin GameScript channel so far has been request/reply. This adds the other direction: subscribe_events() opens a push stream so a bot can react to the game instead of polling it, consumed either by awaiting wait_for_event() or via an on_event callback. Both see every event; an event goes to at most one waiter, and unclaimed ones sit in a bounded buffer. Sixteen kinds, from two sources. The engine raises no GameScript event for a vehicle reaching a stop or cargo arriving, so vehicle_arrive, vehicle_depart and cargo_waiting are synthesised by the bridge sampling state every `interval` ticks and diffing against the previous sample -- which means a stop shorter than the interval is never reported, and the first sample only establishes a baseline. The rest (crashes, industries, towns, companies, subsidies) are engine events forwarded verbatim. vehicle_lost, vehicle_waiting_in_depot and vehicle_unprofitable are deliberately absent: the engine raises those only for AI companies, so a GameScript can never observe them. The server-side half lives in the AdminBridge GameScript, which is not in this repo -- docker/config is gitignored -- so it has to be updated separately for any of this to work. Also repoints the scheduled-dispatch E2E test at a dedicated vehicle (DISPATCH_VEHICLE_ID). It had been silently skipping because vehicle 7 carries a hand-built annual dispatch schedule, which left eight dispatch methods unverified end to end while check_public_calls.py reported them green off static analysis of the call sites. Co-Authored-By: Claude <[email protected]>
This commit is contained in:
+21
-2
@@ -7,7 +7,7 @@ import sys
|
||||
sys.path.append(os.path.join(os.path.dirname(__file__), 'lib'))
|
||||
|
||||
from openttd import OpenTTDAdminClient
|
||||
from openttd.protocol import AdminUpdateFrequency, AdminUpdateType
|
||||
from openttd.protocol import AdminUpdateFrequency, AdminUpdateType, GameEventType
|
||||
|
||||
# Configuration
|
||||
SERVER_HOST = "127.0.0.1"
|
||||
@@ -85,7 +85,26 @@ async def run_admin():
|
||||
except Exception as e: # noqa: BLE001 - demo script: one failed station query should not abort the walk
|
||||
print(f"!!! station query failed: {e}")
|
||||
|
||||
await asyncio.sleep(5)
|
||||
# Watch the game live: vehicles reaching/leaving stops and cargo piling up at stations.
|
||||
print("--- Subscribing to game events ---")
|
||||
try:
|
||||
accepted = await admin.subscribe_events(
|
||||
events=[GameEventType.VehicleArrive, GameEventType.VehicleDepart,
|
||||
GameEventType.CargoWaiting],
|
||||
interval=5, timeout=10.0)
|
||||
print(f" subscribed to {accepted['events']} every {accepted['interval']} ticks")
|
||||
|
||||
for _ in range(5):
|
||||
try:
|
||||
event = await admin.wait_for_event(timeout=15.0)
|
||||
except asyncio.TimeoutError:
|
||||
print(" (nothing happened -- is the server paused or idle?)")
|
||||
break
|
||||
print(f">>> [EVENT] {event}")
|
||||
await admin.unsubscribe_events()
|
||||
except Exception as e: # noqa: BLE001 - demo script: report and carry on to a clean quit
|
||||
print(f"!!! event subscription failed: {e}")
|
||||
|
||||
print("--- Quitting ---")
|
||||
await admin.quit()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user