Zum Hauptinhalt springen

Lua-Skripting: Fehlerbehebung

Diese Seite behandelt häufige Probleme, die beim Schreiben oder Debuggen von FreeMinecraftModels-Prop-Skripten auftreten können, sowie Tipps für die Arbeit mit dem System der verzögerten Konfigurationserzeugung. Wenn du nach funktionierenden Beispielen suchst, siehe Beispiele & Muster. Wenn du gerade erst anfängst, siehe Erste Schritte.


Häufige Probleme

1. Konfigurationsdatei wird nicht geladen / Skript nicht angehängt

Symptom: Der Prop spawnt, reagiert aber nicht auf Klicks oder andere Hooks.

Ursachen und Lösungen:

  • Keine .yml-Konfigurationsdatei existiert noch. FMM erzeugt die Konfiguration verzögert beim ersten Prop-Spawn. Beim ersten Mal, wenn ein Modell gespawnt wird, erstellt FMM die .yml-Konfiguration asynchron mit Standardwerten (aktiviert, keine Skripte). Du musst die generierte Konfiguration bearbeiten, um deine Skriptdateinamen hinzuzufügen, und dann den Prop erneut spawnen.

  • Die Konfiguration hat isEnabled: false. Öffne die .yml-Datei neben der Modelldatei und setze isEnabled: true.

  • Die scripts:-Liste ist leer. Füge deine Skriptdateinamen hinzu:

    isEnabled: true
    scripts:
    - my_script.lua
  • Der .yml-Dateiname stimmt nicht mit dem Modelldateinamen überein. Die Konfiguration muss denselben Basisnamen wie die Modelldatei haben. Zum Beispiel braucht torch_01.fmmodel eine torch_01.yml im selben Verzeichnis.


2. Skriptdatei nicht gefunden

Symptom: Konsole zeigt: [FMM Scripts] Script 'my_script.lua' not found in scripts/ folder

Ursachen und Lösungen:

  • Falsches Verzeichnis. Skriptdateien müssen in plugins/FreeMinecraftModels/scripts/ sein, nicht neben der Modelldatei.

  • Dateinamen-Abweichung. Der Name in der .yml-Konfiguration muss exakt mit dem Dateinamen im scripts/-Ordner übereinstimmen, einschließlich Groß-/Kleinschreibung und der .lua-Endung.

  • Datei nicht vorhanden. Überprüfe nochmals, ob die .lua-Datei tatsächlich im scripts/-Ordner existiert.


3. Skript wird überhaupt nicht geladen

Symptom: Kein Konsolenfehler, aber keine Hooks feuern.

Überprüfe die Serverkonsole auf Lua-Syntaxfehler beim Start. Die häufigsten Ursachen sind:

  • Fehlendes end zum Schließen einer Funktion oder eines if-Blocks
  • Nicht übereinstimmende Klammern
  • Fehlendes Komma zwischen Hook-Definitionen in der zurückgegebenen Tabelle
  • Datei endet nicht mit .lua

Wenn ein Lua-Fehler vorliegt, gibt die Konsole einen [Lua]-Fehlerblock mit Dateiname, Zeilennummer und einer Beschreibung aus.


4. Hook wird nie ausgelöst

Symptom: Das Skript wird geladen (du siehst die [FMM Scripts] Bound script-Nachricht), aber ein bestimmter Hook wird nie ausgelöst.

Überprüfe, ob der Hook-Name exakt so geschrieben ist wie in der Hook-Referenz aufgeführt. Häufige Fehler:

Falscher NameKorrekter Name
on_clickon_right_click oder on_left_click
on_interacton_right_click
on_hiton_left_click
on_tickon_game_tick
on_removeon_destroy
on_arrow_hiton_projectile_hit

Überprüfe auch, ob der Prop tatsächlich eine darunterliegende Armor-Stand-Entity hat. Einige Prop-Konfigurationen erzeugen möglicherweise keine anklickbare Entity.


5. Timeout / Ausführungsbudget überschritten

Symptom: Konsole zeigt eine Nachricht wie:

[Lua] my_script.lua took 73ms in 'on_game_tick' (limit: 50ms) -- script disabled to prevent lag.

Das Skript hat zu viel Arbeit in einem einzelnen Hook-Aufruf erledigt. Häufige Ursachen:

  • Zu viele Entities in on_game_tick durchiterieren
  • Zu viele Partikel pro Tick erstellen
  • Aufwändige Schleifen ohne Verteilung der Arbeit über Ticks

Lösung: Schwere Arbeit hinter einen state-basierten Cooldown verschieben oder scheduler:run_repeating() mit einem vernünftigen Intervall anstelle von on_game_tick verwenden.


6. context.event ist nil in einem Klick-Hook

Das sollte normalerweise nicht für on_left_click und on_right_click passieren, aber schütze immer mit:

if context.event then
context.event.cancel()
end

Innerhalb von Scheduler-Callbacks ist context.event immer nil -- das ist erwartetes Verhalten. Event-Modifikation kann nur innerhalb des Event-Hooks selbst erfolgen.


