Files
lucashahmannandClaude Opus 5.5 e66f89f49e feat: ATM10-Statistikportal
Statistikportal für den All-the-Mods-10-Server (Minecraft 1.21.1, NeoForge 21.1):

- mod/: serverseitige NeoForge-Mod atmstats – Ereignisse, Live-Zähler, Servergesundheit,
  FTB-Dateien; Outbox auf der Festplatte, signierter gzip-Versand per HTTPS mit Backoff
- backend/: Fastify + PostgreSQL – idempotenter Ingest, Projektionen, Parser für SNBT,
  FTB Quests/Teams, world/stats, world/advancements und latest.log; Ranglisten, Snapshots,
  Retention, öffentliche API, SSE-Live-Updates, Admin mit argon2/CSRF, SFTP-Worker
- web/: Next.js-Dashboard – Übersicht, Ranglisten, Spielerprofile, ATM10, Server,
  Datenquellen, Verwaltung
- shared/: Protokoll v1 und API-Typen; tools/: Simulator, Log-Anonymisierer, RCON-Client
- deploy/: Docker Compose hinter Traefik, Backup; docs/: Architektur, Datenquellen, Betrieb

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 09:33:25 +02:00

21 KiB
Raw Permalink Blame History

ATM10 Stats – Design-Spezifikation

Stand: 2026-10-13 · Status: zur Freigabe

1. Ziel

Ein öffentliches, modernes Statistikportal für den bei Mine-Hoster gehosteten All-The-Mods-10-Server (ATM10). Vorbild für Inhalt und Anmutung ist craftattack.one/stats (Kennzahlen, „Gerade online“, Top-10-Listen); das Portal geht darüber hinaus mit Spielerprofilen, historischen Diagrammen und ATM10-spezifischen Auswertungen (Mods, FTB Quests, Servergesundheit).

Erfolgskriterien:

  • Spieler sehen ihre echten Werte innerhalb weniger Sekunden (Ereignisse) bzw. ≤ 5 Minuten (Zähler) nach dem Geschehen.
  • Keine erfundenen Daten: Jede angezeigte Kennzahl hat eine dokumentierte, nachprüfbare Quelle.
  • Die Mod verursacht keine messbare Tick-Last; kein Datenverlust bei Neustarts von Gameserver oder Backend.
  • Betrieb per Docker Compose hinter dem vorhandenen Traefik in der DMZ.

2. Verifizierte Ausgangslage

Quelle: server-snapshot/ (vom Betreiber per SFTP bereitgestellt).

