Zum Hauptinhalt springen

EternalTD-Level & Karten

Ein "Level" in EternalTD ist eine YAML-Konfiguration in plugins/EternalTD/levels/, gepaart mit einem Vorlagen-Weltordner in plugins/EternalTD/worlds/. Wenn ein Spieler beitritt, klont EternalTD die Vorlagenwelt in den Server-Weltcontainer und führt die Sitzung in dieser geklonten Kopie aus.

Felder der Level-Konfiguration

FeldTypStandardHinweise
isEnabledbooltrueDeaktivierte Level werden beim Laden übersprungen
levelNamestringnullAnzeigename, der in Nachrichten, Scoreboards und NPC-Menüs angezeigt wird
levelDescriptionstring list[]Zeilen, die in NPC-Menüs angezeigt werden. Unterstützt die Platzhalter $highscoreWave und $highscorePlayer
worldNamestringnullDer Name des Vorlagenordners unter plugins/EternalTD/worlds/
startLocationstring listnullListe serialisierter Positionen, an denen Mobs spawnen
endLocationstring listnullListe serialisierter Positionen, zu denen die Mobs laufen (die "roten" Felder)
levelLocationsstring listnullJedes begehbare Rasterfeld im Level, automatisch generiert, wenn du eine Bodenauswahl registrierst
wavesConfigFilestringerforderlichDateiname der verknüpften Wellenkonfiguration (waves/<name>.yml)
waveCountint-1Zwischengespeicherte Wellenanzahl, derzeit nur informativ
highscoreWaveint0Beste erreichte Welle in diesem Level
highscorePlayerNamestring"no one"Anzeigename des Spielers, der den Punktestand aufgestellt hat
environmentenumNORMALWeltumgebung, die beim Laden der geklonten Welt verwendet wird

Die durchgängig verwendete Rastergröße beträgt 3 Blöcke pro logischem Feld (Konstante GRID_SIZE im Code).

Format der Positions-Strings

Positionen in EternalTD werden als kommagetrennte Strings in folgender Form serialisiert:

worldName,x,y,z,yaw,pitch

Normalerweise schreibst du diese nicht von Hand — /etd selectfloor zusammen mit den Register-Befehlen berechnet und speichert sie für dich.

Welt-Lebenszyklus

Wenn ein Spieler einem Level beitritt:

  1. EternalTD sucht den Vorlagenordner anhand von worldName in plugins/EternalTD/worlds/.
  2. Es wählt das nächste freie numerische Suffix (<worldName>_0, <worldName>_1, ...) und schreibt den Klon in den Server-Weltcontainer, wobei zuvor veraltete Kopien im Legacy- oder modernen Layout bereinigt werden.
  3. Die geklonte Welt wird über MagmaCores TemporaryWorldManager als temporäre Void-Welt geladen, sodass die Migration unter Paper 26.1+ in Quarantäne gehalten wird.
  4. Der Spieler wird in die neue Welt teleportiert; ein interner InstanceProtector wendet die Schutzregeln von EternalTD an.

Wenn die Sitzung endet:

  • Alle verbleibenden Spieler in der geklonten Welt werden zur Spawn-Position aus config.yml zurückteleportiert oder gekickt, wenn kein Spawn konfiguriert ist.
  • Die geklonte Welt wird entladen und von der Festplatte gelöscht (TemporaryWorldManager.permanentlyDeleteWorld).

Instanz-Schutzregeln

Während ein Level aktiv ist, gelten für die geklonte Welt diese Regeln:

  • Explosionen deaktiviert
  • Flüssigkeitsfluss deaktiviert
  • Elytra deaktiviert
  • Umschalten des Flugmodus verhindert
  • Friendly Fire verhindert
  • Vanilla-Mob-Spawning verhindert

Workflow zur Kartenerstellung

