Lua-Skripting: Prop- und Item-API
Diese Seite behandelt jede API, die FreeMinecraftModels-Prop- und Item-Skripten zur Verfügung steht: context.prop, context.item, context.event, context.player, context.world, context.zones, context.scheduler, context.state und context.log. Wenn du neu im Skripting bist, beginne zuerst mit Erste Schritte.
context.prop
Die Prop-Tabelle bietet Informationen über die Prop-Entity und Methoden zur Steuerung ihrer Animationen. Diese wird für jeden Hook-Aufruf neu erstellt.
Felder
| Feld | Typ | Hinweise |
|---|---|---|
prop.model_id | string | Der Vorlagen-Modellname (z.B. "torch_01") |
prop.current_location | Location-Tabelle | Die Position des Props zum Zeitpunkt der Context-Erstellung |
Die Location-Tabelle hat die Standardfelder: x, y, z, world, yaw, pitch.
Beispiel: Prop-Informationen lesen
return {
api_version = 1,
on_spawn = function(context)
context.log:info("Prop spawned: " .. (context.prop.model_id or "unknown"))
local loc = context.prop.current_location
if loc then
context.log:info("Location: " .. loc.x .. ", " .. loc.y .. ", " .. loc.z)
end
end
}
prop:play_animation(name, blend, loop)
Spielt eine benannte Animation auf dem Prop-Modell ab.
| Parameter | Typ | Standard | Hinweise |
|---|---|---|---|
name | string | erforderlich | Der Animationsname wie in der Modelldatei definiert |
blend | boolean | true | Ob mit der aktuellen Animation geblendet werden soll |
loop | boolean | true | Ob die Animation wiederholt werden soll |
Gibt true zurück, wenn die Animation gefunden und gestartet wurde, sonst false.
Beispiel
return {
api_version = 1,
on_right_click = function(context)
local success = context.prop:play_animation("open", true, false)
if not success then
context.log:warn("Animation 'open' not found on this model!")
end
end
}
prop:stop_animation()
Stoppt alle derzeit laufenden Animationen auf dem Prop.
Nimmt keine Parameter entgegen.
Beispiel
return {
api_version = 1,
on_right_click = function(context)
context.prop:stop_animation()
end
}
prop:hurt_visual()
Spielt die visuelle Verletzungsanimation (roter Blitz) auf dem Prop ab, ohne ihm tatsächlichen Schaden zuzufügen.
Nimmt keine Parameter entgegen.
Beispiel
return {
api_version = 1,
on_left_click = function(context)
-- Flash red when punched, but don't actually take damage
if context.event then
context.event.cancel()
end
context.prop:hurt_visual()
end
}
prop:pickup()
Entfernt den Prop aus der Welt und droppt ein Platzierungs-Papier-Item an seiner Position. Das gedroppte Item kann per Rechtsklick auf einen Block platziert werden, um den Prop erneut zu platzieren.
Nimmt keine Parameter entgegen.
Beispiel
return {
api_version = 1,
on_right_click = function(context)
-- Let players pick up the prop by right-clicking it
context.prop:pickup()
end
}
prop:mount(player)
Montiert einen Spieler auf den ersten verfügbaren Montagepunkt-Sitz des Props. Das Modell muss Montagepunkt-Bones definiert haben.
| Parameter | Typ | Hinweise |
|---|---|---|
player | Entity-Tabelle | Eine Spieler-Entity-Tabelle (z.B. von context.event.player) |
Beispiel
return {
api_version = 1,
on_right_click = function(context)
local player = context.event and context.event.player
if player then
context.prop:mount(player)
end
end
}
prop:dismount(player)
Demontiert einen Spieler von seinem Montagepunkt-Sitz auf dem Prop.
| Parameter | Typ | Hinweise |
|---|---|---|
player | Entity-Tabelle | Eine Spieler-Entity-Tabelle |
Beispiel
return {
api_version = 1,
on_right_click = function(context)
local player = context.event and context.event.player
if player then
-- Toggle mount/dismount
local passengers = context.prop:get_passengers()
for i = 1, #passengers do
if passengers[i].uuid == player.uuid then
context.prop:dismount(player)
return
end
end
context.prop:mount(player)
end
end
}
prop:get_passengers()
Gibt ein Lua-Array von Entity-Tabellen für alle aktuellen Passagiere auf dem Prop zurück.
Nimmt keine Parameter entgegen.
Beispiel
return {
api_version = 1,
on_game_tick = function(context)
local passengers = context.prop:get_passengers()
if #passengers > 0 then
context.log:info("Prop has " .. #passengers .. " passenger(s)")
end
end
}
prop:has_mount_points()
Gibt zurück, ob dieser Prop Montagepunkt-Bones in seinem Modell definiert hat.
Nimmt keine Parameter entgegen. Gibt true oder false zurück.
Beispiel
return {
api_version = 1,
on_right_click = function(context)
local player = context.event and context.event.player
if player and context.prop:has_mount_points() then
context.prop:mount(player)
end
end
}
prop:spawn_elitemobs_boss(filename, x, y, z)
Spawnt einen EliteMobs-Custom-Boss an der angegebenen Position. Erfordert, dass EliteMobs auf dem Server installiert ist.
| Parameter | Typ | Hinweise |
|---|---|---|
filename | string | Der Custom-Boss-Dateiname (z.B. "my_boss.yml") |
x | number | X-Koordinate |
y | number | Y-Koordinate |
z | number | Z-Koordinate |
Gibt eine Living-Entity-Tabelle für den gespawnten Boss zurück, oder nil, wenn EliteMobs nicht installiert ist oder die Boss-Datei nicht existiert.
Beispiel
return {
api_version = 1,
on_right_click = function(context)
local loc = context.prop.current_location
if loc then
local boss = context.prop:spawn_elitemobs_boss("dungeon_guardian.yml", loc.x, loc.y + 1, loc.z)
if boss then
context.log:info("Spawned boss: " .. (boss.name or "unknown"))
else
context.log:warn("Could not spawn boss -- is EliteMobs installed?")
end
end
end
}
prop:open_inventory(player, title, rows)
Öffnet ein persistentes Truhen-Inventar-GUI für den Spieler. Der Inhalt wird im PersistentDataContainer des Props gespeichert, wenn das Inventar geschlossen wird, und beim erneuten Öffnen wiederhergestellt.
| Parameter | Typ | Standard | Hinweise |
|---|---|---|---|
player | Entity-Tabelle | erforderlich | Der Spieler, dem das Inventar gezeigt wird |
title | string | erforderlich | Der Inventartitel (unterstützt &-Farbcodes) |
rows | int | 3 | Anzahl der Reihen (1-6, wobei 6 = 54 Slots = Doppeltruhe) |
Gibt true zurück, wenn das Inventar geöffnet wurde, sonst false.
prop:is_viewing_inventory(player)
Gibt zurück, ob der angegebene Spieler derzeit das Inventar dieses Props geöffnet hat.
| Parameter | Typ | Hinweise |
|---|---|---|
player | Entity-Tabelle | Der zu prüfende Spieler |
Gibt true oder false zurück.
Beispiel: Schließ-Animation wenn Inventar geschlossen wird
context.state["task_" .. player.uuid] = context.scheduler:run_repeating(5, 5, function(tick_context)
if not tick_context.prop:is_viewing_inventory(player) then
tick_context.prop:play_animation("close", true, false)
tick_context.scheduler:cancel(tick_context.state["task_" .. player.uuid])
end
end)
prop:place_book(player)
Nimmt das geschriebene oder beschreibbare Buch aus der Haupthand des Spielers und speichert es auf dem Prop.
| Parameter | Typ | Hinweise |
|---|---|---|
player | Entity-Tabelle | Der Spieler, der das Buch hält |
Gibt true bei Erfolg zurück.
prop:read_book(player)
Öffnet das gespeicherte Buch zum Lesen für den Spieler.
| Parameter | Typ | Hinweise |
|---|---|---|
player | Entity-Tabelle | Der Spieler, dem das Buch gezeigt wird |
Gibt true zurück, wenn ein Buch geöffnet wurde.
prop:take_book(player)
Gibt das gespeicherte Buch an das Inventar des Spielers zurück und entfernt es vom Prop.
| Parameter | Typ | Hinweise |
|---|---|---|
player | Entity-Tabelle | Der Spieler, dem das Buch gegeben wird |
Gibt true bei Erfolg zurück.
prop:has_book()
Gibt zurück, ob ein Buch auf diesem Prop gespeichert ist. Nimmt keine Parameter entgegen.
prop:drop_inventory()
Droppt alle gespeicherten Inventarinhalte an der Position des Props als Item-Entities, löscht dann die gespeicherten Daten. Schließt automatisch das Inventar für alle Spieler, die es gerade betrachten.
Nimmt keine Parameter entgegen. Gibt true bei Erfolg zurück.
prop:drop_book()
Droppt das gespeicherte Buch an der Position des Props als Item-Entity und löscht die gespeicherten Buchdaten.
Nimmt keine Parameter entgegen. Gibt true bei Erfolg zurück.
prop:set_persistent_data(key, value)
Speichert einen String-Wert im PersistentDataContainer des Armor Stands des Props. Diese Daten überleben Server-Neustarts und Chunk-Entladungen.
| Parameter | Typ | Hinweise |
|---|---|---|
key | string | Ein eindeutiger Schlüsselname (intern als fmm_lua_<key> gespeichert) |
value | string | Der zu speichernde Wert. Verwende tostring() für Zahlen und Booleans. |
Gibt true bei Erfolg zurück, false wenn der Prop keinen unterliegenden Armor Stand hat.
prop:get_persistent_data(key)
Ruft einen zuvor mit set_persistent_data gespeicherten String-Wert ab. Gibt nil zurück, wenn der Schlüssel nicht gesetzt wurde.
| Parameter | Typ | Hinweise |
|---|---|---|
key | string | Der in set_persistent_data verwendete Schlüsselname |
Beispiel: Persistenter Umschaltzustand
return {
api_version = 1,
on_spawn = function(context)
local saved = context.prop:get_persistent_data("active")
context.state.active = saved == "true"
end,
on_right_click = function(context)
context.state.active = not context.state.active
context.prop:set_persistent_data("active", tostring(context.state.active))
end
}
context.item
Die Item-Tabelle ist nur in Item-Skripten verfügbar (nicht in Prop-Skripten). Sie bietet Informationen über das benutzerdefinierte Item und Methoden zu dessen Manipulation. Diese Tabelle wird für jeden Hook-Aufruf neu erstellt.
Felder
| Feld | Typ | Hinweise |
|---|---|---|
item.id | string | Die Item-Typ-ID (die fmm_item_id aus der YML-Konfiguration) |
item:material()
Gibt den Materialnamen des Items als String zurück (z.B. "DIAMOND_SWORD", "STICK").
item:get_amount() / item:set_amount(n)
Holt oder setzt die Stack-Größe des Items.
| Parameter | Typ | Hinweise |
|---|---|---|
n | int | Die neue Stack-Menge |
item:consume(n)
Verringert die Stack-Menge des Items um n (Standard 1). Wenn die resultierende Menge 0 oder weniger ist, wird das Item aus dem Inventar des Spielers entfernt.
| Parameter | Typ | Standard | Hinweise |
|---|---|---|---|
n | int | 1 | Menge zum Verbrauchen |
item:get_uses() / item:set_uses(n)
Holt oder setzt einen benutzerdefinierten Verwendungszähler, der im PersistentDataContainer des Items gespeichert ist. Dies ist unabhängig von der Vanilla-Haltbarkeit und kann zur Implementierung benutzerdefinierter Haltbarkeits- oder Ladesysteme verwendet werden.
| Parameter | Typ | Hinweise |
|---|---|---|
n | int | Der neue Verwendungszähler |
item:get_name() / item:set_name(s)
Holt oder setzt den Anzeigenamen des Items. Unterstützt Farbcodes mit &.
| Parameter | Typ | Hinweise |
|---|---|---|
s | string | Der neue Anzeigename (z.B. "&b&lFrost Sword") |
item:get_lore() / item:set_lore(table)
Holt oder setzt die Lore des Items. get_lore() gibt eine Tabelle von Strings zurück (eine pro Zeile). set_lore() nimmt eine Tabelle von Strings.
| Parameter | Typ | Hinweise |
|---|---|---|
table | table | Array von Strings, eine pro Lore-Zeile |
Beispiel: Item-Skript das Verwendungen verfolgt
return {
api_version = 1,
on_right_click = function(context)
local uses = context.item:get_uses()
if uses <= 0 then
context.player:send_message("&cThis item is out of charges!")
return
end
context.item:set_uses(uses - 1)
context.player:send_message("&aUsed! Charges remaining: " .. (uses - 1))
end
}
item:get_durability()
Gibt eine Tabelle mit current- und max-Feldern zurück, die die Vanilla-Haltbarkeit des Items darstellen, oder nil wenn das Item keine Haltbarkeitsleiste hat.
Beispiel
local dur = context.item:get_durability()
if dur then
context.player:send_message("Durability: " .. dur.current .. "/" .. dur.max)
end
item:get_durability_percentage()
Gibt die verbleibende Haltbarkeit als Bruchteil von 0.0 bis 1.0 zurück, oder nil wenn das Item keine Haltbarkeitsleiste hat.
item:use_durability(amount, can_break)
Reduziert die Vanilla-Haltbarkeit des Items um einen festen Betrag.
| Parameter | Typ | Standard | Hinweise |
|---|---|---|---|
amount | int | erforderlich | Wie viele Haltbarkeitspunkte verbraucht werden |
can_break | boolean | false | Wenn true, wird das Item zerstört wenn die Haltbarkeit aufgebraucht ist. Wenn false, stoppt die Haltbarkeit bei 1. |
item:use_durability_percentage(fraction, can_break)
Reduziert die Vanilla-Haltbarkeit des Items um einen Prozentsatz seines Maximums.
| Parameter | Typ | Standard | Hinweise |
|---|---|---|---|
fraction | number | erforderlich | Bruchteil der maximalen Haltbarkeit zum Verbrauchen (z.B. 0.1 = 10%) |
can_break | boolean | false | Wenn true, wird das Item zerstört wenn die Haltbarkeit aufgebraucht ist. Wenn false, stoppt die Haltbarkeit bei 1. |
context.event
Event-Daten für den aktuellen Hook. Verfügbar in Klick-, Kampf- und Interaktions-Hooks sowohl für Prop- als auch Item-Skripte. Gibt nil in Hooks zurück, die kein zugehöriges Event haben (on_spawn, on_game_tick, on_destroy, on_zone_enter, on_zone_leave, on_equip).
Felder und Methoden
| Feld oder Methode | Typ | Hinweise |
|---|---|---|
event.player | Spieler-Entity-Tabelle | Der Spieler, der das Event ausgelöst hat. Verfügbar in on_left_click, on_right_click und on_projectile_hit (der Schütze, falls es ein Spieler war). Siehe Spieler-Entity-Methoden für alle Felder und Methoden. |
event.is_cancelled | boolean | Ob das Event derzeit abgebrochen ist |
event.cancel() | function | Bricht das Event ab (z.B. verhindert Schaden oder Interaktion) |
event.uncancel() | function | Hebt den Abbruch eines zuvor abgebrochenen Events auf |
Nicht alle Events sind abbrechbar. Wenn das zugrunde liegende Bukkit-Event Cancellable nicht implementiert, werden event.cancel() und event.uncancel() nicht vorhanden sein und event.is_cancelled wird immer false sein.
Beispiel: Einen Prop unverwundbar machen
Beispiel
return {
api_version = 1,
on_left_click = function(context)
if context.event then
context.event.cancel()
end
end
}
Beispiel: Abbruchstatus prüfen
Beispiel
return {
api_version = 1,
on_left_click = function(context)
if context.event and not context.event.is_cancelled then
context.event.cancel()
context.log:info("Damage cancelled!")
end
end
}
Innerhalb von geplanten Callbacks (scheduler:run_later, scheduler:run_repeating) ist context.event immer nil. Event-Modifikation kann nur während des Event-Hooks selbst erfolgen.
context.world
Die World-API wird über alle Nightbreak-Plugins geteilt. Siehe context.world für die vollständige Referenz.
FMM-Props verwenden dieselbe MagmaCore-World-Tabelle wie EliteMobs-Bosse. Alle auf der globalen Seite dokumentierten Methoden (get_block_at, set_block_at, spawn_particle, play_sound, strike_lightning, get_time, set_time, get_nearby_entities, get_nearby_players, spawn_entity, get_highest_block_y, raycast, spawn_firework) sind in FMM verfügbar. Siehe die MagmaCore World-API für vollständige Details zu world:raycast() (Strahl werfen und getroffene Entities/Blöcke erkennen) und world:spawn_firework() (Feuerwerksraketen mit benutzerdefinierten Farben und Formen spawnen). EliteMobs erweitert die World-Tabelle mit zusätzlichen Methoden zum Spawnen von Bossen, Verstärkungen und mehr -- siehe EliteMobs Welt und Umgebung.
Spieler-Entity-Methoden
Spieler-Entity-Tabellen werden von context.event.player, context.world:get_nearby_players() und Zonen-Callbacks zurückgegeben.
Die Entity-Tabellen, Living-Entity-Methoden, spielerspezifischen Methoden und Spieler-UI-Methoden werden über alle Nightbreak-Plugins geteilt. Siehe die MagmaCore Lua-Skripting-Engine für die vollständige Referenz, die Entity-Basisfelder, Living-Entity-Felder und -Methoden, spielerspezifische Felder und Methoden sowie Spieler-UI-Methoden abdeckt. Neue Spielermethoden umfassen player:get_target_entity() (Raycast-Targeting), player:get_eye_location(), player:get_look_direction(), player:send_block_change() (spielerspezifische Fake-Blöcke) und player:reset_block() -- siehe Spielerspezifische Methoden für Details.
context.zones
Die Zones-API wird über alle Nightbreak-Plugins geteilt. Siehe context.zones für die vollständige Referenz.
context.scheduler
Die Scheduler-API wird über alle Nightbreak-Plugins geteilt. Siehe context.scheduler für die vollständige Referenz.
context.state
Die State-API wird über alle Nightbreak-Plugins geteilt. Siehe context.state für die vollständige Referenz.
context.log
Die Logging-API wird über alle Nightbreak-Plugins geteilt. Siehe context.log für die vollständige Referenz.
Laufzeitmodell
Eine Laufzeit pro Skriptinstanz
Jede Prop-Entity, die Skripte angehängt hat, bekommt ihre eigene unabhängige Lua-Laufzeitinstanz. Wenn der Prop spawnt, lädt FMM den Lua-Quellcode, wertet ihn in einer frischen sandboxed Umgebung aus und speichert die zurückgegebene Tabelle. Wenn der Prop entfernt wird, wird die Laufzeit heruntergefahren.
Für Item-Skripte wird eine Laufzeit pro (Spieler, itemId)-Paar erstellt. Wenn ein Spieler ein benutzerdefiniertes Item ausrüstet, erstellt FMM eine Skriptinstanz für diesen Spieler und Item-Typ. Wenn das Item abgelegt wird, wird die Laufzeit heruntergefahren.
Das bedeutet:
- Lokale Variablen, die auf Dateiebene deklariert werden, sind privat für diese Skriptinstanz.
context.stateist vollständig isoliert zwischen Instanzen, selbst wenn sie dieselbe Skriptdatei teilen.
Geplante Aufgaben-Eigentümerschaft
Alle über context.scheduler erstellten Aufgaben gehören der Laufzeit, die sie erstellt hat. Wenn ein Prop entfernt wird:
- Die Laufzeit wird heruntergefahren.
- Jede eigene Aufgabe -- sowohl einmalige als auch wiederholende -- wird automatisch abgebrochen.
- Alle Zonenüberwachungen werden aufgeräumt.
Ausführungsbudget
Jeder Hook-Aufruf und jeder Callback-Aufruf wird zeitlich gemessen. Wenn ein einzelner Aufruf länger als 50 Millisekunden dauert, wird das Skript mit einer Konsolenwarnung deaktiviert:
[Lua] my_script.lua took 73ms in 'on_game_tick' (limit: 50ms) -- script disabled to prevent lag.
Um im Budget zu bleiben:
- Vermeide unbegrenzte Schleifen innerhalb von Hooks.
- Halte
on_game_tick-Handler leichtgewichtig -- sie laufen bei jedem einzelnen Tick. - Verwende
context.scheduler:run_repeating(...), um Arbeit auf mehrere Ticks zu verteilen.
Vollständige Hook-Referenz
Diese Tabelle listet alle Hooks auf, die in Prop- und Item-Skripten verfügbar sind.
Prop-Hooks (8)
| Hook | Feuert wenn | context.event |
|---|---|---|
on_spawn | Prop spawnt in die Welt | nil |
on_game_tick | Jeden Server-Tick (50ms) | nil |
on_destroy | Prop wird entfernt | nil |
on_left_click | Spieler klickt links auf den Prop | Schadens-Event |
on_right_click | Spieler klickt rechts auf den Prop | Interaktions-Event |
on_projectile_hit | Projektil trifft den Prop | Projektil-Treffer-Event |
on_zone_enter | Spieler betritt eine überwachte Zone | nil |
on_zone_leave | Spieler verlässt eine überwachte Zone | nil |
Item-Hooks (22)
| Hook | Kategorie | Feuert wenn | context.event |
|---|---|---|---|
on_attack_entity | Kampf | Spieler greift eine Entity an | Schadens-Event |
on_kill_entity | Kampf | Spieler tötet eine Entity | Todes-Event |
on_take_damage | Kampf | Spieler nimmt Schaden | Schadens-Event |
on_shield_block | Kampf | Spieler blockt mit Schild | Schadens-Event |
on_shoot_bow | Kampf | Spieler schießt einen Bogen | Bogenschuss-Event |
on_projectile_hit | Kampf | Spieler-Projektil trifft | Projektil-Treffer-Event |
on_projectile_launch | Kampf | Spieler wirft Projektil | Wurf-Event |
on_right_click | Interaktion | Spieler macht Rechtsklick | Interaktions-Event |
on_left_click | Interaktion | Spieler macht Linksklick | Interaktions-Event |
on_shift_right_click | Interaktion | Spieler macht Shift+Rechtsklick | Interaktions-Event |
on_shift_left_click | Interaktion | Spieler macht Shift+Linksklick | Interaktions-Event |
on_interact_entity | Interaktion | Spieler klickt rechts auf Entity | Entity-Interaktions-Event |
on_equip | Ausrüstung | Item kommt in aktiven Slot | nil |
on_unequip | Ausrüstung | Item verlässt aktiven Slot | nil |
on_swap_hands | Ausrüstung | Tauscht Haupt-/Nebenhand | Tausch-Event |
on_drop | Ausrüstung | Spieler lässt Item fallen | Drop-Event |
on_break_block | Werkzeug | Spieler baut Block ab | Blockbruch-Event |
on_consume | Werkzeug | Spieler konsumiert Item | Konsum-Event |
on_item_damage | Werkzeug | Item nimmt Haltbarkeitsschaden | Item-Schadens-Event |
on_fish | Werkzeug | Spieler benutzt Angel | Angel-Event |
on_death | Werkzeug | Spieler stirbt während ausgerüstet | Todes-Event |
on_game_tick | Lebenszyklus | Jeden Tick solange ausgerüstet | nil |
Nächste Schritte
- Beispiele & Muster -- vollständige funktionierende Prop- und Item-Skripte mit Erklärungen
- Fehlerbehebung -- häufige Probleme, Debugging-Tipps und eine QC-Checkliste
- Erste Schritte -- Dateistruktur, Hooks, erste Skript-Anleitung