Saltar al contenido principal

Motor de Scripting Lua de MagmaCore

MagmaCore proporciona el sandbox de Lua compartido y el runtime genérico ScriptInstance usados por varios plugins de Nightbreak. Los poderes de jefe de EliteMobs, los scripts de NPC de EliteMobs, los props de FreeMinecraftModels y los ítems de FreeMinecraftModels se ejecutan todos sobre este runtime y comparten la misma validación de archivos, sandbox, ciclo de vida del context, propiedad del planificador, contrato de cooldowns, contrato de logging, motor de vigilancia de zonas y modelo de context.state.

Los props/ítems de FreeMinecraftModels y los scripts de NPC de EliteMobs heredan directamente las tablas de context genéricas de MagmaCore (context.world, context.zones, context.scheduler, context.cooldowns, context.log, context.event, context.player y context.state) y añaden su tabla propietaria (context.prop, context.item o context.npc). Los poderes de jefe de EliteMobs se ejecutan sobre el mismo runtime pero exponen variantes más ricas y específicas de jefe para varias tablas (context.world, context.zones, context.cooldowns, context.scheduler, context.log, context.event) además de helpers exclusivos de jefe como context.players, context.entities, context.vectors, context.settings y context.script.

Actualmente, los siguientes plugins usan este motor:

  • EliteMobs -- Poderes Lua para jefes personalizados (hooks como on_boss_damaged_by_player, on_enter_combat, etc.) y scripts Lua de NPC para comportamiento de interacción/proximidad (hooks como on_npc_interact, on_npc_proximity_enter, etc.)
  • FreeMinecraftModels -- Scripts Lua para props y objetos personalizados (hooks como on_right_click, on_left_click, on_equip, etc.)

Esta página documenta las características compartidas del motor. Para hooks, APIs y flujos de trabajo específicos de cada plugin, consulta las páginas de plugin enlazadas arriba.


Mini Introducción a Lua

Si eres completamente nuevo en Lua, aquí tienes la sintaxis mínima que necesitas para escribir scripts para cualquier plugin de Nightbreak.

Variables

Usa local para almacenar un valor:

local cooldown_key = "fire_burst"
local damage_multiplier = 1.5

local significa que la variable pertenece solo a este archivo o bloque.

Funciones

Las funciones son bloques de lógica reutilizables:

local function warn_player(player)
player:send_message("&cMove!")
end

Más adelante, puedes invocarla:

warn_player(some_player)

Comprobaciones if

Usa if cuando algo solo deba ocurrir a veces:

if context.player == nil then
return
end

Eso significa "si no hay jugador para este hook, detente aquí".

nil

nil significa "ningún valor". Es la versión de Lua de "no hay nada aquí".

A menudo comprobarás nil con:

if context.event ~= nil then
-- hacer algo con el evento
end

~= significa "no es igual a".

Tablas

Lua usa tablas para varios propósitos:

  • Listas
  • Objetos con claves nombradas
  • La definición final del script que se retorna

Ejemplo de una tabla con claves nombradas:

local particle = {
particle = "FLAME",
amount = 1,
speed = 0.05
}

Retornando la definición del script

Al final de cada archivo de script, retornas una tabla:

return {
api_version = 1,

on_spawn = function(context)
end
}

Esa tabla retornada es el archivo de script.

Comentarios

Usa -- para escribir una nota para humanos:

-- Este cooldown evita que el ataque se dispare en cada golpe
context.cooldowns:set_local(60, "fire_burst")

Sandbox de Lua

Todos los scripts Lua se ejecutan dentro de un entorno LuaJ sandboxeado. Varios globales que podrían acceder al sistema de archivos o al runtime de Java se eliminan. Las reglas del sandbox son idénticas en todos los plugins que usan MagmaCore.

Globales Eliminados

Los siguientes globales estándar de Lua se establecen a nil y no se pueden usar:

EliminadoPor qué
debugExpone el estado interno de la VM
dofileAcceso al sistema de archivos
ioAcceso al sistema de archivos
loadCarga arbitraria de código
loadfileAcceso al sistema de archivos
luajavaAcceso directo a clases de Java
moduleSistema de módulos (no necesario)
osAcceso al sistema operativo
packageSistema de módulos (no necesario)
requireSistema de módulos / acceso al sistema de archivos

Biblioteca Estándar Disponible

Todo lo demás de la biblioteca estándar de Lua funciona con normalidad:

CategoríaFunciones
Matemáticasmath.abs, math.ceil, math.floor, math.max, math.min, math.random, math.sin, math.cos, math.sqrt, math.pi, y todas las demás funciones math.*
Cadenasstring.byte, string.char, string.find, string.format, string.gsub, string.len, string.lower, string.match, string.rep, string.sub, string.upper, y todas las demás funciones string.*
Tablastable.insert, table.remove, table.sort, table.concat, y todas las demás funciones table.*
Iteradorespairs, ipairs, next
Tipotype, tostring, tonumber, select, unpack
Manejo de errorespcall, xpcall, error, assert
Otrosprint, rawget, rawset, rawequal, rawlen, setmetatable, getmetatable
La biblioteca os no está disponible

La biblioteca os está completamente eliminada del sandbox. Usa context.world:get_time() para el tiempo del mundo en las superficies genéricas de MagmaCore; los poderes de jefe de EliteMobs lo reciben a través de la base compartida de su tabla world de jefe. Para lógica de tiempo transcurrido, guarda contadores de ticks en context.state mediante el hook on_game_tick.

consejo

print escribe en la consola del servidor, pero prefiere context.log:info(msg). Todas las superficies exponen context.log: los scripts de FreeMinecraftModels y los scripts de NPC de EliteMobs exponen info, warn y error; los poderes de jefe de EliteMobs exponen info, warn y debug.


Contrato del Archivo

Cada script Lua debe return una tabla. Esa tabla es intencionadamente estricta.

Campos de Nivel Superior Requeridos y Opcionales