7. Animation wird nicht abgespielt

Symptom: play_animation() gibt false zurück, oder es passiert nichts Sichtbares.

Ursachen und Lösungen:

  • Falscher Animationsname. Der Name muss exakt mit dem übereinstimmen, was in der Modelldatei definiert ist. Überprüfe deine .bbmodel- oder .fmmodel-Datei auf den korrekten Animationsnamen.

  • Modell hat keine Animationen. Nicht alle Modelle haben Animationen. Überprüfe, ob die Modelldatei tatsächlich Animationsdaten enthält.

  • Spieler sind nicht in Ressourcenpaket-Reichweite. Die Animation ist serverseitig, aber Spieler brauchen das FMM-Ressourcenpaket geladen, um das Modell überhaupt zu sehen.


8. Partikel erscheinen nicht

  • Überprüfe, ob der Partikelname ein gültiger Bukkit Particle Enum-Wert in GROSSBUCHSTABEN ist: "FLAME", nicht "flame".
  • Überprüfe, ob die Position in einem geladenen Chunk ist. Wenn keine Spieler in der Nähe sind, kann der Chunk entladen sein.
  • Überprüfe, ob count mindestens 1 ist.
  • Einige Partikel (wie DUST) benötigen spezifische Zusatzdaten, die das Basis-spawn_particle() möglicherweise nicht unterstützt. Verwende Standard-Partikel wie FLAME, HEART, HAPPY_VILLAGER, NOTE, ENCHANT, etc.

9. Sound wird nicht abgespielt

  • Überprüfe, ob der Soundname eine gültige Bukkit Sound Enum-Konstante in GROSSBUCHSTABEN ist. Beispiel: "BLOCK_NOTE_BLOCK_HARP", nicht "block.note_block.harp".
  • Überprüfe, ob die Positionskoordinaten korrekt sind (nicht alles Nullen oder NaN).
  • Überprüfe, ob die Lautstärke größer als 0 ist.

10. State setzt sich unerwartet zurück

context.state ist pro Prop-Instanz und bleibt für die Lebensdauer des Props bestehen. Wenn State sich scheinbar zurücksetzt:

  • Der Prop könnte entfernt und erneut gespawnt worden sein (jeder Spawn erstellt eine neue Instanz).
  • Du liest möglicherweise State in einem Scheduler-Callback mit der falschen Context-Variable. Verwende immer den eigenen Context-Parameter des Callbacks.

Wie die verzögerte Konfigurationserzeugung funktioniert

Das Verständnis des verzögerten Konfigurationssystems hilft, Verwirrung bei der Einrichtung neuer Props zu vermeiden:

  1. Erster Spawn: Wenn ein Prop spawnt und keine begleitende .yml-Datei existiert, erstellt FMM die Konfiguration asynchron. Das bedeutet, die Datei wird in einem Hintergrund-Thread geschrieben und ist nicht sofort verfügbar.

  2. Standardwerte: Die generierte Konfiguration hat isEnabled: true und eine leere scripts: []-Liste.

  3. Keine Skripte beim ersten Spawn: Da die Konfiguration erstellt wird, nachdem der Prop bereits gespawnt hat (und keine Skripte auflistet), wird der Prop bei seinem ersten Spawn keine Skripte angehängt haben.

  4. Bearbeiten und erneut spawnen: Nachdem FMM die Konfiguration erstellt hat, bearbeitest du sie, um deine Skriptdateinamen hinzuzufügen. Beim nächsten Spawn des Props werden Skripte geladen.

  5. Konfigurationsort: Die .yml-Datei wird im selben Verzeichnis wie die Modelldatei erstellt, mit demselben Basisnamen. Zum Beispiel:

    • Modell: plugins/FreeMinecraftModels/models/fountain.fmmodel
    • Konfiguration: plugins/FreeMinecraftModels/models/fountain.yml
Schneller Einrichtungs-Workflow
  1. Modell in models/ platzieren
  2. Skript in scripts/ platzieren
  3. Den Prop einmal spawnen (generiert die .yml)
  4. Die .yml bearbeiten und scripts: [my_script.lua] hinzufügen
  5. Den Prop erneut spawnen -- Skript ist jetzt aktiv

Fehlermeldungen lesen

Wenn in einem Lua-Prop-Skript etwas schiefgeht, gibt die Konsole einen [Lua]-Fehlerblock aus. Diese Meldungen sagen dir genau, welche Datei, welche Zeile, welcher Hook und was schiefgelaufen ist, in verständlicher Sprache.

Ein typischer Fehler sieht so aus:

[Lua] Error in 'my_door.lua' at line 12 during 'on_right_click':
[Lua] -> You tried to call a method or function that doesn't exist.
[Lua] -> Check the method name for typos, or make sure you're using ':' (colon) for method calls, not '.' (dot).
[Lua] -> Script has been disabled for this entity to prevent further errors.

Das System übersetzt häufige Lua-Fehler in verständliche Sprache:

