Zum Hauptinhalt springen

Lua-Skripting: Erste Schritte

Diese Seite zeigt dir, wie du dein erstes Lua-Skript für ein FreeMinecraftModels-Prop schreibst, von einer leeren Datei bis hin zu einem funktionierenden interaktiven Prop. Am Ende wirst du Hooks, Context, die Prop-API und die allgemeine Struktur jeder Prop-Skriptdatei verstehen.

Sobald du dich mit den Grundlagen wohlfühlst, fahre mit den Begleitseiten fort:

  • Prop-API -- die context.prop-, context.event-, context.world- und andere Context-APIs
  • Beispiele & Muster -- vollständige funktionierende Skripte, die du studieren und anpassen kannst
  • Fehlerbehebung -- häufige Fehler, Debugging-Tipps und die QC-Checkliste
Experimentelle Funktion

Lua-Prop-Skripte sind derzeit experimentell. Hook-Namen, Hilfsmethoden und Verhalten können sich noch ändern, während sich FreeMinecraftModels weiterentwickelt. Teste daher sorgfältig, bevor du sie auf einem Produktionsserver einsetzt.

Beziehung zu EliteMobs Lua

FreeMinecraftModels teilt dieselbe Lua-Engine (Magmacore) wie EliteMobs. Wenn du bereits Lua-Powers für EliteMobs schreibst, sind die Kernkonzepte -- Hooks, context, api_version, Scheduler, Zonen und die Sandbox -- identisch. Der Unterschied ist:

  • EliteMobs-Skripte laufen auf Bossen und haben Hooks wie on_boss_damaged_by_player, on_enter_combat, etc.
  • FMM-Skripte laufen auf Props und haben Hooks wie on_right_click, on_left_click, on_projectile_hit, etc.

Die context.world-, context.zones-, context.scheduler-, context.state- und context.log-APIs sind in beiden Plugins identisch. Diese Seite behandelt nur, was spezifisch für FMM-Props ist.


Was Prop-Skripte sind

Prop-Skripte sind eigenständige .lua-Dateien, die im Ordner plugins/FreeMinecraftModels/scripts/ liegen. Sie werden von einer YAML-Konfigurationsdatei referenziert, die neben der Modelldatei liegt, und sie laufen, sobald der Prop in die Welt gespawnt wird.

Wofür Prop-Skripte gut sind

Prop-Skripte eignen sich hervorragend, wenn du Folgendes benötigst:

  • Interaktive Props, die auf Spielerklicks reagieren (Türen, Hebel, Knöpfe)
  • Unverwundbare dekorative Props, die von Spielern nicht zerstört werden können
  • Näherungsauslöser, die erkennen, wenn Spieler einen Bereich betreten oder verlassen
  • Animierte Props, die Animationen bei Interaktion oder nach einem Timer abspielen
  • Sound-emittierende Props, die Sounds abspielen, wenn sie angeklickt oder angenähert werden
  • Jedes Prop-Verhalten, das Logik jenseits statischer Dekoration erfordert

Wenn dein Prop rein dekorativ ist und keine Interaktion benötigt, brauchst du kein Skript.


Für wen diese Seite ist

Diese Seite ist für drei Arten von Lesern geschrieben:

  • Jemand, der bereits EliteMobs-Lua-Skripting kennt und die FMM-spezifischen Hooks und APIs lernen möchte
  • Jemand, der neu im Lua-Skripting ist und eine vollständige, exakte Namensreferenz für Props benötigt
  • Jemand, der KI zum Erstellen von Prop-Skripten verwendet und genügend Details braucht, um zu erkennen, wenn die KI etwas Falsches erfunden hat

Du musst kein vollständiger Lua-Entwickler werden, bevor du nützliche Prop-Skripte schreiben kannst. Für die meisten praktischen Prop-Skripte brauchst du nur:

  • Wie man einen gültigen Hook in der zurückgegebenen Tabelle platziert
  • Wie man Werte aus context liest
  • Wie man frühzeitig mit if ... then return end abbricht
  • Wie man ein paar Hilfsmethoden exakt aufruft

Kleiner Lua-Einstieg

Wenn du völlig neu in Lua bist, hier ist die minimale Syntax, die du brauchst.

Variablen

Verwende local, um einen Wert zu speichern:

local animation_name = "open"
local sound_volume = 1.0

