Module framework: slice 1 follow-ups + open design questions #27

Open
opened 2026-10-29 14:45:52 +00:00 by muse-lantern · 1 comment
Member

Status: slice 1 built, local only, no PR yet. Branch modular-slice-1 (local, 2 commits on merged main b9e7cd73): module = .pck pack + addon.json manifest (id, version, elements, NO order field — an order field is a hard manifest error); typed registry under namespaced ids modid.type.name (types: rig_hands, rig_arms, rig_body, item); ties are startup errors naming both sides (two packs claiming one module id, one element id twice, two modules replacing one target — all tested with negative controls); shipped names are addition-only (same rule as da_*); base game ships as module deadair (glove hands, PSX arms dormant, capsule body, 6 starter-kit items); grip resolution explicit pose → auto-detect → wrist-pivot fallback; discovery scans res://modules/ after packs mount; sandbox spawn path exists via ModuleSpawner.spawn_item(). Docs updated in docs/addons.md (Modules section). Items are ONE collapsed GenericItem (kind tags + grip_poses[] + markers dict) — pending Zach's veto/blessing; if vetoed, kind tags become subclasses (one-file refactor). The old ItemRegistry stub is untouched; unification is later work.

Follow-ups, in value order.

  1. Boot wiring — the framework is complete and tested, but Game boot does not load modules yet. Wire boot-time loading once the shape is blessed.
  2. replaces lookup redirect — slice 1 conflict-checks replaces only; a single replacer does not yet redirect lookups. Lands with the loader rewrite.
  3. Sandbox menu button for the spawner path (path exists, no UI entry yet).
  4. Pck-only enforcement (if wanted) — slice 1 is pck-only by convention + docs, NOT enforced: Godot cannot attribute a res:// file to its pack, so enforcement belongs in AddonLoader (refuse zips containing modules/ dirs).
  5. Load-order system (deferred in slice 1 — decide if/when; determinism today is namespaced ids + replaces declarations).
  6. In-game addon manager + packager + example addon.
  7. Dependency resolution reported before content loads.
  8. Data-tier reload (Minecraft /reload-style) — later.

Niceties status vs the candidate v1 list. Done: addition-only names; tie errors (stronger than a conflict report); manifest validation (order field errors, unknown fields noted); dangling content persists inert, backup-first saves (pre-existing). NOT done / still open: soft-fail validation (slice 1 fails the load loudly rather than disabling one addon and keeping booting — decide if soft-disable is still wanted); dependency resolution; manager/packager; reload; load order.