CampoRequeridoTipoNotas
api_versionNumberActualmente debe ser 1
priorityNoNumberValor de ordenación opcional. Los scripts de jefe y de NPC de EliteMobs ejecutan primero los valores más bajos. FMM valida el campo, pero los scripts de prop se ejecutan en el orden de la lista scripts: y los scripts de ítem solo vinculan el primer script válido
claves de hooks soportadasNoFunctionDeben usar uno de los nombres exactos de hooks soportados por el plugin

Reglas de Validación

  • El archivo debe retornar una tabla.
  • api_version es requerido y actualmente debe ser 1.
  • priority debe ser numérico si está presente.
  • Cada clave extra de nivel superior debe ser un nombre de hook soportado.
  • Cada clave de hook debe apuntar a una función.
  • Las claves de nivel superior desconocidas se rechazan.
Priority is provider-specific

El validador de Lua acepta priority para todos los scripts respaldados por MagmaCore. EliteMobs lo usa para el orden de los scripts de jefe y de NPC. FreeMinecraftModels actualmente no ordena por priority: los props siguen el orden de la lista scripts: de la configuración, y los ítems personalizados solo vinculan el primer script válido de esa lista.

Dónde viven los archivos de script

Cada plugin apunta el motor a un único directorio de scripts. Ese directorio se escanea de forma recursiva, así que los archivos .lua en subcarpetas también se recogen y puedes organizar los scripts como quieras. Los archivos se visitan en orden alfabético dentro de cada carpeta.

File names must be unique

Los scripts se indexan por nombre de archivo, no por ruta. Dos archivos llamados door.lua en subcarpetas distintas son la misma clave, y solo uno de ellos acaba registrado. Dale a cada script un nombre de archivo distinto.

Las funciones auxiliares y las constantes locales deben vivir encima del return final, no dentro de la tabla retornada salvo que sean hooks reales.

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
}

Nombres de Hooks Comunes

Estos nombres de hook aparecen en varios runtimes de Lua. Cada tipo de script habilita solo el subconjunto que tiene sentido para ese propietario: los scripts de prop de FMM usan todos estos, los scripts de ítem de FMM usan on_game_tick de este grupo más sus hooks específicos de ítem, los poderes de jefe de EliteMobs usan su propia lista de hooks de jefe, y los scripts de NPC de EliteMobs usan on_spawn, on_remove, on_game_tick, on_npc_interact, on_npc_proximity_enter, on_npc_proximity_leave, on_zone_enter y on_zone_leave.

HookCuándo se dispara
on_spawnSe llama una vez cuando se crea la instancia del script para los propietarios soportados (props de FMM, jefes de EliteMobs y scripts de NPC de EliteMobs)
on_game_tickSe llama cada tick del servidor mientras la entidad esté viva/activa
on_zone_enterSe llama cuando una zona soportada por el runtime informa de un evento de entrada. Las vigilancias de zona de FMM y de los NPC de EliteMobs se basan en jugadores; los hooks de zona de nivel superior de los jefes de EliteMobs provienen de eventos de zona de EliteScript.
on_zone_leaveSe llama cuando una zona soportada por el runtime informa de un evento de salida. Las vigilancias de zona de FMM y de los NPC de EliteMobs se basan en jugadores; los hooks de zona de nivel superior de los jefes de EliteMobs provienen de eventos de zona de EliteScript.

Sintaxis de Métodos: : vs .

En Lua, object:method(arg) es una forma abreviada de object.method(object, arg). La API de MagmaCore acepta ambas formas, así que cualquiera funciona:

context.log:info("hello")
context.log.info("hello") -- lo mismo

Toda la documentación usa : de forma consistente.


Presupuesto de Ejecución

Cada invocación de hook, cada callback programado y la propia evaluación inicial del archivo de script se ejecutan bajo un presupuesto de ejecución estricto. El presupuesto se aplica dentro de la VM de Lua, así que actúa mientras tu código sigue ejecutándose en lugar de limitarse a mirar el reloj después.

Una invocación individual se aborta en cuanto supera cualquiera de los dos límites:

LímiteValor
Tiempo de reloj50 milisegundos
Instrucciones de Lua ejecutadas250,000

Alcanzar cualquiera de los dos límites lanza un error de Lua dentro del script, que el runtime trata entonces como cualquier otro error de script: el mensaje se registra y la instancia del script se deshabilita para esa entidad.

Infinite loops are caught, but they still cost you a tick

Como la comprobación ocurre por instrucción, un while true do end ya no congela el servidor -- se corta al llegar al presupuesto. Aún así consume hasta 50 ms del tick en el que se ejecutó, y aún así deshabilita el script, así que esto es una red de seguridad, no una licencia para escribir bucles sin límite.

Una llamada que retorna con normalidad pero que aun así superó los 50 ms de reloj también se deshabilita, con su propia advertencia en consola:

[Lua] my_script.lua took 73ms in 'on_game_tick' (limit: 50ms) -- script disabled to prevent lag.

Las llamadas anidadas comparten un único presupuesto: si un hook invoca un callback que invoca otro, toda la cadena se mide como una única asignación de 50 ms / 250,000 instrucciones, no una asignación para cada uno.

Para mantenerte dentro del presupuesto:

  • Evita bucles sin límite dentro de los hooks.
  • Mantén los manejadores de on_game_tick ligeros -- se ejecutan en cada tick.
  • Usa context.scheduler:run_repeating(...) para repartir el trabajo entre ticks.
  • Mueve el trabajo costoso detrás de context.cooldowns o un intervalo razonable.
Errores en tiempo de ejecución de scripts

Si un script Lua lanza un error en tiempo de ejecución en cualquier hook o callback planificado, la instancia del script se deshabilita inmediata y permanentemente para esa entidad. Corrige el error en tu archivo de script -- el script se reinicializará en el próximo spawn de entidad.


context.state

Una tabla Lua simple que persiste durante toda la vida útil de la instancia del script. Úsala para almacenar flags, contadores, IDs de tareas, estados de alternancia y cualquier dato que necesites compartir entre hooks.

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
información