Funktionen

Funktionen sind wiederverwendbare Logikblöcke:

local function log_click(context)
context.log:info("Prop wurde angeklickt!")
end

if-Abfragen

Verwende if, wenn etwas nur manchmal passieren soll:

if context.event == nil then
return
end

nil

nil bedeutet "kein Wert". Du wirst oft darauf prüfen:

if context.event ~= nil then
context.event.cancel()
end

Tabellen

Lua verwendet Tabellen für Objekte mit benannten Schlüsseln und für die zurückgegebene Skriptdefinition:

return {
api_version = 1,

on_spawn = function(context)
end
}

Kommentare

Verwende -- für Anmerkungen:

-- Schaden-Event abbrechen, damit der Prop nicht zerstört werden kann
context.event.cancel()
tipp

Für einen ausführlicheren Lua-Einstieg siehe die EliteMobs Erste Schritte-Seite. Die Syntax-Grundlagen sind identisch.


Wo die Dateien liegen

Skriptdateien

Platziere .lua-Dateien im zentralen Skript-Ordner:

plugins/
FreeMinecraftModels/
scripts/
invulnerable.lua
interactive_door.lua
proximity_sound.lua

FMM erkennt alle .lua-Dateien in plugins/FreeMinecraftModels/scripts/ beim Start.

Modelldateien und Konfigurationsdateien

Jede Modelldatei kann eine begleitende .yml-Konfigurationsdatei im selben Verzeichnis haben:

plugins/
FreeMinecraftModels/
models/
torch_01.fmmodel
torch_01.yml <-- Skript-Konfiguration für torch_01
scripts/
invulnerable.lua <-- referenziert von torch_01.yml

Die .yml-Konfiguration ist das, was ein Modell mit seinen Skripten verbindet.


Konfigurationsdatei-Format

Die YAML-Konfigurationsdatei, die neben einer Modelldatei liegt, hat folgende Felder:

isEnabled: true
scripts:
- invulnerable.lua

Für benutzerdefinierte Items (Modelle, die Spieler halten oder ausrüsten können) setzt du zusätzlich das Feld material und optional name, lore und enchantments:

isEnabled: true
material: DIAMOND_SWORD
name: "&bFrost Blade"
lore:
- "&7A sword forged in eternal ice"
- "&7Slows enemies on hit"
enchantments:
- "SHARPNESS,5"
- "UNBREAKING,3"
scripts:
- frost_sword.lua
FeldTypStandardHinweise
isEnabledbooleantrueOb Skripte für diesen Prop/dieses Item aktiv sind
scriptsListe von Strings[]Dateinamen von .lua-Skripten im scripts/-Ordner
voxelizebooleanfalsePlatzierung an 90-Grad-Drehung und Blockraster-Ausrichtung einrasten
solidifybooleanfalsePaket-basierte Barrier-Blöcke im Grundriss des Props platzieren (erfordert voxelize)
materialstring""Ein gültiger Bukkit Material-Name (z.B. DIAMOND_SWORD). Wenn gesetzt, wird das Modell zu einem benutzerdefinierten Item, das Spieler halten oder ausrüsten können, wodurch das Item-Scripting-System aktiviert wird
namestring""Anzeigename für das benutzerdefinierte Item. Unterstützt &-Farbcodes
loreListe von Strings[]Lore-Zeilen, die im Item-Tooltip angezeigt werden. Unterstützt &-Farbcodes
enchantmentsListe von Strings[]Verzauberungen, die auf das Item angewendet werden. Format: "VERZAUBERUNGSNAME,STUFE" (z.B. "SHARPNESS,5")

Du kannst mehrere Skripte an denselben Prop anhängen. Jedes Skript ist seine eigene unabhängige Instanz.

Item-ID und Skript-Limit
  • Die Item-ID wird vom YML-Dateinamen ohne Endung abgeleitet. Zum Beispiel ergibt frost_sword.yml die Item-ID frost_sword. Dies ist die ID, die von /fmm giveitem und dem fmm_item_id PDC-Schlüssel verwendet wird.
  • Items verwenden nur das erste Skript in der scripts:-Liste. Im Gegensatz zu Props, die alle aufgelisteten Skripte als unabhängige Instanzen ausführen, ignorieren benutzerdefinierte Items alle Skripte nach dem ersten Eintrag.
  • Die .lua-Endung wird automatisch an Skriptdateinamen angehängt, wenn du sie weglässt, sodass frost_sword und frost_sword.lua in der scripts:-Liste gleichwertig sind.

