nx_mod_registry.nx
buildroot/runtime/nx_mod_registry.nx
about
nx_mod_registry.nx -- mod manifest + hook registries.
Per user 2026-05-16: "make sure we roadmap mods and offline playing
if the player wants to play offline without giving up a bunch of
our nishi language work. i dont want someone ripping and hacking
what we built into something nefarious."
This primitive ships the foundation of the mod system:
- ModManifest record (mod id, hash, capability flags, hook count)
- 5 registry types (block / entity / recipe / worldgen / event)
- Add / lookup / iterate APIs
- CAS-style hash on the mod's code; the runtime can verify mods
against the manifest to detect tampering.
SECURITY POSTURE:
- Mods declare their capability flags (BLOCK_KIND / ENTITY_KIND /
etc.). Runtime denies any operation the manifest doesn't grant.
- Mod's manifest_hash = caller-provided 64-bit content hash.
The official runtime cross-checks this against a known-trusted
list AND requires a manifest signature (Ed25519, future).
- Mods marked UNTRUSTED can run but the multiplayer layer rejects
them.
ManifestRecord (8 i64):
m[0] = mod_id unique integer
m[1] = name_hash fnv-style 64-bit hash of the mod name
m[2] = code_hash 64-bit Merkle / CAS hash of the mod .wasm
m[3] = capability_flags
m[4] = trust_level 0 = UNTRUSTED, 1 = COMMUNITY, 2 = OFFICIAL
m[5] = version
m[6] = enabled 0/1
m[7] = reserved
HookRegistry (variable):
reg[0] = n_entries
reg[1] = max_entries
reg[2..] = per-entry (4 i64): mod_id, kind_id, handler_ptr, reserved
PUBLIC APIs:
nx_mod_manifest_init(m, mod_id, name_hash, code_hash, caps,
dependencies 2 imports · 0 importers
imports: nx_syscalls.nxnx_tier.nx
imported by: nobody (leaf or entry point)
call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown
structs
| none |
consts
| 58 | const NX_MAGIC_12345: i64 = 12345 |
| 59 | const NX_MAGIC_67890: i64 = 67890 |
| 61 | const NX_MOD_Q: nx_int = 16384 |
| 64 | const NX_MOD_CAP_BLOCK_KIND: nx_int = 1 |
| 65 | const NX_MOD_CAP_ENTITY_KIND: nx_int = 2 |
| 66 | const NX_MOD_CAP_RECIPE: nx_int = 4 |
| 67 | const NX_MOD_CAP_WORLDGEN_HOOK: nx_int = 8 |
| 68 | const NX_MOD_CAP_EVENT_LISTEN: nx_int = 16 |
| 69 | const NX_MOD_CAP_UI_PANEL: nx_int = 32 |
| 70 | const NX_MOD_CAP_MULTIPLAYER: nx_int = 64 // mod is network-safe |
| 73 | const NX_MOD_TRUST_UNTRUSTED: nx_int = 0 |
| 74 | const NX_MOD_TRUST_COMMUNITY: nx_int = 1 |
| 75 | const NX_MOD_TRUST_OFFICIAL: nx_int = 2 |
| 78 | const NX_MOD_MANIFEST_STRIDE: nx_int = 8 |
| 79 | const NX_MOD_M_OFF_ID: nx_int = 0 |
| 80 | const NX_MOD_M_OFF_NAME_HASH: nx_int = 1 |
| 81 | const NX_MOD_M_OFF_CODE_HASH: nx_int = 2 |
| 82 | const NX_MOD_M_OFF_CAPS: nx_int = 3 |
| 83 | const NX_MOD_M_OFF_TRUST: nx_int = 4 |
| 84 | const NX_MOD_M_OFF_VERSION: nx_int = 5 |
| 85 | const NX_MOD_M_OFF_ENABLED: nx_int = 6 |
| 88 | const NX_MOD_REG_HEADER_SIZE: nx_int = 2 |
| 89 | const NX_MOD_REG_ENTRY_STRIDE: nx_int = 4 |
| 90 | const NX_MOD_REG_OFF_N: nx_int = 0 |
| 91 | const NX_MOD_REG_OFF_MAX: nx_int = 1 |
| 92 | const NX_MOD_E_MOD_ID: nx_int = 0 |
| 93 | const NX_MOD_E_KIND_ID: nx_int = 1 |
| 94 | const NX_MOD_E_HANDLER: nx_int = 2 |
functions
| 97 | func nx_mod_manifest_init( called by 1: main |
| 111 | func nx_mod_manifest_has_cap(m: *i64, cap: nx_int) -> nx_int called by 1: main |
| 117 | func nx_mod_manifest_is_trusted(m: *i64) -> nx_int called by 1: main |
| 123 | func nx_mod_registry_alloc(max_entries: nx_int) -> *i64 |
| 134 | func nx_mod_registry_register( called by 1: main |
| 158 | func nx_mod_registry_lookup(reg: *i64, kind_id: nx_int) -> nx_int called by 1: main |
| 171 | func nx_mod_registry_count(reg: *i64) -> nx_int called by 1: main |
| 177 | func nx_mod_registry_at(reg: *i64, idx: nx_int, out_buf: *i64) -> nx_int called by 1: main |
| 191 | func nx_mod_verify_code_hash(m: *i64, actual_hash: nx_int) -> nx_int called by 1: main |
| 197 | func main() -> i64 |