Der aktuelle Ablauf zur Kartenerstellung nutzt die spielinternen Werkzeuge:

  1. Lege einen Vorlagen-Weltordner unter plugins/EternalTD/worlds/<worldName>/ ab.
  2. Erstelle oder lade eine passende Level-YAML in plugins/EternalTD/levels/.
  3. Führe /etd reload aus und tritt der Level-Welt manuell bei (oder öffne sie im Einzelspielermodus zur Einrichtung).
  4. Verwende /etd selectfloor und klicke mit Rechts-/Linksklick zwei Ecken an, um den Spielbereich zu markieren, oder verwende /etd selectfloorcoordinates <x1> <y1> <z1> <x2> <y2> <z2>, um sie direkt anzugeben.
  5. Führe /etd showselection <level> aus, um zu bestätigen, dass die Auswahl korrekt aussieht.
  6. Führe /etd register <level> aus, um die Auswahl zu löschen. Beachte, dass im aktuellen Build weder register noch showselection den Bodenbereich tatsächlich speichern — der Helfer, der levelLocations speichern würde (LevelsConfigFields#addLevelLocations), ist zwar definiert, wird aber von keinem Befehl aufgerufen. Du musst levelLocations derzeit von Hand in die Level-YAML schreiben, falls es nicht bereits durch ein heruntergeladenes Paket befüllt ist.
  7. Stelle dich auf ein Start-Spawnfeld und führe /etd register <level> start aus. Wiederhole dies für jedes Startfeld (dieser Befehl speichert tatsächlich in startLocation).
  8. Stelle dich auf ein Endfeld und führe /etd register <level> end aus. Wiederhole dies für jedes Endfeld (dieser Befehl speichert tatsächlich in endLocation).
  9. Lade erneut neu und teste das Level, indem du ihm über das NPC-Menü oder /etd join <level> beitrittst.

Die Auswahlbefehle generieren Rasterfelder mithilfe folgender Formel:

size = abs(corner1 - corner2 + 1) / 3

Felder, deren oberster Block Luft ist (oder deren Bodenblock durchlässig ist), werden übersprungen, sodass Bodenblöcke solide sein müssen, damit ein Feld als bespielbar registriert wird.

Pfadvalidierung

EternalTD führt bei jeder Platzierung eines Turms eine A*-Wegfindungsprüfung durch. Wenn das Platzieren des Turms dazu führen würde, dass ein Startfeld keinen begehbaren Pfad zu einem Endfeld mehr hat, wird die Platzierung abgelehnt und das Gold nicht ausgegeben.

Luft-Gegner verwenden einen separaten Pfad, der Türme vollständig ignoriert und stattdessen dem Luftoffset folgt (4 Blöcke über dem konfigurierten Pfad).

NPCs und Level-Menüs

NPC-Konfigurationen in plugins/EternalTD/npcs/ verknüpfen Dorfbewohner-NPCs mit einem oder mehreren Levels. Ein Rechtsklick auf den NPC öffnet ein Inventar mit 9 Slots, in dem jedes Level als grün gefärbte Glasscheibe mit dem Level-Namen und der Beschreibung aufgeführt ist.

FeldTypStandardHinweise
isEnabledbooltrueDeaktivierte NPCs werden übersprungen
levelIDsstring listerforderlichDateinamen der Levels, die dieser NPC anbietet
locationstringnullSpawn-Position im Standardformat worldName,x,y,z,yaw,pitch
namestring"Default Name"NPC-Anzeigename
difficultystring"Difficulty: Not Set"Schwierigkeitslabel, das über dem NPC angezeigt wird
disguisestringnullLibsDisguises-Deskriptor (z. B. custom:etd_tutorial_npc)
customDisguiseDatastringnullZusätzliche LibsDisguises-Befehlsdaten — meist der lange Spieler-Skin-String

Der Dorfbewohner wird unverwundbar, mit deaktivierter KI, persistent und mit dem namensraumbasierten NPC-Schlüssel von EternalTD getaggt gespawnt. Wenn LibsDisguises installiert ist und sowohl disguise als auch customDisguiseData gesetzt sind, wird der Dorfbewohner beim Spawnen verkleidet.

Ein schwebender Rüstungsständer mit dem difficulty-Label wird 2,3 Blöcke über dem NPC gespawnt.

Spawn-Verhalten

DefaultConfig steuert, wie Spieler in der Hub-Welt verwaltet werden:

  • setupDone — Flag, das verfolgt, ob die Ersteinrichtungs-Anleitung abgeschlossen wurde (Standard false).
  • spawnLocations — Standard ist etd_spawn,0,65,0,0,0. Wird nur verwendet, wenn die Welt etd_spawn existiert.
  • manageSpawn — Standard ist true. Wenn aktiviert, werden beitretende Spieler 1 Tick nach dem Login zur Spawn-Position teleportiert.
  • playerGuide — der Text des spielinternen Anleitungsbuchs.
  • nightbreak.autoDownloadPluginUpdates — gemeinsame MagmaCore-Einstellung (Standard false). Wenn aktiviert, werden Plugin- und Inhalts-Updates beim Start automatisch heruntergeladen.

Wenn manageSpawn auf true gesetzt und die Spawn-Welt geladen ist, wird jeder Spieler, der dem Server beitritt, zu spawnLocations teleportiert.