Verzögerte Konfigurationserzeugung

Wenn ein Prop gespawnt wird und keine begleitende .yml-Datei existiert, erstellt FMM automatisch eine Standardkonfigurationsdatei mit isEnabled: true und einer leeren scripts:-Liste. Dies geschieht asynchron, sodass der Prop bei seinem ersten Spawn keine Skripte haben wird -- erst nachdem die Konfiguration erstellt wurde und du sie bearbeitest, um Skriptdateinamen hinzuzufügen.

Das bedeutet:

  1. Platziere deine Modelldatei in models/
  2. Spawne den Prop einmal (FMM erstellt die .yml automatisch)
  3. Bearbeite die generierte .yml, um deine Skriptdateinamen hinzuzufügen
  4. Spawne den Prop erneut oder lade neu (Skripte sind jetzt aktiv)

Hook-Referenz

Jede Lua-Prop-Skriptdatei gibt eine Tabelle zurück. Jeder Schlüssel in dieser Tabelle (außer api_version und priority) muss einer der unten aufgeführten Hooks sein. Die Laufzeit ruft die passende Funktion auf, wenn das entsprechende Spielereignis ausgelöst wird.

HookWird ausgelöst wennHinweise
on_spawnDer Prop in die Welt gespawnt wirdLäuft einmal, wenn das Skript gebunden wird
on_game_tickEinmal pro Server-Tick (50 ms)Nur aktiv, wenn das Skript diesen Hook definiert
on_destroyDer Prop aus der Welt entfernt wirdAufräum-Hook
on_left_clickEin Spieler den Prop links anklickt (schlägt)context.event ist das Schadens-Event
on_right_clickEin Spieler den Prop rechts anklicktcontext.event ist das Interaktions-Event
on_projectile_hitEin Projektil den Prop trifftcontext.event ist das Projektiltreffer-Event
on_zone_enterEin Spieler eine überwachte Zone betrittErfordert eine eingerichtete Zonenüberwachung
on_zone_leaveEin Spieler eine überwachte Zone verlässtErfordert eine eingerichtete Zonenüberwachung

Minimaler Dateivertrag

Jedes Lua-Prop-Skript muss eine Tabelle returnen.

Erforderliche und optionale Top-Level-Felder

FeldErforderlichTypHinweise
api_versionJaZahlMuss derzeit 1 sein
priorityNeinZahlAusführungspriorität. Niedrigere Werte werden zuerst ausgeführt. Standard ist 0
Unterstützte Hook-SchlüsselNeinFunktionMuss einen der exakten Hook-Namen aus der Hook-Referenz verwenden

Validierungsregeln

  • Die Datei muss eine Tabelle zurückgeben.
  • api_version ist erforderlich und muss derzeit 1 sein.
  • priority muss numerisch sein, wenn vorhanden.
  • Jeder zusätzliche Top-Level-Schlüssel muss ein unterstützter Hook-Name sein.
  • Jeder Hook-Schlüssel muss auf eine Funktion zeigen.
  • Unbekannte Top-Level-Schlüssel werden abgelehnt.

Hilfsfunktionen und lokale Konstanten sollten oberhalb des abschließenden return leben, nicht innerhalb der zurückgegebenen Tabelle.


Dein erstes funktionierendes Prop-Skript, Schritt für Schritt

Vor Schritt 1: Konfiguration einrichten

  1. Platziere deine Modelldatei (z.B. my_prop.fmmodel) in plugins/FreeMinecraftModels/models/
  2. Spawne den Prop einmal, um die .yml-Konfiguration zu generieren
  3. Erstelle deine Skriptdatei in plugins/FreeMinecraftModels/scripts/first_test.lua
  4. Bearbeite plugins/FreeMinecraftModels/models/my_prop.yml:
isEnabled: true
scripts:
- first_test.lua
  1. Spawne den Prop erneut oder lade den Server neu

Schritt 1: Die Datei zum Laden bringen

return {
api_version = 1,

on_spawn = function(context)
end
}

