MagmaCore Lua-Scripting-Engine
MagmaCore stellt eine gemeinsame Lua-Scripting-Engine bereit, die von mehreren Nightbreak-Plugins genutzt wird. Die Engine kümmert sich um Sandboxing, Scheduling, Zonenverwaltung, Weltinteraktion, Entity-Tabellen und Spieler-UI -- alles mit einer einheitlichen API über alle Plugins hinweg.
Aktuell nutzen die folgenden Plugins diese Engine:
- EliteMobs -- Lua-Powers für Custom Bosses (Hooks wie
on_boss_damaged_by_player,on_enter_combat, usw.) - FreeMinecraftModels -- Lua-Skripte für Props und Custom Items (Hooks wie
on_right_click,on_left_click,on_equip, usw.)
Diese Seite dokumentiert die gemeinsamen Funktionen der Engine. Plugin-spezifische Hooks, APIs und Arbeitsabläufe findest du auf den oben verlinkten Plugin-Seiten.
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
-- mach etwas mit dem 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
}
Diese zurückgegebene Tabelle ist die Skriptdatei.
Kommentare
Verwende --, um eine Notiz für Menschen zu schreiben:
-- Dieser Cooldown verhindert, dass der Angriff bei jedem Treffer auslöst
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
Alles andere aus der Lua-Standardbibliothek funktioniert ganz normal:
| 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. Wenn du Zeitinformationen benötigst, verwende context.world:get_time() für die Weltzeit oder speichere Zeitstempel in context.state mit Tick-Zählern über den on_game_tick-Hook.
print schreibt in die Serverkonsole, doch bevorzuge context.log:info(msg) für die Ausgabe. Logmeldungen werden mit dem Skriptdateinamen versehen, was das Nachverfolgen erleichtert, welches Skript die Meldung erzeugt hat.
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 | Ausführungspriorität. Niedrigere Werte laufen zuerst. Standard ist 0 |
| 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.
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
}
Gemeinsame Engine-Hooks
Die folgenden Hooks stehen allen Plugins zur Verfügung, die die MagmaCore-Scripting-Engine verwenden. Einzelne Plugins ergänzen diese um eigene Hooks.
| Hook | Wann er ausgelöst wird |
|---|---|
on_spawn | Wird einmal aufgerufen, wenn die Skript-Instanz erstellt wird (Entity spawnt oder Prop wird platziert) |
on_game_tick | Wird in jedem Server-Tick aufgerufen, solange die Entity lebt/aktiv ist |
on_zone_enter | Wird aufgerufen, wenn ein Spieler eine beobachtete Zone betritt |
on_zone_leave | Wird aufgerufen, wenn ein Spieler eine beobachtete Zone verlässt |
Methodensyntax: : vs .
In Lua ist object:method(arg) die Kurzform für object.method(object, arg). Die MagmaCore-API akzeptiert beide Formen, also funktionieren beide:
context.log:info("hello")
context.log.info("hello") -- dasselbe
Die gesamte Dokumentation verwendet durchgängig :.
Laufzeit-Budget
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 schlank -- sie laufen in jedem einzelnen Tick. - Verwende
context.scheduler:run_repeating(...), um Arbeit auf mehrere Ticks zu verteilen. - Verlagere aufwändige Arbeit hinter einen zustandsbasierten Cooldown oder ein angemessenes Intervall.
Wenn ein Lua-Skript in einem Hook oder geplanten Callback einen Laufzeitfehler wirft, wird die Skript-Instanz für diese Entity sofort und dauerhaft deaktiviert. Behebe den Fehler in deiner Skriptdatei -- das Skript initialisiert sich beim nächsten Entity-Spawn neu.
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.
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 bei jedem Aufruf neu aufgebaut. context.state wird nicht neu aufgebaut -- sie besteht ab dem Moment, in dem die Skript-Instanz erstellt wird, bis zu deren Zerstörung.
context.log
Methoden zum Logging in die Konsole. Meldungen werden in der Serverkonsole mit dem Skriptdateinamen versehen.
| 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")
context.log:error("Critical failure in zone setup")
context.cooldowns
Die Cooldowns-Tabelle verwaltet zeitbasierte Cooldowns für deine Skripte. Es gibt zwei Geltungsbereiche:
- Lokale Cooldowns gelten pro Skript-Instanz und werden über einen String-Schlüssel identifiziert. Wird kein Schlüssel angegeben, wird der Dateiname des Skripts als Standardschlüssel verwendet.
- Globale Cooldowns werden über alle Skripte auf derselben Owner-Entity geteilt (z. B. alle Skripte auf demselben Prop oder alle Lua-Powers auf demselben Boss).
cooldowns:check_local(key?, duration)
Die häufigste Methode. Prüft, ob der Cooldown bereit ist, startet ihn in diesem Fall und gibt true zurück. Wenn nicht bereit, gibt false zurück. Dies ist ein atomares Check-and-Set — keine Race Conditions.
| Parameter | Typ | Hinweise |
|---|---|---|
key | string (optional) | Cooldown-Bezeichner. Standard ist der Skriptdateiname. |
duration | int | Cooldown-Dauer in Ticks (20 = 1 Sekunde) |
on_right_click = function(context)
-- Diese Aktion nur alle 3 Sekunden erlauben
if not context.cooldowns:check_local("interact", 60) then
return
end
-- ... Aktion ausführen
end
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. Standard ist der Skriptdateiname. |
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.
| 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. - FMM-Prop-Skripte — geteilt pro
PropEntity(ein Bucket pro platziertem Prop). - FMM-Item-Skripte — geteilt pro Spieler-UUID (ein Bucket pro Spieler). Lokale Cooldowns auf Items bleiben über Equip/Unequip-Zyklen hinweg bestehen, gekennzeichnet durch
playerUUID → "itemId:scriptFile" → key, sodass ein Cooldown bestehen bleibt, wenn der Spieler das Item aus seiner Hotbar herausnimmt und wieder hineinlegt.
context.scheduler
Der Scheduler erlaubt es dir, verzögerte und sich wiederholende Tasks auszuführen. Alle Tasks gehören zur Skript-Instanz und werden automatisch abgebrochen, wenn die Skript-Instanz zerstört wird (z. B. wenn ein Prop entfernt wird oder ein Boss stirbt).
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 einen geplanten Task anhand seiner ID ab.
| Parameter | Typ | Hinweise |
|---|---|---|
taskId | int | Die von run_later oder run_repeating zurückgegebene Task-ID |
Wenn du einen sich wiederholenden Task startest, brich ihn immer in deinem Cleanup-Hook ab (on_destroy für Props, on_exit_combat / on_death für Bosse, on_unequip für Items). Vergisst du den Abbruch, läuft ein Hintergrundtask weiter, bis die Skript-Instanz zerstört wird, was Leistung verschwendet und Fehler verursachen kann.
Geplante Callbacks erhalten einen frischen Kontext als Parameter. Verwende immer das eigene Kontext-Argument des Callbacks, nicht den äußeren context aus dem Hook, der den Callback erstellt hat. Der äußere Kontext kann veraltete Referenzen enthalten.
context.world
Die Welt-Tabelle bietet Methoden zum Abfragen und Interagieren mit der Minecraft-Welt. Sie wird aus der aktuellen Welt der Entity aufgebaut.
EliteMobs erweitert context.world um zusätzliche Methoden zum Spawnen von Bossen, Verstärkungen, fallenden Blöcken, Feuerwerken, Wurftränken und temporären Blöcken. Siehe EliteMobs World & Environment für die vollständige erweiterte API. Die hier dokumentierten Methoden stehen über alle Plugins hinweg zur Verfügung.
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").
| 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.
| 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 der Block erfolgreich gesetzt wurde, sonst false.
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, UPPER_CASE (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 |
Einige Partikeltypen benötigen Block- oder Item-Daten, die von dieser einfachen API nicht unterstützt werden. BLOCK_CRACK, FALLING_DUST, BLOCK_DUST und ITEM_CRACK schlagen fehl oder erzeugen keinen sichtbaren Effekt. Verwende stattdessen datenfreie Alternativen: CLOUD, SMOKE, CAMPFIRE_COSY_SMOKE, SNOWFLAKE, FLAME, DUST usw.
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, UPPER_CASE (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 |
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 Array von Entity-Wrapper-Tabellen für alle Entities innerhalb einer um die angegebenen Koordinaten zentrierten Bounding Box zurück.
| 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 (Armor Stands, gedroppter Items 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 Array von Spieler-Wrapper-Tabellen für alle Spieler innerhalb einer um die angegebenen Koordinaten zentrierten Bounding Box zurück.
| 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 für die gespawnte Entity zurück (mit Methoden für lebende Entities, falls zutreffend), oder nil, wenn der Entity-Type ungültig ist.
world:get_highest_block_y(x, z)
Gibt die Y-Koordinate des höchsten Nicht-Luft-Blocks an der angegebenen X/Z-Position zurück.
| 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])
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 |
Gibt eine Tabelle mit den folgenden Feldern zurück:
| 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 |
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 |
-- Beispiel: rot-goldenes Feuerwerk
context.world:spawn_firework(loc.x, loc.y, loc.z, {"RED", "GOLD"}, "BURST", 2)
world:place_temporary_block(x, y, z, material, [ticks], [require_air])
Platziert einen Block, der nach einer Verzögerung automatisch in seinen ursprünglichen Zustand zurückkehrt.
| 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, bevor der Block zurückgesetzt wird. 0 bedeutet dauerhaft. |
require_air | boolean | false | Wenn true, wird der Block nur gesetzt, wenn das Ziel Luft ist |
Gibt true zurück, wenn der Block platziert wurde, false, wenn das Material ungültig war oder die Luft-Bedingung nicht erfüllt wurde.
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 Zonen-Tabelle ermöglicht es dir, räumliche Zonen zu erstellen und sie auf Spieler-Eintritts-/Austrittsereignisse zu überwachen. Zonen sind an die Skript-Instanz gebunden und werden automatisch aufgeräumt, wenn die Skript-Instanz zerstört wird.
zones:create_sphere(x, y, z, radius)
Erstellt eine Kugelzone, zentriert an den angegebenen Koordinaten. Gibt ein numerisches Zonen-Handle zurück.
| 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. Gibt ein numerisches Zonen-Handle zurück.
| 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. Gibt ein numerisches Zonen-Handle zurück.
| 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)
Beginnt, eine Zone auf Spieler-Eintritts-/Austrittsereignisse zu überwachen. Die Callback-Parameter wirken als boolesche Signale — die Übergabe eines Nicht-nil-Werts (z. B. eine Funktion oder true) aktiviert den entsprechenden Hook am Skript. Die Callbacks selbst werden nicht direkt aufgerufen. Stattdessen wird die Eintritts-/Austrittslogik über die on_zone_enter / on_zone_leave Hooks des Skripts ausgelöst.
| Parameter | Typ | Hinweise |
|---|---|---|
handle | int | Zonen-Handle aus einem create_*-Aufruf |
onEnterCallback | any non-nil oder nil | Non-nil aktiviert den on_zone_enter Hook für diese Zone |
onLeaveCallback | any non-nil oder nil | Non-nil aktiviert den on_zone_leave Hook für diese Zone |
Gibt true zurück, wenn die Überwachung erfolgreich eingerichtet wurde, nil, wenn das Zonen-Handle ungültig war.
Zonen-Überwachungen werden in jedem Server-Tick gegen alle Spieler in derselben Welt geprüft. Halte die Anzahl der Zonen vernünftig, um Performance-Overhead zu vermeiden.
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 -- oder context.boss:get_location()
if loc == nil then return end
local handle = context.zones:create_sphere(loc.x, loc.y, loc.z, 5)
-- Übergibt Nicht-nil-Werte, um die Hooks on_zone_enter und on_zone_leave zu aktivieren.
-- Dies sind boolesche Signale, keine Callbacks — die eigentliche Logik gehört in die Hooks darunter.
context.zones:watch(handle, true, true)
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 durch ein Spielereignis ausgelöst wurde (z. B. on_right_click, on_zone_enter). Sie ist nicht vorhanden während on_game_tick oder geplanter Callbacks.
| Feld / Methode | Typ | Hinweise |
|---|---|---|
is_cancelled | boolean | Ob das Event abgebrochen wurde |
cancel() | method | Bricht das Event ab (verhindert das Standardverhalten) |
uncancel() | method | Hebt den Abbruch eines zuvor abgebrochenen Events auf |
player | entity table | Der am Event beteiligte Spieler, falls vorhanden |
on_right_click = function(context)
if context.event then
context.event:cancel() -- die Standard-Rechtsklick-Interaktion verhindern
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 Reference für die vollständigen EliteMobs-Event-Felder.
em Helper-Namespace
Die em-Tabelle ist zum Zeitpunkt des Dateiladens verfügbar (bevor ein Hook läuft). Sie stellt Hilfskonstruktoren bereit, um Location-Tabellen, Vektor-Tabellen und Zonen-Definitionen zu erstellen, die in der gesamten API verwendet werden.
| 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 |
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", "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 |
Zonen-Builder geben verkettbare Tabellen mit :set_center(loc) (oder :set_origin(loc) / :set_destination(loc) je nach Zonentyp) zurück:
-- Auf Dateiebene: eine wiederverwendbare Zonenform erstellen
local blast_zone = em.zone.create_sphere_zone(5)
return {
api_version = 1,
on_spawn = function(context)
-- Die Zone zum Aufrufzeitpunkt verankern
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
Entity-Tabellen werden aus Weltabfragen, Event-Daten und Zonen-Callbacks zurückgegeben. Sie stellen je nach Entity-Typ einen geschichteten Satz von Feldern 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 ein feindlicher Mob ist (Zombie, Skeleton usw.) |
is_passive | boolean | Ob die Entity ein passiver Mob ist (Kuh, Schwein, Huhn usw.) |
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 | Teleportiert die Entity. Die Location-Tabelle muss die Felder x, y, z, world enthalten; yaw und pitch sind optional. |
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 | Wendet einen Geschwindigkeitsimpuls an |
set_facing(x, y, z) | void | Setzt die Richtung, in die die Entity blickt |
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 aktuelle Entity-Skalierung zurück (Standard 1.0 auf Servern ohne das generic.scale-Attribut) |
set_scale(value) | void | Setzt die Entity-Skalierung über das generic.scale-Attribut. No-op auf Servern vor 1.20.5. |
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 enthalten automatisch Felder zur Erkennung und Interaktion mit Entities, die von anderen Nightbreak-Plugins verwaltet werden. Diese Felder werden nur befüllt, wenn das jeweilige Plugin installiert ist -- andernfalls sind sie standardmäßig false / nil ohne jeglichen Overhead.
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 | 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 die ordnungsgemäße Entfernungspipeline von EliteMobs (räumt Tracking, Loot usw. auf) |
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
-- Doppelten Schaden gegen 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 | 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 | Spielt eine benannte Animation ab. blend ist standardmäßig false, loop ist standardmäßig false. Gibt true zurück, wenn die Animation gefunden wurde. |
model:stop_animations() | void | Stoppt alle derzeit laufenden Animationen auf dem Modell. |
model:remove() | void | Entfernt die modellierte Entity über die ordnungsgemäße Entfernungspipeline von FMM. |
Die Modell-Bridge (auf jeder Entity verfügbar) verwendet für blend und loop standardmäßig false. Die Prop-Tabelle (prop table) play_animation verwendet beide standardmäßig true, weil Props typischerweise geblendete, geloopte Animationen wünschen.
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
-- Props überspringen
elseif entity.is_player then
entity:damage(5)
elseif entity.entity_type == "villager" then
-- Dorfbewohnern keinen Schaden zufügen
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
| Methode | Gibt zurück | Hinweise |
|---|---|---|
send_message(msg) | void | Sendet eine Chatnachricht an den Spieler. Unterstützt &-Farbcodes. |
get_held_item() | table oder nil | Gibt {type, amount, display_name} für das Item in der Haupthand des Spielers zurück, oder nil, wenn leer |
consume_held_item(amount?) | void | Verbraucht Items aus der Haupthand des Spielers. amount ist standardmäßig 1 |
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 | Gibt die Entity zurück, die der Spieler per Raycast anvisiert, oder nil, wenn keine. Standardreichweite ist 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 | Sendet einen Fake-Block, der nur für diesen Spieler sichtbar ist. Wenn ticks angegeben ist, setzt sich der Fake-Block nach dieser Dauer automatisch zurück. Gibt true bei Erfolg zurück, false, wenn das Material ungültig ist. |
reset_block(x, y, z) | boolean | Setzt einen Fake-Block für diesen Spieler auf den echten Block zurück. Gibt immer true zurück. |
sleep(x, y, z) | void | Lässt den Spieler an den angegebenen Koordinaten in eine Bett-Schlafanimation eintreten. Der Block wird automatisch wiederhergestellt, wenn der Spieler aufhört zu schlafen. |
wake_up() | void | Weckt einen schlafenden Spieler auf. |
Spieler-UI-Methoden
Diese Methoden sind auf jeder Spieler-Entity-Tabelle verfügbar und bieten Möglichkeiten, dem Spieler Informationen über Minecrafts eingebaute UI-Elemente anzuzeigen.
player:show_boss_bar(text, [color], progress, [ticks])
Zeigt dem Spieler eine Bossleiste an.
| 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 | nil | Optionale Auto-Ausblendverzögerung in Ticks. Wenn weggelassen, bleibt die Leiste, bis sie manuell ausgeblendet wird. |
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 | nil | Optionale Dauer in Ticks. Falls angegeben, wird die Nachricht alle 40 Ticks erneut gesendet, um sie für die volle Dauer sichtbar zu halten. |
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 | Hooks & Lebenszyklus | Boss & Entities | Welt & Umgebung | Zonen & Targeting
- FreeMinecraftModels: Erste Schritte | Prop & Item API | Beispiele