Documentation Index
Fetch the complete documentation index at: https://mintlify.com/TaylorZaneKirk/MMO-Project/llms.txt
Use this file to discover all available pages before exploring further.
GameStateStore and GameSessionPresenter are the two state-management scripts that live under screens/game/state/. Together they form the boundary between raw WebSocket transport and the rendering controllers. GameSessionPresenter receives every inbound message from SessionClient, classifies it by name, and routes it to the correct method on GameStateStore. GameStateStore owns the single authoritative view of local player state, remote players, NPCs, and ground items — and emits typed signals that controllers subscribe to for rendering.
GameSessionPresenter
File: prototype/client/screens/game/state/game_session_presenter.gd
GameSessionPresenter extends Node and is configured with references to GameStateStore and SessionClient via configure(state_store, session_client). It subscribes to GameStateStore.resync_requested to forward resync requests through the transport layer.
Message routing
handle_message(message_name, payload) is called for every frame emitted by SessionClient.message_received. Routing rules:
message_name | Routed to |
|---|
"world_snapshot" | _state_store.apply_world_snapshot(payload) — full hydration |
"character_state_updated" | _state_store.apply_character_state_updated(payload) — delta patch |
"ground_item_spawned" | _state_store.apply_ground_item_spawned(payload) — map stream update |
"ground_item_removed" | _state_store.apply_ground_item_removed(payload) — map stream update |
"movement_applied" | _state_store.apply_movement_applied_update(payload) — positional update |
"player_state_update" | _state_store.apply_remote_player_state_update(payload) — remote player position |
"npc_state_update" | _state_store.apply_npc_state_update(payload) — NPC position |
| Any other name | command_response_received signal — passed to GameScreen for command-response handling (inventory use, drop, pickup, unequip) |
Resync forwarding
When GameStateStore detects a revision gap it emits resync_requested(streams, reason). GameSessionPresenter handles this signal and calls _session_client.send_world_resync_request(streams, character_revision, map_revision, reason).
GameStateStore
File: prototype/client/screens/game/state/game_state_store.gd
GameStateStore extends Node and tracks two independent revision counters.
Revision counters
| Property | Tracks |
|---|
character_revision | Revision of local player data: inventory, equipment, status, skills, private ground items |
map_revision | Revision of map-scoped data: NPC positions, remote player positions, public ground items |
Signals
| Signal | Emitted when |
|---|
world_snapshot_changed(payload) | Full snapshot applied, or delta patch applied — all controllers re-render |
movement_applied(payload) | movement_applied message accepted — LocalPlayerController updates movement visuals |
remote_player_state_updated(payload) | player_state_update message accepted — RemotePlayerController interpolates |
npc_state_updated(payload) | npc_state_update message accepted — NpcController interpolates |
resync_requested(streams, reason) | Revision gap detected — GameSessionPresenter forwards to server |
Full snapshot hydration
apply_world_snapshot(payload) replaces the internal _world_snapshot dictionary with a deep copy, updates both revision counters, clears stale flags, clears _resync_in_flight, calls SessionState.apply_world_snapshot(_world_snapshot), and emits world_snapshot_changed. All controllers that subscribed to world_snapshot_changed will re-render fully from the new snapshot.
Delta mode (character_state_updated)
Clients that sent runtime_delta_protocol: 1 during login receive character_state_updated messages for local-player changes instead of full snapshot refreshes. apply_character_state_updated(payload) reads character_revision from the payload and applies a revision check before patching.
The changes dictionary may contain any subset of these keys:
| Key | Applied as |
|---|
inventory | Replaces _world_snapshot["player"]["inventory"] |
equipment | Replaces _world_snapshot["player"]["equipment"] |
status | Replaces _world_snapshot["player"]["status"] |
skills | Replaces _world_snapshot["player"]["skills"] |
private_ground_items | Replaces _world_snapshot["private_ground_items"]; ground_items is recomposed by merging public and private arrays |
After patching, character_revision is updated, SessionState.apply_world_snapshot is called with the patched snapshot, and world_snapshot_changed is emitted.
Revision acceptance rules
Before applying any delta, GameStateStore checks the incoming revision:
- If
next_revision <= current_revision → duplicate or out-of-order; silently drop.
- If
next_revision == current_revision + 1 and the stream is not stale → accept and apply.
- Otherwise → mark the stream stale, set
_resync_in_flight, emit resync_requested with the affected stream name and "revision_gap" as the reason; drop the delta.
Only one resync request is in flight at a time (_resync_in_flight flag). The flag clears when a fresh world_snapshot arrives via apply_world_snapshot.
Resync flow
GameStateStore detects revision gap
→ resync_requested.emit(["character"], "revision_gap")
→ GameSessionPresenter._on_resync_requested
→ SessionClient.send_world_resync_request(streams, character_revision, map_revision, reason)
→ Server responds with world_snapshot
→ GameStateStore.apply_world_snapshot(payload)
→ character_revision and map_revision reset to snapshot values
→ world_snapshot_changed.emit → all controllers re-render
Controllers should render exclusively from store-driven signals
(world_snapshot_changed, movement_applied, remote_player_state_updated,
npc_state_updated). Direct subscription to SessionClient.message_received
for game-state messages bypasses revision tracking and should be avoided.