Skip to content

Modding Workflow

ElGregor edited this page Aug 15, 2026 · 1 revision

Modding-Workflow — Mods pflegen, von der YAML bis zum Restart

Home

Der prozedurale Ablauf rund um die Mod-Liste: eine Mod sauber hinzufügen, verstehen, wie Load-Order und Generator zusammenarbeiten, typische Fehler vermeiden und eigene Mods im servermods/-Format anlegen. Die reine Feld-Referenz von mods.yaml und alle Mods des Repos stehen auf Mods-Referenz.

Vertieft in Repo: docs/04-modding-workflow.md

Best Practice: Mod hinzufügen

Die komplette Schrittfolge von der Workshop-Seite bis zur Verifikation (Grundgerüst Repo-Default aus docs/04, um Render-/Restart- und Log-Schritte erweitert):

  1. Workshop-Seite öffnen und die workshop_id aus der URL kopieren (...filedetails/?id=<Zahl>).

  2. mod_id heraussuchen — aus der Workshop-Beschreibung oder der mod.info der Mod. Beide IDs notieren; sie sind grundverschieden (Zahl = Download, Text = Laden).

  3. mods.yaml pflegen: neuen Eintrag anlegen, Kategorie wählen (siehe unten), enabled: true, bei Karten zusätzlich map_name: mit dem internen Map-Ordnernamen, bei Abhängigkeiten requires:. B42-Mods only — B41-Mods sind inkompatibel (Repo-Regel aus mods.yaml-Kopf).

  4. Generieren und validieren:

    make mods      # mods-validate.sh && mods-generate.sh (Repo-Default)

    Bei Validierungsfehlern bricht das Target vor der Generierung ab (Exit 1, Repo-Default aus dem Makefile).

  5. Manuell in die Ini übernehmen und dann rendern/restarten: die WorkshopItems=/Mods=/Map=-Zeilen aus config/generated/workshop-items.txt per Hand in ${PZ_DATA_DIR}/Server/servertest.ini kopieren (mit dem Repo-Default SERVER_NAME=servertest; siehe Architektur „Datenfluss (a)") — erst danach rendern und restarten, weil make render allein die drei Zeilen nicht in die Ini schreibt (Repo-Stand, render-config.sh):

    make render && make restart

    Direkt auf dem Server bearbeitet man so; alternativ der Repo-Weg aus docs/04: Commit + Push (CI prüft mit shellcheck + mods-validate mit) und auf dem Server make update.

  6. Im Log verifizieren (make logs): Die Zeile Workshop: Download item <workshop_id> zeigt, dass die Mod gezogen wird; danach darf kein ERROR, keine Exception und kein Lua-Fehler auftauchen (Log-Kriterien Repo-Default aus docs/10). Fehlt die Mod später im Spiel, zuerst die Mods=-Zeile prüfen — siehe Mods-Referenz.

Load-Order: automatisch per Kategorien

Die Ladereihenfolge wird nicht von Hand gepflegt — sie ergibt sich aus der Kategorie jedes Eintrags (Repo-Default, fest im Generator verdrahtet):

library  ->  framework  ->  map  ->  gameplay  ->  qol

Innerhalb einer Kategorie zählt die Eintragsreihenfolge in mods.yaml (Repo-Default).

Warum Frameworks zuerst: Die Eintragsreihenfolge in der Mods=-Zeile ist die Ladereihenfolge; Libraries und Frameworks müssen geladen sein, bevor Content- und QoL-Mods sie nutzen, und bei Konflikten gewinnt die spätere Mod (Community-Quelle: PZ-Community-Doku, dokumentiert in docs/10). Die Kategorie-Sortierung des Generators setzt genau das automatisch um — WorkshopItems=-Reihenfolge ist dagegen egal, sie steuert nur den Download (Repo-Default).

requires: deklariert Abhängigkeiten als Liste von mod_ids. Der Validator prüft beim make mods-Lauf, dass jede Abhängigkeit einer aktiven Mod existiert — sonst ERROR und Abbruch (Repo-Default aus mods-validate.sh). Das ersetzt kein Nachdenken: Eine Mod, die eine deaktivierte Framework benötigt, läuft nicht, nur weil der Eintrag noch in der YAML steht.

Was der Generator automatisch erledigt

scripts/mods-generate.sh (Repo-Default, 1:1 aus dem Skript):

  • Filter: nur Einträge mit enabled: true werden berücksichtigt (mods = [m for m in data.get("mods", []) if m.get("enabled")]).
  • Sortierung: aktive Mods werden nach der festen Kategorie-Reihenfolge library, framework, map, gameplay, qol sortiert (mods.sort(key=lambda m: ORDER.index(...))).
  • B42-Backslash-Pflicht: Build 42 verlangt einen Backslash vor jeder Mod-ID in der Mods=-Zeile. Der Generator baut die Zeile als "\\" + mod_id pro Eintrag — heraus kommt Mods=\damnlib;\NeatUI_Framework;....
  • Map=-Zeile inkl. Muldraugh-zuletzt-Regel: alle aktiven Karten-Mods mit map_name werden semikolongetrennt gesammelt, und "Muldraugh, KY" (Vanilla-Basismap) wird automatisch immer ans Ende gehängt (map_line = ";".join(maps + ["Muldraugh, KY"])) — frühere Maps gewinnen bei Überlappung, deshalb muss Vanilla zuletzt (Community-Quelle: Repo-Changelog 0.3.0; Regeln detailliert auf Mods-Referenz).
  • Ausgabe: alles landet in config/generated/workshop-items.txt (drei Zeilen: WorkshopItems=, Mods=, Map=). Die Übernahme in die Server-ini ist manuell (siehe Schritt 5 oben und Architektur „Datenfluss (a)") — make render rendert nur die envsubst-Templates und schreibt diese drei Zeilen nicht in die servertest.ini (Repo-Stand, scripts/render-config.sh + servertest.ini.tmpl).

Häufige Fehler

Die ersten fünf Zeilen sind Repo-Default aus docs/04, die letzten drei Zeilen sind Ergänzungen mit jeweiligem Quellen-Label:

Symptom Ursache Fix
Mod lädt nicht workshop_id != mod_id verwechselt beide Felder prüfen
Server startet nicht fehlende Abhängigkeit make validate
Version mismatch Client/Server-Build oder Mod-Version differieren Steam-Dateien prüfen, Mod-Update
Doppelte Items zwei Overhaul-Mods gleichzeitig (z. B. Brita's + Firearms) nur einen aktivieren
Mod „not found" im Log workshop_id fehlt in WorkshopItems= make mods neu generieren
Mod still inaktiv trotz Download Eintrag fehlt in Mods= — Download ohne Mods=-Eintrag lädt nie (Community-Quelle: PZ-Community-Doku; häufigster Fehler laut docs/10) generierte Mods=-Zeile prüfen
Karte lädt, Spawns fehlen map_name/folder nur geraten statt verifiziert (Heuristik — vor Aktivierung Ordner-Verifikation, siehe Fix) Ordner per ls verifizieren (Anleitung: Spawn-System)
Validierung warnt bei Platzhalter-ID workshop_id im TODO-Bereich 3600000000–3600000099 — erzeugt nur eine WARNung, keinen Abbruch (Repo-Default aus mods-validate.sh) echte ID von der Steam-Seite eintragen

Eigene Mods entwickeln

Eigene Mods leben im Repo unter servermods/ im Workshop-Format. Alles in diesem Abschnitt: Repo-Default, 1:1 aus servermods/README.md.

Ordnerstruktur (Build 42)

servermods/mein-mod/
├── mod.info                 # name, id, description, author
├── poster.png               # 256x256 Vorschaubild
└── Contents/mods/mein-mod/
    ├── 42/                  # Build-42-spezifisch
    │   └── media/
    │       ├── scripts/     # Items/Rezepte (.txt)
    │       └── lua/
    │           ├── shared/  # Client+Server
    │           ├── client/  # UI, Kontextmenues
    │           └── server/  # autoritative Logik
    └── common/              # build-uebergreifend (optional)

Regeln

  1. mod_id in mod.info muss eindeutig sein → in mods.yaml eintragen.
  2. Client-Code darf niemals Server-Dateien per require laden (und umgekehrt).
  3. Bestehende Funktionen hooken statt überschreiben (Konfliktvermeidung).
  4. Lokaler Test: Ordner nach ~/Zomboid/mods/ kopieren, im Spiel aktivieren.

Minimal-Beispiel mod.info

name=Mein Mod
id=MeinMod
description=Erster eigener Mod
author=Du

Lua-Einstieg

local function onGameStart() print("MeinMod geladen") end
Events.OnGameStart.Add(onGameStart)

Für Feldbedeutungen, die komplette Mod-Liste des Repos und die generierten ini-Zeilen siehe Mods-Referenz.


Weiter: Mods-Referenz · Spawn-System · Performance-Guide

Clone this wiki locally