Fakt Beleg
Minecraft 1.21.1 DataVersion: 3955 in world/stats/*.json
NeoForge 21.1.x, Java 21 Modliste (*-neoforge-1.21.1-*), MC 1.21.1 setzt Java 21 voraus. Exakte NeoForge-/Java-Version: fehlt im Log-Ausschnitt → wird von der Mod beim Start ermittelt und gemeldet
464 Mod-JARs mod-list.txt
FTB Quests 2101.1.36, FTB Teams 2101.1.11, FTB Chunks, FTB Ranks, FTB Essentials mod-list.txt
Quest-Fortschritt pro Team als SNBT (task_progress, completed, started, claimed_rewards, completion_count) world-ftbquests/*.snbt
Spark 1.10.124 installiert mod-list.txt (wird nicht als API genutzt)
Log enthält Login (UUID + IP), Join/Leave, Advancements/Goals/Challenges im Klartext, „Can't keep up“ latest.log
Server läuft mit ~2,2 GB Heap und hat Lags bis 10 s latest.log (AllTheLeaks, Can't keep up)
Mine-Hoster: SFTP-Vollzugriff, eigene Mods in mods/ möglich Mine-Hoster-Support (SFTP-, Mods-, Modpack-Artikel)
Ausgehendes HTTPS vom Gameserver unbekannt → Hybrid-Design (Push + SFTP-Pull)

Mod-spezifische Zähler, die bereits in Vanilla-Stats auftauchen: apotheosis:world_tiers_activated, lootr:looted_stat, waystones:waystone_activated. Item-/Block-Statistiken enthalten Einträge aus u. a. mekanism, powah, mysticalagriculture, ars_nouveau, irons_spellbooks, modern_industrialization, oritech, create, refinedstorage, draconicevolution, silentgear, occultism, theurgy, xycraft_world, minecolonies.

Nicht installiert (daher keine Integration): Blood Magic, Botania.

Datenschutz: latest.log enthält Spieler-IP-Adressen. server-snapshot/ wird nicht versioniert; Testfixtures aus dem Log werden anonymisiert (IP entfernt).

3. Architektur

 Mine-Hoster (ATM10, NeoForge 1.21.1)                 Eigener Server in der DMZ
 ┌──────────────────────────────┐   HTTPS POST    OPNsense → Traefik → Docker Compose
 │ atmstats (serverseitige Mod) │ ──────────────▶ ┌────────────────────────────────┐
 │  Event-Hooks, Outbox-Journal │  Bearer + HMAC  │ api     Fastify/TS: ingest,    │
 │  async Sender mit Backoff    │                 │         REST, SSE, admin       │
 └──────────────────────────────┘                 │ worker  SFTP-Pull, Snapshots,  │
        ▲ world/stats, world/ftbquests,           │         Retention              │
        │ config/ftbquests, logs                  │ web     Next.js (App Router)   │
        └───────────── SFTP-Pull ◀────────────────│ db      PostgreSQL 16          │
                                                  │ backup  pg_dump täglich        │
                                                  └────────────────────────────────┘

Monorepo:

mod/        NeoForge-Mod (Gradle, Java 21, ModDevGradle)
backend/    api + worker (TypeScript, Fastify, gemeinsamer Code, zwei Entrypoints)
web/        Next.js-Frontend (TypeScript)
shared/     gemeinsame TS-Typen + Zod-Schemas (Ingest-Protokoll, API-DTOs)
deploy/     docker-compose.yml, .env.example, Backup-Skript
tools/      Simulator (sendet realistische Mod-Batches), Fixture-Anonymisierer
docs/       README-Ergänzungen, ARCHITECTURE, DATA-SOURCES, OPERATIONS

3.1 Datenquellen und Zuständigkeit

Daten Primärquelle Fallback
Online-Status, Sessions Mod: Login/Logout-Events SFTP: Log-Parser (joined/left the game, UUID of player)
Gesamtzähler (Stats) SFTP: world/stats/<uuid>.json (maßgeblich, absolut) —
Zähler zwischen Speicherungen Mod: 5-min-Snapshot der Live-ServerStatsCounter online Spieler (absolute Werte) —
Tode (Ursache, Killer, Dimension, Position grob) Mod: LivingDeathEvent Log: nicht verlässlich (Death-Messages lokalisiert/mod-abhängig) → nur Zähler aus Stats
Spieler-/Boss-Kills mit Waffe/Dimension Mod: LivingDeathEvent mit Spieler als Quelle Stats minecraft:killed (nur Zähler)
Advancements Mod: AdvancementEvent.AdvancementEarnEvent Log-Parser (has made the advancement/reached the goal/completed the challenge)
Dimensionswechsel Mod: PlayerChangedDimensionEvent —
FTB-Quest-Fortschritt Mod liest world/ftbquests/*.snbt (eigener Thread, nur bei Änderung) SFTP: dieselben Dateien
Quest-Definitionen (Kapitel, Titel) Mod liest config/ftbquests/quests/** beim Start SFTP
Teams SNBT-Dateien von FTB Teams/Quests (world/ftbteams/ wird beim Bau verifiziert) SFTP
Versionen, Modliste Mod: ModList, SharedConstants, System.getProperty("java.version") beim Start Log-Header (falls vorhanden)
Servergesundheit (MSPT/TPS, Spieler, geladene Chunks, Heap) Mod: eigene Messung über ServerTickEvent.Pre/Post, 60-s-Aggregat Log: „Can't keep up“-Zählung

Konfliktregel für Zähler: Werte sind absolut (nicht Deltas). stat_current übernimmt pro Schlüssel den Wert mit dem neuesten Beobachtungszeitpunkt; ein kleinerer Wert ersetzt einen größeren nur, wenn er aus einer neueren Stats-Datei stammt (z. B. nach Admin-Reset). Damit sind wiederholte und verspätete Lieferungen unschädlich.

Quest-Texte: Titel können als Übersetzungsschlüssel vorliegen (ftbquestslangsplitter ist installiert). Die Mod liest zusätzlich config/ftbquests/quests/lang/en_us.snbt bzw. die Lang-Dateien, falls vorhanden; sonst wird die Quest-ID angezeigt. Exakte Pfade werden in der Umsetzung anhand einer Kopie von config/ftbquests/ verifiziert, bevor der Parser fest verdrahtet wird.

3.2 Bewusst nicht unterstützt

Ohne verlässliche, dokumentierte serverseitige Quelle oder nur mit ungeprüften Mod-Interna erreichbar; wird im Portal unter „Datenquellen“ transparent ausgewiesen:

  • Energieproduktion/-verbrauch von Maschinen (Mekanism, Powah …)
  • Inhalte von AE2-/Refined-Storage-Netzwerken
  • Mana, Zauber, Source (Ars Nouveau, Iron's Spellbooks), Occultism-Rituale
  • MineColonies-Kolonien
  • exakte Spielerposition/Heatmaps (Datenschutz + Last)

Spätere Erweiterung ist über das Ereignisprotokoll möglich (neue Event-Typen), jeweils erst nach Prüfung der jeweiligen Mod-API gegen die installierte Version.

4. Mod atmstats

  • NeoForge 21.1.x (Build gegen die zur ATM10-Version passende Version), Java 21, ModDevGradle. Mod-ID atmstats.
  • Rein serverseitig: displayTest = "IGNORE_ALL_VERSION" in neoforge.mods.toml; Clients brauchen die Mod nicht. Keine Registrierungen (Blöcke, Items, Netzwerkpakete).
  • Keine Compile-Abhängigkeit auf andere Mods.

4.1 Threading und Last

  • Event-Handler auf dem Server-Thread erzeugen nur kleine, unveränderliche Event-Objekte und legen sie in eine ConcurrentLinkedQueue (O(1), keine I/O, keine Serialisierung).
  • Stats-Snapshot alle 5 min (konfigurierbar): auf dem Server-Thread werden je online Spieler die Zählerwerte in ein Object2IntMap kopiert; Serialisierung und Versand erfolgen im Mod-eigenen Daemon-Thread. Der Snapshot wird über mehrere Ticks verteilt, falls viele Spieler online sind (max. 2 Spieler/Tick).
  • Ein einzelner Daemon-Worker-Thread: Queue → Journal → Sender. SNBT-Dateilesen ebenfalls dort (nur bei geänderter mtime, alle 2 min).
  • Tick-Messung: System.nanoTime() in Pre/Post, Aggregat (avg/p95/max MSPT) im Ringpuffer, Versand einmal pro Minute.

4.2 Zuverlässigkeit

  • Event-ID: UUIDv7 (zeitlich sortierbar), erzeugt beim Entstehen des Events.
  • Outbox-Journal: <server>/atmstats/outbox/ als Segmentdateien (JSON Lines, fsync beim Rotieren, max. 1 MB/Segment). Ein Segment wird erst gelöscht, wenn das Backend alle IDs bestätigt hat.
  • Begrenzung: max. 50 MB bzw. 7 Tage; bei Überschreitung werden die ältesten Stats-Snapshots zuerst verworfen (sind durch spätere ersetzbar), Ereignisse zuletzt; Verwerfen wird geloggt.
  • Beim Serverstopp (ServerStoppingEvent): Queue synchron ins Journal flushen (Zeitlimit 2 s), Session-Ende für alle online Spieler erzeugen.
  • Beim Start: Journal-Segmente werden erneut gesendet; ein server_start-Event ermöglicht dem Backend, offene Sessions eines Absturzes zu schließen.
  • Versand: java.net.http.HttpClient (HTTP/2, TLS-Verifikation an), Batches bis 500 Events/256 KB, gzip, Timeout 10 s. Backoff exponentiell 1 s → 5 min mit Jitter. Bei 4xx (außer 408/429) wird der Batch nicht endlos wiederholt, sondern in outbox/rejected/ abgelegt und geloggt.
  • Startup-Selbsttest: GET /api/ingest/ping → Ergebnis ins Log („atmstats: backend reachable / NOT reachable: “). Damit wird die offene Frage „ausgehendes HTTPS erlaubt?“ beim ersten Start beantwortet.

4.3 Konfiguration (config/atmstats-server.toml, NeoForge ModConfigSpec)

enabled, endpoint, serverId, token, hmacSecret, statsSnapshotMinutes (5), questScanMinutes (2), healthIntervalSeconds (60), maxOutboxMb (50). Ohne Token bleibt die Mod passiv (nur Log-Hinweis).

4.4 Protokoll (Version 1)

POST /api/ingest
Authorization: Bearer <token>
X-ATM-Server: <serverId>
X-ATM-Timestamp: <unix ms>
X-ATM-Signature: hex(HMAC-SHA256(secret, timestamp + "." + sha256(body)))
Content-Encoding: gzip
{ "protocol": 1, "events": [ { "id": "<uuidv7>", "type": "...", "ts": <ms>, ...payload } ] }
→ 200 { "accepted": ["<id>", ...], "duplicate": ["<id>", ...], "rejected": [{ "id", "reason" }] }

Event-Typen: server_start (Versionen, Modliste), server_stop, player_join, player_leave, player_death, entity_kill, advancement, dimension_change, stats_snapshot (absolute Werte je Kategorie), quest_progress (Team-ID, abgeschlossene Quest-IDs mit Zeitstempel, Task-Fortschritt-Zähler), quest_defs (Kapitel/Quests/Titel, nur bei Änderung, mit Hash), team_info, health. Schemas als Zod in shared/ und als JSON-Schema-Testfixtures, gegen die auch die Java-Serialisierung getestet wird.

5. Backend

TypeScript, Node 22 LTS, Fastify, Zod, pg mit SQL (kein ORM), Migrationen mit node-pg-migrate. Zwei Prozesse aus einer Codebasis:

api

  • GET /api/ingest/ping (authentifiziert), POST /api/ingest. Prüft Token (konstante Zeit), Zeitfenster ±5 min, HMAC; Rate-Limit; Body-Limit 2 MB entpackt. Verarbeitung pro Batch in einer Transaktion: INSERT INTO events … ON CONFLICT (event_id) DO NOTHING, nur neu eingefügte Events werden projiziert (sessions, deaths, stat_current …). Danach Benachrichtigung via pg_notify('atm_live', …).
  • Öffentlich: GET /api/overview, /api/online, /api/leaderboards (Liste der Boards), /api/leaderboards/:board?period=all|30d|7d, /api/players?search=, /api/players/:uuid, /api/players/:uuid/history?metric=&range=, /api/players/:uuid/items?mod=, /api/mods (Modliste + Aktivität je Mod), /api/quests (Kapitelfortschritt), /api/server (Versionen, Health-Verlauf), /api/sources (Datenquellen-Status: letzter Push, letzter SFTP-Sync), /api/avatar/:uuid (Proxy-Cache für Spielerköpfe, 24 h; keine Besucher-IPs an Dritte).
  • GET /api/live (SSE): abonniert LISTEN atm_live; Events online, death, advancement, quest, counters; Heartbeat 25 s, Last-Event-ID-Resume aus einem In-Memory-Ringpuffer (500 Einträge).
  • Admin (/api/admin/*): Login mit Benutzer/Passwort (argon2id), Session-Cookie (httpOnly, Secure, SameSite=Strict), CSRF-Token im Header, Login-Rate-Limit. Funktionen: Status Mod/SFTP, letzte Fehler, manueller Sync, Spieler ausblenden/einblenden, Ingest-Token rotieren (Anzeige einmalig). Erster Admin wird per CLI (npm run admin:create) angelegt.
  • Ausgeblendete Spieler erscheinen in keiner öffentlichen Antwort.
  • Sicherheitsheader (über Fastify-Helmet), CORS nur eigene Domain.

worker

  • SFTP-Pull (ssh2-sftp-client) alle 15 min (konfigurierbar): Verzeichnislisten von world/stats, world/advancements, world/ftbquests, config/ftbquests/quests, logs/latest.log. Herunterladen nur bei geänderter Größe/mtime (Zustand in sync_state); Log inkrementell ab Byte-Offset, Rotation erkannt über kleineren Größenwert. Ergebnisse durchlaufen dieselben Projektionen wie Ingest (synthetische, deterministische Event-IDs aus Datei+Inhalt-Hash → idempotent).
  • Advancements-Dateien (world/advancements/<uuid>.json) liefern die vollständige Liste erreichter Advancements inkl. Zeitpunkten.
  • Snapshot-Job: stündlich stat_snapshots (Auswahl relevanter Metriken je Spieler), täglich um 00:05 Tageswerte; Retention: stündlich 30 Tage, täglich unbegrenzt; server_health Minutenwerte 14 Tage, danach Stundenaggregate.
  • Sitzungsbereinigung: offene Sessions ohne Lebenszeichen > 10 min nach server_start werden mit letztem bekannten Zeitpunkt geschlossen.
  • Job-Locking über pg_try_advisory_lock, damit Jobs nie doppelt laufen.

Der Worker ist optional: ohne SFTP-Zugangsdaten läuft das System nur mit Push. Ohne erreichbaren Push läuft es nur mit Pull (dann Online-Status und Tode mit bis zu 15 min Verzögerung bzw. nur als Zähler).

6. Datenbank

Kern-Tabellen (Details in Migrationen):

  • players(uuid PK, name, first_seen, last_seen, hidden bool)
  • name_history(uuid, name, seen_at)
  • teams(team_id PK, name, type), team_members(team_id, uuid)
  • events(event_id PK, server_id, type, ts, received_at, source 'push'|'sftp', payload jsonb)
  • sessions(id, uuid, started_at, ended_at, end_reason)
  • stat_current(uuid, category, key, value bigint, observed_at, source, PK(uuid, category, key))
  • stat_snapshots(uuid, metric, bucket timestamptz, granularity 'hour'|'day', value bigint)
  • deaths(event_id, uuid, ts, dimension, cause, killer_type, killer_name)
  • kills(event_id, uuid, ts, dimension, victim_type, is_boss, weapon)
  • advancements(uuid, advancement_id, achieved_at, title, PK(uuid, advancement_id))
  • quest_defs(quest_id PK, chapter_id, chapter_title, title, def_hash)
  • quest_progress(team_id, quest_id, completed_at, PK(team_id, quest_id))
  • server_info(id, started_at, mc_version, neoforge_version, java_version, mods jsonb)
  • server_health(bucket, mspt_avg, mspt_p95, mspt_max, tps, players, chunks, heap_used_mb, heap_max_mb)
  • sync_state(path PK, size, mtime, offset, hash, synced_at)
  • admin_users, admin_sessions, ingest_tokens(id, hash, created_at, revoked_at)

Ranglisten werden aus stat_current mit Indizes auf (category, key, value DESC) berechnet. Abgeleitete Metriken (z. B. Gesamtstrecke = Summe aller *_one_cm, Items je Mod = Summe nach Namespace) liegen als SQL-Views vor. Eine Materialized View leaderboard_cache wird höchstens alle 60 s REFRESH … CONCURRENTLY aktualisiert.

7. Ranglisten (Start-Set, alle aus belegten Quellen)

Board Metrik
Dauerzocker minecraft:custom/minecraft:play_time (Ticks → h)
Friedhof minecraft:custom/minecraft:deaths
Monsterjäger minecraft:custom/minecraft:mob_kills
Abrissbirne Summe minecraft:mined/*
Weltenbummler Summe minecraft:custom/*_one_cm (→ km)
Flieger minecraft:custom/minecraft:fly_one_cm
Diamantenbank minecraft:mined/minecraft:diamond_ore + deepslate_diamond_ore (Abbau, nicht Besitz – so ausgewiesen)
Techniker Summe crafted+used in Tech-Namespaces (mekanism, mekanismgenerators, powah, modern_industrialization, oritech, create, immersiveengineering, appliedenergistics2, refinedstorage, draconicevolution, integrateddynamics, pneumaticcraft)
Magier dito Magie-Namespaces (ars_nouveau, ars_elemental, ars_additions, irons_spellbooks, occultism, theurgy, rootsclassic, forbidden_arcanus, evilcraft, reliquary)
Farmer dito (mysticalagriculture, mysticalagradditions, productivebees, botanypots, pamhc2*, farmersdelight, herbsandharvest)
Questmeister Anzahl abgeschlossener Quests des Teams (Teamleaderboard + Spieler über Mitgliedschaft)
Abenteurer Anzahl Advancements
Schatzjäger lootr:looted_stat
Weltenstufe apotheosis:world_tiers_activated

Die Namespace-Kategorien liegen in einer editierbaren Konfigurationsdatei (backend/config/mod-categories.json) und werden mit der echten Modliste abgeglichen; Namespaces ohne installierte Mod werden ignoriert und geloggt.

8. Frontend

Next.js (App Router), TypeScript, Tailwind CSS, Recharts. Dunkles, eigenständiges Gaming-Design (kein Nachbau von craftattack-Assets), responsiv, zugänglich (Kontrast, Tastatur, prefers-reduced-motion). Server-Rendering mit kurzer Revalidierung; Live-Teile clientseitig per SSE.

Seiten:

  • / Übersicht: Kennzahlen (Online, Spielstunden gesamt, Tode, Quests, Advancements), „Gerade online“, Live-Ticker, Top-10-Karten.
  • /leaderboards und /leaderboards/[board] (Zeitraum all/30d/7d aus Snapshots).
  • /players (Suche) und /players/[name]: Kopf, Spielzeit, Sessions-Heatmap (Wochentag × Stunde), Verlaufsdiagramme, Bewegung nach Art, Kampf (Kills nach Mob, Todesursachen), Items nach Mod (Tabs mined/crafted/used/picked_up), Advancements, Team-Quests, Rangpositionen.
  • /atm10: Aktivität je Mod/Kategorie, Quest-Kapitelfortschritt, meistgenutzte Mods.
  • /server: Versionen (MC, NeoForge, Java, ATM10-Modliste mit Suche), TPS/MSPT-, Spieler- und Heap-Verlauf.
  • /sources: Datenquellen, Aktualität, Einschränkungen (aus DATA-SOURCES).
  • /admin: Login, Status, Sync, Spieler ausblenden, Token-Rotation.

9. Deployment und Betrieb

  • deploy/docker-compose.yml: db (postgres:16-alpine, Volume), api, worker, web, backup. Nur web und api hängen am externen Traefik-Netz (TRAEFIK_NETWORK); db nur im internen Netz.
  • Traefik-Labels: Router Host(${DOMAIN}) && PathPrefix(/api) → api, Host(${DOMAIN}) → web; Entrypoint/Cert-Resolver per .env. Optionale Middleware ipAllowList für /api/ingest (INGEST_ALLOWED_IPS).
  • OPNsense: eingehend 443 → Traefik (bereits vorhanden); für den Pull-Fallback ausgehend DMZ-Host → Mine-Hoster-SFTP-Host/-Port.
  • Healthchecks für alle Container; api und worker warten auf DB und führen Migrationen beim Start aus (Advisory-Lock).
  • Backup: täglicher pg_dump -Fc mit 14-Tage-Rotation in ein Volume; Restore-Anleitung in OPERATIONS.md.
  • Logs strukturiert (pino, JSON), keine Tokens/IPs im Log.

10. Tests

  • Mod (JUnit 5, ohne Minecraft-Laufzeit): Journal (Schreiben, Rotation, Recovery nach abgeschnittener letzter Zeile), Backoff, Batch-Bildung, HMAC, JSON gegen Schema-Fixtures, SNBT-Parser an den echten Quest-Dateien. Minecraft-abhängiger Code ist dünn und von der Logik getrennt. Zusätzlich manueller Testlauf auf einem lokalen NeoForge-Server (runServer).
  • Backend (Vitest + Postgres im Compose-Testprofil): Ingest-Auth (falsches Token, abgelaufener Zeitstempel, falsche Signatur), Idempotenz (gleicher Batch doppelt), Projektionen, Stats-Parser an echten world/stats-Dateien, Log-Parser an anonymisiertem Log, Ranglisten-SQL, SSE.
  • Frontend: Komponententests (Vitest + Testing Library) und Playwright-Smoke-Test gegen den Compose-Stack mit Simulator-Daten.
  • Simulator (tools/simulator): erzeugt signierte Batches im echten Protokoll.

11. Dokumentation

README.md (Überblick, Schnellstart), docs/ARCHITECTURE.md, docs/DATA-SOURCES.md (jede Kennzahl → Quelle, Aktualität, Einschränkungen), docs/OPERATIONS.md (Deployment Traefik/OPNsense, Mod-Installation per Mine-Hoster-SFTP, Konfiguration, Token-Rotation, Backup/Restore, Neustartverhalten, Fehlerbilder), mod/README.md.

12. Offene Punkte, die in der Umsetzung geklärt werden

  1. Exakte NeoForge-Version des Servers → Mod-Build gegen 21.1.x; Kompatibilität innerhalb 21.1 ist gegeben, finale Version per Startup-Log bestätigen.
  2. Ausgehendes HTTPS bei Mine-Hoster → Selbsttest beim ersten Start.
  3. Struktur von config/ftbquests/quests/ und world/ftbteams/ → Betreiber stellt Kopie bereit, bevor Quest-Titel/Team-Namen-Parser finalisiert werden; bis dahin werden Quest-IDs angezeigt. → Geklärt am 13.10.2026 anhand der echten Dateien, siehe docs/DATA-SOURCES.md.
  4. SFTP-Host/Port/Benutzer → .env des Betreibers (nicht im Repo).