Lua-Scripting: Prop-API
Diese Seite behandelt alle APIs, die FreeMinecraftModels-Prop-Skripten zur Verfügung stehen: context.prop, context.event, context.world, context.zones, context.scheduler, context.state und context.log. Wenn Sie neu im Prop-Scripting sind, beginnen Sie zuerst mit Erste Schritte.
context.prop
Die Prop-Tabelle liefert Informationen über die Prop-Entität und Methoden zur Steuerung ihrer Animationen. Sie wird für jeden Hook-Aufruf neu erstellt.
Felder
| Feld | Typ | Hinweise |
|---|---|---|
prop.model_id | string | Der Blueprint-Modellname (z. B. "torch_01") |
prop.current_location | location table | Die Position des Props zum Zeitpunkt der Kontexterstellung |
Die Location-Tabelle hat die Standardfelder: x, y, z, world, yaw, pitch.
Beispiel: Prop-Informationen auslesen
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 er in der Modelldatei definiert ist |
blend | boolean | true | Ob mit der aktuellen Animation überblendet werden soll |
loop | boolean | true | Ob die Animation in einer Schleife abgespielt wird |
Gibt true zurück, wenn die Animation gefunden und gestartet wurde, andernfalls 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 aktuell abgespielten Animationen des Props.
Nimmt keine Parameter entgegen.
Beispiel
return {
api_version = 1,
on_right_click = function(context)
context.prop:stop_animation()
end
}
context.event
Ereignisdaten für den aktuellen Hook. Verfügbar in on_left_click, on_right_click und on_projectile_hit. Gibt nil zurück in Hooks ohne zugehöriges Ereignis (on_spawn, on_game_tick, on_destroy, on_zone_enter, on_zone_leave).
Felder und Methoden
| Feld oder Methode | Typ | Hinweise |
|---|---|---|
event.is_cancelled | boolean | Ob das Ereignis aktuell abgebrochen ist |
event.cancel() | function | Bricht das Ereignis ab (verhindert z. B. Schaden oder Interaktion) |
event.uncancel() | function | Hebt die Stornierung eines zuvor abgebrochenen Ereignisses auf |
Nicht alle Ereignisse können abgebrochen werden. Wenn das zugrunde liegende Bukkit-Event Cancellable nicht implementiert, sind event.cancel() und event.uncancel() nicht vorhanden, und event.is_cancelled ist immer false.
Beispiel: Ein Prop unverwundbar machen
Beispiel
return {
api_version = 1,
on_left_click = function(context)
if context.event then
context.event.cancel()
end
end
}
Beispiel: Stornierungsstatus 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
}
In geplanten Callbacks (scheduler:run_later, scheduler:run_repeating) ist context.event immer nil. Ereignismodifikationen können nur während des Ereignis-Hooks selbst vorgenommen werden.
context.world
Die World-Tabelle stellt Methoden zum Abfragen und Interagieren mit der Minecraft-Welt bereit. Sie wird aus der aktuellen Welt des Props erstellt.
Die context.world-API wird mit EliteMobs geteilt. FMM-Props verwenden dieselbe Magmacore-World-Tabelle wie EliteMobs-Bosse. Die hier dokumentierten Methoden sind die der Basis-Magmacore-Implementierung. Die vollständige Referenz finden Sie auf der Seite EliteMobs World & Environment -- die dort als Teil der Kern-context.world-API aufgeführten Methoden sind auch in FMM verfügbar.
world.name
Ein String-Feld, das den Weltnamen enthält.
world:get_block_at(x, y, z)
Gibt den Materialnamen des Blocks an den angegebenen Koordinaten als Kleinbuchstaben-String zurück (z. B. "stone", "air").
| Parameter | Typ | Hinweise |
|---|---|---|
x | int | Block-X-Koordinate |
y | int | Block-Y-Koordinate |
z | int | Block-Z-Koordinate |
Beispiel
return {
api_version = 1,
on_spawn = function(context)
local loc = context.prop.current_location
if loc then
local block = context.world:get_block_at(
math.floor(loc.x),
math.floor(loc.y) - 1,
math.floor(loc.z)
)
context.log:info("Prop is standing on: " .. block)
end
end
}
world:spawn_particle(particle, x, y, z, count, dx, dy, dz, speed)
Erzeugt Partikel an einer Position.
| Parameter | Typ | Standard | Hinweise |
|---|---|---|---|
particle | string | erforderlich | Bukkit Particle-Enum-Name, GROSSBUCHSTABEN (z. B. "FLAME", "DUST") |
x | number | erforderlich | X-Koordinate |
y | number | erforderlich | Y-Koordinate |
z | number | erforderlich | Z-Koordinate |
count | int | 1 | Anzahl der Partikel |
dx | number | 0 | X-Streuung/Versatz |
dy | number | 0 | Y-Streuung/Versatz |
dz | number | 0 | Z-Streuung/Versatz |
speed | number | 0 | Partikelgeschwindigkeit |
Beispiel
return {
api_version = 1,
on_right_click = function(context)
local loc = context.prop.current_location
if loc then
context.world:spawn_particle("HEART", loc.x, loc.y + 1, loc.z, 5, 0.3, 0.3, 0.3, 0)
end
end
}
world:play_sound(sound, x, y, z, volume, pitch)
Spielt einen Sound an einer Position ab.
| Parameter | Typ | Standard | Hinweise |
|---|---|---|---|
sound | string | erforderlich | Bukkit Sound-Enum-Name, GROSSBUCHSTABEN (z. B. "ENTITY_EXPERIENCE_ORB_PICKUP") |
x | number | erforderlich | X-Koordinate |
y | number | erforderlich | Y-Koordinate |
z | number | erforderlich | Z-Koordinate |
volume | number | 1.0 | Lautstärke |
pitch | number | 1.0 | Tonhöhe |
Beispiel
return {
api_version = 1,
on_right_click = function(context)
local loc = context.prop.current_location
if loc then
context.world:play_sound("BLOCK_NOTE_BLOCK_PLING", loc.x, loc.y, loc.z, 1.0, 1.2)
end
end
}
world:strike_lightning(x, y, z)
Lässt einen Blitz an einer Position einschlagen (visuell und schadensverursachend).
| Parameter | Typ | Hinweise |
|---|---|---|
x | number | X-Koordinate |
y | number | Y-Koordinate |
z | number | Z-Koordinate |
Beispiel
return {
api_version = 1,
on_projectile_hit = function(context)
local loc = context.prop.current_location
if loc then
context.world:strike_lightning(loc.x, loc.y, loc.z)
end
end
}
world:get_time()
Gibt die aktuelle Weltzeit in Ticks zurück.
world:set_time(ticks)
Setzt die Weltzeit.
| Parameter | Typ | Hinweise |
|---|---|---|
ticks | int | Weltzeit (0 = Morgendämmerung, 6000 = Mittag, 13000 = Nacht, 18000 = Mitternacht) |
world:get_nearby_entities(x, y, z, radius)
Gibt ein Array von Entity-Wrapper-Tabellen für alle lebenden Entitäten innerhalb eines Begrenzungsrahmens zurück, der an den angegebenen Koordinaten zentriert ist.
| Parameter | Typ | Hinweise |
|---|---|---|
x | number | Zentrum X |
y | number | Zentrum Y |
z | number | Zentrum Z |
radius | number | Suchradius (wird als halbe Ausdehnung in allen drei Achsen verwendet) |
Beispiel
return {
api_version = 1,
on_right_click = function(context)
local loc = context.prop.current_location
if loc then
local entities = context.world:get_nearby_entities(loc.x, loc.y, loc.z, 10)
context.log:info("Found " .. #entities .. " entities nearby")
end
end
}
world:get_nearby_players(x, y, z, radius)
Gibt ein Array von Player-Wrapper-Tabellen für alle Spieler innerhalb eines Begrenzungsrahmens zurück, der an den angegebenen Koordinaten zentriert ist.
| Parameter | Typ | Hinweise |
|---|---|---|
x | number | Zentrum X |
y | number | Zentrum Y |
z | number | Zentrum Z |
radius | number | Suchradius |
Beispiel
return {
api_version = 1,
on_right_click = function(context)
local loc = context.prop.current_location
if loc then
local players = context.world:get_nearby_players(loc.x, loc.y, loc.z, 20)
for i = 1, #players do
context.log:info("Nearby player: " .. (players[i].name or "unknown"))
end
end
end
}
context.zones
Die Zones-Tabelle ermöglicht das Erstellen räumlicher Zonen und deren Überwachung auf Spieler-Betreten/Verlassen-Ereignisse. Zonen sind an die Skriptinstanz gebunden und werden automatisch bereinigt, wenn das Prop entfernt wird.
zones:create_sphere(x, y, z, radius)
Erstellt eine Kugelzone, die an den angegebenen Koordinaten zentriert ist. Gibt ein numerisches Zonen-Handle zurück.
| Parameter | Typ | Hinweise |
|---|---|---|
x | number | Zentrum X |
y | number | Zentrum Y |
z | number | Zentrum Z |
radius | number | Kugelradius |
zones:create_cylinder(x, y, z, radius, height)
Erstellt eine Zylinderzone. Gibt ein numerisches Zonen-Handle zurück.
| Parameter | Typ | Hinweise |
|---|---|---|
x | number | Zentrum X |
y | number | Zentrum Y (Basis) |
z | number | Zentrum Z |
radius | number | Zylinderradius |
height | number | Zylinderhöhe |
zones:create_cuboid(x, y, z, xSize, ySize, zSize)
Erstellt eine Quaderzone. Gibt ein numerisches Zonen-Handle zurück.
| Parameter | Typ | Hinweise |
|---|---|---|
x | number | Zentrum X |
y | number | Zentrum Y |
z | number | Zentrum Z |
xSize | number | Halbe Ausdehnung in X |
ySize | number | Halbe Ausdehnung in Y |
zSize | number | Halbe Ausdehnung in Z |
zones:watch(handle, onEnterCallback, onLeaveCallback)
Beginnt die Überwachung einer Zone auf Spieler-Betreten/Verlassen-Ereignisse. Wenn ein Spieler die Zone betritt oder verlässt, wird der entsprechende Hook ausgelöst (on_zone_enter oder on_zone_leave).
| Parameter | Typ | Hinweise |
|---|---|---|
handle | int | Zonen-Handle von einem create_*-Aufruf |
onEnterCallback | function oder nil | Wird aufgerufen, wenn ein Spieler die Zone betritt |
onLeaveCallback | function oder nil | Wird aufgerufen, wenn ein Spieler die Zone verlässt |
Gibt true zurück, wenn die Überwachung erfolgreich eingerichtet wurde, nil wenn das Zonen-Handle ungültig war.
Zonenüberwachungen werden jeden Server-Tick gegen alle Spieler in derselben Welt geprüft. Halten Sie die Anzahl der Zonen angemessen, um Leistungseinbußen zu vermeiden.
zones:unwatch(handle)
Beendet die Überwachung einer Zone und bereinigt ihre Ressourcen.
| Parameter | Typ | Hinweise |
|---|---|---|
handle | int | Zonen-Handle, dessen Überwachung beendet werden soll |
Beispiel: Näherungsauslöser-Zone
Beispiel
return {
api_version = 1,
on_spawn = function(context)
local loc = context.prop.current_location
if loc == nil then return end
-- Create a sphere zone around the prop
local handle = context.zones:create_sphere(loc.x, loc.y, loc.z, 5)
-- Watch for player enter/leave
context.zones:watch(
handle,
function(player)
context.log:info("Player entered zone!")
end,
function(player)
context.log:info("Player left zone!")
end
)
-- Store handle so we can clean up later if needed
context.state.zone_handle = handle
end,
on_destroy = function(context)
if context.state.zone_handle then
context.zones:unwatch(context.state.zone_handle)
end
end
}
context.scheduler
Der Scheduler ermöglicht die Ausführung verzögerter und wiederkehrender Aufgaben. Alle Aufgaben gehören zur Skriptinstanz und werden automatisch abgebrochen, wenn das Prop entfernt wird.
scheduler:run_later(ticks, callback)
Führt einen Callback einmalig nach einer Verzögerung aus. Gibt eine numerische Aufgaben-ID zurück.
| Parameter | Typ | Hinweise |
|---|---|---|
ticks | int | Verzögerung in Server-Ticks (20 Ticks = 1 Sekunde) |
callback | function | Wird mit einem frischen context aufgerufen, wenn die Verzögerung abläuft |
Beispiel
return {
api_version = 1,
on_right_click = function(context)
context.log:info("Something will happen in 2 seconds...")
context.scheduler:run_later(40, function(delayed_context)
local loc = delayed_context.prop.current_location
if loc then
delayed_context.world:spawn_particle("EXPLOSION_EMITTER", loc.x, loc.y, loc.z, 1)
end
end)
end
}
scheduler:run_repeating(delay, interval, callback)
Führt einen Callback wiederholt in festem Intervall aus. Gibt eine numerische Aufgaben-ID zurück.
| Parameter | Typ | Hinweise |
|---|---|---|
delay | int | Anfangsverzögerung in Ticks vor dem ersten Durchlauf |
interval | int | Ticks zwischen jedem weiteren Durchlauf |
callback | function | Wird mit einem frischen context bei jedem Intervall aufgerufen |
Beispiel
return {
api_version = 1,
on_spawn = function(context)
-- Emit particles every second
context.state.particle_task = context.scheduler:run_repeating(0, 20, function(tick_context)
local loc = tick_context.prop.current_location
if loc then
tick_context.world:spawn_particle("FLAME", loc.x, loc.y + 1, loc.z, 3, 0.1, 0.1, 0.1, 0.02)
end
end)
end,
on_destroy = function(context)
if context.state.particle_task then
context.scheduler:cancel(context.state.particle_task)
end
end
}
scheduler:cancel(taskId)
Bricht eine geplante Aufgabe anhand ihrer ID ab.
| Parameter | Typ | Hinweise |
|---|---|---|
taskId | int | Die von run_later oder run_repeating zurückgegebene Aufgaben-ID |
Wenn Sie eine wiederkehrende Aufgabe starten, brechen Sie diese immer in on_destroy ab (oder wenn sie nicht mehr benötigt wird). Das Vergessen des Abbruchs lässt eine Hintergrundaufgabe laufen, bis das Prop vom Server entfernt wird, was Leistung verschwendet und Fehler verursachen kann.
context.state
Eine einfache Lua-Tabelle, die für die gesamte Lebensdauer des Props bestehen bleibt. Verwenden Sie sie zum Speichern von Flags, Zählern, Aufgaben-IDs, Umschaltzuständen und allen Daten, die Sie zwischen Hooks teilen müssen.
on_spawn = function(context)
context.state.is_open = false
context.state.click_count = 0
context.state.task_id = nil
end,
on_right_click = function(context)
context.state.click_count = (context.state.click_count or 0) + 1
end
Nur context.state bleibt zwischen Hook-Aufrufen erhalten. Alle anderen Kontexttabellen (context.prop, context.world, context.event usw.) werden jedes Mal neu erstellt.
context.log
Konsolen-Logging-Methoden. Nachrichten werden in der Serverkonsole mit dem Skript-Dateinamen als Präfix versehen.
| Methode | Hinweise |
|---|---|
log:info(message) | Informationsnachricht |
log:warn(message) | Warnmeldung |
log:error(message) | Fehlermeldung (funktional identisch mit warn) |
Beispiel
return {
api_version = 1,
on_spawn = function(context)
context.log:info("Script loaded!")
end,
on_right_click = function(context)
context.log:warn("Prop was clicked -- this is a debug warning")
end
}
Laufzeitmodell
Eine Laufzeit pro Prop
Jede Prop-Entität, der Skripte zugewiesen sind, erhält ihre eigene unabhängige Lua-Laufzeitinstanz. Beim Spawnen des Props lädt FMM den Lua-Quellcode, wertet ihn in einer frischen Sandbox-Umgebung aus und speichert die zurückgegebene Tabelle. Wenn das Prop entfernt wird, wird die Laufzeit heruntergefahren.
Das bedeutet:
- Lokale Variablen, die auf Dateiebene deklariert werden, sind für diese Prop-Instanz privat.
context.stateist zwischen Prop-Instanzen vollständig isoliert, selbst wenn sie dieselbe Skriptdatei verwenden.
Aufgabenbesitz
Alle über context.scheduler erstellten Aufgaben gehören der Laufzeit, die sie erstellt hat. Wenn ein Prop entfernt wird:
- Die Laufzeit wird heruntergefahren.
- Jede zugehörige Aufgabe -- sowohl einmalige als auch wiederkehrende -- wird automatisch abgebrochen.
- Alle Zonenüberwachungen werden bereinigt.
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 innerhalb des Budgets zu bleiben:
- Vermeiden Sie unbegrenzte Schleifen innerhalb von Hooks.
- Halten Sie
on_game_tick-Handler leichtgewichtig -- sie laufen bei jedem einzelnen Tick. - Verwenden Sie
context.scheduler:run_repeating(...), um Arbeit auf mehrere Ticks zu verteilen.
Nächste Schritte
- Beispiele & Muster -- vollständige funktionierende Prop-Skripte mit Erklärungen
- Fehlerbehebung -- häufige Probleme, Debugging-Tipps und eine QC-Checkliste
- Erste Schritte -- Dateistruktur, Hooks, erste Skript-Anleitung