Solo context.state está pensado para datos persistentes propiedad del script. La mayoría de las demás tablas de context (context.world, context.event, etc.) se reconstruyen o se recrean de forma perezosa según haga falta. FreeMinecraftModels cachea context.prop por prop por rendimiento, pero sus campos en vivo como current_location son perezosos, así que las lecturas siguen reflejando el estado actual. context.state sobrevive desde el momento en que se crea la instancia del script hasta que se destruye.


context.log

Métodos de logging en consola, disponibles en todas las superficies de script. Los mensajes se prefijan con el nombre del archivo del script en la consola del servidor. Los scripts de FreeMinecraftModels y los scripts de NPC de EliteMobs exponen info, warn y error; los poderes de jefe de EliteMobs exponen info, warn y debug.

MétodoNotas
log:info(message)Mensaje informativo
log:warn(message)Mensaje de advertencia
log:error(message)Mensaje de nivel warning (registrado a nivel WARN, igual que log:warn)
Variante de EliteMobs

El context.log de EliteMobs registra debug en lugar de error. Usa log:debug(message) para la salida de depuración (aparece a nivel info con un prefijo debug).

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

La tabla cooldowns gestiona los cooldowns basados en tiempo de tus scripts. Hay dos ámbitos:

  • Los cooldowns locales son por instancia de script e identificados por una clave de cadena. Si no se proporciona una clave, se usa el nombre del archivo del script como clave por defecto.
  • Los cooldowns globales se comparten entre todos los scripts de la misma entidad propietaria (por ejemplo, todos los scripts del mismo prop, o todos los poderes Lua del mismo jefe).

cooldowns:check_local(key?, duration)

El método más común. Comprueba si el cooldown está listo, y si lo está, lo inicia y devuelve true. Si no está listo, devuelve false. Es una comprobación-y-establecimiento atómica — sin condiciones de carrera.

ParámetroTipoNotas
keystring (opcional)Identificador del cooldown. Por defecto, el nombre del archivo del script.
durationintDuración del cooldown en ticks (20 = 1 segundo)
on_right_click = function(context)
-- Solo permite esta acción una vez cada 3 segundos
if not context.cooldowns:check_local("interact", 60) then
return
end
-- ... ejecutar la acción
end
Shared cooldown order

Todas las superficies de script — poderes de jefe, scripts de NPC y scripts de FreeMinecraftModels — usan el orden compartido mostrado arriba: check_local(key?, duration). (Las compilaciones experimentales anteriores de NPC usaban check_local(duration, key?); actualiza cualquier script de NPC antiguo al orden compartido.)

cooldowns:local_ready(key?)

Devuelve true si el cooldown local ha expirado (o nunca se estableció), false si sigue activo.

cooldowns:local_remaining(key?)

Devuelve el número de ticks restantes en el cooldown local, o 0 si está listo.

cooldowns:set_local(duration, key?)

Establece un cooldown local sin comprobar si ya hay uno activo. Úsalo para reinicios incondicionales de cooldown.

ParámetroTipoNotas
durationintDuración en ticks. Pasa 0 o un valor negativo para limpiar.
keystring (opcional)Identificador del cooldown. Por defecto, el nombre del archivo del script.

cooldowns:global_ready()

Devuelve true si el cooldown global (compartido entre todos los scripts de la misma entidad) ha expirado.

cooldowns:set_global(duration)

Establece el cooldown global.

ParámetroTipoNotas
durationintDuración en ticks
Ámbitos del cooldown global

El "propietario" de un cooldown global depende del tipo de script:

  • Poderes Lua de EliteMobs — compartidos por EliteEntity (un cubo por jefe). global_ready() / set_global() usan el sistema integrado de cooldowns de poderes del jefe; los cooldowns locales también se comparten entre todos los poderes del mismo jefe.
  • Scripts de NPC de EliteMobs — los cooldowns globales se comparten por NPC (un cubo para todos los scripts de ese NPC); los cooldowns locales son por instancia de script del NPC.
  • Scripts de prop de FMM — compartidos por PropEntity (un cubo por prop colocado).
  • Scripts de objeto de FMM — compartidos por UUID de jugador (un cubo por jugador). Los cooldowns locales en objetos persisten entre ciclos de equipar/desequipar, indexados por playerUUID → "itemId:scriptFile" → key, de modo que un cooldown sobrevive a que el jugador saque el objeto de su hotbar y vuelva a meterlo.

context.scheduler

Esta sección usa los nombres del planificador de MagmaCore (run_later, run_repeating, cancel). Los nombres de EliteMobs (run_after(ticks, callback), run_every(interval, callback), cancel_task(taskId)) se aceptan como alias en todas las superficies, así que cualquiera de los dos estilos funciona en cualquier script.

El planificador te permite ejecutar tareas retrasadas y repetidas. Todas las tareas son propiedad de la instancia del script y se cancelan automáticamente cuando la instancia del script se destruye (por ejemplo, cuando se retira un prop o muere un jefe).

scheduler:run_later(ticks, callback)

Ejecuta un callback una vez tras un retraso. Devuelve un ID numérico de tarea.

ParámetroTipoNotas
ticksintRetraso en ticks del servidor (20 ticks = 1 segundo)
callbackfunctionLlamada con un context fresco cuando expira el retraso
context.scheduler:run_later(40, function(delayed_context)
delayed_context.log:info("2 seconds have passed!")
end)

scheduler:run_repeating(delay, interval, callback)

Ejecuta un callback repetidamente en un intervalo fijo. Devuelve un ID numérico de tarea.

ParámetroTipoNotas
delayintRetraso inicial en ticks antes de la primera ejecución
intervalintTicks entre cada ejecución posterior
callbackfunctionLlamada con un context fresco en cada intervalo
context.state.particle_task = context.scheduler:run_repeating(0, 20, function(tick_context)
tick_context.log:info("Another second passed!")
end)