Wenn dies ohne Fehler in der Konsole geladen wird, hast du bewiesen:

  • Die Datei ist gültiges Lua
  • FMM hat sie im scripts/-Ordner gefunden
  • Die Konfiguration referenziert sie korrekt
  • Die Form der zurückgegebenen Tabelle ist korrekt

Schritt 2: Den Prop eine sichtbare Sache tun lassen

return {
api_version = 1,

on_spawn = function(context)
context.log:info("Prop-Skript geladen fuer: " .. (context.prop.model_id or "unbekannt"))
end
}

Überprüfe die Serverkonsole. Wenn du die Log-Nachricht siehst, feuert dein Hook.

Schritt 3: Auf einen Spielerklick reagieren

return {
api_version = 1,

on_right_click = function(context)
context.log:info("Prop wurde rechts angeklickt!")
end
}

Rechtsklicke den Prop im Spiel. Wenn die Konsole die Nachricht zeigt, funktioniert der Klick-Hook.

Schritt 4: Schaden abbrechen, um den Prop unverwundbar zu machen

return {
api_version = 1,

on_left_click = function(context)
if context.event then
context.event.cancel()
end
end
}

Dies ist das Muster, das das mitgelieferte invulnerable.lua-Skript verwendet. Es bricht das Schadens-Event ab, damit der darunterliegende Armor Stand des Props nicht zerstört werden kann.

Schritt 5: Eine Animation bei Klick abspielen

return {
api_version = 1,

on_right_click = function(context)
context.prop:play_animation("open", true, false)
end
}

Dies spielt die "open"-Animation auf dem Prop-Modell ab, geblendet und nicht-wiederholend.


Was ist context?

Jede Hook-Funktion erhält ein Argument namens context. Stelle es dir wie einen Werkzeugkasten vor, den FMM dir jedes Mal übergibt, wenn etwas passiert -- er enthält alles, was du brauchst, um mit dem Prop, der Welt, Zonen und mehr zu interagieren.

on_right_click = function(context)
-- context.prop = der Prop, der angeklickt wurde
-- context.event = das Klick-Event (kann abgebrochen werden)
-- context.world = Werkzeuge für Partikel, Sounds, Block-Abfragen
-- context.state = dein eigener persistenter Speicher
-- context.log = Konsolen-Logging
-- context.scheduler = verzögerte und wiederholende Aufgaben
-- context.zones = räumliche Zonenerstellung und -überwachung
end

Du erstellst context nicht selbst -- FMM erstellt es und übergibt es an deinen Hook.

info

context wird für jeden Hook-Aufruf neu erstellt, außer context.state, das für die gesamte Lebensdauer des Props bestehen bleibt. Das bedeutet, du kannst Daten in context.state speichern und sie später in einem anderen Hook wieder auslesen.


Wichtige context-APIs

Hier ist eine Zusammenfassung des Verfügbaren. Für vollständige Details siehe Prop-API.

  • context.prop -- Die Prop-Entity. Bietet model_id, current_location, play_animation() und stop_animation().

  • context.event -- Das Bukkit-Event, das diesen Hook ausgelöst hat. Verfügbar in on_left_click, on_right_click und on_projectile_hit. Bietet cancel(), uncancel() und is_cancelled. Ist nil in Hooks ohne Event (wie on_spawn und on_game_tick).

  • context.state -- Eine einfache Lua-Tabelle, die für die gesamte Lebensdauer des Props bestehen bleibt. Verwende sie zum Speichern von Flags, Umschaltzuständen, Aufgaben-IDs und allem, was du zwischen Hooks merken musst.

  • context.log -- Konsolen-Logging mit log:info(msg), log:warn(msg) und log:error(msg).

  • context.scheduler -- Verzögerte und wiederholende Aufgaben mit scheduler:run_later(ticks, callback) und scheduler:run_repeating(delay, interval, callback). Callbacks erhalten einen frischen Context. Aufgaben abbrechen mit scheduler:cancel(taskId).

  • context.world -- Weltinteraktion: Partikel, Sounds, Block-Abfragen, Blitze, nahegelegene Entities. Siehe Prop-API für die vollständige Methodenliste.

  • context.zones -- Erstelle und überwache räumliche Zonen (Kugeln, Zylinder, Quader). Siehe Prop-API für die vollständige Methodenliste.


Methodensyntax: : vs .

