From 793797dacb5dee7a65c2ad6f66b96116f963c520 Mon Sep 17 00:00:00 2001
From: anima
Date: Fri, 6 Nov 2026 18:06:09 +0100
Subject: [PATCH] patch char name length by create
---
Dockerfile | 8 ++++
README.md | 20 ++++++++++
docker/patch-character-name-length.js | 55 +++++++++++++++++++++++++++
files/config/options.js | 5 +++
4 files changed, 88 insertions(+)
create mode 100644 docker/patch-character-name-length.js
diff --git a/Dockerfile b/Dockerfile
index 1034ba6..74a00a8 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -74,6 +74,14 @@ RUN node /tmp/patch-custom-game.js /app
COPY docker/patch-auto-verify-email.js /tmp/patch-auto-verify-email.js
RUN node /tmp/patch-auto-verify-email.js /app
+# Local patch: make the minimum length for newly created character names
+# configurable (docker/patch-character-name-length.js). Upstream rejects names
+# shorter than 4 at creation, while rename/chat already accept 1-12; options
+# .character_name_min_length defaults to 4 and can be set to 3 in
+# files/config/options.js to allow 3-character names at creation.
+COPY docker/patch-character-name-length.js /tmp/patch-character-name-length.js
+RUN node /tmp/patch-character-name-length.js /app
+
# Local patch: make the Steam/MAS auth-id requirement for tutorial and class
# rewards optional (docker/patch-tutorial-reward-auth.js). Controlled at runtime
# by options.tutorial_reward_requires_auth_id.
diff --git a/README.md b/README.md
index 7c1ba93..150304c 100644
--- a/README.md
+++ b/README.md
@@ -48,6 +48,20 @@ docker compose exec al-mongo mongosh adventureland --eval \
)'
```
+**Charakternamen mit 3 Zeichen:** Beim Anlegen verlangt Upstream mindestens 4
+Zeichen; kürzere Namen sind nur über die kostenpflichtige Umbenennung möglich
+(3 Zeichen: 24.000 Muscheln). `files/config/options.js` setzt deshalb
+`character_name_min_length: 3`. Der Build-Patch
+`docker/patch-character-name-length.js` liest den Wert in `is_name_allowed`;
+die übrigen Regeln bleiben unverändert: 1–12 Zeichen im Validator,
+`[A-Za-z0-9_]`, keine reinen Zahlen und keine Prototype-Schlüssel. Mit dem hier
+gesetzten Wert 3 bleiben 1–2 Zeichen weiterhin der Umbenennung vorbehalten.
+Bestehende kurze Namen sind nicht betroffen. Zum Zurückstellen den Wert auf `4`
+setzen und `al-backend` sowie `al-game` neu starten; ein Rebuild ist nur nötig,
+wenn der Patch selbst fehlt. Der Patch ändert nur die Erstellung:
+3-Zeichen-Namen sind damit kostenlos, obwohl eine Umbenennung auf 3 Zeichen
+weiterhin 24.000 Muscheln kostet.
+
**Admin werden:** Die Admin-Seiten (`/admin/executor`, `/admin/renderer`) sind
standardmäßig gesperrt. `is_admin` in `common/admin.js` prüft das Feld
`user.admin`; setzen lässt es sich direkt in MongoDB:
@@ -276,6 +290,12 @@ Nicht-Händlern bzw. 1 Händler ab. Der Patch liest beide Stellen aus
`merchant_owner_limit`). Fehlt ein Anker in `node/server_functions.js` oder
`adventure_functions.js`, bricht der Build ab.
+`docker/patch-character-name-length.js` macht die Mindestlänge neuer
+Charakternamen konfigurierbar. `options.character_name_min_length` (Standard 4)
+ersetzt die feste 4 in `is_name_allowed`; die Umbenennung (`is_name_xallowed`)
+und ihre Preislogik bleiben unverändert. Fehlt der Anker in `api.js`, bricht der
+Build ab.
+
## Spieldaten anpassen (`files/custom/game.js`)
Werte bestehender Elemente und neue Elemente lassen sich ohne Quelltextänderung
diff --git a/docker/patch-character-name-length.js b/docker/patch-character-name-length.js
new file mode 100644
index 0000000..31db448
--- /dev/null
+++ b/docker/patch-character-name-length.js
@@ -0,0 +1,55 @@
+#!/usr/bin/env node
+// Local patch: make the minimum length for newly created character names
+// configurable.
+//
+// Upstream's is_name_allowed() rejects names shorter than 4 characters, while
+// is_name_xallowed() already accepts 1-12 for rename, chat and login. Three
+// character names are therefore fully supported; the 4-character gate only
+// applies to character creation and makes them a paid rename target (24,000
+// shells). This patch reads options.character_name_min_length (default 4) so a
+// local server can allow 3-character names at creation without changing the
+// rename rules or prices.
+//
+// The patch is idempotent and fails loudly if the anchor is gone.
+
+const fs = require("node:fs");
+const path = require("node:path");
+
+const app = path.resolve(process.argv[2] || "/app");
+const file = path.join(app, "api.js");
+let source = fs.readFileSync(file, "utf8");
+
+const oldLine = "\tif (name.length < 4) return false;";
+const newLines = [
+ "\tvar min_length =",
+ '\t\ttypeof options === "undefined" || !options || options.character_name_min_length === undefined',
+ "\t\t\t? 4",
+ "\t\t\t: Number(options.character_name_min_length);",
+ "\tif (!Number.isSafeInteger(min_length) || min_length < 1 || min_length > 12) min_length = 4;",
+ "\tif (name.length < min_length) return false;",
+].join("\n");
+
+function fail(message) {
+ console.error("patch-character-name-length: " + message);
+ process.exit(1);
+}
+
+const marker = "options.character_name_min_length";
+const oldCount = source.split(oldLine).length - 1;
+const patchedCount = source.split("if (name.length < min_length) return false;").length - 1;
+
+if (oldCount === 1 && patchedCount === 0) {
+ source = source.replace(oldLine, newLines);
+ fs.writeFileSync(file, source);
+ console.log("patch-character-name-length: patched " + file);
+} else if (oldCount === 0 && patchedCount === 1 && source.includes(marker)) {
+ console.log("patch-character-name-length: already patched");
+} else {
+ fail(
+ "expected 1 unpatched creation length check, found " +
+ oldCount +
+ " unpatched and " +
+ patchedCount +
+ " patched; refusing partial patch",
+ );
+}
diff --git a/files/config/options.js b/files/config/options.js
index 611957a..83ade3c 100644
--- a/files/config/options.js
+++ b/files/config/options.js
@@ -54,6 +54,11 @@ module.exports = {
// these values; 9 here allows 3 accounts with 3 characters each from one IP.
ip_limit: 9,
character_limit: 3,
+ // Minimum length for newly created character names. Upstream is 4; 3 lets
+ // short names be created for free instead of only via the paid rename
+ // (3 characters costs 24,000 shells). Valid 1-12; invalid values fall back
+ // to 4. Rename/chat/login already accept short names either way.
+ character_name_min_length: 3,
// Max concurrent merchant characters per IP and per account. Upstream is
// hard-coded to 1/1; this local build reads these options in login and in
// the backend cron. 3 here means three merchant accounts may share one IP.