scheduler:cancel(taskId)

Cancela una tarea planificada por su ID.

ParámetroTipoNotas
taskIdintEl ID de tarea devuelto por run_later o run_repeating
Cancela siempre las tareas repetidas

Si inicias una tarea repetida, cancélala siempre en tu hook de limpieza (on_destroy para props, on_exit_combat / on_death para jefes, on_unequip para objetos). Olvidar cancelarla deja una tarea en segundo plano ejecutándose hasta que se destruya la instancia del script, lo que desperdicia rendimiento y puede causar errores.

Los callbacks reciben un context fresco

Los callbacks planificados reciben un context fresco como su parámetro. Usa siempre el argumento context propio del callback, no el context externo del hook que creó el callback. El context externo puede contener referencias obsoletas.


context.world

La tabla world proporciona métodos para consultar e interactuar con el mundo de Minecraft. Se construye a partir del mundo actual de la entidad.

Shared world table on every surface

Los métodos documentados aquí son la tabla context.world compartida de MagmaCore. Los props/ítems de FreeMinecraftModels y los scripts de NPC de EliteMobs reciben esta tabla directamente, incluido strike_lightning(...). FreeMinecraftModels además añade tres helpers opcionales de botín de EliteMobs (drop_elitemobs_procedural_loot, drop_elitemobs_random_loot, drop_elitemobs_custom_loot) que solo hacen algo cuando EliteMobs está instalado; consulta context.world: adiciones de FreeMinecraftModels. Los poderes de jefe de EliteMobs parten de esta misma tabla base y después añaden o sobrescriben métodos específicos de EliteMobs como rayos protegidos, proyectiles falsos, generación de refuerzos y helpers de botín de jugador; consulta Mundo y Entorno de EliteMobs.

Coordinate and location-table overloads coexist

context.world acepta tanto llamadas con coordenadas (p. ej. strike_lightning(x, y, z), spawn_particle(name, x, y, z, ...)) como sobrecargas con tabla de ubicación (p. ej. strike_lightning_at_location(loc), spawn_particle_at_location(loc, ...)) en las superficies genéricas. Los poderes de jefe de EliteMobs también admiten ambos estilos generales, pero algunos métodos con tabla de ubicación tienen comportamiento específico de jefe.

world.name

Un campo de cadena que contiene el nombre del mundo.


world:get_block_at(x, y, z)

Devuelve el nombre del material del bloque en las coordenadas dadas como cadena en minúsculas (por ejemplo, "stone", "air").

ParámetroTipoNotas
xintCoordenada X del bloque
yintCoordenada Y del bloque
zintCoordenada Z del bloque

world:set_block_at(x, y, z, material)

Establece el bloque en las coordenadas dadas. Se ejecuta en el hilo principal.

ParámetroTipoNotas
xintCoordenada X del bloque
yintCoordenada Y del bloque
zintCoordenada Z del bloque
materialstringNombre del Material de Bukkit, en minúsculas (por ejemplo, "stone", "air", "oak_planks")

Devuelve true si el bloque se estableció correctamente, false en caso contrario.


world:spawn_particle(particle, x, y, z, count, dx, dy, dz, speed)

Genera partículas en una ubicación.

ParámetroTipoPor defectoNotas
particlestringrequeridoNombre del enum Particle de Bukkit, EN MAYÚSCULAS (por ejemplo, "FLAME", "HAPPY_VILLAGER")
xnumberrequeridoCoordenada X
ynumberrequeridoCoordenada Y
znumberrequeridoCoordenada Z
countint1Número de partículas
dxnumber0Dispersión/offset X
dynumber0Dispersión/offset Y
dznumber0Dispersión/offset Z
speednumber0Velocidad de la partícula
Data-requiring particles

Algunos tipos de partículas requieren datos extra que esta API simple no soporta. DUST, BLOCK_CRACK, FALLING_DUST, BLOCK_DUST e ITEM_CRACK pueden fallar o no producir un efecto visible. Usa alternativas sin datos en su lugar: CLOUD, SMOKE, CAMPFIRE_COSY_SMOKE, SNOWFLAKE, FLAME, HAPPY_VILLAGER, HEART, NOTE, ENCHANT, etc.

Como la API simple no proporciona objetos de datos de partícula de Bukkit, las partículas que requieren datos pueden lanzar una excepción subyacente de Bukkit y deshabilitar la instancia del script. Prefiere los nombres de partícula sin datos de arriba para los scripts de FMM/MagmaCore.


world:play_sound(sound, x, y, z, volume, pitch)

Reproduce un sonido en una ubicación.

ParámetroTipoPor defectoNotas
soundstringrequeridoNombre del enum Sound de Bukkit (p. ej. "ENTITY_EXPERIENCE_ORB_PICKUP") o una clave de sonido personalizada del resource pack (p. ej. "mypack:boss.roar")
xnumberrequeridoCoordenada X
ynumberrequeridoCoordenada Y
znumberrequeridoCoordenada Z
volumenumber1.0Volumen
pitchnumber1.0Tono
Custom resource-pack sounds

El nombre se compara primero con los sonidos registrados de Bukkit (sin distinguir mayúsculas, así que "ENTITY_ARROW_SHOOT" y "entity_arrow_shoot" son lo mismo). Si nada coincide, se normaliza a una clave con namespace en minúsculas y se reproduce como un sonido personalizado del resource pack. Un valor que no es ni un sonido conocido ni una clave con namespace válida no reproduce nada en lugar de dar error, así que una errata simplemente no hace nada en vez de deshabilitar tu script.

Lo mismo aplica a world:play_sound_at_location(loc, sound, volume, pitch).


world:strike_lightning(x, y, z)

Lanza un rayo en una ubicación (visual y dañino).

ParámetroTipoNotas
xnumberCoordenada X
ynumberCoordenada Y
znumberCoordenada Z

world:get_time()

Devuelve el tiempo actual del mundo en ticks.


world:set_time(ticks)

Establece el tiempo del mundo.

