update README.md
This commit is contained in:
@@ -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_<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_<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 <volume-mountpoint>`) 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
|
||||
|
||||
Submodule source-repos/adventureland_mongodb updated: 93bb1c76f8...a5c133dcc3
Reference in New Issue
Block a user