diff --git a/plan/04-mods.md b/plan/04-mods.md index 34ad82c..1caf6e0 100644 --- a/plan/04-mods.md +++ b/plan/04-mods.md @@ -147,24 +147,64 @@ in the deploy path (keeps deploy offline + deterministic). ## Decommission checklist (on execution) -- [ ] `tooling/classify-mods.py` + generate initial `mods-sides.json` (review it). -- [ ] `tooling/sync-server-mods.sh`. -- [ ] compose: drop `PACKWIZ_URL`, `pack.` extra_host, `./pack`/`./custom` mounts, - `pack.` caddy vhost; add `server-mods` mount + `REMOVE_OLD_MODS`. -- [ ] delete `tooling/render-pack.sh`; remove its call from docs/deploy. -- [ ] delete `pack/` (pack.toml, index.toml, `*.pw.toml*`, `.packwizignore`, - CustomSkinLoader templates if duplicated in DIST) and `custom/` (jars now - sourced from `$DIST`). -- [ ] `.gitignore`: drop packwiz lines; add `server-mods/`. -- [ ] supersede `plan/04-packwiz.md`; update `05-minecraft.md`, `14-deploy.md`, - `CLAUDE.md` (mod source section), and the landing join steps if they still - reference `pack.toml`. -- [ ] resolves the host-local divergence around `pack/` ([[cochi-host-local-divergence]]). +Done at first cutover (commits `27237bc`, `84196d5`, `c249172`): +- [x] `tooling/classify-mods.py` + generated initial `mods-sides.json`. +- [x] `tooling/sync-server-mods.sh`. +- [x] compose: dropped `PACKWIZ_URL`, `pack.` extra_host, `./pack`/`./custom` + mounts, `pack.` caddy vhost; added `server-mods` mount + `REMOVE_OLD_MODS`. +- [x] deleted `tooling/render-pack.sh` (+ dead `add-custom-mod.sh`). +- [x] deleted `pack/` and `custom/` (jars now sourced from `$DIST`). +- [x] `.gitignore`: dropped packwiz lines; added `server-mods/`. +- [x] superseded `plan/04-packwiz.md`; updated `05-minecraft.md`, `14-deploy.md`, + `CLAUDE.md`. +- [x] resolved the host-local divergence around `pack/` + ([[cochi-host-local-divergence]]). +- [ ] **STILL OPEN (roadmap):** landing join steps still reference the dead + `pack.toml` URL (`site.ts packwizUrl`, `i18n/ui.ts` step 3) — rework around + the HeliosLauncher/`distribution.json` flow. +- [x] deployed to `cochi`: NeoForge bumped to 21.1.233, 52 server mods, `Done`, + mc-status `online:true`. + +## Deployment gotchas (learned 2026-06-10, first cutover) + +### NeoForge version MUST match the distribution +The distribution's mods are built against a specific NeoForge (in +`distribution.json` → `21.1.233`). Several hard-require it (ferritecore ≥21.1.218, +farmersdelight ≥21.1.219, configured ≥21.1.211). A lower `NEOFORGE_VERSION` pin +fails pre-load with `Missing or unsupported mandatory dependencies: neoforge`. +Keep `docker-compose.yml`'s pin in lockstep with the distribution on every mod +update. + +### Client-only mods that declare `BOTH` crash the dedicated server +tomllib classifies by the `minecraft`/`neoforge` dependency `side`. Mods that +declare **`BOTH`** but are actually client-only (touch `net.minecraft.client.*`) +pass through as `both`, load on the server, and crash hard: + +``` +java.lang.RuntimeException: Attempted to load class +net/minecraft/client/gui/screens/Screen for invalid dist DEDICATED_SERVER +- has failed to load correctly +``` + +This is **not** mere RAM waste — it's a fatal crashloop. tomllib cannot detect +it (the manifest lies). **Fix = hand-set the mod to `client` in +`mods-sides.json`, re-sync, recreate minecraft.** First cutover required marking +these (leaf client-GUI mods, nothing server-loaded depends on them): +`BetterF3, JustEnoughResources, MouseTweaks, Searchables, TravelersTitles, +drippyloadingscreen, entityculling, fancymenu, konkrete, melody, ponderjs, +welcomescreen, yeetusexperimentus` — on top of the 11 tomllib auto-caught +(sodium, sodium-extra, iris, ImmediatelyFast, appleskin, Controlling, BridgingMod, +CustomSkinLoader, entity_model_features, entity_texture_features, tagtooltips). + +**Current state: 24 `client` / 52 `both`.** The 52 may still hide a client-only +mod that loaded without crashing; if a future restart trips another +`invalid dist DEDICATED_SERVER`, flip that one jar to `client` and re-sync — same +one-line loop. When excluding, prefer leaf mods; if a `both` mod hard-depends on +the one you exclude you'll get a `Missing mandatory dependency` instead — put it +back. ## Open questions / risks -- **Cosmetic-client mods** load on the server unless manually set `client` — RAM - waste, not a crash. Curate `mods-sides.json` over time. - **No manifest** in a jar → defaults `both`. Acceptable; review the defaulted list `classify-mods` prints. - **Nebula regen** may rename jars (version bumps) → `mods-sides.json` keys go