ParámetroTipoNotas
ticksintTiempo del mundo (0 = amanecer, 6000 = mediodía, 13000 = noche, 18000 = medianoche)

world:get_nearby_entities(x, y, z, radius)

Devuelve un array de tablas envoltorio de entidades para todas las entidades dentro de una caja delimitadora centrada en las coordenadas dadas.

ParámetroTipoNotas
xnumberCentro X
ynumberCentro Y
znumberCentro Z
radiusnumberRadio de búsqueda (utilizado como semi-extensión en los tres ejes)
precaución

Esto devuelve TODAS las entidades en el rango, incluidas las entidades no vivientes (armor stands, objetos soltados, etc.). Protege siempre con if entity.damage then antes de llamar a métodos de entidad viviente.


world:get_nearby_players(x, y, z, radius)

Devuelve un array de tablas envoltorio de jugador para todos los jugadores dentro de una caja delimitadora centrada en las coordenadas dadas.

ParámetroTipoNotas
xnumberCentro X
ynumberCentro Y
znumberCentro Z
radiusnumberRadio de búsqueda

world:spawn_entity(entity_type, x, y, z)

Genera una entidad vanilla de Minecraft en la ubicación dada.

ParámetroTipoNotas
entity_typestringNombre del tipo de entidad de Bukkit, en minúsculas (por ejemplo, "zombie", "skeleton", "pig")
xnumberCoordenada X
ynumberCoordenada Y
znumberCoordenada Z

Devuelve una tabla de entidad para la entidad generada (con métodos de entidad viviente si aplica), o nil si el tipo de entidad es inválido.


world:get_highest_block_y(x, z)

Devuelve la coordenada Y del bloque no-aire más alto en la posición X/Z dada.

ParámetroTipoNotas
xintCoordenada X del bloque
zintCoordenada Z del bloque

world:raycast(from_x, from_y, from_z, dir_x, dir_y, dir_z, [max_distance])

Lanza un rayo desde un punto en una dirección y devuelve información sobre lo que golpea.

ParámetroTipoPor defectoNotas
from_xnumberrequeridoOrigen X
from_ynumberrequeridoOrigen Y
from_znumberrequeridoOrigen Z
dir_xnumberrequeridoComponente X de la dirección
dir_ynumberrequeridoComponente Y de la dirección
dir_znumberrequeridoComponente Z de la dirección
max_distancenumber50Distancia máxima del rayo

Devuelve una tabla con los siguientes campos:

CampoTipoNotas
hit_entitytabla entidad o nilLa primera entidad alcanzada por el rayo, o nil si ninguna
hit_locationtabla location o nilEl punto exacto donde el rayo golpeó algo
hit_blocktabla o nil{x, y, z, material} del bloque golpeado, o nil si no se golpeó ningún bloque

world:spawn_firework(x, y, z, colors, [type], [power])

Genera un cohete de fuegos artificiales en la ubicación dada.

ParámetroTipoPor defectoNotas
xnumberrequeridoCoordenada X
ynumberrequeridoCoordenada Y
znumberrequeridoCoordenada Z
colorstablarequeridoArray de cadenas de color, por ejemplo, {"RED", "BLUE", "WHITE"}
typestring"BALL"Forma del fuego artificial: "BALL", "BALL_LARGE", "STAR", "BURST", "CREEPER"
powerint1Potencia de vuelo, 0-127
-- Ejemplo: explosión de fuegos artificiales rojos y dorados
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])

Coloca un bloque que se revierte automáticamente a su estado original tras un retraso.

ParámetroTipoPor defectoNotas
xintrequeridoCoordenada X del bloque
yintrequeridoCoordenada Y del bloque
zintrequeridoCoordenada Z del bloque
materialstringrequeridoNombre del Material de Bukkit (por ejemplo, "stone", "ice")
ticksint0Duración en ticks antes de que el bloque revierta. 0 significa permanente.
require_airbooleanfalseSi es true, solo coloca el bloque si el destino es aire

Devuelve true si se colocó el bloque, false si el material era inválido o no se cumplió el requisito de aire.


world:drop_item(x, y, z, material, [amount])

Suelta una entidad de objeto en la ubicación dada con dispersión natural.

ParámetroTipoPor defectoNotas
xnumberrequeridoCoordenada X
ynumberrequeridoCoordenada Y
znumberrequeridoCoordenada Z
materialstringrequeridoNombre del Material de Bukkit
amountint1Tamaño de la pila

Devuelve una tabla de entidad para el objeto soltado, o nil si el material era inválido.


context.zones

La tabla zones permite a los scripts crear zonas espaciales y vigilarlas en busca de eventos de entrada/salida de jugadores. Los props de FMM, los ítems de FMM y los scripts de NPC de EliteMobs usan los métodos genéricos create_sphere(...) / create_cylinder(...) / create_cuboid(...) más watch(...) / unwatch(...) documentados aquí, que disparan los hooks on_zone_enter / on_zone_leave. Las zonas están ligadas a la instancia del script y se limpian automáticamente cuando la instancia del script se destruye. Los poderes de jefe de EliteMobs usan una tabla de zonas separada y específica de jefe con métodos como get_entities_in_zone(...), get_locations_in_zone(...) y watch_zone(...); consulta EliteMobs Zones & Targeting.

zones:create_sphere(x, y, z, radius)

Crea una zona esférica centrada en las coordenadas dadas. Devuelve un handle numérico de zona.

ParámetroTipoNotas
xnumberCentro X
ynumberCentro Y
znumberCentro Z
radiusnumberRadio de la esfera

zones:create_cylinder(x, y, z, radius, height)

Crea una zona cilíndrica. Devuelve un handle numérico de zona.

ParámetroTipoNotas
xnumberCentro X
ynumberCentro Y (base)
znumberCentro Z
radiusnumberRadio del cilindro
heightnumberAltura del cilindro

zones:create_cuboid(x, y, z, xSize, ySize, zSize)

