Project tour
Start here. New to the codebase? Read this book in this order:
- Project tour – this page: the crate map and where to change X.
- Architecture – the full crate graph, app assembly, state machines and frame flow.
- Building & running – toolchain, cargo commands, examples, the web build, and how to contribute a change.
- Then pick the guide for your change: Add a ship section or Extend the scenario engine.
This page only orients you: the crate map and where to change X. For exact symbols per concept, use the Concept index.
Nova Protocol is a 3D space game built on Bevy 0.19 with avian3d physics.
You build ships out of modular sections (hull, controller, thruster, turret,
torpedo bay), fly them with real Newtonian thrust and a diegetic GOTO/ORBIT/
STOP autopilot, work inverse-square gravity wells, and fight with deliberate
angular radar lock-on. On top of the game sits an event-driven scenario/modding
engine (RON data) and a web site + WASM build. It is a Cargo workspace: the root
nova-protocol crate is a thin shell; all the real code lives under crates/.
Crate map at a glance
Slugs are the workspace members. One line each – see Architecture for responsibilities and the dependency graph.
| Crate | Owns |
|---|---|
nova-protocol (root) | src/main.rs clap CLI + entrypoint; src/lib.rs re-exports nova_core. |
nova_core | Wiring only: AppBuilder assembles the whole plugin stack. No gameplay. |
nova_gameplay | The shared gameplay layer under the ship: integrity, damage, gravity, the SFX engine, juice, objectives, mesh/transform rigs, entity markers. Owns GameStates/PauseStates/GameMode. |
nova_ship | The ship and how it is flown: sections, input (player/ai/radar), flight and its autopilot verbs, the camera rigs, the PD controller, the ship’s soundtrack. |
nova_wfc | Generated hulls: a catalog plus a code-owned WfcPlan in, a ShipDesign out. Owns the plan types; every caller builds its own plan. No App, no systems - the editor’s Generate verb and the wfc_* examples call it. |
nova_hud | The flight HUD: one module per widget (crosshairs, target inset, ammo readout, objective markers, comms panel, keybind dock). Reads the ship, never drives it. |
nova_command | The command language and the NOVA COMMANDS terminal model: catalog, parser, prompt state. No bevy UI. |
nova_interface | The TAB interface (Map, Ship and Inventory panes) and the : CRT command modal: pointer forwarding, casing, the back-out owner. A peer of the HUD, added by nova_core. |
nova_console | The command shell’s dispatcher: the executor behind the cmd> prompt and the channel’s command lane. Sits above nova_menu because a setting command writes the resources the settings screen owns. |
nova_scenario | Scenario engine: events, filters, actions, variables, world, loader, objects. |
nova_world | The streamed open world: a cell generated from its coordinate alone by a SectorGenerator type, checked, and a 5x5x5 active window streamed around one live scenario. Names no content; the game gets it through nova_world_base. Examples with their own game plugins install their own generator. |
nova_world_base | The base game’s open world: the NovaLayeredWorld generator and its cluster policy over three environment fields, the OpenWorldSession seed New Game writes, and the plugin AppBuilder adds that streams the world only while an OpenWorld scenario runs with one player ship. |
nova_events | Shared game-event kinds + entity identity components (gameplay <-> scenario). |
nova_events_macros | The EventKind derive behind nova_events’ engine events. Its only consumer is nova_events. |
nova_assets | bevy_asset_loader setup; loads glb/textures/shaders/sounds; owns the mod merge, safe mode (a broken optional mod is disabled, not fatal, except during a scenario) + prefs. |
nova_modding | Bundle/content/catalog asset loaders and the Content routing enum. |
nova_mod_format | Pure serde types for the mod formats (engine-free); re-exported by nova_modding. The static mod portal is built by scripts/gen-portal.py. |
nova_editor | The ship editor scene (NovaEditorPlugin), shown in GameMode::Sandbox. |
nova_menu | Main menu + the ESC pause overlay; hands off to Playing. New Game opens the world seed modal first. |
nova_training | The training handbook’s data: the Lesson content type, catalog ordering, field notes, progress, and the pure lesson validation both content lint and the runtime merge run. A leaf under nova_modding, nova_assets and nova_menu. |
nova_input | The bindings registry: the one table of named actions and the sources each holds, the shared rebind capture, and the by-name dispatch. A leaf under every rig and every rebind surface. |
nova_ui | Shared theme, skin, themed widgets, screen composition, unit formatting. A leaf: every UI-drawing crate (nova_gameplay, nova_hud, nova_interface, nova_menu, nova_editor, nova_assets) draws from it. |
nova_debug | Debug-only plugin (inspector, overlays); compiled under the debug feature. |
nova_info | Exposes APP_VERSION, injected by build.rs. |
nova_autopilot | Scripted automation drivers + the run-completion protocol. Bevy-only, game-agnostic. |
nova_channel | Dev tooling: the process channel. Named inputs, pointer moves, text, keys and command lines in on stdin; world snapshots and acknowledgements out on stdout. |
nova_probe | Dev tool (not in the shipped game): the in-game half of the run-harness - the capability plugins an example wires (frame time, timeline, invariants, world snapshot, scene census, frame cost). |
nova_probe_cli | Dev tool: the host half - spawns runs, grades artifacts, renders reports; the probe run/report CLI. |
nova_bench | Dev tool: the agent bench - referees an external agent (a scripted baseline, pi, any process) playing a scenario over the process channel, audits and scores the run; the bench play/replay CLI. |
nova_perf_web | Dev tool: the wasm app probe run --platform web boots and measures. |
nova_authoring | Offline content pipeline: the Rust builders for built-in scenarios/sections, content -- gen (writes assets/base/**/*.content.ron), content -- lint. |
nova_meta_gen | Binary under tools/ (web-build tooling, not a game crate): writes default .meta sidecars for web assets (Trunk post_build hook). |
Want to change X? Start here
The highest-value table. Verified paths; follow the linked page for depth.
| I want to change… | Start in | Read |
|---|---|---|
| A ship section behavior | crates/nova_ship/src/sections/ | Ship sections, Add a ship section |
| Damage types / how a round travels | crates/nova_gameplay/src/damage.rs | Ship sections |
| Integrity (disable/destroy) | crates/nova_gameplay/src/integrity/ | Ship sections |
| How a body wears its damage | crates/nova_ship/src/sections/damage_*.rs + crates/nova_gameplay/src/integrity/{erosion,carve}.rs | Ship sections |
| How an asteroid carves, and what it costs | crates/nova_scenario/src/objects/asteroid_carve.rs | Scenario engine |
| Flight / autopilot verbs | crates/nova_ship/src/flight/ | – |
| Player input / AI | crates/nova_ship/src/input/{player,ai}/ | – |
| Radar targeting / lock-on | crates/nova_ship/src/input/targeting/ | – |
| Gravity wells | crates/nova_gameplay/src/gravity.rs | – |
| A unit, or what a field is measured in | crates/nova_events/src/units.rs + crates/nova_events/src/scale.rs | Architecture |
| The HUD (widgets) | crates/nova_hud/src/ | – |
The TAB interface, its panes, and the : command modal | crates/nova_interface/src/ | – |
| The command catalog and parser | crates/nova_command/src/commands.rs | Architecture |
| A scenario event/filter/action | crates/nova_scenario/src/{events.rs,filters.rs,actions/} | Scenario engine, Extend the scenario engine |
| Scenario objects / loading | crates/nova_scenario/src/{objects/,loader/} | Scenario engine |
| What a streamed world cell holds, or when one comes and goes | crates/nova_world/src/{generation.rs,streaming.rs}, base generator, clusters and environment fields in crates/nova_world_base/src/{layered.rs,clusters.rs,environment.rs} | Architecture |
| Mod loading / merge | crates/nova_assets/ + crates/nova_modding/ | Mod files, Publish a mod |
| A built-in scenario or section | crates/nova_authoring/src/ (builders), then content -- gen | Create your first scenario |
| A generated hull, or the plan it is drawn from | crates/nova_wfc/ (plan.rs for the plan, WfcPlan::standard_hull for the shipped one) and each caller’s own plan builder | Concept index, Ship layout sense |
| The ship editor | crates/nova_editor/ | – |
| Shared UI theme / widgets | crates/nova_ui/ | – |
| The web site / wiki | web/ | Building & running |
The boot path in one glance
AppBuilder (in crates/nova_core/src/lib.rs) is the single place the app is
wired – DefaultPlugins + window/log/asset/render setup, then the plugin stack
(assets, gameplay, ship, scenario, HUD + interface, editor, menu, debug).
The state machines:
GameStates { Loading, MainMenu, Playing }– top-level lifecycle. LeavingPlayingreturns throughLoading: the content is re-read on the way to the front door, and the menu is built once, on the far side of it.PauseStates { Unpaused, Paused }– the ESC overlay, nested inPlaying.GameAssetsStates { Boot, Loading, Processing, Loaded, Failed }– the asset pipeline that gates entry; onOnEnter(Loaded)the app hands off toMainMenu/Playing. Only the base game is MANDATORY: an optional mod loads beside the pipeline, and a broken one is switched off and reported instead of failing the boot.Failedis the mandatory failure, and it is terminal - the loading animation is replaced by a report.
Gameplay systems run an explicit chain configured identically in Update and
FixedUpdate; avian3d physics runs on a fixed timestep in FixedPostUpdate.
The plugin order, exact sets, frame flow, and the Update-vs-FixedUpdate rule
live in Architecture – start there once the shape clicks.
flowchart LR
player["Player / AI input"] --> game["Game crates<br/>(nova_ship + nova_gameplay + nova_core)"]
game --> scenario["nova_scenario<br/>(events / filters / actions)"]
data["Data (RON)<br/>scenarios + mods"] --> assets["nova_assets + nova_modding"]
assets --> game
scenario --> game
game --> screen["Rendered frame + HUD"]