mud_server.core.world ===================== .. py:module:: mud_server.core.world .. autoapi-nested-parse:: World data management and structures. This module defines the world data structures (rooms and items) and provides the World class for loading and querying world data. The world is loaded from JSON files at server startup and kept in memory for fast access. World Structure: - Rooms: Named locations with descriptions, exits to other rooms, and items - Items: Objects that can be found in rooms and picked up by players - Exits: Directional connections between rooms (north, south, east, west, up, down) - Zones: Collections of related rooms loaded from separate files Data Storage (Zone-based - preferred): - World registry: data/world.json (zone list, global config) - Zone files: data/zones/.json (rooms and items per zone) Data Storage (Legacy - fallback): - Single file: data/world_data.json (all rooms and items) Design Notes: - Rooms and items are identified by unique string IDs - Exits are one-way unless defined in both rooms - Items in rooms are shared (multiple players can pick up same item) - Room descriptions are generated dynamically to include current state - Cross-zone exits use "zone:room" format (e.g., "docks:east_pier") Attributes ---------- .. autoapisummary:: mud_server.core.world.logger mud_server.core.world.DATA_DIR mud_server.core.world.WORLD_JSON_PATH mud_server.core.world.ZONES_DIR Classes ------- .. autoapisummary:: mud_server.core.world.Room mud_server.core.world.Item mud_server.core.world.Zone mud_server.core.world.World Module Contents --------------- .. py:data:: logger .. py:data:: DATA_DIR .. py:data:: WORLD_JSON_PATH .. py:data:: ZONES_DIR .. py:class:: Room Represents a room/location in the MUD world. Rooms are the fundamental spatial unit of the game world. Players move between rooms using directional exits. Each room can contain items and multiple players. .. attribute:: id Unique identifier for this room (e.g., "spawn", "forest_1") .. attribute:: name Human-readable name displayed to players (e.g., "Spawn Zone") .. attribute:: description Detailed description of the room's appearance .. attribute:: exits Dictionary mapping directions to destination room IDs Format: {"north": "forest_1", "south": "desert_1"} .. attribute:: items List of item IDs currently in this room .. admonition:: Example Room( id="spawn", name="Spawn Zone", description="You stand in a peaceful plaza...", exits={"north": "forest_1", "south": "desert_1"}, items=["torch", "rope"] ) .. py:attribute:: id :type: str .. py:attribute:: name :type: str .. py:attribute:: description :type: str .. py:attribute:: exits :type: dict[str, str] .. py:attribute:: items :type: list[str] .. py:class:: Item Represents an item/object in the MUD world. Items can be found in rooms and picked up by players. They are stored in player inventories and can be dropped back into rooms. .. attribute:: id Unique identifier for this item (e.g., "torch", "sword_1") .. attribute:: name Human-readable name displayed to players (e.g., "Rusty Torch") .. attribute:: description Detailed description of the item's appearance .. admonition:: Example Item( id="torch", name="Rusty Torch", description="A flickering torch that barely lights the way." ) .. note:: Items currently have no gameplay mechanics (no stats, durability, etc.) They are purely for inventory and flavor. Future enhancements could add item types, usability, combat stats, etc. .. py:attribute:: id :type: str .. py:attribute:: name :type: str .. py:attribute:: description :type: str .. py:class:: Zone Represents a zone/region in the MUD world. Zones are collections of related rooms loaded from separate JSON files. Each zone has its own spawn point and can define zone-specific items. .. attribute:: id Unique identifier for this zone (e.g., "crooked_pipe", "docks") .. attribute:: name Human-readable name (e.g., "Crooked Pipe District") .. attribute:: description Description of the zone's theme/purpose .. attribute:: spawn_room Default room ID for players entering this zone .. attribute:: rooms List of room IDs belonging to this zone .. admonition:: Example Zone( id="crooked_pipe", name="Crooked Pipe District", description="A warren of goblin pubs...", spawn_room="spawn", rooms=["spawn", "front_parlour", "back_parlour", ...] ) .. py:attribute:: id :type: str .. py:attribute:: name :type: str .. py:attribute:: description :type: str .. py:attribute:: spawn_room :type: str .. py:attribute:: rooms :type: list[str] :value: [] .. py:class:: World(*, world_root = None) Manages the MUD world data, providing access to rooms and items. This class is instantiated once at server startup and loads all world data from JSON files into memory. It supports two loading modes: 1. Zone-based (preferred): Loads world.json registry + individual zone files 2. Legacy (fallback): Loads single world_data.json file .. attribute:: rooms Dictionary mapping room IDs to Room objects .. attribute:: items Dictionary mapping item IDs to Item objects .. attribute:: zones Dictionary mapping zone IDs to Zone objects .. attribute:: default_spawn Tuple of (zone_id, room_id) for new player spawn .. attribute:: world_name Name of the world (from world.json) Design Notes: - World data is immutable after loading (read-only) - All data kept in memory for fast access - No database storage for world data (uses JSON files) - Changes to JSON require server restart to take effect - Zone-based loading allows modular world building Initialize the World by loading data from JSON files. Loads zone-based data (world.json + zones/). :param world_root: Optional path to a world package directory. When provided, world.json and zones are loaded relative to this directory. :raises FileNotFoundError: If no world data files exist :raises JSONDecodeError: If JSON files are malformed :raises KeyError: If required fields are missing from JSON .. py:attribute:: rooms :type: dict[str, Room] .. py:attribute:: items :type: dict[str, Item] .. py:attribute:: zones :type: dict[str, Zone] .. py:attribute:: world_name :type: str :value: 'Unknown World' .. py:attribute:: default_spawn :type: tuple[str, str] :value: ('', 'spawn') .. py:method:: resolve_room(room_ref) Resolve a room reference to a Room object. Handles both simple room IDs and cross-zone references (zone:room). Currently all rooms are stored in a flat namespace, so the zone prefix is parsed but the room is looked up by ID only. :param room_ref: Room reference (e.g., "spawn" or "docks:east_pier") :returns: Room object if found, None if room doesn't exist .. admonition:: Example >>> world.resolve_room("spawn") Room(id='spawn', ...) >>> world.resolve_room("docks:east_pier") Room(id='east_pier', ...) # Looks up 'east_pier' in rooms .. py:method:: get_room(room_id) Retrieve a room by its ID. For cross-zone references (zone:room format), use resolve_room() instead. :param room_id: Unique room identifier (e.g., "spawn", "forest_1") :returns: Room object if found, None if room doesn't exist .. admonition:: Example >>> world.get_room("spawn") Room(id='spawn', name='Spawn Zone', ...) >>> world.get_room("nonexistent") None .. py:method:: get_item(item_id) Retrieve an item by its ID. :param item_id: Unique item identifier (e.g., "torch", "sword_1") :returns: Item object if found, None if item doesn't exist .. admonition:: Example >>> world.get_item("torch") Item(id='torch', name='Rusty Torch', ...) >>> world.get_item("nonexistent") None .. py:method:: get_room_description(room_id, username, *, world_id = None) Generate a detailed, formatted description of a room. Creates a comprehensive room description including: - Room name and description - Items present in the room - Other players in the room (excluding the requesting player) - Available exits with destination names :param room_id: ID of the room to describe :param username: Username of the player requesting description (excluded from the player list) :returns: Formatted multi-line string with complete room information Returns "Unknown room." if room_id doesn't exist Format: === Room Name === Room description text here. [Items here]: - Item Name 1 - Item Name 2 [Players here]: - Player1 - Player2 [Exits]: - north: Destination Room Name - south: Another Room Name .. admonition:: Example >>> world.get_room_description("spawn", "player1") ''' === Spawn Zone === You stand in a peaceful plaza... [Items here]: - Torch - Rope [Players here]: - player2 - admin [Exits]: - north: Enchanted Forest - south: Golden Desert ''' .. py:method:: can_move(room_id, direction) Check if movement in a direction is valid and get the destination. Validates that: 1. The current room exists 2. The room has an exit in the specified direction 3. The destination room exists (supports cross-zone exits) Cross-zone exits use "zone:room" format (e.g., "docks:east_pier"). The zone will be lazy-loaded if not already present. :param room_id: Current room ID :param direction: Direction to move (e.g., "north", "south", "east", "west") Case-insensitive :returns: Tuple of (can_move, destination_room_id) - (True, "room_id"): Movement is valid, destination is the room ID - (False, None): Movement is invalid .. admonition:: Example >>> world.can_move("spawn", "north") (True, "forest_1") >>> world.can_move("spawn", "west") (False, None) # No west exit >>> world.can_move("pub_entrance", "west") (True, "east_pier") # Cross-zone exit "docks:east_pier" resolves to "east_pier"