Crea una zona cuboide. Devuelve un handle numérico de zona.

ParámetroTipoNotas
xnumberCentro X
ynumberCentro Y
znumberCentro Z
xSizenumberSemi-extensión en X
ySizenumberSemi-extensión en Y
zSizenumberSemi-extensión en Z

zones:watch(handle, onEnterCallback, onLeaveCallback)

Comienza a vigilar una zona para eventos de entrada/salida de jugadores. Los parámetros del callback actúan como señales booleanas — pasar un valor no-nulo (por ejemplo, una función o true) habilita el hook correspondiente en el script. Los propios callbacks no se invocan directamente. En su lugar, la lógica de entrada/salida se dispara mediante los hooks on_zone_enter / on_zone_leave del script.

ParámetroTipoNotas
handleintHandle de zona de una llamada create_*
onEnterCallbackcualquier no-nulo o nilNo-nulo habilita el hook on_zone_enter para esta zona
onLeaveCallbackcualquier no-nulo o nilNo-nulo habilita el hook on_zone_leave para esta zona

Devuelve true si la vigilancia se configuró correctamente, nil si el handle de zona era inválido.

información

Las vigilancias de zona se comprueban cada tick del servidor contra todos los jugadores en el mismo mundo. Mantén la cuenta de zonas razonable para evitar sobrecarga de rendimiento.


zones:unwatch(handle)

Detiene la vigilancia de una zona y limpia sus recursos.

ParámetroTipoNotas
handleintHandle de zona para dejar de vigilar

Ejemplo: Zona disparada por proximidad

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)

-- Pasa valores no-nulos para habilitar los hooks on_zone_enter y on_zone_leave.
-- Son señales booleanas, no callbacks — la lógica real va en los hooks de abajo.
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

La tabla event está presente cuando el hook actual se desencadenó por un evento de Bukkit (por ejemplo on_right_click) o cuando el runtime proporciona un actor jugador para un hook genérico de zona de MagmaCore. No está presente durante on_game_tick, callbacks planificados ni hooks de ciclo de vida sin jugador desencadenante.

Para los hooks genéricos on_zone_enter / on_zone_leave, context.player y context.event.player identifican al jugador que entra o sale de la zona. Esos hooks de zona no están respaldados por un evento cancelable de Bukkit, así que cancel() y uncancel() no están presentes ahí.

Campo / MétodoTipoNotas
is_cancelledbooleanEstado de cancelación en el momento en que se construyó el context. Este campo no se refresca tras llamar a cancel() o uncancel().
cancel()methodCancela el evento (evita el comportamiento por defecto)
uncancel()methodDes-cancela un evento previamente cancelado
playertabla entidadEl jugador involucrado en el evento, si lo hay
on_right_click = function(context)
if context.event then
context.event:cancel() -- evita la interacción por defecto del clic derecho
end
end
Tabla de eventos de EliteMobs

Los scripts de poder de EliteMobs tienen una tabla de eventos más detallada con cantidades de daño, causas de daño, referencias del dañador y métodos de modificación de daño. Consulta Referencia de la API de Lua para los campos completos de eventos de EliteMobs.


Namespace de Ayuda em

La tabla em está disponible en el momento de carga del archivo (antes de que se ejecute cualquier hook). Proporciona constructores auxiliares para construir tablas de ubicación, tablas de vector y definiciones de zona usadas a lo largo de la API.

FunciónPropósito
em.create_location(x, y, z [, world, yaw, pitch])Crea una tabla de ubicación con nombre de mundo, yaw y pitch opcionales. La tabla devuelta también tiene un método .add(dx, dy, dz) que desplaza la ubicación en su lugar y se devuelve a sí misma para encadenamiento.
em.create_vector(x, y, z)Crea una tabla de vector
em.zone.create_sphere_zone(radius)Crea una definición de zona esférica
em.zone.create_dome_zone(radius)Crea una definición de zona de cúpula
em.zone.create_cylinder_zone(radius, height)Crea una definición de zona cilíndrica
em.zone.create_cuboid_zone(x, y, z)Crea una definición de zona cuboide
em.zone.create_cone_zone(length, radius)Crea una definición de zona cónica
em.zone.create_static_ray_zone(length, thickness)Crea una definición de zona de rayo estático
em.zone.create_rotating_ray_zone(length, point_radius, animation_duration)Crea una definición de zona de rayo rotatorio
em.zone.create_translating_ray_zone(length, point_radius, animation_duration)Crea una definición de zona de rayo trasladante
em.location.is_in_dungeon(loc)Comprueba si una ubicación está dentro de alguna región de dungeon registrada (cualquier propietario que reporte el tipo "dungeon")
em.location.is_protected(loc)Comprueba si una ubicación está dentro de alguna región protegida (WorldGuard, GriefPrevention, regiones de EM, etc.)
em.location.owned_by(loc, namespace)Comprueba si un namespace de plugin específico posee la ubicación (por ejemplo, "EliteMobs")
em.location.owners(loc)Array de cadenas de namespace que poseen la ubicación
em.location.kinds_at(loc)Array de etiquetas de tipo en la ubicación ("elitemobs", "dungeon", "world_package", "open_world_dungeon", categoría de tamaño de dungeon)
em.location.has_kind(loc, kind)Comprueba si la ubicación está etiquetada con el tipo dado
Region plugins are detected automatically

MagmaCore incluye sus propios adaptadores de WorldGuard y GriefPrevention y los registra por ti la primera vez que se ejecuta una consulta de protección -- no hay configuración ni dependencia obligatoria. Sin ninguno de los dos plugins instalados y sin ningún plugin de contenido registrando propiedad, em.location.is_protected(loc) simplemente devuelve false y una advertencia única en consola explica por qué. Pasar una ubicación nula o inválida devuelve false desde los predicados y una tabla vacía desde owners / kinds_at; estos helpers nunca lanzan excepciones.

Los constructores de zonas devuelven tablas encadenables con :set_center(loc) (o :set_origin(loc) / :set_destination(loc) dependiendo del tipo de zona):

