Files
MCMapper-Mod/test
octoturge 6e2739672c Add itzg-based docker-compose for live-testing the mod against real MC servers
Three services (mc-1_12_2 default, mc-1_7_10/mc-neoforge-26_1 opt-in via
Compose profiles) using itzg/docker-minecraft-server, with mods/config bind-
mounted per loader/version (mods/<loader>/<version>/) so jars can be dropped
in and swapped without touching the compose file. Verified against real
containers: fixed a WSL docker credential-helper misconfig blocking pulls,
and pinned legacy Forge services to the java8 image tag after itzg's
:latest (Java 25) crashed LaunchWrapper with a ClassCastException — mc-1_12_2
now boots cleanly to "Done" on java8.
2026-08-10 06:08:49 +02:00
..

Live test servers

Real Minecraft servers (via itzg/docker-minecraft-server, MIT — handles EULA acceptance, Forge/NeoForge installation, memory flags, etc. so this compose file doesn't reimplement any of that) for exercising the mod end-to-end against a running MCMapper-Backend stack — the thing the plan's own per-phase verification steps keep asking for ("place/break blocks, confirm they appear on the map") but that no session has actually done yet.

Only mc-1_12_2 runs by default — it's the actual driving use case (Enigmatica 2, see the plan's version priority). mc-1_7_10 and mc-neoforge-26_1 are opt-in via Compose profiles:

docker compose up                           # 1.12.2 only (default)
docker compose --profile legacy-1_7_10 up    # + 1.7.10
docker compose --profile neoforge-26_1 up    # + 26.1.2 NeoForge (least tested, lowest priority)

1. Start a backend stack

From MCMapper-Backend, either:

  • docker compose up (full stack — api/frontend/worker/postgres/redis/caddy; Caddy publishes :80 on the host, routing /ws* to api per the Caddyfile), or
  • run api directly (cd api && bun run dev) for a lighter loop — it listens on :3000 with no proxy in front.

Either way, register a server row so the mod has a token to authenticate with:

cd MCMapper-Backend/api
MCMAPPER_SEED_SERVER_NAME=test-1_12_2 MCMAPPER_SEED_SERVER_TOKEN=<pick-any-string> \
MCMAPPER_SEED_SERVER_AUTH_MODE=offline \
DATABASE_URL=postgres://mcmapper:mcmapper@localhost:<pg-port>/mcmapper bun run seed

(authMode=offline matches this compose's default ONLINE_MODE=FALSE — see docker-compose.yml's comment on that variable. Use online + ONLINE_MODE=TRUE instead to test the real UUID-merge identity path.) The admin panel (/admin on the frontend, Phase 6) is the other way to register a server, if the backend is already up with MCMAPPER_ADMIN_TOKEN set.

2. Build the mod and drop the jar in

cd MCMapper-Mod
./gradlew :forge-1_12_2:build
cp forge-1_12_2/build/libs/forge-1_12_2-*.jar test/mods/forge/1.12.2/

(Swap the leaf/version for forge-1_7_10/mods/forge/1.7.10 or neoforge-26_1/mods/neoforge/26.1.2 — note neoforge-26_1 has its own standalone Gradle wrapper, see the root README's "Building". Mods are split by loader first, then version — Forge and NeoForge mod jars aren't interchangeable even for adjacent MC versions. Each mods/<loader>/<version>/ directory maps straight to that server's /data/mods — drop other mod jars in there too to test alongside MCMapper, and remove/swap them any time, then docker compose restart to pick up the change; nothing in mods//config/ is ever committed, see .gitignore.)

3. First boot, then configure

cd test
docker compose up -d
docker compose logs -f mc-1_12_2   # wait for "Done" / world generation to finish

The mod writes config/mcmapper.cfg with empty defaults on this first boot (it needs a backendUrl/serverToken before it'll actually connect — see the root README's "Configuration" section). Edit test/config/forge/1.12.2/mcmapper.cfg:

backendUrl=ws://host.docker.internal:80/ws
serverToken=<the token you seeded above>

Use ws://host.docker.internal:80/ws if the backend is running via its own docker compose up (Caddy on host :80), or ws://host.docker.internal:3000/ws if you ran bun run dev for api directly instead (no Caddy in front). extra_hosts: host.docker.internal:host-gateway in docker-compose.yml is what makes that hostname resolve to the host machine from inside the MC container — works the same whether the host's Docker is Docker Desktop or a bare Linux daemon (Engine ≥20.10, which this project's own WSL2 dockerd is).

Then:

docker compose restart mc-1_12_2

4. Verify

Connect a real Minecraft 1.12.2 client to localhost:${MC_1_12_2_PORT:-25565} (offline/cracked login works fine with the default ONLINE_MODE=FALSE), walk around to load some chunks, place/ break a few blocks, then check the map frontend (http://localhost if using the backend's own docker compose, or http://localhost:3001 if running frontend directly) — this is the actual Phase 1 verification step from the plan, finally exercised against a real server rather than only unit/integration tests. Also useful for later phases' own live-test callouts that were flagged but never actually run: the atlas shader's invertY assumption (Phase 12) and real non-cube block rendering (Phase 13, place/find a vanilla non-cube block like a torch or stairs — or attach a mod that ships one, e.g. Thaumcraft, by dropping its jar in the same mods/forge/1.12.2/ directory).

Notes

  • World/server data persists in named Docker volumes (mc-1_12_2-data etc.) across docker compose restart/down — use docker compose down -v to fully wipe a server and start over (e.g. after bumping the mod jar in a way that needs a clean world).
  • mods/<loader>/<version>/ and config/<loader>/<version>/ contents are gitignored (except the .gitkeep placeholders that keep the mount points present in a fresh checkout) — nothing dropped in them is committed.
  • To add other mods for stress-testing (Thaumcraft was the plan's named non-cube-model stress test for Phase 13) drop their jars in the same mods/forge/1.12.2/ directory itzg's image reads from — no compose changes needed. itzg's image also supports CURSEFORGE_FILES/MODRINTH_PROJECTS for auto-downloading specific mods (CurseForge's downloads generally need a CF_API_KEY now); not wired up here since that needs per-mod IDs/an API key only you can supply — see itzg's own docs (https://docker-minecraft-server.readthedocs.io/) if you want that instead of manual jars.