class_name AdminTexte extends RefCounted ## Verständliche deutsche Texte zu Admin-API-Antworten (kein Fachchinesisch, ## kein rohes JSON) – inklusive der Fehlerliste (422) beim Map-Upload. const TUNNEL_HINWEIS := "Tipp: Die Admin-API hört standardmäßig nur auf dem Server selbst (localhost). Von außen erreichst du sie sicher über einen SSH-Tunnel (z. B. ssh -L 24580:127.0.0.1:24580 benutzer@server, dann hier Adresse 127.0.0.1) oder über einen Reverse-Proxy mit https. Die Verbindung selbst ist sonst unverschlüsselt." ## Erklärungen für häufige Prüfregeln der Map (Server und Editor nutzen dieselben IDs). const REGEL_HILFE := { "V1": "Die Datei ist zu groß.", "V2": "Die Datei ist keine gültige Map-Datei.", "V3": "Format-Version passt nicht – Editor und Server müssen zusammenpassen.", "V4": "Ein Pflichtbereich der Map fehlt.", "V6": "Das Terrain ist zu groß oder zu detailreich.", "V8": "Zu viele Objekte oder zu viele Polygone – Objekte entfernen.", "V11": "Pro Team werden mindestens 4 Spawn-Punkte gebraucht (Spawn-Zonen malen).", "V14": "Die Map ragt über die erlaubte Größe hinaus.", } ## Antwort → Text für den Nutzer ("" bei Erfolg ohne Besonderheiten). static func erklaere(res: Dictionary) -> String: if str(res.get("transport_error", "")) != "": return str(res["transport_error"]) + "\n\n" + TUNNEL_HINWEIS var status := int(res.get("status", 0)) var body: Dictionary = res.get("body", {}) var server_text := str(body.get("error", "")) match status: 401: return "Das Token stimmt nicht (oder fehlt). Es steht beim Server in der Admin-Datei (state_file) – bitte neu eintragen." 429: return "Zu viele falsche Token-Versuche. Der Server sperrt dich kurz – bitte in ein paar Minuten erneut versuchen." 404: if str(body.get("code", "")) == "not_found": return "Diese Funktion kennt der Server nicht. Ist er auf dem neuesten Stand?" 413: return "Die Datei ist größer als der Server erlaubt. " + server_text 422: return erklaere_map_fehler(body) if server_text != "": return server_text if status >= 200 and status < 300: return "" return "Unerwartete Antwort vom Server (Status %d)." % status ## Fehlerliste einer abgelehnten Map als Aufzählung mit Hilfetexten. static func erklaere_map_fehler(body: Dictionary) -> String: var errs: Array = body.get("errors", []) var out := "Der Server hat die Map abgelehnt" out += " (%d Problem%s):\n" % [errs.size(), "" if errs.size() == 1 else "e"] if not errs.is_empty() else ".\n" var hints := {} for e in errs: var t := str(e) out += "• " + t + "\n" var rule := t.split(":")[0].strip_edges() for k in REGEL_HILFE.keys(): if rule == k or rule.begins_with(k) and not rule.substr(k.length(), 1).is_valid_int(): hints[k] = REGEL_HILFE[k] if not hints.is_empty(): out += "\nSo behebst du es:\n" for k in hints.keys(): out += "• %s: %s\n" % [k, hints[k]] return out.strip_edges() ## Dateiname für den Upload: a–z, 0–9, _ und -, höchstens 40 Zeichen (wie der Server). static func slugify(text: String) -> String: var t := text.strip_edges().to_lower() for pair in [["ä", "ae"], ["ö", "oe"], ["ü", "ue"], ["ß", "ss"]]: t = t.replace(pair[0], pair[1]) var out := "" for c in t: out += c if ((c >= "a" and c <= "z") or (c >= "0" and c <= "9") or c == "-") else "_" while out.contains("__"): out = out.replace("__", "_") out = out.lstrip("_-").rstrip("_") return out.substr(0, 40) ## Wirkung einer Einstellung in Klartext. static func wirkung(effect: String) -> String: match effect: "live": return "sofort" "next_map": return "ab der nächsten Map" "restart": return "nach Server-Neustart" return effect static func neustart_zeitueberschreitung(seconds: int) -> String: return "Der Server ist nach %d s nicht zurück. Er kommt nur von selbst wieder, wenn Docker (Restart-Policy), systemd oder tools/start_server.* ihn gestartet haben." % seconds static func sperrdauer_text(minutes: int) -> String: if minutes <= 0: return "dauerhaft" if minutes < 60: return "%d Minuten" % minutes if minutes < 1440: return "%d Stunden" % (minutes / 60) return "%d Tage" % (minutes / 1440)