npb
<!-- zero:scaffolded-readme --> <!-- Replace the line below with what this module provides and who consumes it, then delete both comment lines. -->
npb
<!-- zero:scaffolded-readme --> <!-- Replace the line below with what this module provides and who consumes it, then delete both comment lines. -->TODO: describe this module.
Interface
What this asset declares: the schema it conforms to, what it exposes, and the rendered structured payload.
conforms to
zero/source-extract/v2npb — the shared contract for Ninja Pirates of the Baltic. Every slice of the game requires this module and nothing requires a slice directly. It holds four things and no gameplay: 1. the constants the whole game agrees on (sea, match, rift, palette) 2. the live match state, as ONE table everybody reads and the rules slice writes 3. an event bus, so a slice reacts to what another slice did without knowing it exists 4. two registries — the fleet (what a junk looks like) and the helm (how the player's junk moves) — each with a working fallback, so any slice is playable before the other two land This file is FROZEN for the build phase. A slice that needs a new number keeps it in its own module; a slice that needs to reach another slice does it through a registry or an event declared here.
reset( ) → void
on(name: ?, fn: ?) → void
| arg | type | description |
|---|---|---|
| name | ? | |
| fn | ? |
emit(name: ?, payload: ?) → void
| arg | type | description |
|---|---|---|
| name | ? | |
| payload | ? |
newGeneration( ) → void
Generations — the one rule every long-running loop must follow Hot reload replaces a module with a FRESH COPY and orphans every task the previous copy spawned: the old loop keeps running, nothing holds a handle to cancel it, and its work stacks on top of the new one's. Ten edits in a row and the boat sails ten times too fast for no reason you can see in the code. So every `while true` in this game guards on a generation token, which lives on the shared state table — the one channel an orphaned loop and its replacement still have in common: local gen = NPB.generation() while NPB.isCurrent(gen) do ... task.wait() end Boot bumps the generation once, at the start of every assembly, which retires every loop from every earlier copy on its next tick. A slice READS the generation and never bumps it. Guard the entity too — `entity.exists(e.id)` before writing to it. When THIS module is the copy that got replaced, an orphan holds a whole stale state table and the generation cannot reach it; what stops it then is that every entity it points at is dead.
generation( ) → void
isCurrent(gen: ?) → void
| arg | type | description |
|---|---|---|
| gen | ? |
setOcean(handle: ?) → void
| arg | type | description |
|---|---|---|
| handle | ? |
ocean( ) → void
seaHeight(x: ?, z: ?) → void
Water height at a world point. Falls back to the flat sea level before the ocean exists, so a caller never has to nil-check.
| arg | type | description |
|---|---|---|
| x | ? | |
| z | ? |
seaDisplacement(x: ?, z: ?) → void
Water height AND the horizontal shove the wave gives, as { x, y, z }.
| arg | type | description |
|---|---|---|
| x | ? | |
| z | ? |
box(parent: ?, name: ?, sx: ?, sy: ?, sz: ?, px: ?, py: ?, pz: ?, color: ?) → void
| arg | type | description |
|---|---|---|
| parent | ? | |
| name | ? | |
| sx | ? | |
| sy | ? | |
| sz | ? | |
| px | ? | |
| py | ? | |
| pz | ? | |
| color | ? |
hullLength(kind: ?) → void
| arg | type | description |
|---|---|---|
| kind | ? |
spawnHull(kind: ?, name: ?) → void
| arg | type | description |
|---|---|---|
| kind | ? | |
| name | ? |
registerFleet(api: ?) → void
| arg | type | description |
|---|---|---|
| api | ? |
fleet( ) → void
fleetIsReal( ) → void
throttle( ) → void
speed( ) → void
heading( ) → void
aim( ) → void
registerHelm(api: ?) → void
| arg | type | description |
|---|---|---|
| api | ? |
claimHelm( ) → void
helm( ) → void
transient(e: ?) → void
Small shared helpers Mark an entity as belonging to the RUN, not to the scene file. Every entity in this game is created by code and rebuilt on the next load, so none of them belongs in scene.json. Left unmarked they accumulate there — the ocean's own seabed tiles did exactly that, nine copies of a thing the Ocean component recreates every time. A temporary entity is live in the session and invisible to the scene file, which is what keeps the scene the planning pass's file and not a dumping ground for three agents' runtime. Call it on everything you spawn, root and children alike.
| arg | type | description |
|---|---|---|
| e | ? |
posOf(e: ?) → void
Where an entity is, as plain numbers, or nil if it is gone.
| arg | type | description |
|---|---|---|
| e | ? |
dist2D(a: ?, b: ?) → void
| arg | type | description |
|---|---|---|
| a | ? | |
| b | ? |
clampToSea(x: ?, z: ?) → void
Clamp a world point back inside the play area. Returns x, z, wasClamped.
| arg | type | description |
|---|---|---|
| x | ? | |
| z | ? |
yaw(radians: ?) → void
A yaw-only rotation quaternion, the one every boat on this sea uses.
| arg | type | description |
|---|---|---|
| radians | ? |
Sub-parts
Everything contained inside this part. Assets are composite children (clickable cards). Files are leaf payloads. Expand any row to view its source.
Problems
Everything affecting this asset right now: its own problems, anything wrong inside it, and problems on its direct dependencies.
agent_score is exposed.+ quality × 0.35
+ performance × 0.25
± compat factor
Usability ratings
Did the part work as advertised when consumers tried to drop it in. Separate from upvotes: those are taste; this is "did it function".
Scoped to this part · feeds back into the world's score.