Skip to main content

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_nameRouted 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 namecommand_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

PropertyTracks
character_revisionRevision of local player data: inventory, equipment, status, skills, private ground items
map_revisionRevision of map-scoped data: NPC positions, remote player positions, public ground items

Signals

SignalEmitted 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:
KeyApplied as
inventoryReplaces _world_snapshot["player"]["inventory"]
equipmentReplaces _world_snapshot["player"]["equipment"]
statusReplaces _world_snapshot["player"]["status"]
skillsReplaces _world_snapshot["player"]["skills"]
private_ground_itemsReplaces _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:
  1. If next_revision <= current_revision → duplicate or out-of-order; silently drop.
  2. If next_revision == current_revision + 1 and the stream is not stale → accept and apply.
  3. 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.

Build docs developers (and LLMs) love