Modularization: Fabric-style loader + gameplay foundations (craftanything, for review/testing — merge held for design rulings) #30

Merged
merith-tk merged 13 commits from muse-lantern/da-game:craftanything into main 2026-11-07 02:12:03 +00:00
Member

Takes the slice-1 files as-is and builds on top — Fabric-style loader (manifests, entrypoints, depends/breaks/recommends with SemVer, cycle and tie errors, replaces redirects, user://modules dev folders, ModHost from Game._ready), gameplay foundations (health/stamina/survival, ItemSpec shared by GenericItem and ItemDefinition, firearms, RigInput hand interactor with wrist-pivot/palm-midpoint grips plus throw), desktop play, bridge tools, OpenXR --xr-mode fix, and docs/modding.md with an example mod.

Reorg (Phases 1–6, 8 commits c64b8bd→117065b2, 325 files): PCK-only with zip-modules refused, modid:name ids, ui/ and interactable/ present, CHANGELOG 0.2.0 noting old saves break with no migration, mechanics regenerated from their gameplay source.

Rebased onto main 7a34ec042 (merge of PR #28) as 4dc6f40: 12 commits replayed, conflicts only at the first commit (slice-1 files added on both sides), resolved taking the branch's versions. Head is muse-lantern:craftanything — direct push to upstream craftanything was refused by Forgejo, so this PR comes from the fork.

Verified by Lantern (not the branch author), on lantern-vm under Godot 4.6.3 at 4dc6f40: clean double import after wiping .godot (both passes exit 0, 0 ERROR lines), tools/check.py 6/6 OK, all 17 headless suites PASS (15 CI-listed plus twist_check and rig_chains_check). modloader_check confirms the duplicate-key rule holds including for strings, both sides named. Bridge e2e under xvfb not run (known flaky).

One thing checked specifically because it would have been a fiat ruling: GenericItem is not collapsed. Both classes still exist sharing ItemSpec — GenericItem just moved to modules/deadair/types/item.gd in the Phase 1 shuffle. The design rulings below are still Zach's, untouched by the reorg.

Merge held pending Zach's rulings: shared-spec GenericItem vs collapse, hand-rolled interactor vs DAFunctionPickup adapter, hybrid manifest + entrypoints, soft-fail as menu errors.

Known remainders, named not hidden: spawn button, pck enforcement, data reload, manager/packager, bridge grab sim, untouched #24/#7/#11/#20/#12. .remap handling exists in code but no real exported-pack test is evidenced yet. Phase 0 approval-stop has no in-repo record (MOVE_MAP.md existed with real content, removed in Phase 6 cleanup — can't confirm the stop happened, can't say it didn't).

The opencode.json restoration is explicitly out of this PR — deferred per Zach, tracked in #29, not claimed fixed here.

Review/testing PR only. Do not merge until the rulings land.

Takes the slice-1 files as-is and builds on top — Fabric-style loader (manifests, entrypoints, depends/breaks/recommends with SemVer, cycle and tie errors, replaces redirects, `user://modules` dev folders, ModHost from `Game._ready`), gameplay foundations (health/stamina/survival, ItemSpec shared by GenericItem and ItemDefinition, firearms, RigInput hand interactor with wrist-pivot/palm-midpoint grips plus throw), desktop play, bridge tools, OpenXR `--xr-mode` fix, and `docs/modding.md` with an example mod. Reorg (Phases 1–6, 8 commits `c64b8bd`→`117065b2`, 325 files): PCK-only with zip-modules refused, `modid:name` ids, `ui/` and `interactable/` present, CHANGELOG 0.2.0 noting old saves break with no migration, mechanics regenerated from their gameplay source. Rebased onto main `7a34ec042` (merge of PR #28) as `4dc6f40`: 12 commits replayed, conflicts only at the first commit (slice-1 files added on both sides), resolved taking the branch's versions. Head is `muse-lantern:craftanything` — direct push to upstream `craftanything` was refused by Forgejo, so this PR comes from the fork. Verified by Lantern (not the branch author), on lantern-vm under Godot 4.6.3 at `4dc6f40`: clean double import after wiping `.godot` (both passes exit 0, 0 ERROR lines), `tools/check.py` 6/6 OK, all 17 headless suites PASS (15 CI-listed plus `twist_check` and `rig_chains_check`). `modloader_check` confirms the duplicate-key rule holds including for strings, both sides named. Bridge e2e under xvfb not run (known flaky). One thing checked specifically because it would have been a fiat ruling: GenericItem is **not** collapsed. Both classes still exist sharing ItemSpec — GenericItem just moved to `modules/deadair/types/item.gd` in the Phase 1 shuffle. The design rulings below are still Zach's, untouched by the reorg. **Merge held pending Zach's rulings:** shared-spec GenericItem vs collapse, hand-rolled interactor vs DAFunctionPickup adapter, hybrid manifest + entrypoints, soft-fail as menu errors. **Known remainders, named not hidden:** spawn button, pck enforcement, data reload, manager/packager, bridge grab sim, untouched #24/#7/#11/#20/#12. `.remap` handling exists in code but no real exported-pack test is evidenced yet. Phase 0 approval-stop has no in-repo record (`MOVE_MAP.md` existed with real content, removed in Phase 6 cleanup — can't confirm the stop happened, can't say it didn't). The opencode.json restoration is explicitly out of this PR — deferred per Zach, tracked in #29, not claimed fixed here. Review/testing PR only. Do not merge until the rulings land.
Builds on the module system from PR #28 (its files included as-is) with a loader layer: manifest name/description/authors/license, depends/breaks/recommends with SemVer ranges, entrypoints (ModEntrypoint), element_types declared by modules, dependency-ordered loading with cycle and tie detection, working replaces redirects, relative module paths, frozen registry after boot, and a user://modules dev folder. ModApi helpers per module plus api.deadair game helpers; ModHost boots in Game._ready and emits hooks.

Base game is the deadair module (rig parts, items, base rules, 12 element types); placeholder test content lives in a devkit module. Items, tuning, levels and story text read from modules. The loader core in src/modules/ has no game classes.

Gameplay foundations: Health, Stamina, Survival vitals, item tree and save serialization, WorldItem, Grabbable/GrabPoint/Snapper/Volume/Inventory, Firearm with magazines, chamber, modes, spread, recoil, falloff, wear and jams. Desktop play: FlatController, FlatHud, start loadout.

XR startup: OpenXR starts via --xr-mode on (editor Play passes it, exports via enabled.template), so headless runs never crash with SteamVR open. Debug bridge: modules tool, --screenshot and --self-test. Docs: docs/modding.md with an example module; module_check and modloader_check in CI; MECHANICS.md and mechanics.json generated by tools/gen_mechanics.py. Fix: weak ItemInstance parent link (container/child cycles leaked). gitignore: Craft Anything working records.
- Move data/rules/gameplay.json -> modules/deadair/rules/base.json
  (element file IS the table; keep data/rules/.gitkeep)
- Update RulesElement validation/source_table() to accept inline tables
- Update tools/gen_mechanics.py to read rules from modules/deadair/rules/base.json
  and scan modules/<modid>/items/**/*.json for item stats
- Regenerate MECHANICS.md and mechanics.json (105 values)

All headless suites pass; Godot 4.6.3 headless import runs clean.
- Add examples/example_module/: item with model, script-extended gadget type,
  custom weather type, main.gd entrypoint, replaces example, rules override,
  strings table and hooks.
- Remove stale docs/modding/example_mod/.
- Rewrite docs/modding.md for loader v2 (type folders, ids, entrypoints, walkthrough).
- Rewrite docs/packs.md for PCK-only packs and the module system.
- Update README.md layout/vocabulary paragraph.
- Update tools/package_module.py and validator for loader v2 slim manifests;
  output defaults to <modid>-<version>.pck.
- Add tools/check.py static checks for old paths, old-format ids, addon.json,
  loader independence and modding.md type table.
- Add static-check step to .forgejo/workflows/tests.yml.
- Remove legacy res://data/registry and res://data/levels scans from
  ItemRegistry/LevelRegistry and the res://data/rules fallback from GameRules.
- Fix GenericItem.apply_dict to keep raw data for required-field validation.
- Update tests/addon_check.gd and tests/modloader_check.gd for the new
  example module location and module-based level discovery.

All headless suites pass; static checks pass; Godot 4.6.3 headless import clean.
Phase 6: cleanup, final grep pass and version tag
Some checks failed
tests / test (pull_request) Failing after 45s
4dc6f40137
- Remove docs/reorg/MOVE_MAP.md.
- Rename tests/addon_check.gd -> tests/pack_check.gd and update terminology.
- Update remaining "addon" terminology in docs/input-system.md,
  docs/external-resources.md, tests/save_check.gd, tests/pause_check.gd.
- Update stale comments referencing data/rules/gameplay.json and data/registry
  to modules/deadair/rules/base.json and module elements.
- Add CHANGELOG.md noting the 0.2.0 breaking changes.
- Add CHANGELOG.md whitelist to tools/check.py.

All headless suites pass; static checks pass; Godot 4.6.3 headless import clean.
tests: update e2e expected MCP tool list to the 29 tools the branch exposes
All checks were successful
tests / test (pull_request) Successful in 46s
47842bc826
Sign in to join this conversation.
No reviewers
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!30
No description provided.