-- A nivel de archivo: crear una forma de zona reutilizable
local blast_zone = em.zone.create_sphere_zone(5)

return {
api_version = 1,

on_spawn = function(context)
-- Anclar la zona en el momento de la llamada
blast_zone:set_center(context.boss:get_location())
local entities = context.zones:get_entities_in_zone(blast_zone)
-- ...
end
}
información

El namespace em es particularmente útil en EliteMobs, donde las definiciones de zona se usan con context.zones:get_entities_in_zone() y context.script. En FreeMinecraftModels, los métodos context.zones:create_sphere(...) / create_cylinder(...) / create_cuboid(...) se usan más comúnmente para zonas simples basadas en vigilancia.


Tablas de Entidad

Las tablas de entidad se devuelven de consultas del mundo, datos de eventos y callbacks de zona. Proporcionan un conjunto en capas de campos y métodos según el tipo de entidad.

Campos Base de Entidad

CampoTipoNotas
uuidstringEl UUID de la entidad
entity_typestringEl tipo de entidad (por ejemplo, "player", "zombie", "skeleton", "villager")
is_validbooleanSi la referencia de la entidad sigue siendo válida
is_deadbooleanSi la entidad está muerta
is_playerbooleanSi la entidad es un jugador
is_hostilebooleanSi la entidad es un mob hostil (zombie, esqueleto, etc.)
is_passivebooleanSi la entidad es un mob pasivo (vaca, cerdo, gallina, etc.)
current_locationtabla locationLa posición actual de la entidad (x, y, z, world, yaw, pitch)
worldstringEl nombre del mundo en el que se encuentra la entidad

Métodos Base de Entidad

MétodoDevuelveNotas
teleport(location_table)voidTeletransporta la entidad. La tabla de ubicación debe tener los campos x, y, z, world; yaw y pitch son opcionales.
remove()voidElimina la entidad del mundo. Solo actúa si la entidad sigue siendo válida.
set_silent(flag)voidSuprime o vuelve a habilitar los sonidos de la entidad.
set_invulnerable(flag)voidHace que la entidad sea invulnerable o vulnerable al daño.
set_gravity(flag)voidHabilita o deshabilita la gravedad de la entidad.
set_glowing(flag)voidAlterna el efecto de contorno brillante sobre la entidad.

Campos de Entidad Viviente

Las entidades vivientes (jugadores, mobs, etc.) tienen todos los campos base de entidad más:

CampoTipoNotas
healthnumberSalud actual
maximum_healthnumberSalud máxima
namestringNombre mostrado
is_alivebooleanSi la entidad está viva

Métodos de Entidad Viviente

MétodoDevuelveNotas
damage(amount)voidInflige la cantidad dada de daño a la entidad
push(x, y, z)voidAplica un impulso de velocidad
set_facing(x, y, z)voidEstablece la dirección a la que mira la entidad
add_potion_effect(effect, duration, amplifier)voidAñade un efecto de poción. effect es una cadena (por ejemplo, "speed", "slowness", "regeneration"). duration está en ticks. amplifier es el nivel del efecto menos 1 (0 = nivel I).
remove_potion_effect(effect)voidElimina un efecto de poción por nombre
get_scale()numberDevuelve la escala actual de la entidad (por defecto 1.0 en servidores sin el atributo generic.scale)
set_scale(value)voidEstablece la escala de la entidad mediante el atributo generic.scale. Sin efecto en servidores anteriores a 1.20.5.
precaución

No todas las entidades devueltas por get_nearby_entities() son entidades vivientes. Puedes usar entity.is_player, entity.is_hostile o entity.is_passive para filtrar por categoría, o comprobar if entity.damage then antes de llamar a métodos de entidad viviente como damage(), push() o add_potion_effect().


Campos de Integración con Plugins

Las tablas de entidad incluyen automáticamente campos para detectar e interactuar con entidades gestionadas por otros plugins de Nightbreak. Estos campos solo se rellenan cuando el plugin relevante está instalado -- de lo contrario, por defecto son false / nil sin sobrecarga.

Campos de EliteMobs

Disponible cuando EliteMobs está instalado.

CampoTipoNotas
is_elitebooleanSi la entidad es un elite de EliteMobs
is_custom_bossbooleanSi la entidad es un jefe personalizado de EliteMobs (también disponible dentro de la subtabla elite)
is_significant_bossbooleanSi la entidad es un jefe personalizado con un multiplicador de salud superior a 1 (es decir, un encuentro diseñado, no un elite de relleno)
elitetabla o nilSubtabla de información del elite (ver abajo). nil si la entidad no es un elite.

La subtabla elite contiene:

CampoTipoNotas
elite.levelintEl nivel del elite
elite.namestringEl nombre mostrado del elite
elite.healthnumberSalud actual
elite.max_healthnumberSalud máxima
elite.is_custom_bossbooleanSi es un jefe personalizado (en oposición a un elite natural)
elite.health_multipliernumberMultiplicador de salud definido en la configuración
elite.damage_multipliernumberMultiplicador de daño definido en la configuración
elite:remove()voidElimina el elite mediante el pipeline de eliminación adecuado de EliteMobs (limpia tracking, botín, etc.)
Ejemplo: Dañar elites de forma diferente
local entities = context.world:get_nearby_entities(x, y, z, 5)
for _, entity in ipairs(entities) do
if entity.is_elite then
-- Inflige el doble de daño a 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

Campos de FreeMinecraftModels

Disponible cuando FreeMinecraftModels está instalado.

CampoTipoNotas
is_modeledbooleanSi la entidad tiene un modelo FMM adjunto (DynamicEntity o PropEntity)
is_propbooleanSi la entidad es un prop de FMM (entidad decorativa estática)
modeltabla o nilSubtabla de información del modelo (ver abajo). nil si la entidad no está modelada.

La subtabla model contiene:

