add admin docs
This commit is contained in:
@@ -0,0 +1,130 @@
|
||||
# Game-Server-API (`/server.api/...`)
|
||||
|
||||
Der Game-Server läuft separat vom Backend und lauscht lokal auf Port `7192`.
|
||||
Seine Admin-Endpunkte liegen unter `/server.api/` und sind **nicht** die
|
||||
öffentliche JSON-API des Backends (`/api`).
|
||||
|
||||
## Endpunkte
|
||||
|
||||
| Methode | Endpunkt | Zweck |
|
||||
|---|---|---|
|
||||
| `POST` | `/server.api/eval` | JavaScript im Game-Server ausführen |
|
||||
| `POST` | `/server.api/cupdate` | Shells eines online Characters setzen |
|
||||
| `POST` | `/server.api/shutdown` | Game-Server herunterfahren |
|
||||
| `POST` | `/server.api/new_friend` | intern: Freund hinzufügen |
|
||||
| `POST` | `/server.api/lost_friend` | intern: Freund entfernen |
|
||||
|
||||
Alle diese Endpunkte verlangen `spass` = `keys.ACCESS_MASTER`. Der Key erlaubt
|
||||
beliebige Codeausführung im Game-Server und darf niemals öffentlich werden.
|
||||
|
||||
## `ACCESS_MASTER` lesen
|
||||
|
||||
```sh
|
||||
cd /data/ai/gaming/adventureland
|
||||
|
||||
ACCESS_MASTER="$(docker compose exec -T al-game node -e \
|
||||
'process.stdout.write(require("/app/secretsandconfig/keys").ACCESS_MASTER)')"
|
||||
```
|
||||
|
||||
Den Wert nicht in Chat, Logs oder Commits schreiben.
|
||||
|
||||
## `/server.api/eval`
|
||||
|
||||
Felder:
|
||||
|
||||
- `spass` – `ACCESS_MASTER`
|
||||
- `code` – JavaScript, wird im Game-Server ausgeführt
|
||||
- `data` – JSON-String, im Code als `data` verfügbar
|
||||
|
||||
Der Code läuft im Modul-Scope des Game-Servers. Verfügbar sind unter anderem
|
||||
`players`, `name_to_id`, `get_player(name)`, `add_item`, `resend`,
|
||||
`calculate_player_stats` und `output`.
|
||||
|
||||
### Gold geben (live)
|
||||
|
||||
```sh
|
||||
curl -sS -X POST http://127.0.0.1:7192/server.api/eval \
|
||||
--data-urlencode "spass=$ACCESS_MASTER" \
|
||||
--data-urlencode 'code=var p=get_player("CharName"); if(p){ p.gold += 100000; resend(p,"reopen+u+cid"); output={ok:true,gold:p.gold}; } else { output={ok:false,reason:"offline"}; }' \
|
||||
--data-urlencode 'data={}'
|
||||
```
|
||||
|
||||
### Item geben (live)
|
||||
|
||||
```sh
|
||||
curl -sS -X POST http://127.0.0.1:7192/server.api/eval \
|
||||
--data-urlencode "spass=$ACCESS_MASTER" \
|
||||
--data-urlencode 'code=var p=get_player("CharName"); if(p){ var n=add_item(p,{name:"hpot0",q:100},{announce:false}); resend(p,"reopen+u+cid"); output={ok:true,slot:n}; } else { output={ok:false,reason:"offline"}; }' \
|
||||
--data-urlencode 'data={}'
|
||||
```
|
||||
|
||||
`add_item` prüft Inventarplatz und stapelt stackbare Items. `announce:false`
|
||||
verhindert eine globale Fundmeldung.
|
||||
|
||||
### XP geben (live)
|
||||
|
||||
```sh
|
||||
curl -sS -X POST http://127.0.0.1:7192/server.api/eval \
|
||||
--data-urlencode "spass=$ACCESS_MASTER" \
|
||||
--data-urlencode 'code=var p=get_player("CharName"); if(p){ p.xp += 100000; resend(p,"reopen"); output={ok:true,level:p.level,xp:p.xp}; } else { output={ok:false,reason:"offline"}; }' \
|
||||
--data-urlencode 'data={}'
|
||||
```
|
||||
|
||||
`resend(p,"reopen")` ruft `calculate_player_stats` auf und führt Level-Ups aus.
|
||||
|
||||
## `/server.api/cupdate`
|
||||
|
||||
Felder:
|
||||
|
||||
- `spass` – `ACCESS_MASTER`
|
||||
- `id` – Character-Name (`player.id` ist der Name, nicht `CH_...`)
|
||||
- `cash` – neuer Gesamtstand der Shells
|
||||
- `ncash` – Betrag für die „received shells“-Meldung; wird **nicht** addiert
|
||||
|
||||
`cupdate` setzt `player.cash` auf `cash`. Es ist kein Inkrement. Deshalb zuerst
|
||||
den neuen Gesamtstand in MongoDB schreiben und dann `cupdate` aufrufen.
|
||||
|
||||
```sh
|
||||
# 1. Account-Cash erhöhen
|
||||
docker compose exec al-mongo mongosh adventureland --eval \
|
||||
'db.user.updateOne({"info.email":"du@example.com"}, { $inc: { cash: 1000 } })'
|
||||
|
||||
# 2. Neuen Gesamtstand lesen
|
||||
NEW_TOTAL="$(docker compose exec -T al-mongo mongosh adventureland --quiet --eval \
|
||||
'db.user.findOne({"info.email":"du@example.com"},{cash:1}).cash')"
|
||||
|
||||
# 3. Online-Character aktualisieren
|
||||
curl -sS -X POST http://127.0.0.1:7192/server.api/cupdate \
|
||||
--data-urlencode "spass=$ACCESS_MASTER" \
|
||||
--data-urlencode 'id=CharName' \
|
||||
--data-urlencode "cash=$NEW_TOTAL" \
|
||||
--data-urlencode 'ncash=1000'
|
||||
```
|
||||
|
||||
Ohne online Character reicht der MongoDB-Wert; beim nächsten Login wird
|
||||
`user.cash` geladen.
|
||||
|
||||
## Wichtige Hinweise
|
||||
|
||||
- **Shells** sind accountweit (`user.cash`). Ein `/cupdate` ändert nur die
|
||||
laufende Kopie im Game-Server; die DB muss separat aktualisiert werden.
|
||||
- **Gold** ist pro Character (`character.info.gold` / `player.gold`) oder
|
||||
accountweit in der Bank (`user.info.gold`).
|
||||
- `eval` ist mächtig und ungefiltert. Nur lokal oder hinter einer
|
||||
vertrauenswürdigen Admin-Schicht betreiben.
|
||||
- `aadd_item` nicht verwenden: Es ruft `reopen()` auf, das im Node-Port nicht
|
||||
definiert ist. Stattdessen `add_item` + `resend`.
|
||||
- Der Game-Server speichert live geänderte Character-Daten regelmäßig. Für
|
||||
dauerhafte Änderungen an Offline-Characters die MongoDB-Variante verwenden;
|
||||
für laufende Characters `eval`.
|
||||
- `ACCESS_MASTER` rotieren, bevor der Port öffentlich erreichbar ist. Der
|
||||
Default steht in `files/config/keys.js`.
|
||||
|
||||
## Quellen
|
||||
|
||||
- `source-repos/adventureland_mongodb/node/server.js` – `server_api`-Router,
|
||||
`/eval`, `/cupdate`, `/shutdown`; `add_item`, `resend`
|
||||
- `source-repos/adventureland_mongodb/adventure_functions.js` –
|
||||
`server_url`, `server_eval`, `server_eval_safe`, `character_eval`
|
||||
- `files/config/options.js` – `api_path: "/server.api/"`, `local_port: 7192`
|
||||
- `source-repos/adventureland_mongodb/README.md` – Admin-/Executor-Hinweise
|
||||
Reference in New Issue
Block a user