# Project notes for agents ## Project overview Station is a persistent-world, RPG-style station simulation inspired by Space Station 13, with singleplayer and multiplayer. It is built in Rust (edition 2024) with Bevy 0.19 (ECS), bevy_replicon + renet (networking), Rune (scripting), rsn (data files) and Tiled (maps). Project documentation: [README.md](README.md). ## Agent rules - Never push changes unless explicitly told to. - After changing files, run `cargo fmt --all`. Do not override project formatting configuration or invoke a formatter directly on individual files. - Use conventional commits with the types `feat`, `fix`, `refactor`, `perf`, `test`, `docs`, `ci`, `build` and `chore`, scoped by crate or area where useful (`feat(server): ...`, `ci(gitea): ...`). Use `!` and a `BREAKING CHANGE:` footer for breaking API, save-format or protocol changes. - End commit messages with a co-author trailer appropriate to the agent and product. For example: `Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>`. - Inform the user about commits and other Git changes, including commit messages. - Commit changes after each step unless the user says not to or a `.NOCOMMIT` file exists in the repository root. - Changes affecting compilation or tests may only be committed after `cargo clippy --workspace --all-targets -- -D warnings` and `cargo nextest run --workspace` pass. - Documentation, CI, editor, and deployment configuration changes do not require code checks; validate workflow YAML syntax. - Check the current branch before every commit. - Commit formatting-only changes separately when formatting reformats code unrelated to the functional changes. - Add user-visible changes to the `Unreleased` section of `CHANGELOG.md` (Keep a Changelog format). ## Repository structure - `crates/game_core/`: shared data definitions (`data.rs`), ECS components, grid helpers, Tiled loader (`map.rs`) and network protocol (`protocol.rs`). - `crates/game_server/`: authoritative simulation, Rune engine (`scripting.rs`), persistence, and the `game-server` dedicated server binary. Integration tests live in `crates/game_server/tests/`. - `crates/game_client/`: the `game` binary: rendering, UI and input; embeds the server for singleplayer and hosting. - `assets/data/`: item, recipe, building and skill definitions (`.rsn`). - `assets/scripts/`: Rune scripts (`.rn`), referenced as `"module::function"`. - `assets/maps/`, `assets/tilesets/`, `assets/sprites/`: Tiled maps and art. - `tools/gen_placeholder_assets.py`: regenerates placeholder art and the example map (generated output is committed). - `.github/workflows/`, `.gitea/workflows/`: CI for GitHub and Gitea. - `.config/nextest.toml`: test runner configuration. Keep `README.md` (run instructions, controls, data formats, script API, Tiled conventions) in sync with API, configuration, and behavior changes. ## Architecture and constraints - The server is authoritative. Clients only send protocol events (`Login`, `SetMoveDir`, `Interact`, `Craft`, ...) and render replicated state; never mutate game state from client code. Singleplayer runs the same server plugin in-process, so behavior must not depend on the mode. - Game rules belong in data files or Rune scripts where possible; Rust code provides generic mechanics. Data references and script hooks are validated at load time. - Protocol registration order in `game_core::protocol` must match between client and server; changing it breaks compatibility. - Rune scripts stage changes in `ScriptState`; they are applied after the script returns, and a failing script has no effect. Ctx methods need `#[rune::function(keep)]`; script-facing numbers are integers. - Save files (`persistence.rs`, `SAVE_VERSION`) are the source of truth for an existing world; the Tiled map only seeds new worlds. Changing saved types requires a version bump or a compatible migration. - Characters are identified by name only (no authentication); renet uses unsecure authentication. Do not treat client input as trusted. - Replicon builds its systems in `Plugin::finish`; headless tests must call `app.finish(); app.cleanup();` and update the app once more per round trip. - Release builds of the client on Windows use the `windows` subsystem (no console output). ## Commands ```sh cargo fmt --all cargo build --workspace cargo clippy --workspace --all-targets -- -D warnings cargo nextest run --workspace ``` Run binaries with `cargo run` (client; `--host`, `--connect`) and `cargo run -p game_server --bin game-server`. The Windows client can be cross-built with `cargo build --release -p game_client --target x86_64-pc-windows-gnu` (needs MinGW). Running the client requires a Vulkan or GL capable GPU or a software driver such as lavapipe. ## Conventions - Write comments for *why*, not *what*: invariants, non-obvious constraints, workarounds (with the reason or a link), and units/timebases where the type doesn't say. Never restate what the code does. - Before committing, review every comment in your diff (`git diff`): delete those that restate the code or describe the change itself (e.g. "now uses X instead of Y"; that belongs in the commit message), and shorten the rest to one line where possible. - Comment only code that needs clarification; keep comments short. - Follow the repository's formatting, lint, error-handling, logging, and dependency-management conventions. - Prefer existing helpers and patterns; keep changes focused and surface failures explicitly. - Preserve existing line endings when editing files that use non-default line endings. - Do not add tests in locations the project's normal test commands do not discover. ## Code reviews For reviews of commits, branches, diffs, or specific files, report every finding as an entry in a list with this shape: - **Location:** `file:line` (use a range such as `file:120-146` when the finding spans several lines) - **Category:** one of `Blocking`, `FYI`, or `Nit` (use another category, such as `Question`, only when none of those fit) - **Comment:** the concrete issue or risk and, when claiming a defect, its failure scenario rather than only an abstract concern Order findings by severity, with `Blocking` first. Use `Blocking` for defects, unbounded resource use, or policy violations that must change before merge; use `FYI` for design consequences and risks worth a conscious decision; use `Nit` for style and cleanliness. Verify findings against the code and run the relevant lint and test commands before reporting them. Say when a finding is a possibility rather than a confirmed defect.