Tour of the client code ======================= ``ishtaria-client`` is a Godot 4.5 project that builds almost all of its interface in code. There is one scene (``scenes/main.tscn``); ``scripts/main.gd`` creates every node, wires the signals and handles input. Principles ---------- * **The client shows and asks; it does not decide.** Every ``*_client.gd`` and ``player_session.gd`` is a thin HTTP layer that sends an intention and emits a signal with a *validated* answer. * **Validate every answer.** Each client has static ``valid_*`` functions that check type, shape and range; what does not pass is dropped. They are the first thing to test. * **Refusals are message keys.** Map the server's fixed error text to a translatable key in a static ``error_key`` function; never show server text. * **A generation counter guards requests.** Each client increments ``_generation`` in ``stop()`` and ignores answers that belong to an earlier connection, so a late answer never changes a newly chosen server. * **English is the source, Czech a translation** (``locales/client.csv``; add every new text key there). Files ----- .. list-table:: :header-rows: 1 :widths: 30 70 * - File - Responsibility * - ``main.gd`` - the planet preview and surface view, input (``_input``: E, G, I, J, F, P, Enter, 1-9, Esc), wiring * - ``player_session.gd`` - account, profile, equipment, gathering, crafting, eating, drinking * - ``character_controls.gd``, ``character_catalog.gd``, ``character_creator.gd`` - walking and camera, the playable models, character creation * - ``surface_environment.gd`` - generated scenery, animals, NPCs, props and placed things (``apply_*``, ``nearest_*``) * - ``remote_players.gd`` - other players near you, with smooth movement * - ``social.gd``, ``chat_feed.gd``, ``friends_panel.gd`` - friends, the ``/events`` poll, chat lines and the chat input * - ``trading.gd``, ``trade_panel.gd`` - merchants, finds bought from NPCs, and exchanges between players * - ``placed_client.gd`` - placing, planting, picking up, harvesting, fishing * - ``magic_client.gd`` - spells, scrolls, casting * - ``survival_panel.gd``, ``player_hud.gd``, ``item_icons.gd`` - inventory, crafting and spells window; HUD meters; item icons * - ``minimap.gd`` - top-down minimap showing nearby entities with colored icons (diamond for NPCs, square for places, star for quests, circle for objects), name initials, player arrow, and north direction; uses texture caching and optimized updates * - ``story_client.gd``, ``dialogue_panel.gd``, ``quest_panel.gd`` - datadisk stories, conversations, quests * - ``portal_panel.gd``, ``escape_menu.gd``, ``control_settings.gd`` - portals, the menu, display, sound and key settings * - ``achievements_client.gd``, ``achievements_panel.gd``, ``achievement_toast.gd`` - achievements: the list from the server (a datadisk's texts come from ``/story/strings``), the window of the ESC menu, the banner of a new one * - ``ui/ui_theme.gd``, ``ui/ui_kit.gd``, ``ui/framed_style_box.gd`` - the interface theme (palette, fonts, Godot ``Theme`` merged into the default one in ``main.gd``) and the shared pieces: framed panel, divider, backdrop, open animation, button sounds Look of a new window -------------------- Do not build style boxes or pick colours in a panel. Give its ``PanelContainer`` ``theme_type_variation = &"FramePanel"`` (or build it with ``UiKit.framed_panel``), its title ``&"HeaderLabel"``, its main command ``&"PrimaryButton"`` and a quiet one ``&"GhostButton"``, and open it with ``UiKit.open_animated``. A list row goes on a card (``UiKit.card``, buttons centred with ``UiKit.center_buttons``); an answer in a conversation is a ``&"ChoiceButton"``. Add the window to ``tests/panels_look.gd`` and look at its screenshots from a native run. Colours, when a label really needs one, come from the constants of ``ui_theme.gd``. Long text keeps the default font; the Kenney display font is for titles, buttons and headers only. Keys and Settings ----------------- Every gameplay key belongs in ``character_controls.ACTIONS`` (with a default and a Settings label) and is handled through ``matches_action`` / ``spell_slot`` from ``main.gd``. Settings lists them all and lets the player rebind them; that window is the in-game key reference. ``RESERVED_KEYS`` holds only Escape (menu / cancel capture). When you add a new action, extend ``ACTIONS`` / ``DEFAULT_KEYS`` / ``LABELS``, wire it in ``main.gd``, and add the label to ``locales/client.csv``. Tests ----- ``tests/*.gd`` are ``SceneTree`` scripts started with ``godot4 --headless --script``; each has a ``make test-...`` target. A check calls ``_check(ok, "what")``, the script prints ``... passed`` and ``quit(1)`` on a failure. An error *inside* an ``await`` kills the script without ``quit`` and the run hangs: if a test seems to hang, run it with ``timeout`` and look for a script error.