From 389abd7de76bafb81ce1a3a4e40ecd49cf18ed8d Mon Sep 17 00:00:00 2001 From: ml Date: Sat, 26 Sep 2026 15:41:56 +0200 Subject: [PATCH] Add a first-party MDL mod-build system and reorganize modding/ under src/ modding/mods/ holds message edits as plain JSON (type, index, language, plus only the changed fields - a long body can live in a sibling .txt to avoid escaping in JSON), so mod authoring is reviewable in git instead of living only in hacked's GUI. mdlp (modding/src/mdlp/, its own Docker image mdlp-image/) turns them into the same mod folder/zip hacked's own Save produces, reusing hacked's ss1/edit, ss1/world and ss1/content/text packages via a go.mod replace - no GUI/GLFW/GTK needed. `make mods` builds every mod into dist/mods//, scoped per-mod so it never touches hacked's own build output; `make` (no target) now builds both. Fixes a bug this surfaced: hacked's FileLocation.AbsolutePathFrom silently writes into the current directory instead of the given output folder when passed a relative path (the GUI never hits this since its folder picker is always absolute) - mdlp now resolves its own paths up front. res/run-mods.sh/.bat are new companion launchers to run.sh/.bat: they pass every dist/mods/*/mod folder to the engine as a separate absolute argument, since ProcessModDirectory() only scans one directory level deep. Wired into `make dist`/`dist-win` only, not the release archives. modding/hacked/, its patches, sqweek-dialog/, its patches, and the new mdlp/ move under modding/src/, separating source from the surrounding Docker/script scaffolding; all path references updated to match. NOTICE.txt gains a section for hacked's distributed build, listing hacked (New BSD), sqweek/dialog (ISC - corrected from a wrong "New BSD" note), and hacked's other direct Go dependencies. --- Makefile | 5 +- NOTICE.txt | 14 + README.md | 9 +- modding/Makefile | 25 +- modding/README.md | 167 ++++++++-- modding/hacked-build-image/Dockerfile | 6 +- modding/hacked-build-image/build-hacked.sh | 14 +- modding/mdlp-image.sh | 34 ++ modding/mdlp-image/Dockerfile | 51 +++ modding/mdlp-image/VERSION | 1 + modding/mdlp-image/docker-entrypoint.sh | 35 ++ modding/mdlp-image/process-mods.sh | 39 +++ modding/mdlp-run-image.sh | 51 +++ modding/mdlp-upload-image.sh | 40 +++ modding/mods/modversion/messages/log-021.json | 6 + modding/mods/modversion/messages/log-021.txt | 1 + .../mods/rebecca-test/messages/mail-026.json | 7 + .../mods/rebecca-test/messages/mail-026.txt | 1 + modding/src/mdlp/go.mod | 12 + modding/src/mdlp/go.sum | 10 + modding/src/mdlp/main.go | 301 ++++++++++++++++++ registry.env.example | 4 + res/run-mods.bat | 20 ++ res/run-mods.sh | 21 ++ 24 files changed, 839 insertions(+), 35 deletions(-) create mode 100755 modding/mdlp-image.sh create mode 100644 modding/mdlp-image/Dockerfile create mode 100644 modding/mdlp-image/VERSION create mode 100644 modding/mdlp-image/docker-entrypoint.sh create mode 100644 modding/mdlp-image/process-mods.sh create mode 100755 modding/mdlp-run-image.sh create mode 100755 modding/mdlp-upload-image.sh create mode 100644 modding/mods/modversion/messages/log-021.json create mode 100644 modding/mods/modversion/messages/log-021.txt create mode 100644 modding/mods/rebecca-test/messages/mail-026.json create mode 100644 modding/mods/rebecca-test/messages/mail-026.txt create mode 100644 modding/src/mdlp/go.mod create mode 100644 modding/src/mdlp/go.sum create mode 100644 modding/src/mdlp/main.go create mode 100644 res/run-mods.bat create mode 100644 res/run-mods.sh diff --git a/Makefile b/Makefile index e4104f0..1e1ec7f 100644 --- a/Makefile +++ b/Makefile @@ -73,7 +73,7 @@ dist: dist-linux dist-win dist-linux: engine assets @echo "== Assembling $(DIST_DIR) ==" rm -rf "$(DIST_DIR)/systemshock" "$(DIST_DIR)/lib" "$(DIST_DIR)/res" \ - "$(DIST_DIR)/shaders" "$(DIST_DIR)/run.sh" + "$(DIST_DIR)/shaders" "$(DIST_DIR)/run.sh" "$(DIST_DIR)/run-mods.sh" mkdir -p "$(DIST_DIR)/lib" "$(DIST_DIR)/res/data" "$(DIST_DIR)/res/sound" cp "$(ENGINE_OUT)/systemshock" "$(DIST_DIR)/" cp -a "$(ENGINE_OUT)/lib/." "$(DIST_DIR)/lib/" @@ -83,6 +83,8 @@ dist-linux: engine assets cp -a "$(ASSETS_DIR)/sound/." "$(DIST_DIR)/res/sound/" cp res/run.sh "$(DIST_DIR)/run.sh" chmod +x "$(DIST_DIR)/run.sh" + cp res/run-mods.sh "$(DIST_DIR)/run-mods.sh" + chmod +x "$(DIST_DIR)/run-mods.sh" @echo "== Done - run $(DIST_DIR)/run.sh to play ==" # Windows counterpart of dist-linux. Unlike dist/, the DLLs sit flat @@ -100,6 +102,7 @@ dist-win: engine-win assets cp -a "$(ASSETS_DIR)/data/." "$(DIST_WIN_DIR)/res/data/" cp -a "$(ASSETS_DIR)/sound/." "$(DIST_WIN_DIR)/res/sound/" cp res/run.bat "$(DIST_WIN_DIR)/run.bat" + cp res/run-mods.bat "$(DIST_WIN_DIR)/run-mods.bat" @echo "== Done - run $(DIST_WIN_DIR)/run.bat (or systemshock.exe) to play ==" # Builds both platforms' redistributable archives. `package-linux`/ diff --git a/NOTICE.txt b/NOTICE.txt index 098af6e..0089e17 100644 --- a/NOTICE.txt +++ b/NOTICE.txt @@ -35,3 +35,17 @@ cross-build") additionally bundles: statically into systemshock.exe instead of shipped as a DLL, under the GCC Runtime Library Exception - this doesn't subject the rest of the binary to the GPL.) + +The modding tools' `hacked` build (see modding/README.md; output under +modding/dist/*.tgz and *.zip) additionally bundles: + +- InkyBlackness HackEd (https://github.com/inkyblackness/hacked), vendored + unmodified as modding/src/hacked/. It is New BSD-licensed. +- github.com/sqweek/dialog, vendored and patched (see + modding/src/sqweek-dialog-patches/) as modding/src/sqweek-dialog/. It is + ISC-licensed. +- hacked's further direct Go dependencies (fetched at build time, not + vendored in this repository): github.com/inkyblackness/imgui-go (New BSD); + github.com/go-gl/glfw, github.com/go-gl/mathgl, and golang.org/x/image + (BSD 3-Clause); github.com/go-gl/gl, github.com/asticode/go-astisub, and + github.com/lucasb-eyer/go-colorful (MIT). diff --git a/README.md b/README.md index 72bda3a..72fff3a 100644 --- a/README.md +++ b/README.md @@ -80,7 +80,14 @@ Section "5.1. Installing and playing" has the details. - `res/assets/` - where you place your own purchased copy of the game (see "3. Game assets" below); `res/assets/extract_assets.sh` extracts it into `ss_ee/`. -- `res/run.sh` - the launcher script, copied into `dist/` on build. +- `res/run.sh` / `res/run.bat` - the launcher scripts, copied into + `dist`/`dist-win` on build. `res/run-mods.sh` / `res/run-mods.bat` are + companion launchers that additionally load every mod built under the + `modding/` subproject's own `dist/mods/` (see + [modding/README.md](modding/README.md) section 4.3) - copied into + `dist`/`dist-win` the same way, but not into the redistributable + `package`/`package-win` archives, since that build output is local and + git-ignored. - `res/questshock.config.default.json` - the bundled default configuration (see [CONFIG.md](CONFIG.md)); `res/controller_profiles/` - the per-controller illustrations and labels shown in the Controller Options tab (see diff --git a/modding/Makefile b/modding/Makefile index acb4507..5fed485 100644 --- a/modding/Makefile +++ b/modding/Makefile @@ -1,16 +1,24 @@ # Builds the modding subproject - see README.md. # # Targets: -# all (default) - alias for `hacked`. +# all (default) - `hacked` and `mods`. # build-image - builds the hacked-build-image Docker image # (./hacked-build-image.sh). Only needed once, or after # hacked-build-image/ or hacked/go.mod|go.sum changes. # hacked - compiles hacked/ for Linux and Windows via that image, # offline. Output lands in dist/. +# mdlp-image - builds the mdlp-image Docker image (./mdlp-image.sh). +# Only needed once, or after mdlp-image/ or +# mdlp/go.mod|go.sum changes. +# mods - builds every mod under mods/ via that image, offline. +# Set MODS="name1 name2" to build only those. Output +# lands in dist/mods/. # clean - removes dist/. -.PHONY: all build-image hacked clean +.PHONY: all build-image hacked mdlp-image mods clean -all: hacked +export MODS + +all: hacked mods build-image: ./hacked-build-image.sh @@ -26,5 +34,16 @@ hacked: ./hacked-build-run-image.sh; \ fi +mdlp-image: + ./mdlp-image.sh + +# Same already-in-the-image shortcut as `hacked` above, for MDLP_IMAGE. +mods: + @if [ -n "$$MDLP_IMAGE" ]; then \ + bash mdlp-image/process-mods.sh; \ + else \ + ./mdlp-run-image.sh; \ + fi + clean: rm -rf dist diff --git a/modding/README.md b/modding/README.md index e021ceb..7b98f67 100644 --- a/modding/README.md +++ b/modding/README.md @@ -4,34 +4,59 @@ Tools and reference material for modding System Shock (1994) itself - distinct from the rest of this repository, which is the [QuestShock](../README.md) VR port of the game engine. Everything modding-related lives under this folder. -Both pieces here come from the [InkyBlackness](https://inkyblackness.github.io) -project and are vendored unmodified, each under its own upstream license (see -below) - neither is relicensed by this repository's own MIT license. +`hacked` and `ss-specs` come from the [InkyBlackness](https://inkyblackness.github.io) +project; `sqweek-dialog` is a separate third-party dependency of `hacked`. +All three are vendored unmodified under `src/`, each under its own upstream +license (see below) - none is relicensed by this repository's own MIT +license. `mdlp` (also under `src/`) is first-party code written for this +repository. ## 1. Layout -- `hacked/` - [InkyBlackness HackEd](https://github.com/inkyblackness/hacked), - the graphical mod editor. A vendored source snapshot (New BSD License), - taken from the `main` branch on 2026-09-26. To update it, replace this - directory with a fresh checkout and update that date. -- `ss-specs/` - [InkyBlackness ss-specs](https://github.com/inkyblackness/ss-specs), - the unofficial file-format specifications the editor (and any other modding - tool) is written against. Reference documentation only, not built. A - vendored snapshot (CC BY-NC-SA 4.0 - **non-commercial**, unlike the rest of - this repository), taken from the `main` branch on 2026-09-26. +- `src/` - every vendored and first-party source tree, kept apart from the + Docker/script scaffolding that builds them: + - `hacked/` - [InkyBlackness HackEd](https://github.com/inkyblackness/hacked), + the graphical mod editor. A vendored source snapshot (New BSD License), + taken from the `main` branch on 2026-09-26. To update it, replace this + directory with a fresh checkout and update that date. + - `hacked-patches/` - numbered `patch -p1` files applied to a scratch copy + of `hacked/` at build time (same pattern as the root project's + `android/engine-patches/`, see the repository root's + [AGENTS.md](../AGENTS.md) section 6) - `hacked/` itself is never edited + in place. + - `sqweek-dialog/` - `github.com/sqweek/dialog`, `hacked`'s native + file-dialog dependency. Vendored at the exact version `hacked/go.mod` + would otherwise pull from the module proxy (ISC License), so it can be + patched the same way as `hacked/` itself (see section 2's crash fix). + - `sqweek-dialog-patches/` - patches for `sqweek-dialog/`, same pattern as + `hacked-patches/`. + - `mdlp/` - the **Mod Definition Language Processor** (section 4). First-party + Go source, not vendored - edit it directly, no patch system needed. + - `ss-specs/` - [InkyBlackness ss-specs](https://github.com/inkyblackness/ss-specs), + the unofficial file-format specifications the editor (and any other + modding tool) is written against. Reference documentation only, not + built. A vendored snapshot (CC BY-NC-SA 4.0 - **non-commercial**, unlike + the rest of this repository), taken from the `main` branch on + 2026-09-26. - `hacked-build-image/` - the Dockerfile (and supporting scripts) for the `hacked` build environment: the Go toolchain plus every dependency - `hacked/go.mod` pins, fetched once at image-build time so the actual build - needs no network access. Mirrors the main project's own `build-image/` - (see the repository root's [README.md](../README.md) section 4) one level - down, for this subproject. + `src/hacked/go.mod` pins, fetched once at image-build time so the actual + build needs no network access. Mirrors the main project's own + `build-image/` (see the repository root's [README.md](../README.md) + section 4) one level down, for this subproject. - `hacked-build-image.sh` / `hacked-build-run-image.sh` / `hacked-build-upload-image.sh` - build the image, run it to compile `hacked/`, and push it to a registry, respectively. Same pattern as the root project's own `build-image.sh`/`run-image.sh`/`upload-image.sh`. -- `Makefile` - `hacked` (default) builds `hacked/` via the image; `build-image` - (re)builds the image itself; `clean` removes `dist/`. -- `dist/` - build output (git-ignored), created by `make hacked`. +- `mdlp-image/`, `mdlp-image.sh` / `mdlp-run-image.sh` / `mdlp-upload-image.sh` - + the same pattern again, for `mdlp` (section 4.2). +- `mods/` - mod definitions in the Mod Definition Language (section 4). +- `Makefile` - `hacked` (default) builds `hacked/` via the image; + `build-image` (re)builds that image; `mdlp-image` builds the `mdlp` image; + `mods` processes every mod under `mods/` via that image; `clean` removes + `dist/`. +- `dist/` - build output (git-ignored): `make hacked` under `linux/`/`win/`, + `make mods` under `mods/`. Shockolate (the engine `../engine/` vendors) already has its own modding support (level/resource files, `res/data/`); this folder is about the @@ -51,7 +76,7 @@ to install locally. cd modding # 1. Build the hacked-build-image (once, or after hacked-build-image/ or -# hacked/go.mod|go.sum changes) +# src/hacked/go.mod|go.sum changes) ./hacked-build-image.sh # 2. Compile hacked/ for Linux and Windows @@ -111,3 +136,105 @@ Rebecca Lansing's first email. `ProcessModDirectory()` reports nothing on a bad path). When the path is right, the terminal shows `ProcessModDirectory ...` / `Found resource file: ...` / `Loading mod file ...` for confirmation. + +## 4. Mod Definition Language (mods/) + +The workflow above is manual and its result (whatever you clicked through in +`hacked`) isn't checked into git. `mods/` holds the same kind of edits as +plain, reviewable JSON instead, and `mdlp` (the **Mod Definition Language +Processor**, `mdlp/`) turns them into the same kind of mod folder and a zip, +reproducibly and offline. + +### 4.1. Layout + +``` +mods/ + / + messages/ +