CampoTipoNotas
model.model_idstringEl ID del blueprint del modelo (por ejemplo, "torch_01")
model.is_dynamicbooleanSi la entidad modelada es una DynamicEntity (modelo de mob/jefe) en lugar de un prop estático
model:play_animation(name, [blend], [loop])booleanReproduce una animación con nombre. blend por defecto es false, loop por defecto es false. Devuelve true si se encontró la animación.
model:stop_animations()voidDetiene todas las animaciones que se estén reproduciendo actualmente en el modelo.
model:remove()voidElimina la entidad modelada mediante el pipeline de eliminación adecuado de FMM.
Bridge vs valores por defecto de Prop

El bridge de modelo (disponible en cualquier entidad) tiene por defecto blend y loop en false. El tabla prop play_animation tiene ambos por defecto en true porque los props normalmente quieren animaciones mezcladas y en bucle.

Ejemplo: Filtrar entidades por tipo
local entities = context.world:get_nearby_entities(x, y, z, 10)
for _, entity in ipairs(entities) do
if entity.is_prop then
-- Omitir props
elseif entity.is_player then
entity:damage(5)
elseif entity.entity_type == "villager" then
-- No herir aldeanos
elseif entity.is_elite then
entity:damage(20)
elseif entity.is_hostile then
entity:damage(10)
end
end

Campos Específicos del Jugador

Las entidades de jugador tienen todos los campos de entidad y entidad viviente más:

CampoTipoNotas
game_modestringEl modo de juego del jugador ("creative", "survival", "adventure", "spectator")

Métodos Específicos del Jugador

Text formatting

Allá donde la API dice "admite códigos de color", Magmacore pasa la cadena por su parser MiniMessage integrado. Los códigos & heredados, el hex &#RRGGBB, <#RRGGBB>, <gradient>, <rainbow> y el resto del conjunto de etiquetas de MiniMessage funcionan y se pueden mezclar libremente. Kyori Adventure no es una dependencia y los scripts no tienen ninguna API de Adventure disponible -- no la necesitas.

Los métodos de texto de Lua convierten a una cadena con códigos de color heredados, así que los colores, degradados y decoraciones se renderizan correctamente mientras que las etiquetas interactivas (<hover>, <click>, <insert>, <font>, <key>, <lang>) se analizan pero no tienen efecto. Consulta Códigos de Color para la lista completa de etiquetas.

MétodoDevuelveNotas
send_message(msg)voidEnvía un mensaje de chat al jugador. Admite códigos de color.
get_held_item()tabla o nilDevuelve {type, amount, display_name} para el objeto en la mano principal del jugador, o nil si está vacía. type es el nombre del Material de Bukkit en mayúsculas, como "GOLD_INGOT".
consume_held_item(amount?)voidConsume objetos de la mano principal del jugador. amount por defecto es 1
has_item(material, amount?)booleanDevuelve true si el jugador tiene al menos amount (por defecto 1) del material dado en cualquier parte de su inventario
get_target_entity([range])tabla entidad o nilDevuelve la entidad a la que mira el jugador mediante raycast, o nil si ninguna. El rango por defecto es 50.
get_eye_location()tabla locationDevuelve una tabla de ubicación a la altura de los ojos del jugador
get_look_direction()tablaDevuelve un vector de dirección {x, y, z} para hacia donde mira el jugador
send_block_change(x, y, z, material, [ticks])booleanEnvía un bloque falso visible solo para este jugador. Si se proporciona ticks, el bloque falso se restablece automáticamente tras esa duración. Devuelve true en éxito, false si el material es inválido.
reset_block(x, y, z)booleanRestablece un bloque falso al bloque real para este jugador. Siempre devuelve true.
sleep(x, y, z)voidHace que el jugador entre en una animación de dormir en cama en las coordenadas dadas. El bloque se restaura automáticamente cuando el jugador deja de dormir.
wake_up()voidDespierta a un jugador dormido.

Métodos de UI del Jugador

Estos métodos están disponibles en cualquier tabla de entidad jugador y proporcionan formas de mostrar información al jugador mediante los elementos de UI integrados de Minecraft.

player:show_boss_bar(text, [color], progress, [ticks])

Muestra una barra de jefe al jugador.

ParámetroTipoPor defectoNotas
textstringrequeridoEl texto a mostrar. Admite códigos de color &.
colorstring"WHITE"Color de la barra. Uno de: "RED", "BLUE", "GREEN", "YELLOW", "PURPLE", "PINK", "WHITE"
progressnumberrequeridoCantidad de relleno desde 0.0 (vacío) hasta 1.0 (lleno)
ticksintnilRetraso opcional de auto-cierre en ticks. Si se omite, la barra permanece hasta que se oculta manualmente.

player:hide_boss_bar()

Elimina la barra de jefe de la pantalla del jugador. No toma parámetros.

player:show_action_bar(text, [ticks])

Muestra texto en el área de la barra de acción (sobre el hotbar).

ParámetroTipoPor defectoNotas
textstringrequeridoEl texto a mostrar. Admite códigos de color &.
ticksintnilDuración opcional en ticks. Si se proporciona, el mensaje se reenvía cada 40 ticks para mantenerlo visible durante toda la duración.

player:show_title(title, [subtitle], fade_in, stay, fade_out)

Muestra una pantalla de título al jugador.

ParámetroTipoPor defectoNotas
titlestringrequeridoTexto principal del título. Admite códigos de color &.
subtitlestring""Texto del subtítulo debajo del título principal. Opcional.
fade_inintrequeridoDuración del fundido de entrada en ticks
stayintrequeridoCuánto tiempo permanece el título en pantalla en ticks
fade_outintrequeridoDuración del fundido de salida en ticks

Siguientes Pasos

Para hooks, APIs y flujos de trabajo específicos de cada plugin:

Los constructores actuales exponen em.create_location(...), em.zone.create_sphere_zone(...) y consultas como em.location.is_protected(...); las tablas de jugador añaden has_permission(node). El contexto exacto depende del hook: no presupongas context.event.player en callbacks programados.