87 lines
5.6 KiB
Markdown
87 lines
5.6 KiB
Markdown
# For developers
|
||
|
||
How the code is organised, how to build and test it, and where the engineering notes are.
|
||
|
||
## Build
|
||
|
||
Requirements: a **JDK 25** installed (the Gradle toolchain compiles with it; there is no
|
||
auto-download). Gradle itself and Spotless currently need to run on **Java 21**, e.g.
|
||
`JAVA_HOME=/usr/lib/jvm/java-21-openjdk-amd64 ./gradlew …` on Debian/Ubuntu.
|
||
|
||
```bash
|
||
./gradlew spotlessApply build # compile, format, run the tests
|
||
./gradlew fatJar # build/libs/llamamod-<ver>-all.jar
|
||
java -jar build/libs/llamamod-*-all.jar # launcher
|
||
java -jar build/libs/llamamod-*-all.jar --editor # the editor alone
|
||
./gradlew packageLinux # tar.gz with its own Java runtime
|
||
./gradlew packageWindows # zip with LlamaMod.exe + runtime (built on Linux)
|
||
./gradlew packageAll # both systems, full and launcher (no editor) edition
|
||
```
|
||
|
||
Details (jlink, launch4j, editions, version and build id): [notes/llamamod-app.md](../notes/llamamod-app.md#build).
|
||
|
||
**Tests that need the game.** Golden and in-game-data tests read the CD folder given by
|
||
`-Dllamamod.cd=<…/Setup/<lang>/Cd>` (default: the author's Wine setup); without it they are
|
||
skipped. Byte-exact round trips over all level WADs (WAD, TRAK, MAP, TEXT, strat code) are the
|
||
safety net for every format change.
|
||
|
||
## Code map
|
||
|
||
Package root [`src/main/java/com/eliasmueller/llamamod/`](../src/main/java/com/eliasmueller/llamamod/):
|
||
|
||
| Package | Content | Notes |
|
||
|---|---|---|
|
||
| `format` | WAD, TRAK, STPC, MAP, TEXT, collision, COR | [Reference](reference/README.md) |
|
||
| `format.strat` | strat disassembler, assembler, script view, compiler | [Strats](strats/README.md), [notes/strat-language.md](../notes/strat-language.md) |
|
||
| `format.stpcmerge` | importing object types between levels (code, models, textures, sounds, texts) | [notes/editor-cross-import.md](../notes/editor-cross-import.md) |
|
||
| `levelbuild` | Java level builder (`LevelBuilder`, `LevelScript`) | [Levels from scripts](guide/levels-in-code.md) |
|
||
| `mods` | mod framework (`Mod`, `ModContext`, `ModManager`, options) and the built-in mods | [notes/llamamod-app.md](../notes/llamamod-app.md#mods), `notes/mod-*.md` |
|
||
| `exe` | patching `groove.exe`: PE image, code caves, a tiny x86 emitter | [notes/llamamod-app.md](../notes/llamamod-app.md#grooveexe-patches-and-code-caves-exeexeimage-exex86) |
|
||
| `platform` | install from ISO/CD, data folder, config, registry, Wine/Windows launch | [notes/llamamod-app.md](../notes/llamamod-app.md) |
|
||
| `save` | KSV save games, TestLevel chapters | [Game files](reference/game-files.md#save-games-ksv) |
|
||
| `ui` | launcher window | |
|
||
| `editor.model`, `editor.io` | scene model, commands/undo, project format, WAD import/build | [notes/editor-api.md](../notes/editor-api.md), [notes/editor-format.md](../notes/editor-format.md) |
|
||
| `editor.render` | OpenGL viewport | [notes/editor-render.md](../notes/editor-render.md) |
|
||
| `editor.ui` | editor shell and plugin API | [notes/editor-ui.md](../notes/editor-ui.md) |
|
||
| `editor.tools.*` | editor plugins: geometry, objects, environment, textures, catalog (cross-world import), strats, playtest, gltf, help | `notes/editor-tools-*.md`, [notes/editor-playtest.md](../notes/editor-playtest.md) |
|
||
|
||
## Writing a mod
|
||
|
||
A mod implements [`Mod`](../src/main/java/com/eliasmueller/llamamod/mods/Mod.java): `id`, `name`,
|
||
`description`, `category` (LEVELS, GAMEPLAY, VISUAL, CHEATS), `options()` and `apply(ModContext)`.
|
||
`apply` reads files of the game as earlier mods left them (`ctx.read`) and writes replacements
|
||
(`ctx.write`); `ctx.exe()` gives access to `groove.exe` for patches. Mods are registered in
|
||
[`ModRegistry`](../src/main/java/com/eliasmueller/llamamod/mods/ModRegistry.java). LlamaMod caches
|
||
mod outputs and never touches the original files.
|
||
|
||
Good examples: [`mods/testworld/`](../src/main/java/com/eliasmueller/llamamod/mods/testworld/) (a
|
||
level built in code), [`mods/arena/`](../src/main/java/com/eliasmueller/llamamod/mods/arena/) (level
|
||
+ new strat types, walkthrough: [Arena](strats/arena.md)),
|
||
[`mods/fog/`](../src/main/java/com/eliasmueller/llamamod/mods/fog/) (data-only change of all levels),
|
||
[`mods/practice/`](../src/main/java/com/eliasmueller/llamamod/mods/practice/) (exe code caves with
|
||
hotkeys). Full API: [notes/llamamod-app.md](../notes/llamamod-app.md#writing-a-mod).
|
||
|
||
Every mod should be checked in the running game; [`tools/apptest.py`](../tools/apptest.py) does
|
||
this unattended on Linux ([Tools](tools.md#testing-in-the-game)).
|
||
|
||
## The editor manual
|
||
|
||
[`docs/manual/`](manual/index.md) is the editor's user manual **and** its built-in help: the build
|
||
bundles the folder into the jar (`processResources` in `build.gradle`), the Help window renders it
|
||
with its own small Markdown converter, and F1 maps editor topics to chapter anchors
|
||
(`editor/tools/help/context-help.txt`). Rules for that folder:
|
||
|
||
* Only the Markdown subset described at the top of `index.md`; every chapter must be linked from
|
||
`index.md`; links must stay **inside** `docs/manual` (the help window cannot open other files).
|
||
* Blocks between `generated:NAME` comments (shortcuts, menus, mod reference) are rewritten from the
|
||
live program by `ManualTest` – do not edit them by hand.
|
||
* `./gradlew test --tests '*ManualTest*'` checks links, anchors and images.
|
||
|
||
Maintenance notes: [notes/editor-manual.md](../notes/editor-manual.md).
|
||
|
||
## Engineering notes
|
||
|
||
[`notes/`](../notes/README.md) is the project's lab notebook: one file per format, editor area and
|
||
mod, with addresses in `groove.exe`, confidence levels, what was verified in the game and known
|
||
limits. Process material (agent briefs, review reports) is in [`notes/dev/`](../notes/dev/).
|