MagmaCore Lua-Scripting-Engine
MagmaCore stellt die Lua-Sandbox und die Laufzeit ScriptInstance für EliteMobs-Bossfähigkeiten, NPC-Skripte, FreeMinecraftModels-Props und eigene Verzauberungseffekte bereit. Sie teilen Dateivalidierung und Ressourcenverwaltung. Verfügbare Hooks, Kontexttabellen, Cooldown-Geltungsbereiche und Lebensdauer hängen jedoch vom ausführenden System ab. Verzauberungsabfragen haben außerdem einen eingeschränkten Kontext und eigene Provider-Limits; verwende dafür ihre Referenz weiter unten.
FreeMinecraftModels-Props und EliteMobs-NPC-Skripte übernehmen die generischen MagmaCore-Kontexttabellen direkt (context.world, context.zones, context.scheduler, context.cooldowns, context.log, context.event, context.player und context.state) und ergänzen ihre Besitzertabelle (context.prop oder context.npc). EliteMobs-Bossfähigkeiten verwenden dieselbe Laufzeit, stellen aber umfangreichere bossspezifische Varianten mehrerer Tabellen bereit (context.world, context.zones, context.cooldowns, context.scheduler, context.log, context.event) sowie reine Boss-Hilfen wie context.players, context.entities, context.vectors, context.settings und context.script.
Aktuell nutzen die folgenden Plugins diese Engine:
- EliteMobs — Lua-Fähigkeiten für eigene Bosse (Hooks wie
on_boss_damaged_by_player,on_enter_combatusw.) und NPC-Lua-Skripte für Interaktionen und Annäherungsverhalten (Hooks wieon_npc_interact,on_npc_proximity_enterusw.) - FreeMinecraftModels — Lua-Skripte für Props (Hooks wie
on_right_click,on_left_clickusw.) und eigene Verzauberungseffekte für benutzerdefinierte Items
Diese Seite dokumentiert die generischen MagmaCore-Engine-Funktionen, die FreeMinecraftModels-Skripte verwenden, und Kompatibilitätshinweise für EliteMobs, wo dieselben Konzepte boss- oder NPC-spezifische Varianten haben. Den genauen Boss-Kontext beschreiben die EliteMobs-Lua-Seiten; den genauen NPC-Kontext findest du unter NPC-Lua-Skripting.
Kleine Lua-Einführung
Wenn du komplett neu in Lua bist, ist hier die minimale Syntax, die du brauchst, um Skripte für jedes Nightbreak-Plugin zu schreiben.
Variablen
Verwende local, um einen Wert zu speichern:
local cooldown_key = "fire_burst"
local damage_multiplier = 1.5
local bedeutet, dass die Variable nur zu dieser Datei oder diesem Block gehört.
Funktionen
Funktionen sind wiederverwendbare Logikblöcke:
local function warn_player(player)
player:send_message("&cMove!")
end
Später kannst du sie aufrufen:
warn_player(some_player)
if-Prüfungen
Verwende if, wenn etwas nur manchmal passieren soll:
if context.player == nil then
return
end
Das bedeutet "wenn es für diesen Hook keinen Spieler gibt, hier aufhören".
nil
nil bedeutet "kein Wert". Es ist die Lua-Version von "hier ist nichts".
Häufig prüfst du auf nil mit:
if context.event ~= nil then
-- do something with the event
end
~= bedeutet "ist ungleich".
Tabellen
Lua verwendet Tabellen für verschiedene Zwecke:
- Listen
- Objekte mit benannten Schlüsseln
- Die abschließende zurückgegebene Skriptdefinition
Beispiel für eine Tabelle mit benannten Schlüsseln:
local particle = {
particle = "FLAME",
amount = 1,
speed = 0.05
}
Skriptdefinition zurückgeben
Am Ende jeder Skriptdatei gibst du eine Tabelle zurück:
return {
api_version = 1,
on_spawn = function(context)
end
}
Die zurückgegebene Tabelle ist die Skriptdefinition. Der Loader wertet die Datei zur Validierung aus und führt ihren gespeicherten Quelltext für jede Laufzeitinstanz erneut aus. Dateilokale Variablen gehören deshalb zu dieser Instanz, nicht zu allen Entities mit demselben Dateinamen. Eine Dateiänderung verändert weder eine geladene Definition noch eine laufende Instanz. Lade sie über den vorgesehenen Ablauf des zuständigen Plugins neu.
Kommentare
Verwende --, um eine Notiz für Menschen zu schreiben:
-- This cooldown stops the attack from firing every hit
context.cooldowns:set_local(60, "fire_burst")
Lua-Sandbox
Alle Lua-Skripte laufen in einer abgesicherten LuaJ-Umgebung. Mehrere Globals, die auf das Dateisystem oder die Java-Laufzeit zugreifen könnten, werden entfernt. Die Sandbox-Regeln sind in allen Plugins, die MagmaCore verwenden, identisch.
Entfernte Globals
Die folgenden Lua-Standard-Globals sind auf nil gesetzt und können nicht verwendet werden:
| Entfernt | Grund |
|---|---|
debug | Legt internen VM-Zustand offen |
dofile | Dateisystemzugriff |
io | Dateisystemzugriff |
load | Laden beliebigen Codes |
loadfile | Dateisystemzugriff |
luajava | Direkter Zugriff auf Java-Klassen |
module | Modulsystem (nicht benötigt) |
os | Betriebssystemzugriff |
package | Modulsystem (nicht benötigt) |
require | Modulsystem / Dateisystemzugriff |
Verfügbare Standardbibliothek
Die LuaJ-Standardumgebung stellt diese gewöhnlichen Lua-Funktionen bereit:
| Kategorie | Funktionen |
|---|---|
| Mathematik | math.abs, math.ceil, math.floor, math.max, math.min, math.random, math.sin, math.cos, math.sqrt, math.pi und alle weiteren math.*-Funktionen |
| String | string.byte, string.char, string.find, string.format, string.gsub, string.len, string.lower, string.match, string.rep, string.sub, string.upper und alle weiteren string.*-Funktionen |
| Tabelle | table.insert, table.remove, table.sort, table.concat und alle weiteren table.*-Funktionen |
| Iteratoren | pairs, ipairs, next |
| Typen | type, tostring, tonumber, select, unpack |
| Fehlerbehandlung | pcall, xpcall, error, assert |
| Sonstiges | print, rawget, rawset, rawequal, rawlen, setmetatable, getmetatable |
os-Bibliothek ist nicht verfügbarDie os-Bibliothek wurde vollständig aus der Sandbox entfernt. Verwende context.world:get_time() für die Weltzeit auf den generischen MagmaCore-Oberflächen; EliteMobs-Bossfähigkeiten erhalten die Methode über die gemeinsame Basis ihrer Welt-Tabelle. Für Logik mit vergangener Zeit speichere Tick-Zähler in context.state über den Hook on_game_tick.
print schreibt in die Serverkonsole; bevorzuge jedoch context.log:info(msg). Jede Oberfläche stellt context.log bereit: FreeMinecraftModels-Skripte und EliteMobs-NPC-Skripte bieten info, warn und error; EliteMobs-Bossfähigkeiten bieten info, warn und debug.
Dateivertrag
Jedes Lua-Skript muss eine Tabelle per return zurückgeben. Diese Tabelle ist absichtlich streng.
Erforderliche und optionale Top-Level-Felder
| Feld | Erforderlich | Typ | Hinweise |
|---|---|---|---|
api_version | Ja | Number | Muss aktuell 1 sein |
priority | Nein | Number | Standard 0; wird in eine Ganzzahl umgewandelt. EliteMobs-Boss- und NPC-Skripte führen niedrigere Werte zuerst aus. FMM validiert das Feld, Props folgen aber der scripts:-Liste |
| Unterstützte Hook-Schlüssel | Nein | Function | Muss einer der vom Plugin unterstützten Hook-Namen sein |
Validierungsregeln
- Die Datei muss eine Tabelle zurückgeben.
api_versionist erforderlich und muss derzeit1sein.prioritymuss numerisch sein, falls vorhanden.- Jeder zusätzliche Top-Level-Schlüssel muss ein unterstützter Hook-Name sein.
- Jeder Hook-Schlüssel muss auf eine Funktion verweisen.
- Unbekannte Top-Level-Schlüssel werden abgelehnt.
priority ist anbieterspezifischDer Lua-Validator akzeptiert priority für alle MagmaCore-gestützten Skripte. EliteMobs verwendet es für die Reihenfolge von Boss- und NPC-Skripten. FreeMinecraftModels sortiert derzeit nicht nach priority: Props folgen der Reihenfolge der scripts:-Liste in der Konfiguration. Eigene Verzauberungen verwenden ihren Provider-Katalog und ihren Aktions-/Abfragelebenszyklus.
Wo Skriptdateien liegen
Jeder Provider wählt sein Verzeichnis. Die generische Engine sucht rekursiv nach .lua-Dateien und schließt archivierte Konfigurationspfade aus. Sie sortiert normalisierte absolute Pfade zunächst ohne Beachtung der Groß- und Kleinschreibung, danach exakt. Pro kleingeschriebenem Dateinamen gewinnt die erste Datei; übersprungene Duplikate werden gemeldet, wenn sich ihr Inhalt von der gewählten Datei unterscheidet. Scheitert die gewählte Datei an der Validierung, wird kein Duplikat nachgeladen. Registrierte Abfragen behalten die tatsächliche Schreibweise des gewählten Namens bei; verwende diese in Verweisen. Bossfähigkeiten und Verzauberungskataloge haben eigene Suchregeln. Der gemeinsame Validator macht ihre Verzeichnisse nicht austauschbar.
Skripte werden anhand des Dateinamens geschlüsselt, nicht anhand des Pfads. Zwei Dateien namens door.lua in verschiedenen Unterordnern sind derselbe Schlüssel, und nur eine davon wird registriert. Gib jedem Skript einen eindeutigen Dateinamen.
Hilfsfunktionen und lokale Konstanten sollten oberhalb des abschließenden return stehen, nicht innerhalb der zurückgegebenen Tabelle, es sei denn, sie sind tatsächliche Hooks.
local ANIMATION_NAME = "idle"
local function do_something(context)
context.log:info("Doing something!")
end
return {
api_version = 1,
priority = 0,
on_spawn = function(context)
do_something(context)
end
}
Häufige Hook-Namen
Diese Hook-Namen kommen in mehreren Lua-Laufzeiten vor. Jeder Skripttyp aktiviert nur die für seinen Besitzer sinnvolle Teilmenge: FMM-Prop-Skripte verwenden alle hier aufgeführten Hooks, EliteMobs-Bossfähigkeiten ihre Boss-Hook-Liste und EliteMobs-NPC-Skripte on_spawn, on_remove, on_game_tick, on_npc_interact, on_npc_proximity_enter, on_npc_proximity_leave, on_zone_enter und on_zone_leave.
| Hook | Wann er ausgelöst wird |
|---|---|
on_spawn | Wird vom Spawn-Lebenszyklus des Plugins für FMM-Props sowie EliteMobs-Bosse und NPCs ausgelöst; allein das Erstellen eines ScriptInstance löst ihn nicht aus |
on_game_tick | Läuft jeden Server-Tick, solange die initialisierte Instanz aktiv und nicht pausiert ist |
on_zone_enter | Wird aufgerufen, wenn eine von der Laufzeit unterstützte Zone einen Eintritt meldet. FMM- und EliteMobs-NPC-Zonenüberwachungen beziehen sich auf Spieler; die Top-Level-Zonen-Hooks von EliteMobs-Bossen stammen aus EliteScript-Zonen-Events. |
on_zone_leave | Wird aufgerufen, wenn eine von der Laufzeit unterstützte Zone einen Austritt meldet. FMM- und EliteMobs-NPC-Zonenüberwachungen beziehen sich auf Spieler; die Top-Level-Zonen-Hooks von EliteMobs-Bossen stammen aus EliteScript-Zonen-Events. |
Methodensyntax: : vs .
In Lua ist object:method(arg) die Kurzform für object.method(object, arg). Die Methoden der MagmaCore-Kontexttabellen entfernen dieses implizite erste Argument, daher funktionieren beide Formen bei Methoden wie context.log.info:
context.log:info("hello")
context.log.info("hello") -- same thing
Globale Hilfsfunktionen unter em sind einfache Funktionen und keine Methoden von Kontexttabellen. Rufe sie mit . auf: em.create_location(...), em.zone.create_sphere_zone(...) und em.location.is_protected(...). Auch die EliteMobs-Event-Setter context.event.set_damage_amount(...) und context.event.multiply_damage_amount(...) erfordern .. Die Dokumentation verwendet : für Methoden von Kontexttabellen und . für einfache Funktionen.
Ausführungsbudget
Jeder Hook-Aufruf, jeder geplante Callback-Aufruf und die anfängliche Auswertung der Skriptdatei selbst laufen unter einem harten Ausführungsbudget. Das Budget wird innerhalb der Lua-VM durchgesetzt, greift also, während dein Code noch läuft, statt erst danach die Uhr zu prüfen.
Die gewöhnliche Laufzeit verwendet diese Limits:
| Limit | Wert |
|---|---|
| CPU-Zeit des aktuellen Threads | 50 Millisekunden |
| Ausgeführte Lua-Instruktionen | 250.000 |
Ein überschrittenes Limit löst einen Lua-Fehler aus. Der Instruktionszähler wird bei jeder Lua-Instruktion geprüft, die Uhr alle 1.024 Instruktionen und nach Rückkehr des Aufrufs. Eine laufende Java/Bukkit-Methode wird dadurch nicht unterbrochen. 50 ms CPU-Zeit sind keine Frist von 50 ms Echtzeit. Ein nicht abgefangener Fehler in Hook oder Callback schließt die Instanz; bei der anfänglichen Validierung wird die Definition abgelehnt. Ohne CPU-Zeitmessung des aktuellen Threads gelten 250 Millisekunden vergangene Zeit und dasselbe Instruktionslimit. Verzauberungsabfragen können kleinere gemeinsame Budgets verwenden.
Die VM unterbricht ein gewöhnliches while true do end während der Lua-Instruktionen. Die Schleife verbraucht dennoch Zeit auf dem Server-Thread und schließt die Instanz, wenn der Fehler weitergereicht wird. Begrenze Schleifen trotz dieser Überwachung.
Verschachtelte Aufrufe teilen sich ein Budget: Wenn ein Hook einen Callback aufruft, der wiederum einen weiteren aufruft, wird die gesamte Kette als eine einzige Zuteilung von 50 ms CPU-Zeit / 250.000 Instruktionen gemessen, nicht als je eine Zuteilung pro Aufruf.
Um im Budget zu bleiben:
- Vermeide unbegrenzte Schleifen innerhalb von Hooks.
- Halte
on_game_tick-Handler schlank -- sie laufen in jedem einzelnen Tick. - Verwende
context.scheduler:run_repeating(...), um Arbeit auf mehrere Ticks zu verteilen. - Begrenze aufwendige Arbeit mit
context.cooldownsoder einem angemessenen Intervall.
Ein nicht abgefangener Laufzeitfehler in Hook oder Callback schließt diese Instanz und bricht ihre eigenen Aufgaben ab. Korrigiere und lade die Definition neu, damit das zuständige Plugin eine neue Instanz erstellen kann. Das Speichern der Datei repariert die geschlossene Instanz nicht. Verzauberungssysteme wenden zusätzlich ihre Regeln zur Unterdrückung wiederholter Fehler an.
context.state
Eine einfache Lua-Tabelle, die während der gesamten Lebensdauer der Skript-Instanz erhalten bleibt. Verwende sie, um Flags, Zähler, Task-IDs, Toggle-Zustände und alle Daten zu speichern, die du zwischen Hooks teilen möchtest.
return {
api_version = 1,
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
}
Verwende context.state für Daten zwischen den Hooks einer Instanz. Sie liegen im Arbeitsspeicher und überdauern weder Neuladen noch Neustarts. Andere Tabellen werden bei Bedarf erstellt und können Momentaufnahmen enthalten. FMM speichert context.prop zwischen, liest Felder wie current_location aber bei Bedarf. Lies ein dynamisches Feld erneut, um es zu aktualisieren; eine bereits gespeicherte Tabelle aktualisiert sich nicht selbst. Das Zuweisen eines solchen Feldes verdeckt seinen Getter.
context.log
Methoden zur Konsolenausgabe, verfügbar auf jeder Skript-Oberfläche. Generische log.info-Meldungen tragen das Präfix [Lua]. Ergänze eine Skriptbezeichnung in deiner Nachricht, wenn du die Quelle erkennen möchtest. Fehlerdiagnosen benennen das fehlerhafte Skript; gewöhnliche Logausgaben fügen seinen Dateinamen jedoch nicht automatisch hinzu. FreeMinecraftModels-Skripte und EliteMobs-NPC-Skripte bieten info, warn und error; EliteMobs-Bossfähigkeiten bieten info, warn und debug.
| Methode | Hinweise |
|---|---|
log:info(message) | Informationsmeldung |
log:warn(message) | Warnmeldung |
log:error(message) | Meldung auf Warn-Ebene (wird auf WARN-Level geloggt, identisch zu log:warn) |
Das EliteMobs context.log registriert debug statt error. Verwende log:debug(message) für Debug-Ausgaben (erscheint als Info-Level mit einem Debug-Präfix).
context.log:info("Script loaded!")
context.log:warn("Something unexpected happened")
-- Generic/FMM/NPC logger:
context.log:error("Critical failure in zone setup")
-- EliteMobs boss logger:
context.log:debug("Boss debug detail")
context.cooldowns
Die Tabelle verwaltet Cooldowns. Lokale und generische globale Cooldowns rechnen jeden Tick in 50 ms monoton gemessene Zeit um, einschließlich Pausen und niedriger TPS. Globale Boss-Cooldowns zählen dagegen Server-Ticks. Es gibt zwei Geltungsbereiche:
- Lokale Cooldowns verwenden exakte String-Schlüssel im Speicher des Besitzers, dessen Geltungsbereich unten steht.
nilwählt den Standardschlüssel__lua:gefolgt vom Skriptdateinamen. - Globale Cooldowns werden über alle Skripte derselben Besitzer-Entität geteilt, sofern die Laufzeit globale Cooldown-Methoden anbietet (etwa alle Skripte desselben Props oder alle Lua-Fähigkeiten desselben Bosses).
cooldowns:check_local(key?, duration)
Prüft einen lokalen Schlüssel und startet seinen Cooldown, wenn er bereit ist; dann wird true, sonst false zurückgegeben. Dies ist ein synchroner Lua-Aufruf. Er prüft oder startet keinen globalen Cooldown. Der Speicher ist keine API zur Synchronisierung mehrerer Threads.
| Parameter | Typ | Hinweise |
|---|---|---|
key | string (optional) | Cooldown-Bezeichner. nil wählt den Standardschlüssel. |
duration | int | Cooldown-Dauer in Ticks (20 = 1 Sekunde) |
on_right_click = function(context)
-- Only allow this action once every 3 seconds
if not context.cooldowns:check_local("interact", 60) then
return
end
-- ... do the action
end
Alle Skript-Oberflächen — Bossfähigkeiten, NPC-Skripte und FreeMinecraftModels-Skripte — verwenden die oben gezeigte gemeinsame Reihenfolge: check_local(key?, duration). Für den Standardschlüssel übergib check_local(nil, 60); check_local(60) bedeutet keinen 60-Tick-Cooldown mit Standardschlüssel. (Frühere experimentelle NPC-Builds verwendeten check_local(duration, key?); passe alte NPC-Skripte auf die gemeinsame Reihenfolge an.)
cooldowns:local_ready(key?)
Gibt true zurück, wenn der lokale Cooldown abgelaufen ist (oder nie gesetzt wurde), false, wenn er noch aktiv ist.
cooldowns:local_remaining(key?)
Gibt die Anzahl der verbleibenden Ticks im lokalen Cooldown zurück, oder 0, wenn bereit.
cooldowns:set_local(duration, key?)
Setzt einen lokalen Cooldown, ohne zu prüfen, ob bereits einer aktiv ist. Verwende dies für unbedingte Cooldown-Resets.
| Parameter | Typ | Hinweise |
|---|---|---|
duration | int | Dauer in Ticks. Übergib 0 oder einen negativen Wert, um zu löschen. |
key | string (optional) | Cooldown-Bezeichner. nil wählt den Standardschlüssel. |
cooldowns:global_ready()
Gibt true zurück, wenn der globale Cooldown (geteilt über alle Skripte auf derselben Entity) abgelaufen ist.
cooldowns:set_global(duration)
Setzt den globalen Cooldown. In generischen MagmaCore-Tabellen löschen null oder negative Dauern ihn. Globale Boss-Cooldowns behalten den späteren Ablauf: Eine kürzere Dauer verkürzt nie einen aktiven globalen Cooldown, und null oder negative Dauern bewirken nichts. Das Setzen eines lokalen Cooldowns setzt nicht automatisch den globalen und umgekehrt.
| Parameter | Typ | Hinweise |
|---|---|---|
duration | int | Dauer in Ticks |
Der "Owner" eines globalen Cooldowns hängt vom Skripttyp ab:
- EliteMobs Lua-Powers — geteilt pro
EliteEntity(ein Bucket pro Boss).global_ready()/set_global()verwenden das eingebaute Power-Cooldown-System des Bosses; lokale Cooldowns werden ebenfalls über alle Powers auf demselben Boss geteilt. - EliteMobs-NPC-Skripte: Globale Cooldowns und explizite lokale Schlüssel werden über den einzigen Adapter des NPCs geteilt. Zwei Skripte mit demselben lokalen Schlüssel beeinflussen einander; ausgelassene Schlüssel bleiben dateispezifisch.
- FMM-Prop-Skripte: Globale Cooldowns gelten pro platziertem Prop; jedes angehängte Skript besitzt einen eigenen Adapter mit lokalem Speicher.
- Verzauberungsaktionen — globale Cooldowns gelten gemeinsam pro Spieler innerhalb des Providers; lokale Cooldowns gehören zum Spieler und zur Verzauberungs-ID und überdauern Ausrüstungswechsel und abgeschlossene Aktionen. Siehe eigene Verzauberungen.
context.scheduler
Der Scheduler führt verzögerte und wiederholte Aufgaben aus. Über ihn erstellte Aufgaben gehören zur Instanz und werden beim Schließen abgebrochen. Das macht weder gespawnte Entities noch Weltänderungen oder Timer separater UI-/Effektmethoden rückgängig. Während einer Pause warten fällige einmalige Aufgaben auf die Fortsetzung; wiederholte Aufgaben überspringen ihre pausierten Aufrufe.
Dieser Abschnitt verwendet die MagmaCore-Scheduler-Namen (run_later, run_repeating, cancel). Die EliteMobs-Namen (run_after(ticks, callback), run_every(interval, callback), cancel_task(taskId)) werden auf jeder Oberfläche als Aliasse akzeptiert. Beide Schreibweisen funktionieren daher in jedem Skript.
scheduler:run_later(ticks, callback)
Führt einen Callback einmal nach einer Verzögerung aus. Gibt eine numerische Task-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 |
context.scheduler:run_later(40, function(delayed_context)
delayed_context.log:info("2 seconds have passed!")
end)
scheduler:run_repeating(delay, interval, callback)
Führt einen Callback wiederholt in einem festen Intervall aus. Gibt eine numerische Task-ID zurück.
| Parameter | Typ | Hinweise |
|---|---|---|
delay | int | Anfängliche Verzögerung in Ticks vor dem ersten Lauf |
interval | int | Ticks zwischen jedem nachfolgenden Lauf |
callback | function | Wird in jedem Intervall mit einem frischen context aufgerufen |
context.state.particle_task = context.scheduler:run_repeating(0, 20, function(tick_context)
tick_context.log:info("Another second passed!")
end)
scheduler:cancel(taskId)
Bricht eine eigene Aufgabe dieser Instanz anhand ihrer ID ab. Eine unbekannte oder fremde ID bewirkt nichts.
| Parameter | Typ | Hinweise |
|---|---|---|
taskId | int | Die von run_later oder run_repeating zurückgegebene Task-ID |
Das Schließen bricht eigene Aufgaben automatisch ab. Beende sie früher, wenn eine Interaktion oder Kampfphase endet und die Instanz aktiv bleibt, etwa im Boss-Hook on_exit_combat. Beide Namensfamilien funktionieren. Verwende die Lebenszyklus-Hooks des zuständigen Plugins; ein Fehler schließt die Instanz ohne Garantie eines eigenen Cleanup-Hooks.
Callbacks erhalten einen neuen Kontext ohne ursprüngliches Event oder auslösenden Spieler. Verwende diesen statt des äußeren Kontexts. Falls du den Spieler später brauchst, speichere seine UUID im Hook und löse sie erneut auf; prüfe dabei seine Verfügbarkeit. Ein aufbewahrter äußerer Kontext kann ein dynamisches Event-Feld erst nach Ende des ursprünglichen Events auflösen.
context.world
Die Welt-Tabelle bietet Methoden für Minecraft-Weltabfragen und Änderungen. Sie erfasst die aktuelle Welt des Besitzers beim ersten Aufbau. Eine gespeicherte Tabelle folgt späteren Weltwechseln nicht.
Diese Methoden beschreiben die gemeinsame Tabelle für FMM-Props und EliteMobs-NPCs, einschließlich des schädigenden strike_lightning(...). FMM ergänzt optionale EliteMobs-Transport- und Loot-Helfer; siehe context.world: FreeMinecraftModels-Ergänzungen. EliteMobs ergänzt seine gemeinsamen Tabellen um visuelle Blitze und NPC-/Boss-Spawns mit Prüfung auf geladene Chunks. Bossfähigkeiten ergänzen oder überschreiben anschließend eigene Methoden; siehe EliteMobs: Welt & Umgebung.
context.world akzeptiert auf den generischen Oberflächen sowohl Aufrufe im Koordinatenstil (z. B. strike_lightning(x, y, z), spawn_particle(name, x, y, z, ...)) als auch Überladungen im Location-Tabellen-Stil (z. B. strike_lightning_at_location(loc), spawn_particle_at_location(loc, ...)). EliteMobs-Boss-Powers unterstützen ebenfalls beide Stile, allerdings haben einige Location-Tabellen-Methoden dort boss-spezifisches Verhalten.
Gemeinsame Location-Argumente benötigen x, y und z. Eine ausgelassene oder nicht auflösbare Welt verwendet die Welt der Tabelle. Gemeinsame Partikelaufrufe mit Location verwenden weiterhin diese erfasste Welt; übergib daher eine Position derselben Welt. Boss-Konverter und em.location.*-Abfragen folgen anderen Regeln in ihren Referenzen.
Die vollständige Referenz der Welt-Tabelle beschreibt außerdem Entity-Suchen, Abfragen zu Passierbarkeit und Gebietsschutz, farbige Staubpartikel, Geländeeinschläge und Überladungen mit Location-Tabellen.
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 String in Kleinbuchstaben zurück (z. B. "stone", "air"). Nicht geladene Chunks liefern "air"; die Abfrage lädt sie nicht nach.
| Parameter | Typ | Hinweise |
|---|---|---|
x | int | Block-X-Koordinate |
y | int | Block-Y-Koordinate |
z | int | Block-Z-Koordinate |
world:set_block_at(x, y, z, material)
Setzt den Block an den angegebenen Koordinaten. Wird im Main-Thread ausgeführt und lädt keine Chunks nach.
| Parameter | Typ | Hinweise |
|---|---|---|
x | int | Block-X-Koordinate |
y | int | Block-Y-Koordinate |
z | int | Block-Z-Koordinate |
material | string | Bukkit-Materialname, kleingeschrieben (z. B. "stone", "air", "oak_planks") |
Gibt true zurück, wenn das Material gültig ist und die Änderung eingeplant wurde. Das bestätigt keine tatsächlich erfolgte Platzierung: Ist der Chunk bei Ausführung des Tasks nicht geladen, wird die Änderung übersprungen. Ein ungültiges Material liefert false.
Regionsschutz wird nicht automatisch geprüft. Verwende ein Blockmaterial und frage den passenden Schutz vor der Platzierung ab; eine angenommene Aufgabe beweist keine Blockänderung.
world:spawn_particle(particle, x, y, z, count, dx, dy, dz, speed)
Spawnt Partikel an einer Position.
| Parameter | Typ | Standard | Hinweise |
|---|---|---|---|
particle | string | erforderlich | Name des Bukkit-Particle-Enums; wird vor der Suche großgeschrieben (z. B. "FLAME", "HAPPY_VILLAGER") |
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 |
Einige Partikeltypen benötigen zusätzliche Daten, die diese einfache API nicht übergibt; dazu gehören DUST und FALLING_DUST. Verwende hier datenfreie Partikel wie CLOUD, SMOKE, CAMPFIRE_COSY_SMOKE, SNOWFLAKE, FLAME, HAPPY_VILLAGER, HEART, NOTE oder ENCHANT. Für farbigen Staub verwende world:spawn_dust(...). Ein Partikel, das Daten benötigt, kann bei dieser einfachen Methode eine Bukkit-Ausnahme auslösen und die Skript-Instanz deaktivieren.
world:play_sound(sound, x, y, z, volume, pitch)
Spielt einen Sound an einer Position ab.
| Parameter | Typ | Standard | Hinweise |
|---|---|---|---|
sound | string | erforderlich | Name des Bukkit-Sound-Enums (z. B. "ENTITY_EXPERIENCE_ORB_PICKUP") oder ein benutzerdefinierter Ressourcenpaket-Sound-Schlüssel (z. B. "mypack:boss.roar") |
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 |
Der Name wird zuerst gegen die bei Bukkit registrierten Sounds abgeglichen (ohne Beachtung der Groß-/Kleinschreibung, "ENTITY_ARROW_SHOOT" und "entity_arrow_shoot" sind also dasselbe). Passt nichts, wird er zu einem kleingeschriebenen Namespace-Schlüssel normalisiert und als benutzerdefinierter Ressourcenpaket-Sound abgespielt. Ein Wert, der weder ein bekannter Sound noch ein gültiger Namespace-Schlüssel ist, spielt nichts ab, statt einen Fehler auszulösen — ein Tippfehler bewirkt also still gar nichts, statt dein Skript zu deaktivieren.
Dasselbe gilt für world:play_sound_at_location(loc, sound, volume, pitch).
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 |
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 ab eins indiziertes Array von Entity-Tabellen in einem achsenparallelen Quader um die Koordinaten zurück. Der Skriptbesitzer wird nicht ausgeschlossen.
| Parameter | Typ | Hinweise |
|---|---|---|
x | number | Mittelpunkt X |
y | number | Mittelpunkt Y |
z | number | Mittelpunkt Z |
radius | number | Suchradius (wird als halbe Ausdehnung in allen drei Achsen verwendet) |
Dies gibt ALLE Entities im Bereich zurück, einschließlich nicht lebender Entities (gedroppter Items, Projektile usw.). Sichere immer mit if entity.damage then ab, bevor du Methoden für lebende Entities aufrufst.
world:get_nearby_players(x, y, z, radius)
Gibt ein ab eins indiziertes Array von Spielertabellen in einem achsenparallelen Quader zurück. radius ist jede halbe Ausdehnung. Spielmodi werden nicht gefiltert.
| Parameter | Typ | Hinweise |
|---|---|---|
x | number | Mittelpunkt X |
y | number | Mittelpunkt Y |
z | number | Mittelpunkt Z |
radius | number | Suchradius |
world:spawn_entity(entity_type, x, y, z)
Spawnt eine Vanilla-Minecraft-Entity an der angegebenen Position.
| Parameter | Typ | Hinweise |
|---|---|---|
entity_type | string | Bukkit-Entity-Type-Name, kleingeschrieben (z. B. "zombie", "skeleton", "pig") |
x | number | X-Koordinate |
y | number | Y-Koordinate |
z | number | Z-Koordinate |
Gibt eine Entity-Tabelle mit passenden Methoden für lebende Entities zurück, bei unbekanntem Enum-Namen nil. Ein gültiger, aber nicht spawnbarer Typ kann einen Fehler auslösen. Die Methode prüft nicht, ob der Chunk geladen ist.
world:get_highest_block_y(x, z)
Gibt Bukkits höchste Block-Y-Koordinate bei X/Z zurück. Anders als get_block_at prüft diese Abfrage nicht, ob der Chunk geladen ist.
| Parameter | Typ | Hinweise |
|---|---|---|
x | int | Block-X-Koordinate |
z | int | Block-Z-Koordinate |
world:raycast(from_x, from_y, from_z, dir_x, dir_y, dir_z, [max_distance], [fluid_mode], [blocks_only], [loaded_only])
Wirft einen Strahl von einem Punkt in eine Richtung aus und gibt Informationen darüber zurück, was er trifft.
| Parameter | Typ | Standard | Hinweise |
|---|---|---|---|
from_x | number | erforderlich | Ursprung X |
from_y | number | erforderlich | Ursprung Y |
from_z | number | erforderlich | Ursprung Z |
dir_x | number | erforderlich | Richtungskomponente X |
dir_y | number | erforderlich | Richtungskomponente Y |
dir_z | number | erforderlich | Richtungskomponente Z |
max_distance | number | 50 | Maximale Strahldistanz |
fluid_mode | string | "NEVER" | Flüssigkeitskollisionen: "NEVER", "SOURCE_ONLY" oder "ALWAYS" |
blocks_only | boolean | false | Ignoriert Entities, wenn true |
loaded_only | boolean | false | Gibt nil zurück, wenn irgendein Chunk im umschließenden Rechteck des Strahls nicht geladen ist |
Gibt eine Tabelle mit den folgenden Feldern zurück, oder nil, wenn die Prüfung für loaded_only fehlschlägt. Ohne Treffer sind die Trefferfelder nil.
| Feld | Typ | Hinweise |
|---|---|---|
hit_entity | entity table oder nil | Die erste vom Strahl getroffene Entity, oder nil, wenn keine |
hit_location | location table oder nil | Der exakte Punkt, an dem der Strahl etwas getroffen hat |
hit_block | table oder nil | {x, y, z, material} des getroffenen Blocks, oder nil, wenn kein Block getroffen wurde |
Blockmaterialien sind kleingeschrieben. Die kombinierte Abfrage verwendet die Strahlgröße 0.5 für Entities ohne Entity-Filter. Die Chunk-Prüfung erfasst das gesamte umschließende Rechteck und kann deshalb einen Chunk abseits des exakten Strahls ablehnen. Ein ungültiger Flüssigkeitsmodus löst einen Fehler aus.
world:spawn_firework(x, y, z, colors, [type], [power])
Spawnt eine Feuerwerksrakete an der angegebenen Position.
| Parameter | Typ | Standard | Hinweise |
|---|---|---|---|
x | number | erforderlich | X-Koordinate |
y | number | erforderlich | Y-Koordinate |
z | number | erforderlich | Z-Koordinate |
colors | table | erforderlich | Array von Farb-Strings, z. B. {"RED", "BLUE", "WHITE"} |
type | string | "BALL" | Feuerwerksform: "BALL", "BALL_LARGE", "STAR", "BURST", "CREEPER" |
power | int | 1 | Flugkraft, 0-127 |
-- Example: red and yellow firework burst
context.world:spawn_firework(loc.x, loc.y, loc.z, {"RED", "YELLOW"}, "BURST", 2)
world:place_temporary_block(x, y, z, material, [ticks], [require_air])
Platziert einen temporären Block und stellt gespeicherte BlockData nach einer positiven Dauer wieder her. Vollständiger Blockzustand und Inventar werden nicht erfasst.
| Parameter | Typ | Standard | Hinweise |
|---|---|---|---|
x | int | erforderlich | Block-X-Koordinate |
y | int | erforderlich | Block-Y-Koordinate |
z | int | erforderlich | Block-Z-Koordinate |
material | string | erforderlich | Bukkit-Materialname (z. B. "stone", "ice") |
ticks | int | 0 | Dauer in Ticks bis zur Wiederherstellung. Null oder negative Werte platzieren den Block dauerhaft und ohne Verwaltung. |
require_air | boolean | false | Wenn true, wird der Block nur gesetzt, wenn das Ziel Luft ist |
Gibt bei ungültigem Material oder einem nicht geladenen Chunk false zurück. true bedeutet, dass die Anfrage angenommen wurde; bei require_air=true kann der Manager die Platzierung trotzdem überspringen, wenn das Ziel keine Luft ist.
Bei positiven Ticks sichert der Manager die ursprünglichen Blockdaten und stellt sie wieder her, wenn der Timer endet, wenn der Chunk oder die Welt entladen wird oder wenn das Plugin herunterfährt. Er stellt nur wieder her, solange an der Stelle noch der temporäre Block steht; eine spätere Bearbeitung wird also nicht überschrieben. Eine erneute Platzierung auf einem Block, der noch einen temporären Block enthält, startet dessen Timer neu und behält das zuerst gesicherte Original. Blöcke mit Block-Entities wie Truhen und Schilder sowie Blöcke, die bereits ein anderer Besitzer temporärer Blöcke hält, etwa ein Verzauberungs-Lease, werden übersprungen. Das Abbauen eines temporären Blocks lässt nichts fallen und beendet die Verwaltung ohne Wiederherstellung; auch das Platzieren eines Blocks an dieser Stelle beendet die Verwaltung.
Diese Timer werden nicht mit dem Lua-Skript beendet, und die Platzierung prüft Regionsschutz nicht automatisch.
world:drop_item(x, y, z, material, [amount])
Droppt eine Item-Entity an der angegebenen Position mit natürlicher Streuung.
| Parameter | Typ | Standard | Hinweise |
|---|---|---|---|
x | number | erforderlich | X-Koordinate |
y | number | erforderlich | Y-Koordinate |
z | number | erforderlich | Z-Koordinate |
material | string | erforderlich | Bukkit-Materialname |
amount | int | 1 | Stack-Größe |
Gibt eine Entity-Tabelle für das gedroppte Item zurück, oder nil, wenn das Material ungültig war.
context.zones
Die generische Zonen-Tabelle für FMM-Props und NPCs erstellt räumliche Zonen und überwacht, wann Spielerpunkte sie betreten oder verlassen. Zonen gehören zur Skript-Instanz und werden beim Zerstören der Instanz automatisch aufgeräumt. EliteMobs-Boss-Powers verwenden eine andere Tabelle mit Methoden wie get_entities_in_zone, get_locations_in_zone und watch_zone; siehe Zonen & Targeting.
zones:create_sphere(x, y, z, radius)
Erstellt eine Kugelzone um die Koordinaten und gibt ein numerisches Handle zurück, oder nil, wenn der Besitzer keine Welt hat.
| Parameter | Typ | Hinweise |
|---|---|---|
x | number | Mittelpunkt X |
y | number | Mittelpunkt Y |
z | number | Mittelpunkt Z |
radius | number | Kugelradius |
zones:create_cylinder(x, y, z, radius, height)
Erstellt eine Zylinderzone und gibt ein numerisches Handle zurück, oder nil, wenn der Besitzer keine Welt hat.
| Parameter | Typ | Hinweise |
|---|---|---|
x | number | Mittelpunkt X |
y | number | Mittelpunkt Y (Basis) |
z | number | Mittelpunkt Z |
radius | number | Zylinderradius |
height | number | Zylinderhöhe |
zones:create_cuboid(x, y, z, xSize, ySize, zSize)
Erstellt eine Quaderzone und gibt ein numerisches Handle zurück, oder nil, wenn der Besitzer keine Welt hat. Die Punktprüfung behandelt Größen als halbe Ausdehnungen um den Mittelpunkt. Das unterscheidet sich von EliteMobs-Entity-Abfragen und gesampelten Zonenpositionen. Ist zSize null und xSize ungleich null, wird für Z die X-Größe verwendet.
| Parameter | Typ | Hinweise |
|---|---|---|
x | number | Mittelpunkt X |
y | number | Mittelpunkt Y |
z | number | Mittelpunkt Z |
xSize | number | Halbe Ausdehnung in X |
ySize | number | Halbe Ausdehnung in Y |
zSize | number | Halbe Ausdehnung in Z |
zones:watch(handle, onEnterCallback, onLeaveCallback)
Aktiviert Eintritts- und Austrittsmeldungen einer bereits erstellten Zone. Die Argumente müssen Lua-Funktionen sein; ihre Körper werden nicht direkt aufgerufen. Die Logik läuft in on_zone_enter / on_zone_leave. Anwesenheit wird ab Erstellung erfasst. Ein späteres watch meldet deshalb keinen Eintritt eines bereits darin erfassten Spielers. nil bei einem weiteren watch entfernt keinen zuvor aktivierten Handler.
| Parameter | Typ | Hinweise |
|---|---|---|
handle | int | Zonen-Handle aus einem create_*-Aufruf |
onEnterCallback | function oder nil | Eine Funktion aktiviert den Hook on_zone_enter für diese Zone |
onLeaveCallback | function oder nil | Eine Funktion aktiviert den Hook on_zone_leave für diese Zone |
Gibt true zurück, wenn die Überwachung erfolgreich eingerichtet wurde, nil, wenn das Zonen-Handle ungültig war.
Zonen werden vor on_game_tick anhand der Spielerpositionen in der aktuellen Welt des Besitzers geprüft, nicht anhand ganzer Bounding Boxes. Kugeln verlangen Punkte strikt innerhalb des Radius; Zylinder zusätzlich zwischen eingeschlossener Basis und ausgeschlossener Oberseite. Zonen behalten Koordinaten und Welt ihrer Erstellung. Disconnects oder entfernte Überwachungen garantieren keinen Austritts-Hook. Halte die Zonenanzahl überschaubar.
zones:unwatch(handle)
Beendet die Überwachung einer Zone und räumt deren Ressourcen auf.
| Parameter | Typ | Hinweise |
|---|---|---|
handle | int | Zonen-Handle, dessen Überwachung beendet werden soll |
Beispiel: Näherungs-Triggerzone
return {
api_version = 1,
on_spawn = function(context)
local loc = context.prop.current_location
if loc == nil then return end
local handle = context.zones:create_sphere(loc.x, loc.y, loc.z, 5)
-- Pass placeholder functions to enable on_zone_enter and on_zone_leave hooks.
-- The placeholder bodies are ignored; the actual logic goes in the hooks below.
context.zones:watch(handle, function() end, function() end)
context.state.zone_handle = handle
end,
on_zone_enter = function(context)
context.log:info("Player entered zone!")
end,
on_zone_leave = function(context)
context.log:info("Player left zone!")
end,
on_destroy = function(context)
if context.state.zone_handle then
context.zones:unwatch(context.state.zone_handle)
end
end
}
context.event
Die Event-Tabelle ist vorhanden, wenn der aktuelle Hook ein Event oder einen beteiligten Spieler mitliefert. FMM liefert das Event über den jeweiligen Plugin-Hook; NPCs und generische Zonen-Hooks können einen Spieler ohne Bukkit-Event bereitstellen. Bei on_game_tick, geplanten Callbacks und Lebenszyklus-Hooks ohne beteiligten Spieler fehlt sie gewöhnlich.
Hooks on_projectile_hit von FMM-Props erhalten das abbrechbare Projektiltreffer-Event von FreeMinecraftModels, daher sind cancel() und uncancel() vorhanden. Der Hook läuft, nachdem FMM den Treffer verarbeitet hat; ein Abbruch verhindert also nicht, dass ein nicht durchdringendes Projektil verbraucht wird. Er wird nicht ausgelöst, wenn ein anderes Plugin den Treffer bereits abgebrochen hat. context.event.player ist der Schütze, sofern er eine lebende Entity ist, was auch ein Mob sein kann, und fehlt andernfalls; context.player ist nur gesetzt, wenn ein Spieler das Projektil abgefeuert hat. Der Hook stellt außerdem context.projectile als Entity-Tabelle für das Projektil bereit.
Generische Zonen-Hooks liefern context.player und context.event.player, aber keine Methoden zum Abbrechen eines Events.
| Feld / Methode | Typ | Hinweise |
|---|---|---|
is_cancelled | boolean | Abbruchzustand beim ersten Auflösen der Event-Untertabelle; cancel() und uncancel() aktualisieren ihn nicht |
cancel() | method | Bricht das Event ab (verhindert das Standardverhalten); nur bei abbrechbaren Events vorhanden |
uncancel() | method | Hebt den Abbruch eines Events auf; nur bei abbrechbaren Events vorhanden |
player | entity table | Der am Event beteiligte Spieler, falls vorhanden |
on_right_click = function(context)
if context.event and context.event.cancel then
context.event:cancel() -- prevent the default right-click interaction
end
end
EliteMobs-Power-Skripte haben eine detailliertere Event-Tabelle mit Schadensbeträgen, Schadensursachen, Verweisen auf den Schadensverursacher und Methoden zur Schadensmodifikation. Siehe Lua-API-Referenz für die vollständigen EliteMobs-Event-Felder.
em-Hilfsnamespace
Die em-Tabelle ist beim Laden der Datei verfügbar. Ihre Konstruktoren erstellen Daten, ohne Welten zu laden, Überwachungen anzumelden oder vollständige Formen zu validieren. Zurückgegebene Setter ändern ihre Tabelle und behalten übergebene Location-Tabellen als Referenz.
| Funktion | Zweck |
|---|---|
em.create_location(x, y, z [, world, yaw, pitch]) | Erstellt eine Location-Tabelle mit optionalem Weltnamen, Yaw und Pitch. Die zurückgegebene Tabelle besitzt zusätzlich eine .add(dx, dy, dz)-Methode, die die Location an Ort und Stelle versetzt und sich selbst zur Verkettung zurückgibt. |
em.create_vector(x, y, z) | Erstellt eine Vektor-Tabelle |
em.zone.create_sphere_zone(radius) | Erstellt eine Kugelzonen-Definition |
em.zone.create_dome_zone(radius) | Erstellt eine Kuppelzonen-Definition |
em.zone.create_cylinder_zone(radius, height) | Erstellt eine Zylinderzonen-Definition |
em.zone.create_cuboid_zone(x, y, z) | Erstellt eine Quaderzonen-Definition |
em.zone.create_cone_zone(length, radius) | Erstellt eine Kegelzonen-Definition |
em.zone.create_static_ray_zone(length, thickness) | Erstellt eine statische Strahlenzonen-Definition |
em.zone.create_rotating_ray_zone(length, point_radius, animation_duration) | Erstellt eine rotierende Strahlenzonen-Definition |
em.zone.create_translating_ray_zone(length, point_radius, animation_duration) | Erstellt eine sich bewegende Strahlenzonen-Definition |
em.location.is_in_dungeon(loc) | Prüft, ob sich eine Location innerhalb einer registrierten Dungeon-Region befindet (jeder Besitzer, der das Kind "dungeon" meldet) |
em.location.is_protected(loc) | Prüft, ob sich eine Location innerhalb einer geschützten Region befindet (WorldGuard, GriefPrevention, EM-Regionen usw.) |
em.location.owned_by(loc, namespace) | Prüft, ob ein bestimmter Plugin-Namespace die Location besitzt (z. B. "EliteMobs") |
em.location.owners(loc) | Array von Namespace-Strings, die die Location besitzen |
em.location.kinds_at(loc) | Array von Kind-Tags an der Location ("elitemobs", "dungeon", "world_package", "open_world_dungeon", Dungeon-Größenkategorie) |
em.location.has_kind(loc, kind) | Prüft, ob die Location mit dem angegebenen Kind getaggt ist |
MagmaCore liefert WorldGuard- und GriefPrevention-Adapter. Verbraucher initialisieren sie beim Aktivieren; eine Schutzabfrage kann sie ebenfalls bei Bedarf initialisieren. Abfragen erfassen registrierte Provider, nicht jedes mögliche Schutzplugin. Ein fehlschlagender registrierter Regionsadapter meldet Schutz. Ohne Provider oder geschützten Besitz liefert die Abfrage false; Warnungen melden fehlende Provider.
Für em.location.* muss world den Namen einer geladenen Welt oder {name=...} enthalten. Es gibt keinen Rückfall auf die Besitzerwelt. Eine fehlende oder unbekannte Welt sowie nil liefern false oder ein leeres Array. Fehlende Koordinaten werden null; fehlerhafte Zahlenfelder können jedoch einen Fehler auslösen. Besitzer-Namespaces beachten Groß- und Kleinschreibung, Kind-Tags nicht. Besitz allein bedeutet weder Dungeon-Zugehörigkeit noch Schutz. Die Array-Reihenfolge ist nicht garantiert.
Zonen-Builder geben verkettbare Tabellen mit :set_center(loc) (oder :set_origin(loc) / :set_destination(loc) je nach Zonentyp) zurück:
-- At file scope: create a reusable zone shape
local blast_zone = em.zone.create_sphere_zone(5)
return {
api_version = 1,
on_spawn = function(context)
-- Anchor the zone at call time
blast_zone:set_center(context.boss:get_location())
local entities = context.zones:get_entities_in_zone(blast_zone)
-- ...
end
}
Der em-Namespace ist besonders nützlich in EliteMobs, wo Zonen-Definitionen mit context.zones:get_entities_in_zone() und context.script verwendet werden. In FreeMinecraftModels werden die Methoden context.zones:create_sphere(...) / create_cylinder(...) / create_cuboid(...) häufiger für einfache, beobachtungsbasierte Zonen verwendet.
Entity-Tabellen
Die folgenden Tabellen stellen gängige Methoden vor. Die vollständige Lua-API-Referenz beschreibt außerdem Projektilfelder, Bewegungspfade sowie Besitz- und Schutzabfragen. Sie gelten für generische Entity-Tabellen; die speziellen Wrapper von EliteMobs-Powers haben dort einen eigenen Abschnitt.
Entity-Tabellen werden aus Weltabfragen und Event-Daten zurückgegeben. Sie stellen je nach Entity-Typ aufeinander aufbauende Felder und Methoden bereit.
Entity-Basisfelder
| Feld | Typ | Hinweise |
|---|---|---|
uuid | string | Die UUID der Entity |
entity_type | string | Der Entity-Typ (z. B. "player", "zombie", "skeleton", "villager") |
is_valid | boolean | Ob die Entity-Referenz noch gültig ist |
is_dead | boolean | Ob die Entity tot ist |
is_player | boolean | Ob die Entity ein Spieler ist |
is_hostile | boolean | Ob die Entity Bukkit Monster implementiert, nicht ihre aktuelle Aggressivität |
is_passive | boolean | Ob die Entity Bukkit Animals implementiert, ohne Garantie passiven Verhaltens |
current_location | location table | Die aktuelle Position der Entity (x, y, z, world, yaw, pitch) |
world | string | Der Weltname, in dem sich die Entity befindet |
Entity-Basismethoden
| Methode | Gibt zurück | Hinweise |
|---|---|---|
teleport(location_table) | void | Benötigt x, y, z; fehlende oder unbekannte Welt verwendet die Entity-Welt. yaw und pitch sind standardmäßig null. Keine automatische Bewegungsweg- oder Schutzprüfung. |
remove() | void | Entfernt die Entity aus der Welt. Wirkt nur, wenn die Entity noch gültig ist. |
set_silent(flag) | void | Unterdrückt oder reaktiviert die Sounds der Entity. |
set_invulnerable(flag) | void | Macht die Entity unverwundbar oder verwundbar gegenüber Schaden. |
set_gravity(flag) | void | Aktiviert oder deaktiviert die Schwerkraft für die Entity. |
set_glowing(flag) | void | Schaltet den leuchtenden Umriss-Effekt der Entity um. |
Felder lebender Entities
Lebende Entities (Spieler, Mobs usw.) haben alle Entity-Basisfelder plus:
| Feld | Typ | Hinweise |
|---|---|---|
health | number | Aktuelle Gesundheit |
maximum_health | number | Maximale Gesundheit |
name | string | Anzeigename |
is_alive | boolean | Ob die Entity am Leben ist |
Methoden lebender Entities
| Methode | Gibt zurück | Hinweise |
|---|---|---|
damage(amount) | void | Fügt der Entity den angegebenen Schaden zu |
push(x, y, z) | void | Addiert den Vektor sofort zur aktuellen Geschwindigkeit |
set_facing(x, y, z) | void | Teleportiert auf der Stelle mit neuer Blickrichtung |
add_potion_effect(effect, duration, amplifier) | void | Fügt einen Trankeffekt hinzu. effect ist ein String (z. B. "speed", "slowness", "regeneration"). duration ist in Ticks. amplifier ist die Effektstufe minus 1 (0 = Stufe I). |
remove_potion_effect(effect) | void | Entfernt einen Trankeffekt anhand seines Namens |
get_scale() | number | Gibt die effektive Skalierung inklusive Modifikatoren zurück, oder 1.0, wenn nicht verfügbar |
set_scale(value) | void | Ändert den Basiswert des Skalierungsattributs, falls verfügbar |
Nicht alle von get_nearby_entities() zurückgegebenen Entities sind lebende Entities. Du kannst entity.is_player, entity.is_hostile oder entity.is_passive verwenden, um nach Kategorie zu filtern, oder if entity.damage then prüfen, bevor du Methoden für lebende Entities wie damage(), push() oder add_potion_effect() aufrufst.
Plugin-Integrationsfelder
Entity-Tabellen können Integrationsfelder enthalten. Ohne den passenden Enricher fehlen sie und liefern nil. Tracking-Flags, Modellidentität, Operatorstatus und die meisten verschachtelten Daten sind Momentaufnahmen vom Aufbau; sie folgen späteren Änderungen nicht. Gemeinsame EliteMobs-Gesundheitsfelder werden bei Bedarf gelesen. Modell- und Berechtigungsmethoden fragen ihre Objekte beim Aufruf ab.
EliteMobs-Felder
Verfügbar, wenn EliteMobs installiert ist.
| Feld | Typ | Hinweise |
|---|---|---|
is_elite | boolean | Ob die Entity ein EliteMobs-Elite ist |
is_custom_boss | boolean | Ob die Entity ein EliteMobs Custom Boss ist (auch innerhalb der elite-Untertabelle verfügbar) |
is_significant_boss | boolean | Ob die Entity ein Custom Boss mit einem Gesundheitsmultiplikator über 1 ist (d. h. eine bewusst gestaltete Begegnung, kein Füller-Elite) |
elite | table oder nil | Untertabelle mit Elite-Informationen (siehe unten). nil, wenn die Entity kein Elite ist. |
Die elite-Untertabelle enthält:
| Feld | Typ | Hinweise |
|---|---|---|
elite.level | int | Das Level des Elites |
elite.name | string oder nil | Der Anzeigename des Elites |
elite.health | number | Aktuelle Gesundheit |
elite.max_health | number | Maximale Gesundheit |
elite.is_custom_boss | boolean | Ob es sich um einen Custom Boss handelt (im Gegensatz zu einem natürlichen Elite) |
elite.health_multiplier | number | Konfigurationsdefinierter Gesundheitsmultiplikator |
elite.damage_multiplier | number | Konfigurationsdefinierter Schadensmultiplikator |
elite:remove() | void | Entfernt den Elite über EliteMobs' Entfernungsablauf; dies ist kein Kill und garantiert keinen Loot |
Beispiel: Elites unterschiedlich Schaden zufügen
local entities = context.world:get_nearby_entities(x, y, z, 5)
for _, entity in ipairs(entities) do
if entity.is_elite then
-- Deal double damage to elites
entity:damage(20)
context.log:info("Hit elite: " .. entity.elite.name .. " (level " .. entity.elite.level .. ")")
elseif entity.is_hostile then
entity:damage(10)
end
end
FreeMinecraftModels-Felder
Verfügbar, wenn FreeMinecraftModels installiert ist.
| Feld | Typ | Hinweise |
|---|---|---|
is_modeled | boolean | Ob an der Entity ein FMM-Modell angehängt ist (DynamicEntity oder PropEntity) |
is_prop | boolean | Ob die Entity ein FMM-Prop ist (statische, dekorative Entity) |
model | table oder nil | Untertabelle mit Modell-Informationen (siehe unten). nil, wenn die Entity nicht modelliert ist. |
Die model-Untertabelle enthält:
| Feld | Typ | Hinweise |
|---|---|---|
model.model_id | string oder nil | Die ID des Modell-Blueprints (z. B. "torch_01") |
model.is_dynamic | boolean | Ob die modellierte Entity eine DynamicEntity (Mob/Boss-Modell) statt eines statischen Props ist |
model:play_animation(name, [blend], [loop]) | boolean | Fordert eine benannte Animation an. blend und loop sind standardmäßig false. true bedeutet, dass die Anfrage angenommen wurde: Eingereihte oder während eines Angriffs unterdrückte Animationen können true liefern, ohne sofort zu starten. Ein endgültiger Todeszustand lehnt die Anfrage ab. |
model:stop_animations() | void | Leert laufende und eingereihte Animationen und startet, falls vorhanden, die Idle-Animation. Ein endgültiger Todeszustand bleibt bestehen. |
model:remove() | void | Entfernt die modellierte Entity über die ordnungsgemäße Entfernungspipeline von FMM. |
Auf Spieler-Entity-Tabellen ergänzt der FreeMinecraftModels-Enricher außerdem:
| Feld / Methode | Typ | Hinweise |
|---|---|---|
is_op | boolean | Ob der Spieler ein Serveroperator ist. |
has_permission(node) | boolean | Ob der Spieler den Berechtigungsknoten besitzt. |
Diese beiden Spielerwerte gibt es nur in FreeMinecraftModels-Skripten. Auf gemeinsamen Tabellen, die innerhalb von EliteMobs aufgebaut werden, fügt der eigene FreeMinecraftModels-Adapter von EliteMobs is_modeled, is_prop und model hinzu, aber nicht is_op oder has_permission.
FMM-Spielertabellen bieten auch is_holding_elitemobs_item(filename). Es prüft den EliteMobs-Dateinamentag des Haupthand-Items inklusive .yml, nicht den Anzeigenamen. Leere Hände, andere Items oder fehlende Integration liefern false. EliteMobs' eigener gemeinsamer Enricher ergänzt separat elite_player mit dem Kampfrang, sofern Spielerdaten vorhanden sind. FMMs optionaler EliteMobs-Adapter ergänzt diese Untertabelle nicht.
Die Modell-Bridge (auf jeder Entity verfügbar) verwendet für blend und loop standardmäßig false. Die Prop-Tabelle verwendet bei play_animation beide standardmäßig true. Hier steuert blend das Einreihen und loop die Wiederholung; blend bezeichnet keinen visuellen Crossfade.
Beispiel: Entities nach Typ filtern
local entities = context.world:get_nearby_entities(x, y, z, 10)
for _, entity in ipairs(entities) do
if entity.is_prop then
-- Skip props
elseif entity.is_player then
entity:damage(5)
elseif entity.entity_type == "villager" then
-- Don't hurt villagers
elseif entity.is_elite then
entity:damage(20)
elseif entity.is_hostile then
entity:damage(10)
end
end
Spielerspezifische Felder
Spieler-Entities haben alle Entity- und Living-Entity-Felder plus:
| Feld | Typ | Hinweise |
|---|---|---|
game_mode | string | Der Spielmodus des Spielers ("creative", "survival", "adventure", "spectator") |
Spielerspezifische Methoden
Überall dort, wo die API „unterstützt Farbcodes" sagt, schickt Magmacore den String durch seinen eingebauten MiniMessage-Parser. Legacy-&-Codes, &#RRGGBB-Hex, <#RRGGBB>, <gradient>, <rainbow> und der restliche MiniMessage-Tag-Satz funktionieren alle und können frei gemischt werden. Kyori Adventure ist keine Abhängigkeit und den Scripts steht keine Adventure-API zur Verfügung — du brauchst sie nicht.
Die Lua-Textmethoden wandeln in einen Legacy-String mit Farbcodes um, sodass Farben, Verläufe und Dekorationen korrekt dargestellt werden, während interaktive Tags (<hover>, <click>, <insert>, <font>, <key>, <lang>) zwar geparst werden, aber keine Wirkung haben. Gängige Formate findest du im gemeinsamen Leitfaden Farbcodes.
| Methode | Gibt zurück | Hinweise |
|---|---|---|
send_message(msg) | void | Sendet eine Chatnachricht an den Spieler. Unterstützt Farbcodes. |
chat(text) | void | Sendet farbverarbeiteten Text über Bukkit-Spielerchat, einschließlich Befehlen mit führendem Schrägstrich als dieser Spieler |
get_held_item() | table oder nil | Gibt {type, amount, display_name} für das Item in der Haupthand des Spielers zurück, oder nil bei leerer Hand. type ist der Bukkit-Materialname in Großbuchstaben, beispielsweise "GOLD_INGOT". |
consume_held_item(amount?) | void | Plant Verbrauch aus der Haupthand zum Ausführungszeitpunkt ein. Standard 1; hält kein geprüftes Item fest und bestätigt keine Zahlung. Übergib eine positive Menge; negative Werte werden nicht abgelehnt. |
has_item(material, amount?) | boolean | Gibt true zurück, wenn der Spieler mindestens amount (Standard 1) des angegebenen Materials irgendwo in seinem Inventar hat |
get_target_entity([range]) | entity table oder nil | Prüft einen Strahl von den Augen gegen Blöcke und Entities, ohne den Spieler, mit Entity-Strahlgröße 0.5. Ignoriert Flüssigkeiten und passierbare Blöcke; Standardreichweite 50. |
get_eye_location() | location table | Gibt eine Location-Tabelle auf Augenhöhe des Spielers zurück |
get_look_direction() | table | Gibt einen {x, y, z}-Richtungsvektor zurück, in den der Spieler blickt |
send_block_change(x, y, z, material, [ticks]) | boolean | Plant einen reinen Client-Block mit Rücksetzung nach positiven Ticks ein. True bedeutet eingeplant; ungültige oder nicht als Block verwendbare Materialien liefern false. |
reset_block(x, y, z) | boolean | Plant die Wiederherstellung des echten Blocks für den Spieler ein und liefert true |
sleep(x, y, z) | void | Plant ein echtes weißes Bett und einen Schlafversuch ein. Beim Aufwachen oder Disconnect wird nur BlockData wiederhergestellt, kein Inhalt der Block-Entity. |
wake_up() | void | Weckt einen schlafenden Spieler auf. |
Geplante Blockänderungen und Rücksetzungen lesen die Spielerwelt bei Ausführung. Verlasse dich nach einem Weltwechsel nicht auf die Wiederherstellung des vorgesehenen Blocks. Die Schlafbereinigung prüft nach 20 Ticks und dann alle 10 Ticks. Diese Aufgaben gehören nicht zu context.scheduler.
Spieler-UI-Methoden
Dies sind die Methoden der gemeinsamen Player-Tabelle. Bossfähigkeiten haben andere UI-Signaturen in der API-Referenz. Gemeinsame Leisten werden pro Spieler innerhalb der MagmaCore-Kopie des Plugins verwaltet, nicht pro Skript. Ein Ablauftimer entfernt nur die Leiste oder wiederholte Action-Bar, die ihn gestartet hat; ein älterer Ablauf entfernt also keine neuere. Ihre Bukkit-Timer gehören nicht zu context.scheduler.
player:show_boss_bar(text, [color], progress, [ticks])
Ersetzt die gemeinsame durchgehende Bossleiste des Spielers. Der Fortschritt wird auf 0..1 begrenzt; eine ungültige Farbe wird weiß. Übergib nil bei ausgelassener Farbe, damit der Fortschritt an dritter Stelle bleibt.
| Parameter | Typ | Standard | Hinweise |
|---|---|---|---|
text | string | erforderlich | Der anzuzeigende Text. Unterstützt &-Farbcodes. |
color | string | "WHITE" | Leistenfarbe. Eine von: "RED", "BLUE", "GREEN", "YELLOW", "PURPLE", "PINK", "WHITE" |
progress | number | erforderlich | Füllstand von 0.0 (leer) bis 1.0 (voll) |
ticks | int | -1 | Positive Werte planen das Entfernen ein; sonst bleibt die Leiste bis zum Ausblenden oder Ersetzen |
player:hide_boss_bar()
Entfernt die Bossleiste vom Bildschirm des Spielers. Erwartet keine Parameter.
player:show_action_bar(text, [ticks])
Zeigt Text im Action-Bar-Bereich an (über der Hotbar).
| Parameter | Typ | Standard | Hinweise |
|---|---|---|---|
text | string | erforderlich | Der anzuzeigende Text. Unterstützt &-Farbcodes. |
ticks | int | -1 | Positive Werte wiederholen alle 40 Ticks bis zum Ablauf; sonst einmaliger Versand. Ein neuer Aufruf beendet die vorige Wiederholung. |
player:show_title(title, [subtitle], fade_in, stay, fade_out)
Zeigt dem Spieler einen Titelbildschirm an.
| Parameter | Typ | Standard | Hinweise |
|---|---|---|---|
title | string | erforderlich | Haupttiteltext. Unterstützt &-Farbcodes. |
subtitle | string | "" | Untertiteltext unter dem Haupttitel. Optional. |
fade_in | int | erforderlich | Einblenddauer in Ticks |
stay | int | erforderlich | Wie lange der Titel in Ticks auf dem Bildschirm bleibt |
fade_out | int | erforderlich | Ausblenddauer in Ticks |
Nächste Schritte
Plugin-spezifische Hooks, APIs und Arbeitsabläufe:
- EliteMobs: Erste Schritte | NPC-Skripte | Hooks & Lebenszyklus | Boss & Entities | Welt & Umgebung | Zonen & Targeting
- FreeMinecraftModels: Erste Schritte | Prop-API | Beispiele