Roher Lua-FehlerWas die Konsole dir sagt
attempt to call nilDu hast versucht, eine Methode oder Funktion aufzurufen, die nicht existiert. Prüfe auf Tippfehler und : vs . Verwendung.
index expected, got nilDu hast versucht, auf ein Feld von etwas zuzugreifen, das nil ist. Prüfe, ob vorheriger Code es initialisiert hat.
attempt to indexDu hast versucht, auf eine Eigenschaft eines nil- oder ungültigen Werts zuzugreifen.
bad argumentEine Funktion hat den falschen Argumenttyp erhalten. Die Nachricht zeigt den erwarteten vs. tatsächlichen Typ.
TimeoutDein Skript brauchte Xms in 'hook_name' (Limit: 50ms) -- Skript deaktiviert, um Lag zu verhindern.
tipp

Lies immer die vollständige [Lua]-Fehlermeldung, bevor du in den Code eintauchst. Sie zeigt dir normalerweise direkt die Lösung.


Gehe nicht davon aus, dass undokumentierte Methoden existieren

Die FMM-Lua-API stellt einen bestimmten Satz von Methoden bereit. Gehe nicht davon aus, dass Kurzformen oder alternative Namen existieren. Häufige Fehler:

  • context.prop:get_location() -- existiert nicht. Verwende context.prop.current_location (ein Feld, keine Methode).
  • context.prop:set_animation("open") -- existiert nicht. Verwende context.prop:play_animation("open", true, true).
  • context.event:setCancelled(true) -- existiert nicht. Verwende context.event.cancel().
  • context.cooldowns:check_local(...) -- existiert nicht in FMM. Verwende context.state mit scheduler:run_later() für Cooldowns.
  • context.player -- existiert nicht in FMM-Prop-Skripten. Verwende context.world:get_nearby_players(), um Spieler in der Nähe des Props zu finden.
  • context.boss -- existiert nicht. Das ist EliteMobs. Verwende context.prop in FMM.

Im Zweifelsfall prüfe die Prop-API-Seite. Wenn es dort nicht dokumentiert ist, existiert es nicht.


Debug-Tipps

1. Verwende context.log:info() großzügig

Füge Log-Nachrichten bei jedem Schritt beim Debuggen hinzu:

on_right_click = function(context)
context.log:info("Rechtsklick empfangen!")
context.log:info("Event vorhanden: " .. tostring(context.event ~= nil))
context.log:info("State is_open: " .. tostring(context.state.is_open))
end

2. Überprüfe die Konsole beim Start

FMM protokolliert [FMM Scripts] Bound script 'X' to prop 'Y' für jede erfolgreiche Bindung. Wenn du diese Nachricht nicht siehst, wurde die Konfiguration oder das Skript nicht geladen.

3. Überprüfe den Modelldateipfad

Die .yml-Konfiguration muss ein Geschwister der Modelldatei sein (gleiches Verzeichnis, gleicher Basisname). Überprüfe dies durch:

  • Modelldateipfad: plugins/FreeMinecraftModels/models/my_model.fmmodel
  • Konfigurationsdateipfad: plugins/FreeMinecraftModels/models/my_model.yml

4. Teste Hooks einzeln

Wenn du ein komplexes Skript erstellst, beginne damit, jeden Hook isoliert zu testen. Füge jeweils einen Hook hinzu und überprüfe, ob er feuert, bevor du zum nächsten übergehst.

5. Prüfe auf Tippfehler in Hook-Namen

Der häufigste Grund, warum ein Hook nicht feuert, ist ein falsch geschriebener Hook-Name. Das Skript wird ohne Fehler geladen, aber die falsch geschriebene Hook-Funktion wird während der Validierung abgelehnt.


Anfänger-Lernpfad

Wenn du dieses System von Grund auf lernen möchtest, funktioniert dieser Lernpfad gut:

  1. Schreibe eine Datei mit nur api_version = 1 und on_spawn, das eine Nachricht protokolliert.
  2. Füge das Skript zu einer Prop-Konfiguration hinzu und überprüfe, ob die Log-Nachricht erscheint.
  3. Füge on_right_click hinzu und protokolliere, wenn der Prop angeklickt wird.
  4. Füge on_left_click mit context.event.cancel() für Unverwundbarkeit hinzu.
  5. Spiele eine Animation bei Rechtsklick ab.
  6. Füge einen Sound bei Rechtsklick hinzu.
  7. Füge State und Umschaltverhalten hinzu.
  8. Füge eine Zonenüberwachung für Näherungserkennung hinzu.
  9. Gehe erst dann zu komplexen Multi-Hook-Skripten mit Schedulern über.

Jeder Schritt baut auf dem vorherigen auf, und du kannst in jeder Phase testen.


Nächste Schritte

  • Erste Schritte -- Dateistruktur, Hooks, erste Skript-Erklärung, Kopier-Vorlagen
  • Prop-API -- vollständige API-Referenz
  • Beispiele & Muster -- vollständige funktionierende Skripte, die du studieren und anpassen kannst