Files
adventureland/docs/admin/executor.md
T
2026-11-08 02:16:03 +01:00

7.1 KiB
Raw Blame History

Admin-Executor (/admin/executor)

Der Admin-Executor ist die bequemste Variante für administrative Änderungen. Er führt Backend-JavaScript aus – nicht Game-Server-JavaScript – und hat Zugriff auf die Backend-Funktionen und die MongoDB.

Zugang

Voraussetzung ist user.admin = true oder Local: true zusammen mit unsecure_admin: true in files/config/options.js.

user.admin direkt setzen:

cd /data/ai/gaming/adventureland

docker compose exec al-mongo mongosh adventureland --eval \
  'db.user.updateOne({"info.email": "du@example.com"}, { $set: { admin: true } })'

Danach im Browser neu einloggen und öffnen:

http://localhost:8090/admin/executor

Der frühere Weg /admin/make/user/admin ist im Code deaktiviert (common_engine/admin.js enthält ein frühes return;).

Sicherheit: Der Executor erlaubt beliebige Codeausführung im Backend. unsecure_admin: true macht jeden lokalen Besucher zum Admin. Niemals zusammen mit öffentlichem Zugriff verwenden.

Was im Executor verfügbar ist

Neben normalem JavaScript stehen unter anderem zur Verfügung:

  • req – der Express-Request des Executor-Aufrufs
  • output – wird als [OUTPUT] an die Oberfläche zurückgegeben
  • inspect – wird als JSON zurückgegeben
  • console.log() / console.error() – landen in [LOGS]
  • db – MongoDB-Handle
  • get_user_by_email(email), get_character(name), get(id)
  • save(entity), tx(), tx_get(), tx_save()
  • update_characters(user, reason, name, shells)
  • character_eval(character, code, data)
  • server_eval(server, code, data), server_eval_safe(server, code, data)
  • keys – die Server-Keys, inklusive ACCESS_MASTER

character_eval führt Code auf dem Game-Server aus. Dort heißt der laufende Character player. Ist der Character offline, passiert nichts.

Beispiele

Shells geben (accountweit)

Shells liegen in user.cash. update_characters schickt den neuen Stand an alle online Characters.

var u = await get_user_by_email("du@example.com");
if (!u) throw new Error("user not found");

var amount = 1000;
u.cash = (u.cash || 0) + amount;
await save(u);

await update_characters(u, "", "", amount);

output = { email: u.info.email, cash: u.cash };

Bank-Gold geben (accountweit)

Bank-Gold liegt in user.info.gold.

var u = await get_user_by_email("du@example.com");
if (!u) throw new Error("user not found");

var amount = 100000;
u.info.gold = (u.info.gold || 0) + amount;
await save(u);

output = { bank_gold: u.info.gold };

Danach neu einloggen bzw. die Bank betreten. Steht der Character bereits in der Bank, ist player.user.gold live veraltet; dann zusätzlich per character_eval aktualisieren oder neu einloggen.

Character-Gold geben

Character-Gold liegt in character.info.gold.

var ch = await get_character("CharName");
if (!ch) throw new Error("character not found");

var amount = 100000;

if (ch.online || ch.server) {
  await character_eval(
    ch,
    "player.gold += " + amount + "; resend(player, 'reopen+u+cid');"
  );
  output = { character: ch.info.name, mode: "live" };
} else {
  ch.info.gold = (ch.info.gold || 0) + amount;
  await save(ch);
  output = { character: ch.info.name, gold: ch.info.gold, mode: "db" };
}

Item geben

Live nutzt add_item Stacking und Inventarprüfung. Offline wird direkt in character.info.items geschrieben; dort gibt es keine Prüfung.

var ch = await get_character("CharName");
if (!ch) throw new Error("character not found");

var item = { name: "hpot0", q: 100 };

if (ch.online || ch.server) {
  await character_eval(
    ch,
    "add_item(player, " + JSON.stringify(item) + ", {announce:false});" +
      "resend(player, 'reopen+u+cid');"
  );
  output = { character: ch.info.name, item: item, mode: "live" };
} else {
  ch.info.items = ch.info.items || [];
  ch.info.items.push(item);
  await save(ch);
  output = { character: ch.info.name, item: item, mode: "db" };
}

Item-Namen stehen in design/items.js (G.items), zum Beispiel hpot0, mpot0, helmet, shoes. Das Inventar fasst maximal 42 Einträge.

XP geben

var ch = await get_character("CharName");
if (!ch) throw new Error("character not found");

var amount = 100000;

if (ch.online || ch.server) {
  await character_eval(
    ch,
    "player.xp += " + amount + "; resend(player, 'reopen');"
  );
  output = { character: ch.info.name, mode: "live" };
} else {
  ch.xp = (ch.xp || 0) + amount;
  ch.info.xp = ch.xp;
  await save(ch);
  output = { character: ch.info.name, xp: ch.xp, mode: "db" };
}

resend(player, "reopen") ruft calculate_player_stats auf und führt Level-Ups aus. Offline passiert das beim nächsten Login.

Item in die Bank legen

Bank-Packs liegen in user.info.items0 bis user.info.items47.

var u = await get_user_by_email("du@example.com");
if (!u) throw new Error("user not found");

u.info.items0 = u.info.items0 || [];
u.info.items0.push({ name: "hpot0", q: 100 });
await save(u);

output = { pack: "items0", count: u.info.items0.length };

Danach neu einloggen bzw. die Bank betreten. Pack-Größe beachten (bis 42).

Charakterplätze setzen

var u = await get_user_by_email("du@example.com");
if (!u) throw new Error("user not found");

u.info.slots = 18;
await save(u);

output = { slots: u.info.slots };

info.slots wird bei jeder Anfrage gelesen; ein Neustart ist nicht nötig. Maximum sind 18.

Account verifizieren

var u = await get_user_by_email("du@example.com");
if (!u) throw new Error("user not found");

u.info.verified = true;
await save(u);

output = { verified: true };

GM setzen

GM ist eine Character-Rolle, kein Web-Admin.

var ch = await get_character("CharName");
if (!ch) throw new Error("character not found");

ch.role = "gm";
ch.info.p = ch.info.p || {};
ch.info.p.role = "gm";
await save(ch);

output = { character: ch.info.name, role: "gm" };

Danach den Character neu einloggen.

Grenzen

  • Der Executor ist kein Satz benannter Befehle wie /give shells. Es ist eine Codebox.
  • Er läuft im Backend. Für Funktionen, die es nur im Game-Server gibt (players, add_item, resend), character_eval bzw. server_eval verwenden.
  • Offline-Änderungen an character.info.* werden beim nächsten Sync des Game-Servers überschrieben, wenn der Character online ist. Dann live arbeiten oder den Character vorher ausloggen.
  • aadd_item aus node/server.js nicht verwenden: Es ruft eine nicht definierte reopen()-Funktion auf. Stattdessen add_item(...) + resend(...).

Quellen

  • source-repos/common_engine/admin.js – /admin/executor, execute_api, is_admin
  • source-repos/common_engine/htmls/admin_executor.html – Oberfläche
  • source-repos/adventureland_mongodb/adventure_functions.js – get_user_by_email, get_character, update_characters, character_eval, server_eval, update_character, update_user_data, user_to_server
  • source-repos/adventureland_mongodb/node/server.js – add_item, calculate_player_stats, resend
  • source-repos/adventureland_mongodb/design/items.js – Item-Definitionen