← News  //  2025-11-08  //  v0.2.0

v0.2.0 - A reason to fly

This is the release where Nova Protocol grows past "build a ship and shoot rocks" and gains a reason to exist. v0.1.0 let you assemble a ship and fire at asteroids, which is fun for exactly as long as it takes to run out of things to do. v0.2.0 answers "and then what?" with three shipped pillars: a data-driven game-events and queue system, the first scenario and modding capabilities built directly on top of it, and procedurally generated asteroids that break apart under fire. It is a small update by line count, but it lays the backbone the whole game still runs on today.

Watch the devlog

Prefer to watch? The v0.2.0 devlog walks through this release on video:

Devlog #2 - the full v0.2.0 walkthrough on YouTube.

It is an optional companion to the written highlights below, which stand on their own.

Game events and a queue system

The headline of v0.2.0 is a small, data-driven engine that turns "what happens in the world" into something you author rather than compile. The impulse behind it was deliberate: rather than hardcode a couple of levels, the game leans on a data language for custom content, the same way old modding-friendly strategy games did. You cannot load Rust functions from an asset file, but you can load structs and turn them into logic at runtime, and that single idea is what the entire system is built around.

The three primitives

Everything is composed from three parts:

  • Events fired from the game world. When an object is destroyed, for example, the world emits an event carrying that object's id and type, so a handler downstream knows exactly what happened and to what.
  • Filters that decide when a handler should react. A filter can match by id, match by type, or invert another filter (a NotFilter), so handlers fire only for the objects they care about.
  • Actions that do something in response. An action can read or write scenario variables held in a small hashmap on the game world, or switch the game to another scenario entirely.

Dispatched through a queue

The events, filters, and actions are all dispatched through a queue rather than run inline, which keeps the flow of "world emits, handlers react, state changes" orderly and predictable. Under the hood this is the observer pattern, but the point was never the pattern - it was making the whole thing loadable from an asset instead of baked into the binary.

Why data beats code here

Because a win condition is data rather than compiled Rust, an objective becomes something you can write instead of something you have to build. "When an asteroid is destroyed, increment a counter; when the counter hits its target, switch scene" is an entire objective expressed as filters and actions over game events, with no recompile in the loop. That property is exactly what makes the system double as the foundation for both objectives and modding: the same asset format that authors a level also lets someone outside the codebase author one.

Scenarios and modding

On top of the event engine sits the first scenario system, and with it the first real taste of modding.

A scenario is a bag of event handlers

A scenario is nothing more than a bag of event handlers assembled from the filters and actions above. Because it is data all the way down, custom objectives can be loaded straight from assets, which means a scenario and a mod are the same shape of thing. This is the direct ancestor of the scenario engine the game runs on today - the surface has grown enormously since, but the core idea traces back here.

The objectives HUD

To make a scenario legible while you play it, a HUD lists the active objectives, and Enter advances to the next scenario when the world resource reports one is queued. That is the whole player-facing loop in v0.2.0: read your goals, meet them, press Enter, move on.

From the devlog

The devlog goes further into the corners this release also touched. These are devlog color rather than headline features - the shipped features of v0.2.0 are the event engine, scenarios, and the asteroids below - but they explain a lot about how the release came together.

A first, gloriously dumb enemy AI

v0.2.0 saw the game's first other ships, and the AI flying them is deliberately minimal: rotate toward the player, and if the alignment is good enough, thrust and shoot. The first version did not understand physics and cheerfully flew off into deep space like it had somewhere better to be; the version that shipped at least stopped leaving the map, mostly because it more or less forgot how to use its thrusters. The genuinely interesting failure was target prediction - the AI points its turret straight at you and still misses, because projectiles inherit the ship's motion and you are moving too. That is not just an AI problem; it is the same intercept-lead problem player auto-aim would have to solve later.

The Bevy transform-timing bug that ate a week

Making projectiles inherit their firing ship's velocity sounds trivial and was not. Spawning a projectile needs the turret's GlobalTransform, which Bevy only finalises at the end of the frame, so it lags a frame behind. With physics running in FixedUpdate while the firing logic ran in Update, the transforms desynced and the whole game turned jittery and unplayable. The fix was a trio of counterintuitive moves: disable interpolation (it was supposed to smooth motion but made the jitter worse), move helper systems to PostUpdate so inputs are gathered before logic runs, and compute the global transform on demand with TransformHelper when firing - pricier, but only per shot. A Graphviz view of the system-set graph was what actually pinned down the one system running at the wrong time.

Asteroids with procedural mesh and dynamic destruction

The old sphere asteroids are gone, and their replacement is the most visible change in the release.

Octahedron-sphere base mesh

Asteroids now build from a noise-displaced octahedron sphere rather than a UV sphere. The reason is triangle distribution: an octahedron sphere's triangles stay roughly even in size across the surface instead of bunching up at the poles, which gives noise displacement an even canvas to push and pull against. The base shape is displaced with noise, and a photo of an actual rock, made seamless and projected on with simple planar UVs, finishes the surface so it reads as stone rather than a tinted ball.

Dynamic destruction

Asteroids also support dynamic destruction: instead of simply vanishing when their health runs out, they break apart under fire. That turns a rock from a static prop into something that visibly comes apart when you shoot it, and it pairs with the event system above - a destroyed asteroid is exactly the kind of event a scenario counter listens for.

Point releases

v0.2.1 - Notes for the modders

v0.2.1 is aimed squarely at anyone writing mods, and nothing in it is player-facing.

The modding capabilities that landed in v0.2.0 finally get documentation and worked examples to match. Instead of reading the source to work out how to hook into the game, you get written guidance and sample scenarios to start from, which turns the modding path from an archaeology exercise into something you can follow.

Underneath, the event system got a cleanup refactor - the same events and queue introduced in v0.2.0, reworked to be cleaner and easier to reason about. It is groundwork only, with no change to how the game behaves, but it makes everything built on top of the event engine after this point easier to extend.