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.20 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, 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 Mod Editor (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 Mod 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"]