from __future__ import annotations from dataclasses import dataclass, field from engine.character import Character from engine.character_library import CharacterLibrary from engine.defs import DefRegistry from engine.entity import EntityPosition from engine.world import World @dataclass class StartScreen: """Pure interaction state for the pre-game start screen: pick one of the current account's persistent characters (see engine/character_library.py::CharacterLibrary) to join a session with - single-player continuation or joining someone else's multiplayer world with a character built up over time. No rendering here - same boundary as LayerPickerMenu/AbilityBar/CharacterMenu in engine/ui.py: listing characters as clickable rows and drawing the screen itself is a follow-up UI-layer task. This is the state/logic side: which characters exist for this account, which one is currently selected, and handing off to join_selected_character() once confirmed. Creating a brand new character is a separate flow - see engine/character_creator.py. """ account_id: str characters: list[tuple[str, str, str | None]] = field(default_factory=list) # (character_id, name, species_id) selected_index: int | None = None @classmethod def load_for_account(cls, account_id: str, library: CharacterLibrary) -> "StartScreen": return cls(account_id=account_id, characters=library.list_characters(account_id)) def refresh(self, library: CharacterLibrary) -> None: """Re-reads the character list (e.g. after creating or deleting one) and clears selection.""" self.characters = library.list_characters(self.account_id) self.selected_index = None def select(self, index: int) -> None: if 0 <= index < len(self.characters): self.selected_index = index def selected_character_id(self) -> str | None: if self.selected_index is None: return None return self.characters[self.selected_index][0] def join_world_with_character( world: World, library: CharacterLibrary, account_id: str, character_id: str, registry: DefRegistry, spawn_position: EntityPosition, ) -> Character | None: """Loads a persistent character from the library and drops it into `world` at `spawn_position` - the "confirm join" action once a StartScreen selection is made. Returns None (no-op on `world`) if no such character exists for this account. """ character = library.load_character(account_id, character_id, registry) if character is None: return None character.position = spawn_position world.add_entity(character) return character