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:
@@ -16,6 +16,11 @@ The primary API for developers.
|
||||
- **Event-Driven:** Uses `asyncio.Event` (like `self.joined`) to signal state changes to the calling code.
|
||||
- **Callback System:** Provides hooks like `on_chat` to allow users to react to game events without modifying the core library.
|
||||
|
||||
### 3. `OpenTTDAdminClient` (Admin Network)
|
||||
Talks to the Admin port (TCP 3977) and, through the AdminBridge GameScript's JSON channel, to the running game itself.
|
||||
- **Correlated Queries:** `get_timetable()`, `get_station()`, `get_dispatch()` and friends all funnel through `_gs_query()`, which tags each request with a monotonic `request_id`, parks a future, and lets `receive_ServerGamescript` resolve it when the matching reply arrives.
|
||||
- **Push Events:** `subscribe_events()` opens the one stream that flows the other way. Event batches carry no `request_id`, so `receive_ServerGamescript` routes them to the event consumers instead: each event goes to the longest-waiting matching `wait_for_event()` caller, or into a bounded buffer if nobody is waiting, and to the `on_event` observer either way. See [EVENTS.md](EVENTS.md).
|
||||
|
||||
## Handshake Flow
|
||||
|
||||
1. **Connection:** TCP connection established to Port 3979.
|
||||
|
||||
Reference in New Issue
Block a user