Still Zach's calls. (1) Tribe — slice 1's shape is manifest-driven (addon.json + resource/data elements), NOT a Module script with register() as originally sketched: does that satisfy "Minecraft modders feel at home," or is a script entrypoint still wanted? (2) Which niceties above are v1 vs later (confirm/trim the list). (3) Terminology stays "addon"; docs translate (addon ≈ mod + datapack). Basics-first order stands: generic physics + grab (issues #25, #26) before deep module work beyond slice 1.

Status: slice 1 built, local only, no PR yet. Branch modular-slice-1 (local, 2 commits on merged main b9e7cd73): module = .pck pack + addon.json manifest (id, version, elements, NO order field — an order field is a hard manifest error); typed registry under namespaced ids modid.type.name (types: rig_hands, rig_arms, rig_body, item); ties are startup errors naming both sides (two packs claiming one module id, one element id twice, two modules replacing one target — all tested with negative controls); shipped names are addition-only (same rule as da_*); base game ships as module deadair (glove hands, PSX arms dormant, capsule body, 6 starter-kit items); grip resolution explicit pose → auto-detect → wrist-pivot fallback; discovery scans res://modules/ after packs mount; sandbox spawn path exists via ModuleSpawner.spawn_item(). Docs updated in docs/addons.md (Modules section). Items are ONE collapsed GenericItem (kind tags + grip_poses[] + markers dict) — pending Zach's veto/blessing; if vetoed, kind tags become subclasses (one-file refactor). The old ItemRegistry stub is untouched; unification is later work. Follow-ups, in value order. 1. Boot wiring — the framework is complete and tested, but Game boot does not load modules yet. Wire boot-time loading once the shape is blessed. 2. replaces lookup redirect — slice 1 conflict-checks replaces only; a single replacer does not yet redirect lookups. Lands with the loader rewrite. 3. Sandbox menu button for the spawner path (path exists, no UI entry yet). 4. Pck-only enforcement (if wanted) — slice 1 is pck-only by convention + docs, NOT enforced: Godot cannot attribute a res:// file to its pack, so enforcement belongs in AddonLoader (refuse zips containing modules/ dirs). 5. Load-order system (deferred in slice 1 — decide if/when; determinism today is namespaced ids + replaces declarations). 6. In-game addon manager + packager + example addon. 7. Dependency resolution reported before content loads. 8. Data-tier reload (Minecraft /reload-style) — later. Niceties status vs the candidate v1 list. Done: addition-only names; tie errors (stronger than a conflict report); manifest validation (order field errors, unknown fields noted); dangling content persists inert, backup-first saves (pre-existing). NOT done / still open: soft-fail validation (slice 1 fails the load loudly rather than disabling one addon and keeping booting — decide if soft-disable is still wanted); dependency resolution; manager/packager; reload; load order. Still Zach's calls. (1) Tribe — slice 1's shape is manifest-driven (addon.json + resource/data elements), NOT a Module script with register() as originally sketched: does that satisfy "Minecraft modders feel at home," or is a script entrypoint still wanted? (2) Which niceties above are v1 vs later (confirm/trim the list). (3) Terminology stays "addon"; docs translate (addon ≈ mod + datapack). Basics-first order stands: generic physics + grab (issues #25, #26) before deep module work beyond slice 1.
Author
Member

Update from craftanything (upstream branch, tip c64b8bd, on main b9e7cd73 — it includes the slice-1 files as-is). Several follow-ups from this issue land in-branch:

Done in-branch: boot wiring (ModHost.boot() from Game._ready, registry frozen, registries_ready hook); replaces now redirects lookups (ModuleLoader); dependency resolution (depends/breaks/recommends + SemVer ranges, cycle and tie errors naming both sides); manifest validation with named errors; example module (docs/modding/example_mod); user://modules loose-folder dev loading; failed sets surface as MODULE ERRORS on the menu sign plus the bridge modules tool. The tribe question gets a hybrid answer: manifest + script entrypoints (ModEntrypoint, main runs at boot).

Still open: sandbox spawn button (spawn path only, no button); pck enforcement (AddonLoader unchanged — a zip containing modules/ would still load, so pck-only is still convention); data reload (registry is frozen by design); manager/packager; soft-fail (current design: errors shown, game still boots — not per-module disable). Collapsed-GenericItem gets a third answer: GenericItem and ItemDefinition both remain, sharing a new ItemSpec base (grip_poses + markers) — still needs Zach's ruling.

Verified on the branch (lantern-vm, Godot 4.6.3): clean double import, module_check + modloader_check + the full headless suite list PASS. This comment records branch state, not a close — nothing here is in main yet.

Update from `craftanything` (upstream branch, tip `c64b8bd`, on main `b9e7cd73` — it includes the slice-1 files as-is). Several follow-ups from this issue land in-branch: Done in-branch: boot wiring (`ModHost.boot()` from `Game._ready`, registry frozen, `registries_ready` hook); `replaces` now redirects lookups (`ModuleLoader`); dependency resolution (`depends`/`breaks`/`recommends` + SemVer ranges, cycle and tie errors naming both sides); manifest validation with named errors; example module (`docs/modding/example_mod`); `user://modules` loose-folder dev loading; failed sets surface as MODULE ERRORS on the menu sign plus the bridge `modules` tool. The tribe question gets a hybrid answer: manifest + script entrypoints (`ModEntrypoint`, `main` runs at boot). Still open: sandbox spawn button (spawn path only, no button); pck enforcement (`AddonLoader` unchanged — a zip containing `modules/` would still load, so pck-only is still convention); data reload (registry is frozen by design); manager/packager; soft-fail (current design: errors shown, game still boots — not per-module disable). Collapsed-`GenericItem` gets a third answer: `GenericItem` and `ItemDefinition` both remain, sharing a new `ItemSpec` base (`grip_poses` + `markers`) — still needs Zach's ruling. Verified on the branch (lantern-vm, Godot 4.6.3): clean double import, `module_check` + `modloader_check` + the full headless suite list PASS. This comment records branch state, not a close — nothing here is in main yet.
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
dead-air/engine#27
No description provided.