After a character is authenticated,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.
EnterWorldService reads the character’s last saved map position and makes it the authoritative live presence. A world_snapshot message then hydrates the full game state for the client — tiles, skills, inventory, equipment, NPCs, remote players, and visible ground items — before any gameplay messages flow. The snapshot is the client’s single source of truth at session start and after any resync request.
Enter world
EnterWorldService.EnterWorldAsync orchestrates the transition from authenticated identity to live map presence.
Load character world entry
Reads
map_id, tile_x, and tile_y from the characters table for the given character_id.Normalize position
WorldPositionNormalizationService.NormalizeCharacterWorldEntryAsync checks that the saved coordinates fall within a valid chunk. Out-of-range coordinates are snapped to the nearest valid tile.Ensure map loaded
Calls
WorldPositionNormalizationService.EnsureMapAsync to confirm the resolved map_id has chunk data loaded in WorldChunkCatalog.Upsert map presence
Calls
MapPresenceRepository.UpsertPresenceAsync with the normalized map_id, tile_x, and tile_y. This row drives reconnect, movement validation, and snapshot assembly from this point forward.World snapshot
WorldSnapshotService.BuildSnapshotAsync assembles the complete world_snapshot payload by querying every relevant repository before constructing the result. The snapshot carries both a character_revision and a map_revision so delta clients can detect any gap since the previous message.
The snapshot is organized around six data regions:
| Region | Contents |
|---|---|
| Local player | Tile position, facing, status bars (health, concentration, special — current and max), full skill list with base/equipment/temporary/effective values, 28-slot inventory with skill_requirements, skill_modifiers, and context_actions per item, full equipment slots |
| NPCs | npc_id, display_name, texture_path, tile_x, tile_y, facing, current_state for every NPC on the same map |
| Remote players | character_id, character_name, tile position, facing, and equipment snapshot for every other character present on the map |
| Ground items | All ground_items on the map that are currently visible to this character (ground_item_id, owner_character_id, position, item_name, icon_texture_path, stack_count) |
| Private ground items | Items dropped by this character that are still within the private visibility window — visible only to the owner |
| Revisions | character_revision and map_revision for delta stream tracking |
context_actions (e.g. equip, eat, use, drop) so the client can build right-click menus without duplicating item rules locally. These are menu affordances — not permission to apply mutations client-side.
WorldChunkCatalog
The prototype world is a flat, contiguous grid of chunks.WorldChunkCatalog loads and indexes all chunk definitions from prototype/shared/maps/ at startup.
| Property | Value |
|---|---|
| Grid dimensions | 20 × 20 chunks |
| Chunk tile size | 17 × 9 tiles per chunk |
| Total world tiles | 340 × 180 world-space tiles |
| Named origin chunk | x1000y992 at chunk position (10, 10) |
| Default chunk template | grass_17x9_v1 |
map_id values and dedicated JSON files under chunks/. Unnamed chunks receive a generated map_id in the format chunk_{x}_{y} and render using the default grass template.
WorldChunkCatalog exposes three coordinate conversion methods used by every movement and snapshot path:
ToWorldTile(mapId, localTileX, localTileY)— converts a chunk-local coordinate to an absolute world-tile position.ResolveWorldTile(worldTileX, worldTileY)— converts an absolute world-tile coordinate back to a(mapId, localTileX, localTileY)triple, including the resolvedchunkX/chunkY.ClampWorldTile(worldTileX, worldTileY)— clamps a world coordinate to the valid grid boundary before pathfinding.
Zone simulation
ZoneSimulationService.TickAsync is called every 600 ms by ZoneSimulationWorker. Each tick performs two phases:
-
Character movement — calls
MovementService.AdvanceActiveMovementsAsyncto dequeue one step for every character with an active path. Each resolved step is persisted and broadcast asmovement_appliedto the moving character. Other characters on the same map receive aplayer_state_updatewith the mover’s new tile and walking/idle animation state. -
NPC advancement — calls
NpcRuntimeService.AdvanceNpcStates(600)to tick every NPC’s state machine. NPCs with changed state are grouped by map. For each affected map, a newmap_revisionis allocated and a singlenpc_state_updatemessage is broadcast to all connected clients on that map.
Position normalization
WorldPositionNormalizationService snaps out-of-range chunk-local coordinates to the nearest valid tile and persists or updates the corrected position when a change is detected. It is called consistently across all three position-critical paths:
- Enter world — normalizes the saved
charactersposition before insertingmap_presence. - World snapshot — re-normalizes
map_presencebefore assembling the snapshot (updatePresence: true), keeping presence and snapshot coordinates in sync. - Movement — normalizes current presence before computing the A* path origin and after resolving each step.
Map revisions
world_snapshot carries both character_revision and map_revision. Delta-protocol clients track these values; if a subsequent message arrives with a revision that is non-contiguous, the client sends world_resync_request. The server responds with a fresh world_snapshot, which is the only recovery path for stale delta streams in the current prototype phase.
The 3×3 chunk area around the active player is rendered in the Godot client. The server serves all chunk data from shared JSON fixtures during the prototype phase.