From 644b8601455f4ed19abd265e42836eb17db9deec Mon Sep 17 00:00:00 2001
From: anima
Date: Wed, 4 Nov 2026 22:25:34 +0100
Subject: [PATCH] update README.md
---
README.md | 161 +++++++++++++++++------------
source-repos/adventureland_mongodb | 2 +-
2 files changed, 98 insertions(+), 65 deletions(-)
diff --git a/README.md b/README.md
index a4215ad..2527dc2 100644
--- a/README.md
+++ b/README.md
@@ -19,15 +19,18 @@ docker compose up -d --build
Danach im Browser öffnen: **http://localhost:8090**
Der erste Start dauert ein paar Minuten (Image-Build inkl. `npm install`). Beim
-ersten Start laufen zwei Hilfs-Container: `mongo-init` initialisiert das
-Replica-Set, `seed` importiert die 49 Kartendaten. Erst danach starten Backend
+ersten Start laufen zwei Hilfs-Container: `al-mongo-init` initialisiert das
+Replica-Set, `al-seed` importiert die 49 Kartendaten. Erst danach starten Backend
und Game-Server. Bei späteren Starts überspringt sich der Seed selbst.
**Konto anlegen:** Auf der Startseite unter „Steam“ auf **„Registrieren
[Zum Entwickeln]“** klicken, E-Mail + Passwort eingeben. Danach Charakter
erstellen und auf den Charakter klicken – man landet direkt im Spiel.
-**Charakter Limits anheben** Folgendes Kommando setzt für alle existierenden Spieler das Charakter Limit auf 18.
+**Charakterplätze anheben:** Folgendes Kommando setzt für alle bestehenden
+Konten die Zahl der Charakterplätze (`info.slots`) auf das Maximum von 18. Neue
+Konten starten weiterhin mit 5 Plätzen (mit verknüpfter Steam-ID `pid`: 8):
+
```sh
docker compose exec al-mongo mongosh adventureland --eval \
'db.user.updateMany({}, { $set: { "info.slots": 18 } })'
@@ -42,9 +45,10 @@ docker compose exec al-mongo mongosh adventureland --eval \
'db.user.updateOne({"info.email": "du@example.com"}, { $set: { admin: true } })'
```
-Alternativ in `config/options.js` `unsecure_admin: true` setzen – dann gilt
-**jeder** Besucher als Admin (`/admin/executor` erlaubt Code-Ausführung), daher
-nur bei rein lokalem Zugriff sinnvoll.
+Alternativ in `files/config/options.js` `unsecure_admin: true` setzen – dann
+gilt **jeder** Besucher als Admin, solange `Local: true` ist
+(`/admin/executor` erlaubt Code-Ausführung). Daher nur bei rein lokalem Zugriff
+sinnvoll.
**GM werden (Game):** Der Web-Admin ist **kein** Game-GM. Die GM-Rolle hängt am
Charakter, nicht am Benutzerkonto: Der Game-Server prüft `player.role` bzw.
@@ -79,46 +83,49 @@ docker compose exec al-mongo mongosh adventureland --eval \
## Aufbau
-| Service | Image | Aufgabe |
-| ------------ | ------------------- | ------------------------------------------------------------- |
-| `mongo` | `mongo:8.0` | Datenbank, läuft als Single-Node-Replica-Set `rs0` (Transaktionen) |
-| `mongo-init` | `mongo:8.0` | Einmalig: `rs.initiate()` falls noch nicht geschehen |
-| `seed` | `adventureland:local` | Einmalig: importiert die Kartengeometrie, überspringt sich selbst |
-| `backend` | `adventureland:local` | Express-Backend, Web-Client, API – Port 8090 |
-| `game` | `adventureland:local` | Socket.IO-Game-Server – Port 7192 |
+| Service | Image | Aufgabe |
+| -------------- | --------------------------------------------- | ------------------------------------------------------------- |
+| `al-mongo` | `mongo:8.0` | Datenbank, läuft als Single-Node-Replica-Set `rs0` (Transaktionen) |
+| `al-mongo-init` | `mongo:8.0` | Einmalig: `rs.initiate()` falls noch nicht geschehen |
+| `al-seed` | `git.ao-it.net/gaming/adventureland:latest` | Einmalig: importiert die Kartengeometrie, überspringt sich selbst |
+| `al-backend` | `git.ao-it.net/gaming/adventureland:latest` | Express-Backend, Web-Client, API – Port 8090 |
+| `al-game` | `git.ao-it.net/gaming/adventureland:latest` | Socket.IO-Game-Server – Port 7192 |
-Die Spieldaten (Image) werden beim Build aus drei Repositories geklont und
-liegen im Container unter `/app` – es wird nichts in diesen Ordner geklont.
+Das Image klont beim Build die drei Upstream-Repositories nach `/app`. Die
+Submodule unter `source-repos/` sind lokale Arbeitskopien zur Kontrolle und
+werden nicht ins Image kopiert; die Build-Patches liegen unter `docker/`.
## Konfiguration
-`config/` wird als `/app/secretsandconfig` in die Container gemountet und
+`files/config/` wird als `/app/secretsandconfig` in die Container gemountet und
ersetzt das Template aus dem Upstream-Repo:
-- `config/keys.js` – MongoDB-URI, Master-Keys, Stripe/Steam/SES (alles leer bzw.
- feste Entwicklungs-Defaults). Die Werte sind absichtlich stabil, damit
- Sitzungen und Serverdatensätze Neustarts überleben.
-- `config/options.js` – `base_url`, Ports, Serverdefinition `local`,
+- `files/config/keys.js` – MongoDB-Verbindung, Master-Keys, Stripe/Steam/SES,
+ Discord und Apple. Externe Dienste sind leer, die Master-Keys haben lokale
+ Entwicklungs-Defaults. Die Werte sollten stabil bleiben: Login-Sitzungen
+ liegen in MongoDB und hängen nicht an den Keys, aber `SERVER_MASTER`
+ verschlüsselt die gespeicherten MCP-Token-Geheimnisse.
+- `files/config/options.js` – `base_url`, Ports, Serverdefinition `local`,
Multi-Account-Limits.
Beide Dateien sind normale Node-Module; nach Änderungen Container neu starten:
```sh
-docker compose restart backend game
+docker compose restart al-backend al-game
```
-> Wenn du die Ports änderst, passe sie an **drei** Stellen an:
-> `docker-compose.yml` (`ports`), `config/options.js` (`port`, `local_port`,
-> `address`) und `base_url` (inkl. Port).
+> Wenn du die Ports änderst, passe sie in `docker-compose.yml` (`ports`) und
+> `files/config/options.js` (`port`, `local_port`, `address`; `local_ip` nur bei
+> Bedarf) sowie `base_url` (inkl. Port) an.
### Multi-Account-Limits
-`config/options.js` steuert, wie viele Charaktere gleichzeitig online sein
+`files/config/options.js` steuert, wie viele Charaktere gleichzeitig online sein
dürfen:
| Option | Bedeutung | aktuell |
| --- | --- | --- |
-| `ip_limit` | Nicht-Händler pro IP (mal `ipx` einer IP-Ausnahme) | `9` |
+| `ip_limit` | Nicht-Händler pro IP (multipliziert mit dem `info.limit` einer `IP_`-Ausnahme) | `9` |
| `character_limit` | Nicht-Händler pro Konto | `3` |
| `merchant_ip_limit` | Händler pro IP | `3` |
| `merchant_owner_limit` | Händler pro Konto | `1` |
@@ -128,7 +135,7 @@ Die Werte gelten beim Login (`is_player_allowed`) und im Backend-Cron
`docker/patch-multi-account-limits.js` ersetzt dabei die früher fest codierten
Grenzen (3 Nicht-Händler, 1 Händler). Mit den aktuellen Werten können z. B. drei
Konten von derselben IP jeweils drei Nicht-Händler-Charaktere online haben
-(9 insgesamt); ein zehntes Nicht-Händler-Charakter bzw. ein vierter Händler wird
+(9 insgesamt); ein zehnter Nicht-Händler-Charakter bzw. ein vierter Händler wird
abgewiesen. `character_limit` ist die Zahl der **gleichzeitig online** erlaubten
Charaktere, nicht die Zahl der Charakterplätze (`info.slots`); `ip_limit` ist
ebenfalls keine Slotzahl. Eine `IP_`-Ausnahme mit
@@ -156,31 +163,42 @@ docker compose exec al-mongo mongosh adventureland --eval 'db.getCollectionNames
```sh
docker compose ps
-docker compose logs -f backend game
+docker compose logs -f al-backend al-game
```
## Stoppen, Zurücksetzen, Sichern
```sh
-docker compose stop # anhalten
-docker compose down # Container entfernen, Daten behalten
-docker compose down -v # ALLES löschen, inkl. Konten, Charakteren, Karten
+docker compose stop # Container anhalten, Daten bleiben
+docker compose down # Container entfernen, Daten in ./files/db bleiben
+docker compose down -v # zusätzlich benannte/anonyme Volumes; ./files/db bleibt
```
-Nach `down -v` importiert der `seed`-Container die Karten beim nächsten Start
-wieder. Backup/Restore des Datenbank-Volumes:
+`./files/db` ist ein Bind-Mount, kein Docker-Volume. `down -v` löscht es
+deshalb **nicht**. Für einen vollständigen Reset:
```sh
-docker compose stop backend game
-docker run --rm -v adventureland_mongo-data:/data -v "$PWD":/backup alpine \
- tar czf /backup/mongo-data-$(date +%F).tar.gz -C /data .
-docker compose start backend game
+docker compose down
+sudo find files/db -mindepth 1 -delete
+docker compose up -d
```
-Restore: `docker compose down`, das Volume leeren und das Archiv
-(`tar xzf mongo-data-….tar.gz -C `) zurückkopieren, dann
-`docker compose up -d` – `seed` erkennt die vorhandenen Collections und
-überspringt den Import.
+Beim nächsten Start ist die Datenbank leer; `al-mongo-init` initialisiert das
+Replica-Set und `al-seed` importiert die Karten neu.
+
+Backup/Restore über `mongodump`/`mongorestore` (beide sind im MongoDB-Image):
+
+```sh
+mkdir -p backups
+docker compose exec -T al-mongo mongodump --db adventureland --archive --gzip \
+ > backups/adventureland-$(date +%F-%H%M).dump.gz
+
+# Restore (vorher Backend und Game stoppen):
+docker compose stop al-backend al-game
+docker compose exec -T al-mongo mongorestore --archive --gzip --drop \
+ < backups/adventureland-….dump.gz
+docker compose start al-backend al-game
+```
## Aktualisieren
@@ -227,7 +245,7 @@ bricht der Build ab.
Limits konfigurierbar. Upstream prüft beim Login `options.ip_limit` und
`options.character_limit`, würgt im Backend-Cron aber pauschal nach 3
Nicht-Händlern bzw. 1 Händler ab. Der Patch liest beide Stellen aus
-`config/options.js` (`ip_limit`, `character_limit`, `merchant_ip_limit`,
+`files/config/options.js` (`ip_limit`, `character_limit`, `merchant_ip_limit`,
`merchant_owner_limit`). Fehlt ein Anker in `node/server_functions.js` oder
`adventure_functions.js`, bricht der Build ab.
@@ -247,8 +265,10 @@ Aufbau (alle Angaben optional):
- `items`, `monsters`, `npcs`, `maps`, `sets`, `craft`, `skills`, `conditions`,
`classes`, `levels`, `upgrades`, `compounds`, `multipliers`, `titles`,
`tokens`, `dismantle`: Objekte werden tief zusammengeführt, Arrays ersetzt.
- Neue IDs sind erlaubt, wenn sie eine vorhandene Grafik aus
- `design/dimensions.js` nutzen (Items und Monster brauchen ein `skin`).
+ Neue IDs sind erlaubt, wenn sie vorhandene Grafiken wiederverwenden: Monster
+ aus `design/dimensions.js`, Items und Condition-Icons aus dem Sprite-Atlas
+ (`design/positions.js`). Items brauchen ein `skin`; bei Monstern dient die ID
+ als Fallback, Conditions dürfen ohne `skin` bleiben.
Neue Karten gehen nicht: ihre Geometrie liegt in MongoDB (`MP_*`).
- `drops`: `{ main: [[0.001, "item_id"]] }` hängt Zeilen an die Tabelle an.
- `gold`: überschreibt `drops.gold`, z. B. `{ base: 0.8 }`.
@@ -259,17 +279,19 @@ Aufbau (alle Angaben optional):
Beim Start loggen beide Container `custom-game: loaded ...`; neue IDs stehen
als `(new: ...)` dabei. Unbekannte Top-Level-Schlüssel, unbekannte Drop-Tabellen,
-fehlende Items und fehlende Grafiken brechen den Start mit einer klaren Meldung
-ab, statt das Spiel halb gepatcht zu starten.
+fehlende Items und bei neuen IDs fehlende Grafiken brechen den Start mit einer
+klaren Meldung ab, statt das Spiel halb gepatcht zu starten.
Enthaltenes Beispiel: Der Buff „Lone Wolf“ gibt 10× XP statt 3×. Die
Multiplikatoren liest der Game-Server aus der Condition-Definition (Patch in
`docker/patch-custom-game.js`), der Tooltip-Text kommt aus `phrases`. Die Datei
ist versioniert (`files/custom/`), `files/db` bleibt von Git ausgenommen.
-Grenzen: Alles, was in `design/*.js` als Datum steht, ist überschreibbar.
-Konstanten, die im Code stehen (z. B. andere Encouragement-Raten), brauchen
-weiterhin einen Patch wie den für Lone Wolf. Endet ein Season-Event zur
+Grenzen: Überschreibbar sind genau die oben gelisteten Design-Globals sowie
+`drops`, `gold` und `phrases`. Andere `design/*.js`-Dateien (z. B.
+`positions.js`, `dimensions.js`, `animations.js`) lassen sich darüber nicht
+ersetzen. Konstanten, die im Code stehen (z. B. andere Encouragement-Raten),
+brauchen weiterhin einen Patch wie den für Lone Wolf. Endet ein Season-Event zur
Laufzeit, können eventmodifizierte Monsterfelder auf den Stand vor der
Custom-Datei zurückgesetzt werden; dann den Game-Server neu starten.
@@ -280,7 +302,8 @@ Custom-Datei zurückgesetzt werden; dann den Game-Server neu starten.
nächsten Login auf „verifiziert“; die Verifikationsmail wird übersprungen. Der
„Not Verified“-Debuff (Gold/Glück −25 %) tritt damit nicht mehr auf. Auf
`false` gestellt, gilt wieder der Upstream-Ablauf: Im Backend-Log erscheint
- `send_email error InvalidClientTokenId`, und der Verifizierungslink muss
+ ein SES-Fehler (bei leeren Credentials typischerweise
+ `send_email error InvalidClientTokenId`), und der Verifizierungslink muss
manuell geöffnet werden:
```sh
@@ -289,9 +312,16 @@ Custom-Datei zurückgesetzt werden; dann den Game-Server neu starten.
print("http://localhost:8090/ev/" + u._id + "/" + u.info.everification))'
```
- Link im Browser öffnen, danach neu einloggen. Alternativ `info.verified` direkt
- auf `true` setzen (siehe Admin-Befehl oben). Die `/ev`-Route bleibt in beiden
- Fällen funktionsfähig.
+ Die URL ggf. an `base_url` aus `files/config/options.js` anpassen. Link im
+ Browser öffnen, danach neu einloggen. Alternativ `info.verified` direkt auf
+ `true` setzen:
+
+ ```sh
+ docker compose exec al-mongo mongosh adventureland --eval \
+ 'db.user.updateOne({"info.email": "du@example.com"}, { $set: { "info.verified": true } })'
+ ```
+
+ Die `/ev`-Route bleibt in beiden Fällen funktionsfähig.
- **Tutorial-Belohnung (`c0`):** Jedes verifizierte Konto kann nach
abgeschlossenem Tutorial einmal `c0` abholen. Die Belohnung ist ein zufälliger
@@ -317,22 +347,25 @@ Custom-Datei zurückgesetzt werden; dann den Game-Server neu starten.
- **Der Relay in `docker/entrypoint.sh`:** Das Backend spricht Game-Server über
die Adresse an, die auch der Browser benutzt (`localhost:7192`). Innerhalb des
- Backend-Containers wäre das es selbst, deshalb leitet ein kleines
- `socat`-Relay `127.0.0.1:7192` an den `game`-Container weiter. Ohne das
- schlagen Admin-/Server-Funktionen (`server_eval`) fehl.
+ Backend-Containers wäre das der Backend-Container selbst, deshalb leitet ein
+ kleines `socat`-Relay `127.0.0.1:7192` an den `al-game`-Container weiter. Ohne
+ das schlagen Admin-/Server-Funktionen (`server_eval`) fehl.
- **Lizenz/Attribution:** Die AdventureLandOnlyUse-Lizenz verlangt einen
- crawlable Link auf https://adventure.land. Der ersetzt deshalb die
+ crawlable Link auf https://adventure.land. Der Link ersetzt deshalb die
„E-Mail, für alles“-Zeile im Login (siehe `docker/patch-attribution.js`).
Zusätzlich ist einmalig eine kurze Mail an hello@adventure.land fällig, wenn
die Instanz öffentlich erreichbar geht – das ist keine Code-Änderung.
-- **Nur lokal erreichbar:** Die Ports sind standardmäßig an `127.0.0.1` des
- Hosts gebunden. Für Zugriff aus dem LAN in `docker-compose.yml` die
- `127.0.0.1:`-Präfixe entfernen und `base_url` (sowie ggf.
- `servers.local.address`) in `config/options.js` auf die Host-IP bzw. den
- Hostnamen umstellen. Der Browser verbindet sich direkt mit
- `servers.local.address`.
-- **Passwort-/Key-Änderungen:** `config/keys.js` enthält
+- **Netzwerk/Ports:** Die Ports sind in `docker-compose.yml` derzeit an alle
+ Host-Interfaces gebunden (`8090:8090`, `7192:7192`). Für rein lokalen Betrieb
+ in `docker-compose.yml` `127.0.0.1:` voranstellen. Für Caddy auf einem anderen
+ Host müssen die Ports erreichbar bleiben; dann per Firewall auf die
+ Caddy-/LAN-Adresse beschränken. `base_url` und ggf. `servers.local.address`
+ in `files/config/options.js` auf die öffentliche URL bzw. den Hostnamen
+ umstellen. Der Browser verbindet sich direkt mit `servers.local.address`.
+- **Passwort-/Key-Änderungen:** `files/config/keys.js` enthält
Entwicklungs-Platzhalter. Vor einem öffentlich erreichbaren Betrieb ersetzen.
+ Die Datei wird read-only gemountet; nach einer Änderung genügt ein Neustart
+ von `al-backend` und `al-game`, kein Rebuild. Echte Secrets nicht committen.
- **Quellcode anpassen:** Der Code liegt im Image, nicht im Host-Ordner. Für
eigene Änderungen im `Dockerfile` über die Build-Args `AL_REPO`, `AL_REF`,
`COMMON_REPO`/`COMMON_REF` bzw. `CONFIG_REPO`/`CONFIG_REF` einen Fork oder
diff --git a/source-repos/adventureland_mongodb b/source-repos/adventureland_mongodb
index 93bb1c7..a5c133d 160000
--- a/source-repos/adventureland_mongodb
+++ b/source-repos/adventureland_mongodb
@@ -1 +1 @@
-Subproject commit 93bb1c76f81c52493d90f505a2cd1d2359939eb5
+Subproject commit a5c133dcc31f97edab987119517b4a60581248f6