Motor de Scripting Lua de MagmaCore
MagmaCore proporciona el sandbox de Lua y el entorno ScriptInstance que usan los poderes de jefe de EliteMobs, sus scripts de NPC, los props de FreeMinecraftModels y los efectos de encantamientos personalizados. Comparten la validación de archivos y la gestión de recursos, pero los hooks, las tablas de contexto, los ámbitos de cooldown y la duración dependen del sistema que los ejecuta. Las consultas de encantamientos también tienen un contexto restringido y límites propios del proveedor; consulta su referencia más abajo.
Los props de FreeMinecraftModels y los scripts de NPC de EliteMobs heredan directamente las tablas de contexto genéricas de MagmaCore (context.world, context.zones, context.scheduler, context.cooldowns, context.log, context.event, context.player y context.state) y añaden la tabla de su propietario (context.prop o context.npc). Los poderes de jefe de EliteMobs se ejecutan sobre el mismo entorno, pero exponen variantes ampliadas específicas de jefe para varias tablas (context.world, context.zones, context.cooldowns, context.scheduler, context.log, context.event), además de utilidades exclusivas 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 comoon_npc_interact,on_npc_proximity_enter, etc.) - FreeMinecraftModels -- Scripts Lua para props (hooks como
on_right_click,on_left_click, etc.) y efectos de encantamientos personalizados para objetos personalizados
Esta página documenta las funciones genéricas del motor MagmaCore que usan los scripts de FreeMinecraftModels, junto con notas de compatibilidad para EliteMobs cuando los mismos conceptos tienen variantes específicas de jefe o NPC. Para conocer el contexto exacto de los jefes de EliteMobs, consulta sus páginas de Lua; para el de los NPC, consulta Scripts Lua de NPC.
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
-- do something with the event
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
}
Devolver la definición del script
Al final de cada archivo de script, retornas una tabla:
return {
api_version = 1,
on_spawn = function(context)
end
}
La tabla devuelta es la definición del script. El cargador evalúa el archivo para validarlo y vuelve a evaluar el código guardado para cada instancia. Las variables locales del archivo pertenecen a esa instancia, no a todas las entidades que usan el mismo nombre de archivo. Editar el archivo no cambia una definición ya cargada ni una instancia activa; recárgalo mediante el procedimiento del plugin correspondiente.
Comentarios
Usa -- para escribir una nota para humanos:
-- This cooldown stops the attack from firing every hit
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:
| Eliminado | Por qué |
|---|---|
debug | Expone el estado interno de la VM |
dofile | Acceso al sistema de archivos |
io | Acceso al sistema de archivos |
load | Carga arbitraria de código |
loadfile | Acceso al sistema de archivos |
luajava | Acceso directo a clases de Java |
module | Sistema de módulos (no necesario) |
os | Acceso al sistema operativo |
package | Sistema de módulos (no necesario) |
require | Sistema de módulos / acceso al sistema de archivos |
Biblioteca estándar disponible
El entorno estándar de LuaJ proporciona estas funciones habituales de Lua:
| Categoría | Funciones |
|---|---|
| Matemáticas | math.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.* |
| Cadenas | string.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.* |
| Tablas | table.insert, table.remove, table.sort, table.concat, y todas las demás funciones table.* |
| Iteradores | pairs, ipairs, next |
| Tipo | type, tostring, tonumber, select, unpack |
| Manejo de errores | pcall, xpcall, error, assert |
| Otros | print, rawget, rawset, rawequal, rawlen, setmetatable, getmetatable |
os no está disponibleLa 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.
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 obligatorios y opcionales
| Campo | Requerido | Tipo | Notas |
|---|---|---|---|
api_version | Sí | Number | Actualmente debe ser 1 |
priority | No | Number | Por defecto 0; se convierte en entero. Los scripts de jefe y NPC de EliteMobs ejecutan primero los valores más bajos. FMM valida el campo, pero los scripts de prop siguen el orden de la lista scripts: |
| claves de hooks soportadas | No | Function | Deben usar uno de los nombres exactos de hooks soportados por el plugin |
Reglas de validación
- El archivo debe retornar una tabla.
api_versiones requerido y actualmente debe ser1.prioritydebe 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.
El validador de Lua acepta priority para todos los scripts basados en MagmaCore. EliteMobs lo usa para el orden de los scripts de jefe y NPC. FreeMinecraftModels actualmente no ordena por priority: los props siguen el orden de la lista scripts: de la configuración. Los encantamientos personalizados usan el catálogo de su proveedor y su ciclo de vida de acciones y consultas.
Dónde se guardan los archivos de script
Cada proveedor elige su directorio. El motor genérico busca archivos .lua recursivamente y excluye las rutas de configuración archivada. Ordena las rutas absolutas normalizadas, primero sin distinguir mayúsculas y después por la ruta exacta, selecciona el primer archivo por nombre en minúsculas y registra los duplicados omitidos cuyo contenido difiere del archivo seleccionado. Si el elegido falla la validación, no recurre a otro duplicado. Las búsquedas registradas conservan la escritura exacta del nombre seleccionado: úsala en las referencias. Los poderes de jefe y los catálogos de encantamientos tienen sus propias reglas de búsqueda; compartir validador no hace intercambiables sus directorios.
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 entornos de Lua. Cada tipo de script habilita solo el subconjunto que tiene sentido para su propietario: los scripts de prop de FMM usan todos estos, los poderes de jefe de EliteMobs usan su propia lista de hooks, 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.
| Hook | Cuándo se dispara |
|---|---|
on_spawn | Lo emite el ciclo de aparición del plugin para props de FMM, jefes de EliteMobs y NPC; construir un ScriptInstance por sí solo no lo dispara |
on_game_tick | Se llama cada tick del servidor mientras la instancia inicializada esté activa y sin pausar |
on_zone_enter | Se 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_leave | Se 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). Los métodos de las tablas de contexto de MagmaCore eliminan ese primer argumento implícito, por lo que ambas formas funcionan para métodos como context.log.info:
context.log:info("hello")
context.log.info("hello") -- same thing
Las funciones auxiliares globales de em se llaman con .: em.create_location(...), em.zone.create_sphere_zone(...) y em.location.is_protected(...). Los setters de eventos de EliteMobs context.event.set_damage_amount(...) y context.event.multiply_damage_amount(...) también requieren .. La documentación usa : para métodos de tablas de contexto y . para funciones normales.
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.
El entorno ordinario aplica estos límites:
| Límite | Valor |
|---|---|
| Tiempo de CPU del hilo actual | 50 milisegundos |
| Instrucciones de Lua ejecutadas | 250,000 |
Superar un límite provoca un error de Lua. El contador se comprueba en cada instrucción Lua; el reloj, cada 1.024 instrucciones y al volver de la llamada. Esto no interrumpe un método Java/Bukkit en curso, y 50 ms de CPU no son un plazo de 50 ms de tiempo real. Un error no capturado en un hook o callback cierra la instancia. En la validación inicial se rechaza la definición. Si no se puede medir la CPU del hilo actual, se usan 250 milisegundos de tiempo transcurrido con el mismo límite de instrucciones. Los lotes de consultas de encantamientos pueden imponer cuotas menores.
La VM interrumpe un while true do end ordinario mientras ejecuta instrucciones Lua. El bucle sigue consumiendo tiempo del hilo del servidor y cierra la instancia cuando el error se propaga. Mantén los bucles acotados aunque exista esta protección.
Las llamadas anidadas comparten un único presupuesto: toda la cadena dispone de 50 ms de CPU y 250.000 instrucciones, sin una cuota independiente para cada llamada.
Para mantenerte dentro del presupuesto:
- Evita bucles sin límite dentro de los hooks.
- Mantén los manejadores de
on_game_tickligeros -- se ejecutan en cada tick. - Usa
context.scheduler:run_repeating(...)para repartir el trabajo entre ticks. - Mueve el trabajo costoso detrás de
context.cooldownso un intervalo razonable.
Un error no capturado en un hook o callback cierra esa instancia y cancela su trabajo propio. Corrige y recarga la definición, y deja que el plugin cree una nueva instancia. Guardar el archivo por sí solo no repara la instancia cerrada. Los sistemas de encantamientos aplican además su propia política de supresión de fallos.
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.
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
}
Usa context.state para compartir datos entre hooks de una instancia. Está en memoria y no se guarda entre recargas o reinicios. Las demás tablas se construyen bajo demanda y pueden contener instantáneas. FMM conserva context.prop, pero lee campos como current_location bajo demanda. Vuelve a leer un campo actual para actualizarlo; una tabla guardada en una variable no se actualiza sola. Asignar un valor a un campo calculado oculta su lectura dinámica.
context.log
Métodos de registro en consola, disponibles en todos los tipos de script. Los mensajes genéricos de log.info llevan el prefijo [Lua]; incluye una etiqueta del script en el mensaje si necesitas identificar su origen. Los diagnósticos de error identifican el script que falla, pero los registros ordinarios no añaden automáticamente su nombre de archivo. 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étodo | Notas |
|---|---|
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) |
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 gestiona los tiempos de reutilización. Los cooldowns locales y los globales genéricos convierten cada tick en 50 ms de tiempo monotónico, incluidas las pausas y los TPS bajos. Los globales de jefe, en cambio, cuentan ticks del servidor. Hay dos ámbitos:
- Los cooldowns locales usan claves de cadena exactas en el almacén del propietario, cuyo ámbito se indica abajo. Pasa
nilpara la clave predeterminada,__lua:seguido del nombre de archivo. - Los cooldowns globales se comparten entre todos los scripts de la misma entidad propietaria cuando el entorno expone métodos de cooldown global (por ejemplo, todos los scripts del mismo prop o todos los poderes Lua del mismo jefe).
cooldowns:check_local(key?, duration)
Comprueba una clave local y, si está lista, inicia su cooldown y devuelve true; en caso contrario devuelve false. Es una llamada Lua síncrona. No comprueba ni inicia el cooldown global. El almacén no es una API de bloqueo entre hilos.
| Parámetro | Tipo | Notas |
|---|---|---|
key | string (opcional) | Identificador del cooldown. nil selecciona la clave predeterminada. |
duration | int | Duración del cooldown en ticks (20 = 1 segundo) |
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
Todos los tipos de script —poderes de jefe, scripts de NPC y scripts de FreeMinecraftModels— usan el orden compartido mostrado arriba: check_local(key?, duration). Para usar la clave predeterminada, pasa check_local(nil, 60); check_local(60) no significa un cooldown predeterminado de 60 ticks. (Las compilaciones experimentales anteriores de NPC usaban check_local(duration, key?); actualiza los scripts antiguos 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ámetro | Tipo | Notas |
|---|---|---|
duration | int | Duración en ticks. Pasa 0 o un valor negativo para limpiar. |
key | string (opcional) | Identificador del cooldown. nil selecciona la clave predeterminada. |
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. En las tablas genéricas de MagmaCore, cero o un valor negativo lo elimina. Los cooldowns globales de jefe conservan el vencimiento más tardío: una duración más corta nunca acorta un cooldown global activo, y cero o un valor negativo no hace nada. Establecer el local no establece el global, ni al contrario.
| Parámetro | Tipo | Notas |
|---|---|---|
duration | int | Duración en ticks |
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 globales y las claves locales explícitas se comparten mediante el único adaptador del NPC. Dos scripts con la misma clave local se afectan entre sí; las claves omitidas siguen dependiendo del nombre de archivo.
- Scripts de prop de FMM: los globales se comparten por prop colocado; cada script adjunto tiene su adaptador y almacén local.
- Acciones de encantamiento — los cooldowns globales se comparten por jugador dentro del proveedor; los locales pertenecen al jugador y al ID de encantamiento y sobreviven a los cambios de equipo y a las acciones finalizadas. Consulta los encantamientos personalizados.
context.scheduler
El planificador ejecuta tareas retrasadas y repetidas. Las creadas mediante él pertenecen a la instancia y se cancelan al cerrarla. Esto no revierte entidades generadas, cambios del mundo ni temporizadores de utilidades separadas de interfaz o efectos. Durante una pausa, una tarea única vencida espera a la reanudación y una repetida omite las llamadas pausadas.
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.
scheduler:run_later(ticks, callback)
Ejecuta un callback una vez tras un retraso. Devuelve un ID numérico de tarea.
| Parámetro | Tipo | Notas |
|---|---|---|
ticks | int | Retraso en ticks del servidor (20 ticks = 1 segundo) |
callback | function | Llamada 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ámetro | Tipo | Notas |
|---|---|---|
delay | int | Retraso inicial en ticks antes de la primera ejecución |
interval | int | Ticks entre cada ejecución posterior |
callback | function | Llamada 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 por ID una tarea de esta instancia. Un ID desconocido o de otra instancia no tiene efecto.
| Parámetro | Tipo | Notas |
|---|---|---|
taskId | int | El ID de tarea devuelto por run_later o run_repeating |
El cierre cancela automáticamente las tareas propias. Cancélalas antes si termina una interacción o fase de combate y la instancia sigue activa, por ejemplo en on_exit_combat de un jefe. Ambos grupos de nombres funcionan. Usa los hooks de ciclo de vida del plugin; un error cierra la instancia sin garantizar un hook de limpieza personalizado.
Los callbacks reciben un contexto nuevo sin el evento ni el actor originales. Usa ese argumento, no el contexto externo. Si necesitas al jugador más tarde, captura su UUID durante el hook y búscalo de nuevo, comprobando que siga disponible. Un contexto externo retenido también puede resolver un campo de evento bajo demanda cuando el evento original ya terminó.
context.world
La tabla world permite consultar e interactuar con Minecraft. Captura el mundo actual del propietario al construirse por primera vez; guardarla no hace que siga sus cambios de mundo posteriores.
Estos métodos describen la tabla compartida que reciben props de FMM y scripts de NPC de EliteMobs, incluido strike_lightning(...) con daño. FMM añade utilidades opcionales de transporte y botín de EliteMobs; consulta context.world: adiciones de FreeMinecraftModels. EliteMobs añade a sus tablas compartidas utilidades de rayos visuales, generación de NPC y jefes que requieren chunks cargados. Los poderes de jefe añaden o sobrescriben otros métodos; consulta Mundo y entorno de EliteMobs.
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.
Los argumentos compartidos de ubicación requieren x, y y z. Un mundo omitido o no encontrado usa el mundo de la tabla. Las partículas compartidas por ubicación siguen usando ese mundo capturado, así que pasa una ubicación del mismo mundo. Los convertidores específicos de jefe y em.location.* siguen reglas distintas descritas en sus referencias.
La referencia completa de la tabla World también documenta la búsqueda de entidades, las consultas de transitabilidad y protección, el polvo coloreado, los impactos en el terreno y las sobrecargas con tablas de ubicación.
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"). Si el chunk de destino no está cargado, devuelve "air" en lugar de forzar su carga.
| Parámetro | Tipo | Notas |
|---|---|---|
x | int | Coordenada X del bloque |
y | int | Coordenada Y del bloque |
z | int | Coordenada Z del bloque |
world:set_block_at(x, y, z, material)
Establece el bloque en las coordenadas dadas. Se ejecuta en el hilo principal y evita forzar la carga de chunks.
| Parámetro | Tipo | Notas |
|---|---|---|
x | int | Coordenada X del bloque |
y | int | Coordenada Y del bloque |
z | int | Coordenada Z del bloque |
material | string | Nombre del Material de Bukkit, en minúsculas (por ejemplo, "stone", "air", "oak_planks") |
Devuelve true cuando el nombre del material es válido y el cambio se ha puesto en cola, o false si el material no es válido. Si el chunk de destino está descargado cuando se ejecuta la tarea en cola, se omite el cambio de bloque.
Esto no comprueba automáticamente la protección de regiones. Usa un material de bloque y consulta la protección correspondiente antes de colocarlo; aceptar la cola no demuestra que el bloque cambiara.
world:spawn_particle(particle, x, y, z, count, dx, dy, dz, speed)
Genera partículas en una ubicación.
| Parámetro | Tipo | Por defecto | Notas |
|---|---|---|---|
particle | string | requerido | Nombre del enum Particle de Bukkit; la búsqueda lo convierte a mayúsculas (por ejemplo, "FLAME", "HAPPY_VILLAGER") |
x | number | requerido | Coordenada X |
y | number | requerido | Coordenada Y |
z | number | requerido | Coordenada Z |
count | int | 1 | Número de partículas |
dx | number | 0 | Dispersión/offset X |
dy | number | 0 | Dispersión/offset Y |
dz | number | 0 | Dispersión/offset Z |
speed | number | 0 | Velocidad de la partícula |
Algunos tipos de partículas requieren datos adicionales que esta API sencilla no admite. Por ejemplo, DUST y FALLING_DUST necesitan datos adicionales. Usa alternativas sin datos como CLOUD, SMOKE, CAMPFIRE_COSY_SMOKE, SNOWFLAKE, FLAME, HAPPY_VILLAGER, HEART, NOTE o ENCHANT. Para el polvo coloreado, usa la utilidad específica world:spawn_dust(...) de la referencia de la tabla World.
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ámetro | Tipo | Por defecto | Notas |
|---|---|---|---|
sound | string | requerido | Nombre 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") |
x | number | requerido | Coordenada X |
y | number | requerido | Coordenada Y |
z | number | requerido | Coordenada Z |
volume | number | 1.0 | Volumen |
pitch | number | 1.0 | Tono |
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ámetro | Tipo | Notas |
|---|---|---|
x | number | Coordenada X |
y | number | Coordenada Y |
z | number | Coordenada Z |
world:get_time()
Devuelve el tiempo actual del mundo en ticks.
world:set_time(ticks)
Establece el tiempo del mundo.
| Parámetro | Tipo | Notas |
|---|---|---|
ticks | int | Tiempo del mundo (0 = amanecer, 6000 = mediodía, 13000 = noche, 18000 = medianoche) |
world:get_nearby_entities(x, y, z, radius)
Devuelve un array con índices desde uno de tablas de entidad dentro de una caja alineada con los ejes y centrada en las coordenadas. No excluye al propietario del script.
| Parámetro | Tipo | Notas |
|---|---|---|
x | number | Centro X |
y | number | Centro Y |
z | number | Centro Z |
radius | number | Radio de búsqueda (utilizado como semi-extensión en los tres ejes) |
Esto devuelve TODAS las entidades dentro del alcance, incluidas entidades no vivas (objetos soltados, proyectiles, etc.). Comprueba siempre if entity.damage then antes de llamar a métodos de entidades vivas.
world:get_nearby_players(x, y, z, radius)
Devuelve un array con índices desde uno de tablas de jugador dentro de una caja alineada con los ejes, usando radius como semiextensión en cada eje. No filtra modos de juego.
| Parámetro | Tipo | Notas |
|---|---|---|
x | number | Centro X |
y | number | Centro Y |
z | number | Centro Z |
radius | number | Radio de búsqueda |
world:spawn_entity(entity_type, x, y, z)
Genera una entidad vanilla de Minecraft en la ubicación dada.
| Parámetro | Tipo | Notas |
|---|---|---|
entity_type | string | Nombre del tipo de entidad de Bukkit, en minúsculas (por ejemplo, "zombie", "skeleton", "pig") |
x | number | Coordenada X |
y | number | Coordenada Y |
z | number | Coordenada Z |
Devuelve una tabla de entidad con métodos de entidad viva cuando corresponde, o nil si el nombre del enum es desconocido. Un tipo válido pero no generable puede lanzar un error. Este método no comprueba que el chunk esté cargado.
world:get_highest_block_y(x, z)
Devuelve la Y del bloque más alto según Bukkit en X/Z. A diferencia de get_block_at, no comprueba que el chunk esté cargado.
| Parámetro | Tipo | Notas |
|---|---|---|
x | int | Coordenada X del bloque |
z | int | Coordenada Z del bloque |
world:raycast(from_x, from_y, from_z, dir_x, dir_y, dir_z, [max_distance], [fluid_mode], [blocks_only], [loaded_only])
Lanza un rayo desde un punto en una dirección y devuelve información sobre lo que golpea.
| Parámetro | Tipo | Por defecto | Notas |
|---|---|---|---|
from_x | number | requerido | Origen X |
from_y | number | requerido | Origen Y |
from_z | number | requerido | Origen Z |
dir_x | number | requerido | Componente X de la dirección |
dir_y | number | requerido | Componente Y de la dirección |
dir_z | number | requerido | Componente Z de la dirección |
max_distance | number | 50 | Distancia máxima del rayo |
fluid_mode | string | "NEVER" | NEVER, SOURCE_ONLY o ALWAYS |
blocks_only | boolean | false | Ignora las entidades y traza solo contra bloques |
loaded_only | boolean | false | Devuelve nil en lugar de trazar si algún chunk del rectángulo delimitador del rayo está descargado |
Con loaded_only=true, comprueba también si el resultado es nil. En caso contrario, un rayo que no alcanza nada devuelve una tabla cuyos campos de impacto son nil:
| Campo | Tipo | Notas |
|---|---|---|
hit_entity | tabla entidad o nil | La primera entidad alcanzada por el rayo, o nil si ninguna |
hit_location | tabla location o nil | El punto exacto donde el rayo golpeó algo |
hit_block | tabla o nil | {x, y, z, material} del bloque golpeado, o nil si no se golpeó ningún bloque |
Los materiales aparecen en minúsculas. El trazado combinado usa tamaño 0.5 para entidades sin filtrarlas. La comprobación de chunks cubre todo el rectángulo delimitador, por lo que puede rechazar un chunk alejado del rayo exacto. Un nombre de modo de líquido inválido lanza un error.
world:spawn_firework(x, y, z, colors, [type], [power])
Genera un cohete de fuegos artificiales en la ubicación dada.
| Parámetro | Tipo | Por defecto | Notas |
|---|---|---|---|
x | number | requerido | Coordenada X |
y | number | requerido | Coordenada Y |
z | number | requerido | Coordenada Z |
colors | tabla | requerido | Array de cadenas de color, por ejemplo, {"RED", "BLUE", "WHITE"} |
type | string | "BALL" | Forma del fuego artificial: "BALL", "BALL_LARGE", "STAR", "BURST", "CREEPER" |
power | int | 1 | Potencia de vuelo, 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])
Coloca un bloque temporal y restaura el BlockData guardado tras una duración positiva. No captura el estado completo ni el inventario del bloque.
| Parámetro | Tipo | Por defecto | Notas |
|---|---|---|---|
x | int | requerido | Coordenada X del bloque |
y | int | requerido | Coordenada Y del bloque |
z | int | requerido | Coordenada Z del bloque |
material | string | requerido | Nombre del Material de Bukkit (por ejemplo, "stone", "ice") |
ticks | int | 0 | Duración en ticks antes de restaurar el bloque. Cero o un valor negativo coloca el bloque de forma permanente y sin registrarlo. |
require_air | boolean | false | Si es true, solo coloca el bloque si el destino es aire |
Devuelve false si el material no es válido o el chunk de destino está descargado. En caso contrario, devuelve true cuando se acepta la solicitud de colocación. Si require_air es true y el bloque de destino no es aire, el gestor omite el reemplazo aunque haya aceptado la solicitud.
Con ticks positivos, el gestor guarda los datos originales del bloque y los restaura cuando termina el temporizador, cuando se descarga el chunk o el mundo, o cuando se apaga el plugin. Solo restaura mientras el bloque siga conteniendo el bloque temporal, así que no se sobrescribe una edición posterior. Volver a colocar sobre un bloque que todavía contiene un bloque temporal reinicia su temporizador y conserva el primer original guardado. Se omiten los bloques con entidades de bloque, como cofres y carteles, y los bloques que ya mantiene otro propietario de bloques temporales, como una reserva de un encantamiento. Romper un bloque temporal no suelta nada y termina el registro sin restaurarlo; colocar un bloque en esa posición también termina el registro.
Estos temporizadores no se cancelan con el script, y la colocación no consulta automáticamente la protección de regiones.
world:drop_item(x, y, z, material, [amount])
Suelta una entidad de objeto en la ubicación dada con dispersión natural.
| Parámetro | Tipo | Por defecto | Notas |
|---|---|---|---|
x | number | requerido | Coordenada X |
y | number | requerido | Coordenada Y |
z | number | requerido | Coordenada Z |
material | string | requerido | Nombre del Material de Bukkit |
amount | int | 1 | Tamañ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 crear zonas espaciales y vigilarlas para detectar entradas y salidas de jugadores. Los props de FMM y los scripts de NPC de EliteMobs usan los métodos genéricos create_sphere(...) / create_cylinder(...) / create_cuboid(...) junto con watch(...) / unwatch(...) documentados aquí, que activan los hooks on_zone_enter / on_zone_leave. Las zonas están ligadas a la instancia del script y se limpian automáticamente cuando se destruye. Los poderes de jefe de EliteMobs usan una tabla de zonas independiente y específica de jefe con métodos como get_entities_in_zone(...), get_locations_in_zone(...) y watch_zone(...); consulta Zonas y selección de objetivos de EliteMobs.
zones:create_sphere(x, y, z, radius)
Crea una zona esférica centrada en las coordenadas. Devuelve un identificador numérico, o nil si el propietario no tiene mundo.
| Parámetro | Tipo | Notas |
|---|---|---|
x | number | Centro X |
y | number | Centro Y |
z | number | Centro Z |
radius | number | Radio de la esfera |
zones:create_cylinder(x, y, z, radius, height)
Crea una zona cilíndrica. Devuelve un identificador numérico, o nil si el propietario no tiene mundo.
| Parámetro | Tipo | Notas |
|---|---|---|
x | number | Centro X |
y | number | Centro Y (base) |
z | number | Centro Z |
radius | number | Radio del cilindro |
height | number | Altura del cilindro |
zones:create_cuboid(x, y, z, xSize, ySize, zSize)
Crea una zona cuboide. Devuelve un identificador numérico, o nil si el propietario no tiene mundo. Las vigilancias genéricas comprueban el punto de ubicación del jugador, así que estos tamaños son semiextensiones alrededor del centro. Esto difiere de las operaciones de solapamiento de entidades y de muestreo de ubicaciones de las zonas de jefe de EliteMobs. Si zSize es cero y xSize no lo es, la forma compartida usa xSize para Z.
| Parámetro | Tipo | Notas |
|---|---|---|
x | number | Centro X |
y | number | Centro Y |
z | number | Centro Z |
xSize | number | Semi-extensión en X |
ySize | number | Semi-extensión en Y |
zSize | number | Semi-extensión en Z |
zones:watch(handle, onEnterCallback, onLeaveCallback)
Habilita el envío de entradas y salidas para una zona ya creada. Los parámetros deben ser funciones Lua, pero sus cuerpos no se invocan directamente; la lógica se ejecuta en on_zone_enter / on_zone_leave. El seguimiento empieza al crear la zona, por lo que añadir watch después no informa de la entrada de alguien ya registrado dentro. Pasar nil en otro watch no elimina un manejador habilitado antes.
| Parámetro | Tipo | Notas |
|---|---|---|
handle | int | Handle de zona de una llamada create_* |
onEnterCallback | function o nil | Una función habilita el hook on_zone_enter para esta zona; se ignora su cuerpo |
onLeaveCallback | function o nil | Una función habilita el hook on_zone_leave para esta zona; se ignora su cuerpo |
Devuelve true si la vigilancia se configuró correctamente, nil si el handle de zona era inválido.
Las zonas se comprueban antes de on_game_tick contra puntos de ubicación de jugadores del mundo actual del propietario, no contra sus cajas completas. La esfera exige estar estrictamente dentro del radio; el cilindro, dentro del radio y entre la base incluida y la parte superior excluida. Las zonas conservan las coordenadas y el mundo de creación. Una desconexión o retirada de vigilancia no garantiza un hook de salida. Mantén una cantidad razonable de zonas.
zones:unwatch(handle)
Detiene la vigilancia de una zona y limpia sus recursos.
| Parámetro | Tipo | Notas |
|---|---|---|
handle | int | Handle de zona para dejar de vigilar |
Ejemplo: zona de activación 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)
-- 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
La tabla event está presente cuando el hook actual tiene un evento o un actor. Los clics sobre props de FMM usan una marca de cancelación del plugin; las interacciones de NPC y los hooks genéricos de zona pueden proporcionar un actor sin un evento de Bukkit. No está presente durante on_game_tick, las llamadas programadas ni los hooks de ciclo de vida sin jugador desencadenante.
Los hooks on_projectile_hit de props de FMM reciben el evento cancelable de impacto de proyectil de FreeMinecraftModels, así que cancel() y uncancel() están presentes. El hook se ejecuta después de que FMM haya gestionado el impacto, por lo que cancelarlo no impide que se consuma un proyectil no perforante. No se dispara si otro plugin ya canceló el impacto. context.event.player es el tirador cuando es una entidad viva, que puede ser un mob, y no existe en otro caso; context.player solo se establece cuando el proyectil lo disparó un jugador. El hook también expone context.projectile como tabla de entidad del proyectil.
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étodo | Tipo | Notas |
|---|---|---|
is_cancelled | boolean | Estado de cancelación al resolver por primera vez la subtabla de evento. cancel() y uncancel() no lo actualizan. |
cancel() | method | Cancela el evento; solo está presente para eventos cancelables |
uncancel() | method | Retira la cancelación del evento; solo está presente para eventos cancelables |
player | tabla entidad | El jugador involucrado en el evento, si lo hay |
on_right_click = function(context)
if context.event and context.event.cancel then
context.event:cancel() -- prevent the default right-click interaction
end
end
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 atacante y métodos de modificación de daño. Consulta la referencia de la API de Lua para ver todos los campos de eventos de EliteMobs.
Espacio de nombres de utilidades em
La tabla em está disponible al cargar el archivo. Sus constructores crean datos sin cargar mundos, registrar vigilancias ni validar una forma completa. Los setters devueltos modifican su tabla y conservan por referencia las tablas de ubicación recibidas.
| Función | Propó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 |
MagmaCore incluye adaptadores de WorldGuard y GriefPrevention. Los consumidores los inicializan al activarse, y una consulta de protección puede inicializarlos bajo demanda. Se consultan los proveedores registrados, no cualquier plugin de protección posible. Un fallo de un adaptador de regiones registrado se interpreta como protegido. Sin proveedor ni propiedad protegida, devuelve false; los avisos indican que faltan proveedores.
En em.location.*, pasa en world el nombre de un mundo cargado o {name=...}. No se usa el mundo del propietario como alternativa. Un mundo ausente o no encontrado, o una entrada nil, devuelve false o un array vacío. Las coordenadas ausentes valen cero, pero los campos numéricos mal formados pueden lanzar un error. Los namespaces de propietario distinguen mayúsculas; los tipos no. Tener propietario no implica pertenecer a una mazmorra ni estar protegido. El orden de los arrays no está garantizado.
Los constructores de zonas devuelven tablas encadenables con :set_center(loc) (o :set_origin(loc) / :set_destination(loc) dependiendo del tipo de zona):
-- 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
}
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 siguientes presentan los métodos comunes. La referencia completa de la API de Lua también cubre campos de proyectiles, comprobaciones de rutas de movimiento, propiedad y utilidades de protección. Se aplican a las tablas Entity genéricas; los envoltorios específicos de poderes de EliteMobs tienen su propia sección en esa referencia.
Las tablas de entidad se devuelven desde consultas del mundo y datos de eventos. Proporcionan capas de campos y métodos según el tipo de entidad.
Campos base de entidad
| Campo | Tipo | Notas |
|---|---|---|
uuid | string | El UUID de la entidad |
entity_type | string | El tipo de entidad (por ejemplo, "player", "zombie", "skeleton", "villager") |
is_valid | boolean | Si la referencia de la entidad sigue siendo válida |
is_dead | boolean | Si la entidad está muerta |
is_player | boolean | Si la entidad es un jugador |
is_hostile | boolean | Si implementa Bukkit Monster, no su agresividad actual |
is_passive | boolean | Si implementa Bukkit Animals, sin garantizar comportamiento pasivo |
current_location | tabla location | La posición actual de la entidad (x, y, z, world, yaw, pitch) |
world | string | El nombre del mundo en el que se encuentra la entidad |
Métodos base de entidad
| Método | Devuelve | Notas |
|---|---|---|
teleport(location_table) | void | Requiere x, y, z; un mundo omitido o no encontrado usa el de la entidad. yaw y pitch valen cero por defecto. No comprueba automáticamente el recorrido ni la protección. |
remove() | void | Elimina la entidad del mundo. Solo actúa si la entidad sigue siendo válida. |
set_silent(flag) | void | Suprime o vuelve a habilitar los sonidos de la entidad. |
set_invulnerable(flag) | void | Hace que la entidad sea invulnerable o vulnerable al daño. |
set_gravity(flag) | void | Habilita o deshabilita la gravedad de la entidad. |
set_glowing(flag) | void | Alterna el efecto de contorno brillante sobre la entidad. |
Campos de entidad viva
Las entidades vivientes (jugadores, mobs, etc.) tienen todos los campos base de entidad más:
| Campo | Tipo | Notas |
|---|---|---|
health | number | Salud actual |
maximum_health | number | Salud máxima |
name | string | Nombre mostrado |
is_alive | boolean | Si la entidad está viva |
Métodos de entidad viva
| Método | Devuelve | Notas |
|---|---|---|
damage(amount) | void | Inflige la cantidad dada de daño a la entidad |
push(x, y, z) | void | Añade inmediatamente el vector a la velocidad actual |
set_facing(x, y, z) | void | Teletransporta en el mismo sitio con una nueva dirección de mirada |
add_potion_effect(effect, duration, amplifier) | void | Añ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) | void | Elimina un efecto de poción por nombre |
get_scale() | number | Devuelve la escala efectiva con modificadores, o 1.0 si no está disponible |
set_scale(value) | void | Cambia el valor base del atributo de escala cuando está disponible |
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 pueden incluir campos de integración. Sin el componente correspondiente, no existen y se leen como nil. Los indicadores de seguimiento, la identidad del modelo, el estado de operador y la mayoría de los datos anidados son instantáneas; no siguen cambios posteriores. Los campos compartidos de salud EliteMobs se leen bajo demanda, y los métodos de modelos y permisos consultan los objetos al llamarse.
Campos de EliteMobs
Disponible cuando EliteMobs está instalado.
| Campo | Tipo | Notas |
|---|---|---|
is_elite | boolean | Si la entidad es un elite de EliteMobs |
is_custom_boss | boolean | Si la entidad es un jefe personalizado de EliteMobs (también disponible dentro de la subtabla elite) |
is_significant_boss | boolean | Si 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) |
elite | tabla o nil | Subtabla de información del elite (ver abajo). nil si la entidad no es un elite. |
La subtabla elite contiene:
| Campo | Tipo | Notas |
|---|---|---|
elite.level | int | El nivel del elite |
elite.name | string o nil | El nombre mostrado del élite |
elite.health | number | Salud actual |
elite.max_health | number | Salud máxima |
elite.is_custom_boss | boolean | Si es un jefe personalizado (en oposición a un elite natural) |
elite.health_multiplier | number | Multiplicador de salud definido en la configuración |
elite.damage_multiplier | number | Multiplicador de daño definido en la configuración |
elite:remove() | void | Elimina el élite mediante el proceso de retirada de EliteMobs; no es una muerte ni garantiza botín |
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
-- 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
Campos de FreeMinecraftModels
Disponible cuando FreeMinecraftModels está instalado.
| Campo | Tipo | Notas |
|---|---|---|
is_modeled | boolean | Si la entidad tiene un modelo FMM adjunto (DynamicEntity o PropEntity) |
is_prop | boolean | Si la entidad es un prop de FMM (entidad decorativa estática) |
model | tabla o nil | Subtabla de información del modelo (ver abajo). nil si la entidad no está modelada. |
La subtabla model contiene:
| Campo | Tipo | Notas |
|---|---|---|
model.model_id | string o nil | El ID del blueprint del modelo (por ejemplo, "torch_01") |
model.is_dynamic | boolean | Si la entidad modelada es una DynamicEntity (modelo de mob/jefe) en lugar de un prop estático |
model:play_animation(name, [blend], [loop]) | boolean | Acepta una solicitud de animación por nombre. blend y loop valen false por defecto; ponerla en cola o suprimir un ataque puede devolver true sin reproducirla inmediatamente. La muerte terminal rechaza la reproducción. |
model:stop_animations() | void | Vacía la cola de reproducción y vuelve a idle cuando está disponible; no afecta a la muerte terminal. |
model:remove() | void | Elimina la entidad modelada mediante el pipeline de eliminación adecuado de FMM. |
En las tablas de entidad de jugador, el componente de FreeMinecraftModels también añade:
| Campo / método | Tipo | Notas |
|---|---|---|
is_op | boolean | Indica si el jugador es operador del servidor. |
has_permission(node) | boolean | Indica si el jugador tiene el nodo de permiso. |
Estos dos valores de jugador solo existen en los scripts de FreeMinecraftModels. En las tablas compartidas creadas dentro de EliteMobs, el propio adaptador de FreeMinecraftModels de EliteMobs añade is_modeled, is_prop y model, pero no is_op ni has_permission.
Las tablas de jugador FMM también exponen is_holding_elitemobs_item(filename). Comprueba el tag del nombre de archivo EliteMobs de la mano principal, incluida la extensión .yml, no el nombre visible. Una mano vacía, otro objeto o una integración no disponible devuelve false. El componente compartido de EliteMobs añade por separado elite_player con el rango de combate cuando hay datos; el adaptador opcional de EliteMobs en FMM no añade esa subtabla.
El puente de modelos (disponible en cualquier entidad) usa false por defecto para blend y loop. El método play_animation de la tabla prop usa true para ambos, para reproducir props en cola y en bucle. blend controla la cola; no realiza una transición gradual entre animaciones.
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
-- 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
Campos específicos del jugador
Las entidades de jugador tienen todos los campos de entidad y entidad viviente más:
| Campo | Tipo | Notas |
|---|---|---|
game_mode | string | El modo de juego del jugador ("creative", "survival", "adventure", "spectator") |
Métodos Específicos del Jugador
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 muestran correctamente, mientras que las etiquetas interactivas (<hover>, <click>, <insert>, <font>, <key>, <lang>) se analizan pero no tienen efecto. Consulta la guía compartida de códigos de color para ver los formatos habituales.
| Método | Devuelve | Notas |
|---|---|---|
send_message(msg) | void | Envía un mensaje de chat al jugador. Admite códigos de color. |
chat(text) | void | Envía texto con colores mediante el chat de Bukkit, incluidas las órdenes con barra inicial como ese jugador |
get_held_item() | tabla o nil | Devuelve {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?) | void | Pone en cola el consumo de la mano principal tal como esté al ejecutarse la tarea. Por defecto 1; no conserva el objeto comprobado ni confirma el pago. Pasa una cantidad positiva; no rechaza valores negativos. |
has_item(material, amount?) | boolean | Devuelve 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 nil | Traza desde los ojos contra bloques y entidades, excluyendo al jugador, con tamaño 0.5 para entidades. Ignora líquidos y bloques transitables; alcance predeterminado 50. |
get_eye_location() | tabla location | Devuelve una tabla de ubicación a la altura de los ojos del jugador |
get_look_direction() | tabla | Devuelve un vector de dirección {x, y, z} para hacia donde mira el jugador |
send_block_change(x, y, z, material, [ticks]) | boolean | Pone en cola un bloque solo para el cliente, con restauración tras ticks positivos. True significa encolado; materiales inválidos o no correspondientes a bloques devuelven false. |
reset_block(x, y, z) | boolean | Pone en cola la restauración del bloque real para el jugador y devuelve true |
sleep(x, y, z) | void | Pone en cola una cama blanca real y un intento de dormir. Al despertar o desconectarse restaura solo BlockData, no el contenido de la entidad de bloque. |
wake_up() | void | Despierta a un jugador dormido. |
Los cambios de bloques en cola y sus restauraciones leen el mundo del jugador al ejecutarse; no confíes en que restauren el bloque previsto después de cambiar de mundo. La limpieza del sueño comprueba a los 20 ticks y después cada 10. Estas tareas no pertenecen a context.scheduler.
Métodos de UI del Jugador
Estos son los métodos de la tabla Player compartida. Las tablas de poderes de jefe tienen firmas de interfaz distintas, recogidas en la referencia. Las barras compartidas se indexan por jugador dentro de la copia de MagmaCore del plugin, no por script. Un temporizador de vencimiento solo quita la barra o la barra de acción repetida que lo inició, así que un vencimiento antiguo no borra una más reciente. Sus temporizadores Bukkit no pertenecen a context.scheduler.
player:show_boss_bar(text, [color], progress, [ticks])
Sustituye la barra de jefe sólida compartida del jugador. El progreso se limita a 0..1; un color inválido usa blanco. Pasa nil si omites el color para mantener el progreso en el tercer argumento.
| Parámetro | Tipo | Por defecto | Notas |
|---|---|---|---|
text | string | requerido | El texto a mostrar. Admite códigos de color &. |
color | string | "WHITE" | Color de la barra. Uno de: "RED", "BLUE", "GREEN", "YELLOW", "PURPLE", "PINK", "WHITE" |
progress | number | requerido | Cantidad de relleno desde 0.0 (vacío) hasta 1.0 (lleno) |
ticks | int | -1 | Los valores positivos programan la retirada; en otro caso permanece hasta ocultarla o reemplazarla |
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ámetro | Tipo | Por defecto | Notas |
|---|---|---|---|
text | string | requerido | El texto a mostrar. Admite códigos de color &. |
ticks | int | -1 | Los valores positivos repiten cada 40 ticks hasta vencer; en otro caso se envía una vez. Una llamada nueva cancela la repetición anterior. |
player:show_title(title, [subtitle], fade_in, stay, fade_out)
Muestra una pantalla de título al jugador.
| Parámetro | Tipo | Por defecto | Notas |
|---|---|---|---|
title | string | requerido | Texto principal del título. Admite códigos de color &. |
subtitle | string | "" | Texto del subtítulo debajo del título principal. Opcional. |
fade_in | int | requerido | Duración del fundido de entrada en ticks |
stay | int | requerido | Cuánto tiempo permanece el título en pantalla en ticks |
fade_out | int | requerido | Duración del fundido de salida en ticks |
Siguientes pasos
Para hooks, APIs y flujos de trabajo específicos de cada plugin:
- EliteMobs: Primeros pasos | Scripts de NPC | Hooks y ciclo de vida | Jefes y entidades | Mundo y entorno | Zonas y selección de objetivos
- FreeMinecraftModels: Primeros pasos | API de props | Ejemplos