In Lua ist object:method(arg) eine Kurzform für object.method(object, arg). Die FMM-API akzeptiert beide Formen:

context.log:info("hallo")
context.log.info("hallo") -- dasselbe

Die gesamte Dokumentation verwendet durchgehend :.


Kopier-Vorlagen

Kleinstes gültiges Prop-Skript

return {
api_version = 1,

on_spawn = function(context)
end
}

Unverwundbares Prop-Template

return {
api_version = 1,

on_left_click = function(context)
if context.event then
context.event.cancel()
end
end
}

Interaktives Prop-Template

return {
api_version = 1,

on_spawn = function(context)
context.state.is_active = false
end,

on_right_click = function(context)
context.state.is_active = not context.state.is_active

if context.state.is_active then
context.prop:play_animation("activate", true, true)
else
context.prop:stop_animation()
end
end
}

Größeres Datei-Layout

local ANIMATION_NAME = "idle"

local function do_something(context)
context.log:info("Tue etwas!")
end

return {
api_version = 1,
priority = 0,

on_spawn = function(context)
context.state.task_id = nil
end,

on_right_click = function(context)
do_something(context)
end,

on_destroy = function(context)
if context.state.task_id ~= nil then
context.scheduler:cancel(context.state.task_id)
end
end
}

Erster echter Workflow

Wenn du ein brandneues Prop-Skript erstellst, verwende diese Reihenfolge:

  1. Erstelle die .lua-Datei und bringe on_spawn zum Laufen.
  2. Füge den Skriptdateinamen zur .yml-Konfiguration des Props hinzu.
  3. Wechsle zum tatsächlichen Hook, den du verwenden möchtest (z.B. on_right_click).
  4. Füge zuerst eine Log-Nachricht hinzu, bevor du Animationen oder Effekte hinzufügst.
  5. Füge einen echten Effekt hinzu (Animation, Sound, Partikel).
  6. Erst danach füge Helfer, State, Scheduler-Logik oder Zonen hinzu.

Diese Reihenfolge macht das Debugging dramatisch einfacher, weil sich immer nur eine Sache gleichzeitig ändert.


Mitgelieferte Skripte

FMM wird mit zwei mitgelieferten Lua-Skripten ausgeliefert:

  • invulnerable.lua -- Bricht Linksklick-Schadens-Events ab und macht den Prop unzerstörbar. Dies ist das einfachste nützliche Prop-Skript.
  • pickupable.lua -- Ermöglicht es Spielern, einen Prop aufzuheben, indem sie ihn dreimal schlagen. Jeder Treffer spielt eine Verletzungsanimation auf dem Prop ab, und beim dritten Treffer wird der Prop entfernt und droppt sein Platzierungs-Item, damit der Spieler es aufsammeln kann.

Weitere Beispiele findest du auf der Seite Beispiele & Muster.


Lua-Sandbox

Prop-Skripte laufen in derselben sandboxed LuaJ-Umgebung wie EliteMobs. Die Sandbox-Einschränkungen sind identisch. Für die vollständige Liste der entfernten Globals und verfügbaren Standardbibliotheksfunktionen siehe die EliteMobs Hooks & Lifecycle-Seite.

Zusammenfassung:

  • Entfernt: debug, dofile, io, load, loadfile, luajava, module, os, package, require
  • Verfügbar: Alle math.*-, string.*-, table.*-Funktionen, pairs, ipairs, type, tostring, tonumber, pcall, print und mehr
tipp

print schreibt in die Serverkonsole, aber bevorzuge context.log:info(msg) für die Ausgabe. Log-Nachrichten werden mit dem Skriptdateinamen versehen, was es einfacher macht nachzuverfolgen, welches Skript die Nachricht erzeugt hat.


Nächste Schritte

  • Prop-API -- vollständige context.prop-, context.event-, context.world-, context.zones- und context.scheduler-Referenz
  • Beispiele & Muster -- vollständige funktionierende Skripte mit Erklärungen
  • Fehlerbehebung -- häufige Probleme, Debugging-Tipps und eine QC-Checkliste

Wenn du auch EliteMobs-Lua-Powers schreibst, funktionieren die gemeinsamen APIs (context.world, context.zones, context.scheduler, context.state, context.log) identisch. Siehe die EliteMobs-Lua-Dokumentation für die Boss-spezifischen APIs.