Files
dungeoncraft/INSTALL.md
T
Richard ZinkandClaude Opus 5.5 d76e74b4b0 Switch to the Dinowyde font with DINOBYTE for missing glyphs
Unicode glyph lookup instead of CP437 codes, rope and double-strand
frames with clean title ends, progress bars in eighth blocks.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 15:32:42 +01:00

8.1 KiB
Raw Blame History

Installing and running DungeonCraft

Technical matters, master. Crookfinger does not understand half of it, but the imps say it works.

Just want to play? Open https://dungeon.familie-zink.org/ in a browser. On the title screen, logged-in players can use Download Standalone to save DungeonCraft.html: the whole game in one file, without login and without server. Savegames from the standalone version are downloaded as .dcsave files and loaded again with Load Game (or dropped onto the game window).

Everything below is for running your own server (with user accounts and savegames on the server), building the game yourself or working on it.

Running a server

The easiest way is Docker; the image builds the WASM file and serves it with nginx. A second container runs the savegame service (see below):

docker compose up -d --build
# open http://localhost:18093

Install as an app (PWA)

DungeonCraft is a progressive web app: browsers offer to install it (Chrome/Edge: install icon in the address bar or "Install app" in the menu; Android: "Add to home screen"; iOS Safari: Share → "Add to Home Screen"). The installed game starts in full screen and also works offline (the savegame list on the server then falls back to savegame files).

Browsers only allow the installation over HTTPS (or on localhost), so a public installation needs a reverse proxy with a certificate in front of port 18093.

Building without Docker

Requirements: Rust with the wasm32-unknown-unknown target.

rustup target add wasm32-unknown-unknown
cargo build --release --target wasm32-unknown-unknown
cp target/wasm32-unknown-unknown/release/dungeoncraft.wasm www/
cp ~/.cargo/registry/src/*/macroquad-*/js/mq_js_bundle.js www/
python3 -m http.server 8080 -d www   # open http://localhost:8080

Testing the game logic

The tests run natively: a headless simulation of whole games, a savegame round trip, rendering of all music modules and the audio engine:

cargo test --release

Music

The soundtrack consists of FastTracker 2 modules in assets/music/, generated by tools/compose_music.py (python3 tools/compose_music.py). They can be opened and edited in MilkyTracker. The game plays them with its own XM/MOD replayer (src/xm.rs); sound effects are synthesised chip sounds (src/sfx.rs). Both are mixed in src/audio.rs and streamed to the browser by www/dc_plugin.js.

Controls

Input Action
Esc Pause menu (save, load, settings)
Left click / drag Use the active tool (dig and rooms: drag a rectangle)
Right click Drop a unit from your hand (prisoners anywhere on your ground; onto a free torture place = locked up)
Shift + left click (hand) Backhand own units (15 s faster, costs a little HP and mood) / punch heroes on your ground (15 damage, 1 s stun)
Right drag, WASD, arrows, screen edge Move the camera
Middle drag, Q/E, R/F Rotate / tilt the camera
Mouse wheel Zoom
1–9, 0, X, V, K, J, B, C, T, U, Y, O, N Select a tool or spell (more can be bound in the settings)
P / Space Pause
M, +/- Sound on/off, volume
G Tile outlines on/off
H Help

All keys except Esc and the arrow keys can be changed in Settings → Keys.

The toolbar groups the tools into categories (Dig, Hand, Rooms, Towers, Traps, Spells, Orders) plus a menu button; categories with several tools open a row above the toolbar. The keys select tools directly.

Touch (phones and tablets)

The touch interface switches on automatically on touch devices or after the first touch (Settings → Game → Touch interface: Auto / On / Off). It uses a larger interface and these gestures:

Gesture Action
Tap Use the tool (hand: pick up a unit; spells, flag, towers: at that spot)
Drag Dig, rooms and sell: mark a rectangle; other tools: move the map
Two fingers Move the map, pinch to zoom, twist to rotate the camera
Long press Information about the spot; hand: drop the units there
Double tap (hand) Backhand own units / punch heroes on your ground

The savegame name is entered with the browser's text dialog when the name field is tapped.

Savegames

When the game is served together with the service (server/, started by docker compose), it starts with a login:

  • The very first login creates the admin account with the entered name and password - do this right after installing.
  • The admin creates further users (title screen -> Account); every user can change the password there and log out.
  • Every user only sees the own savegames on the server: Save Game and Load Game open the list (save under a new name, overwrite, load, delete).
  • Download Standalone (title screen) downloads DungeonCraft.html: the whole game in one file, without login and without server. Savegame files (Download as file) open there as well.

If the service cannot be reached (for example the standalone file, www/ opened as local files or a plain web server), there is no login and the game uses savegame files: Save Game downloads a .dcsave file (JSON), Load Game opens the file picker; dropping the file onto the game window works too.

The game also autosaves into the browser every two minutes and when the tab is closed; Continue on the title screen resumes from there.

Savegame service

A small Rust service (axum) in server/ keeps the user accounts (Argon2 password hashes) and the savegames as files in the Docker volume savegames (one folder per user). nginx forwards /api/ to it; the service itself is not published. The standalone file is served under /standalone/ as a public file, so it can be downloaded before login.

Request Meaning
GET /api/health ok when the service runs (ok setup while there is no account yet)
POST /api/login {name, password} -> {token, name, admin}; the first login creates the admin
POST /api/logout, GET /api/me, POST /api/password session, own account, change password
GET/POST /api/users, DELETE /api/users/{name} admin: list, create, delete users
GET /api/saves own savegames (id, name, date, map size, wave, play time), newest first
POST /api/saves?name=... store a new savegame (body: savegame JSON)
PUT /api/saves/{id}?name=... overwrite a savegame
GET /api/saves/{id} savegame JSON
DELETE /api/saves/{id} delete a savegame

A forgotten password is set again on the server with docker compose stop saves && docker compose run --rm --no-deps saves dungeoncraft-saves set-password <name> '<password>' && docker compose up -d saves (ends the user's sessions). To start over with no accounts at all, delete users.json and sessions.json in the savegames volume.

All requests except health and login need Authorization: Bearer <token>. Limits: 1 MB per savegame, 500 MB in total, 30 write requests and 20 login attempts per minute. Settings: SAVE_DIR (default /data), LISTEN (default 0.0.0.0:8080).

Version

VERSION holds the game version as vYYYYMM-NNNNN: year and month of the change, then the number of changes in that month (v202611-00001). The title screen and the pause menu show it, src/menu.rs reads the file with include_str!, and a test checks the scheme.

With every change to the game run python3 tools/bump_version.py before committing: it raises the number by one (a new month starts again at 00001) and prints the old and the new version. Do not edit VERSION by hand.

Adding a language

  1. Copy lang/en.lang to lang/<code>.lang and translate the texts (placeholders {0}, {1} stay as they are).
  2. Add the file to SOURCES in src/i18n.rs.
  3. The Dinowyde font covers Latin (all European accents), Greek and Cyrillic; the test every_text_of_the_game_has_its_glyphs in src/gfx.rs lists characters it cannot draw (add the new file there).

Refreshing the generated files

File How
docs/img/units, docs/img/icons cargo test --release export_doc_images -- --ignored
BESTIARY.md python3 tools/make_bestiary.py
VERSION python3 tools/bump_version.py - with every change to the game