Scripting Lua: API de Props e Ítems
Esta página cubre todas las APIs disponibles para los scripts de props e ítems de FreeMinecraftModels: context.prop, context.item, context.event, context.player, context.world, context.zones, context.scheduler, context.state y context.log. Si eres nuevo en scripting, empieza primero por Primeros Pasos.
context.prop
La tabla prop proporciona información sobre la entidad prop y métodos para controlar sus animaciones. Esta se reconstruye nueva para cada llamada de hook.
Campos
| Campo | Tipo | Notas |
|---|---|---|
prop.model_id | string | El nombre del modelo blueprint (p. ej. "torch_01") |
prop.current_location | tabla de ubicación | La posición del prop en el momento en que se construyó el contexto |
La tabla de ubicación tiene los campos estándar: x, y, z, world, yaw, pitch.
Ejemplo: leyendo la info del prop
return {
api_version = 1,
on_spawn = function(context)
context.log:info("Prop spawned: " .. (context.prop.model_id or "unknown"))
local loc = context.prop.current_location
if loc then
context.log:info("Location: " .. loc.x .. ", " .. loc.y .. ", " .. loc.z)
end
end
}
prop:play_animation(name, blend, loop)
Reproduce una animación nombrada en el modelo del prop.
| Parámetro | Tipo | Predeterminado | Notas |
|---|---|---|---|
name | string | requerido | El nombre de la animación como se define en el archivo del modelo |
blend | booleano | true | Si debe mezclar con la animación actual |
loop | booleano | true | Si la animación se repite |
Devuelve true si la animación se encontró y comenzó, false en caso contrario.
Ejemplo
return {
api_version = 1,
on_right_click = function(context)
local success = context.prop:play_animation("open", true, false)
if not success then
context.log:warn("Animation 'open' not found on this model!")
end
end
}
prop:stop_animation()
Detiene todas las animaciones que se están reproduciendo actualmente en el prop.
No toma parámetros.
Ejemplo
return {
api_version = 1,
on_right_click = function(context)
context.prop:stop_animation()
end
}
prop:hurt_visual()
Reproduce la animación visual de daño (destello rojo) en el prop sin causarle ningún daño real.
No toma parámetros.
Ejemplo
return {
api_version = 1,
on_left_click = function(context)
-- Destellar en rojo cuando reciba un golpe, pero sin recibir daño real
if context.event then
context.event.cancel()
end
context.prop:hurt_visual()
end
}
prop:pickup()
Elimina el prop del mundo y suelta un objeto de papel de colocación en su ubicación. Se puede hacer clic derecho con el objeto soltado sobre un bloque para volver a colocar el prop.
No toma parámetros.
Ejemplo
return {
api_version = 1,
on_right_click = function(context)
-- Permite que los jugadores recojan el prop con clic derecho
context.prop:pickup()
end
}
prop:mount(player)
Monta a un jugador en el primer asiento de mount point disponible en el prop. El modelo debe tener huesos de punto de montaje definidos.
| Parámetro | Tipo | Notas |
|---|---|---|
player | tabla de entidad | Una tabla de entidad de jugador (p. ej. desde context.event.player) |
Ejemplo
return {
api_version = 1,
on_right_click = function(context)
local player = context.event and context.event.player
if player then
context.prop:mount(player)
end
end
}
prop:dismount(player)
Desmonta a un jugador de su asiento de mount point en el prop.
| Parámetro | Tipo | Notas |
|---|---|---|
player | tabla de entidad | Una tabla de entidad de jugador |
Ejemplo
return {
api_version = 1,
on_right_click = function(context)
local player = context.event and context.event.player
if player then
-- Alternar montar/desmontar
local passengers = context.prop:get_passengers()
for i = 1, #passengers do
if passengers[i].uuid == player.uuid then
context.prop:dismount(player)
return
end
end
context.prop:mount(player)
end
end
}
prop:get_passengers()
Devuelve un array Lua de tablas de entidad para todos los pasajeros actuales en el prop.
No toma parámetros.
Ejemplo
return {
api_version = 1,
on_game_tick = function(context)
local passengers = context.prop:get_passengers()
if #passengers > 0 then
context.log:info("Prop has " .. #passengers .. " passenger(s)")
end
end
}
prop:has_mount_points()
Devuelve si este prop tiene huesos de punto de montaje definidos en su modelo.
No toma parámetros. Devuelve true o false.
Ejemplo
return {
api_version = 1,
on_right_click = function(context)
local player = context.event and context.event.player
if player and context.prop:has_mount_points() then
context.prop:mount(player)
end
end
}
prop:spawn_elitemobs_boss(filename, x, y, z)
Genera un jefe personalizado de EliteMobs en la ubicación dada. Requiere que EliteMobs esté instalado en el servidor.
| Parámetro | Tipo | Notas |
|---|---|---|
filename | string | El nombre de archivo del jefe personalizado (p. ej. "my_boss.yml") |
x | número | Coordenada X |
y | número | Coordenada Y |
z | número | Coordenada Z |
Devuelve una tabla de entidad viva para el jefe generado, o nil si EliteMobs no está instalado o el archivo del jefe no existe.
Ejemplo
return {
api_version = 1,
on_right_click = function(context)
local loc = context.prop.current_location
if loc then
local boss = context.prop:spawn_elitemobs_boss("dungeon_guardian.yml", loc.x, loc.y + 1, loc.z)
if boss then
context.log:info("Spawned boss: " .. (boss.name or "unknown"))
else
context.log:warn("Could not spawn boss -- is EliteMobs installed?")
end
end
end
}
prop:open_inventory(player, title, rows)
Abre una GUI de inventario de cofre persistente para el jugador. El contenido se guarda en el PersistentDataContainer del prop cuando se cierra el inventario, y se restaura cuando se abre de nuevo.
| Parámetro | Tipo | Predeterminado | Notas |
|---|---|---|---|
player | tabla de entidad | requerido | El jugador al que mostrar el inventario |
title | string | requerido | El título del inventario (soporta códigos de color &) |
rows | int | 3 | Número de filas (1-6, donde 6 = 54 ranuras = doble cofre) |
Devuelve true si el inventario se abrió, false en caso contrario.
prop:is_viewing_inventory(player)
Devuelve si el jugador dado tiene actualmente el inventario de este prop abierto.
| Parámetro | Tipo | Notas |
|---|---|---|
player | tabla de entidad | El jugador a comprobar |
Devuelve true o false.
Ejemplo: Animación de cierre cuando se cierra el inventario
context.state["task_" .. player.uuid] = context.scheduler:run_repeating(5, 5, function(tick_context)
if not tick_context.prop:is_viewing_inventory(player) then
tick_context.prop:play_animation("close", true, false)
tick_context.scheduler:cancel(tick_context.state["task_" .. player.uuid])
end
end)
prop:place_book(player)
Toma el libro escrito o escribible de la mano principal del jugador y lo almacena en el prop.
| Parámetro | Tipo | Notas |
|---|---|---|
player | tabla de entidad | El jugador que sostiene el libro |
Devuelve true si tiene éxito.
prop:read_book(player)
Abre el libro almacenado para que el jugador lo lea.
| Parámetro | Tipo | Notas |
|---|---|---|
player | tabla de entidad | El jugador al que mostrar el libro |
Devuelve true si se abrió un libro.
prop:take_book(player)
Devuelve el libro almacenado al inventario del jugador y lo elimina del prop.
| Parámetro | Tipo | Notas |
|---|---|---|
player | tabla de entidad | El jugador al que dar el libro |
Devuelve true si tiene éxito.
prop:has_book()
Devuelve si hay un libro almacenado en este prop. No toma parámetros.
prop:drop_inventory()
Suelta todo el contenido del inventario almacenado en la ubicación del prop como entidades de objeto, y luego limpia los datos almacenados. Cierra automáticamente el inventario para cualquier jugador que esté viéndolo actualmente.
No toma parámetros. Devuelve true si tiene éxito.
prop:drop_book()
Suelta el libro almacenado en la ubicación del prop como una entidad de objeto y limpia los datos del libro almacenados.
No toma parámetros. Devuelve true si tiene éxito.
prop:set_persistent_data(key, value)
Almacena un valor string en el PersistentDataContainer del armor stand del prop. Estos datos sobreviven a reinicios del servidor y descargas de chunks.
| Parámetro | Tipo | Notas |
|---|---|---|
key | string | Un nombre de clave único (almacenado internamente bajo fmm_lua_<key>) |
value | string | El valor a almacenar. Usa tostring() para números y booleanos. |
Devuelve true si tiene éxito, false si el prop no tiene un armor stand de respaldo.
prop:get_persistent_data(key)
Recupera un valor string previamente almacenado con set_persistent_data. Devuelve nil si la clave no se ha establecido.
| Parámetro | Tipo | Notas |
|---|---|---|
key | string | El nombre de clave usado en set_persistent_data |
Ejemplo: Estado de toggle persistente
return {
api_version = 1,
on_spawn = function(context)
local saved = context.prop:get_persistent_data("active")
context.state.active = saved == "true"
end,
on_right_click = function(context)
context.state.active = not context.state.active
context.prop:set_persistent_data("active", tostring(context.state.active))
end
}
context.item
La tabla item solo está disponible en scripts de objeto (no en scripts de prop). Proporciona información sobre el objeto personalizado y métodos para manipularlo. Esta tabla se reconstruye nueva para cada llamada de hook.
Campos
| Campo | Tipo | Notas |
|---|---|---|
item.id | string | El ID del tipo de objeto (el fmm_item_id de la configuración YML) |
item:material()
Devuelve el nombre del material del objeto como string (p. ej. "DIAMOND_SWORD", "STICK").
item:get_amount() / item:set_amount(n)
Obtiene o establece el tamaño de stack del objeto.
| Parámetro | Tipo | Notas |
|---|---|---|
n | int | La nueva cantidad de stack |
item:consume(n)
Decrementa la cantidad de stack del objeto en n (por defecto 1). Si la cantidad resultante es 0 o menor, el objeto se elimina del inventario del jugador.
| Parámetro | Tipo | Predeterminado | Notas |
|---|---|---|---|
n | int | 1 | Cantidad a consumir |
item:get_uses() / item:set_uses(n)
Obtiene o establece un contador de usos personalizado almacenado en el PersistentDataContainer del objeto. Es independiente de la durabilidad vanilla y puede usarse para implementar sistemas de durabilidad personalizada o cargas.
| Parámetro | Tipo | Notas |
|---|---|---|
n | int | El nuevo conteo de usos |
item:get_name() / item:set_name(s)
Obtiene o establece el nombre de visualización del objeto. Soporta códigos de color con &.
| Parámetro | Tipo | Notas |
|---|---|---|
s | string | El nuevo nombre de visualización (p. ej. "&b&lFrost Sword") |
item:get_lore() / item:set_lore(table)
Obtiene o establece el lore del objeto. get_lore() devuelve una tabla de strings (uno por línea). set_lore() toma una tabla de strings.
| Parámetro | Tipo | Notas |
|---|---|---|
table | tabla | Array de strings, uno por línea de lore |
Ejemplo: Script de objeto que rastrea usos
return {
api_version = 1,
on_right_click = function(context)
local uses = context.item:get_uses()
if uses <= 0 then
context.player:send_message("&cThis item is out of charges!")
return
end
context.item:set_uses(uses - 1)
context.player:send_message("&aUsed! Charges remaining: " .. (uses - 1))
end
}
item:get_durability()
Devuelve una tabla con campos current y max que representan la durabilidad vanilla del objeto, o nil si el objeto no tiene barra de durabilidad.
Ejemplo
local dur = context.item:get_durability()
if dur then
context.player:send_message("Durability: " .. dur.current .. "/" .. dur.max)
end
item:get_durability_percentage()
Devuelve la durabilidad restante como una fracción de 0.0 a 1.0, o nil si el objeto no tiene barra de durabilidad.
item:use_durability(amount, can_break)
Reduce la durabilidad vanilla del objeto en una cantidad fija.
| Parámetro | Tipo | Predeterminado | Notas |
|---|---|---|---|
amount | int | requerido | Cuántos puntos de durabilidad consumir |
can_break | booleano | false | Si es true, el objeto se destruye cuando se agota la durabilidad. Si es false, la durabilidad se detiene en 1. |
item:use_durability_percentage(fraction, can_break)
Reduce la durabilidad vanilla del objeto en un porcentaje de su máximo.
| Parámetro | Tipo | Predeterminado | Notas |
|---|---|---|---|
fraction | número | requerido | Fracción de durabilidad máxima a consumir (p. ej. 0.1 = 10%) |
can_break | booleano | false | Si es true, el objeto se destruye cuando se agota la durabilidad. Si es false, la durabilidad se detiene en 1. |
context.event
Datos del evento para el hook actual. Disponible en hooks de clic, combate e interacción para scripts de prop e ítems. Devuelve nil en hooks que no tienen evento asociado (on_spawn, on_game_tick, on_destroy, on_zone_enter, on_zone_leave, on_equip).
Campos y Métodos
| Campo o Método | Tipo | Notas |
|---|---|---|
event.player | tabla de entidad de jugador | El jugador que desencadenó el evento. Disponible en on_left_click, on_right_click y on_projectile_hit (el tirador, si era un jugador). Consulta Métodos de Entidad de Jugador para todos los campos y métodos. |
event.is_cancelled | booleano | Si el evento está cancelado actualmente |
event.cancel() | función | Cancela el evento (p. ej. previene daño o interacción) |
event.uncancel() | función | Descancela un evento previamente cancelado |
No todos los eventos son cancelables. Si el evento Bukkit subyacente no implementa Cancellable, event.cancel() y event.uncancel() no estarán presentes y event.is_cancelled siempre será false.
Ejemplo: Hacer un prop invulnerable
Ejemplo
return {
api_version = 1,
on_left_click = function(context)
if context.event then
context.event.cancel()
end
end
}
Ejemplo: Comprobando el estado de cancelación
Ejemplo
return {
api_version = 1,
on_left_click = function(context)
if context.event and not context.event.is_cancelled then
context.event.cancel()
context.log:info("Damage cancelled!")
end
end
}
Dentro de callbacks programados (scheduler:run_later, scheduler:run_repeating), context.event siempre es nil. La modificación del evento solo puede ocurrir durante el propio hook del evento.
context.world
La API de world es compartida entre todos los plugins de Nightbreak. Consulta context.world para la referencia completa.
Los props de FMM usan la misma tabla world de MagmaCore que los jefes de EliteMobs. Todos los métodos documentados en la página global (get_block_at, set_block_at, spawn_particle, play_sound, strike_lightning, get_time, set_time, get_nearby_entities, get_nearby_players, spawn_entity, get_highest_block_y, raycast, spawn_firework) están disponibles en FMM. Consulta la API world de MagmaCore para detalles completos sobre world:raycast() (lanzar un rayo y detectar entidades/bloques impactados) y world:spawn_firework() (generar cohetes de fuegos artificiales con colores y formas personalizados). EliteMobs extiende la tabla world con métodos adicionales para generar jefes, refuerzos y más -- consulta EliteMobs World & Environment.
Métodos de Entidad de Jugador
Las tablas de entidad de jugador se devuelven desde context.event.player, context.world:get_nearby_players() y callbacks de zona.
Las tablas de entidad, los métodos de entidad viva, los métodos específicos de jugador y los métodos de UI de jugador son compartidos entre todos los plugins de Nightbreak. Consulta el Motor de Scripting Lua de MagmaCore para la referencia completa que cubre los campos base de entidad, campos y métodos de entidad viva, campos y métodos específicos de jugador, y Métodos de UI de Jugador. Los nuevos métodos de jugador incluyen player:get_target_entity() (targeting por raycast), player:get_eye_location(), player:get_look_direction(), player:send_block_change() (bloques falsos por jugador) y player:reset_block() -- consulta Métodos Específicos de Jugador para más detalles.
Campos de Entidad Específicos de FMM
Cada tabla de entidad construida dentro de un script de FMM obtiene estos campos extra automáticamente (a través del LuaEntityEnricher de FMM):
| Campo | Tipo | Notas |
|---|---|---|
entity.is_modeled | booleano | true si esta entidad Bukkit es la entidad subyacente de un ModeledEntity |
entity.is_prop | booleano | true si esta entidad es un armor stand que respalda un PropEntity |
entity.model | tabla o nil | Poblado solo cuando is_modeled = true (ver abajo) |
Cuando entity.model está presente, expone:
| Campo / Método | Notas |
|---|---|
model.model_id | El nombre del modelo blueprint (p. ej. "dragon") |
model.is_dynamic | true si es un DynamicEntity (adjunto a una entidad viva) |
model:play_animation(name, blend, loop) | Reproduce una animación nombrada. Devuelve true en caso de éxito |
model:stop_animations() | Detiene todas las animaciones actuales |
model:remove() | Elimina inmediatamente la entidad modelada y todos sus huesos |
on_attack_entity = function(context)
local target = context.event.target
if target and target.is_modeled then
target.model:play_animation("hurt", true, false)
end
end
Campos de Entidad de EliteMobs
Cuando EliteMobs está instalado, FMM reenvía al enricher de EliteMobs para que las mismas tablas de entidad también expongan:
| Campo | Tipo | Notas |
|---|---|---|
entity.is_elite | booleano | true si la entidad es rastreada por EliteMobs |
entity.is_custom_boss | booleano | true si es una configuración de jefe personalizado |
entity.is_significant_boss | booleano | true para jefes personalizados con healthMultiplier > 1 (filtra mobs basura con nombre) |
entity.elite | tabla o nil | Poblado solo cuando is_elite = true. Contiene level, name, health, max_health, health_multiplier, damage_multiplier, is_custom_boss, además de elite:remove() |
context.zones
La API de zones es compartida entre todos los plugins de Nightbreak. Consulta context.zones para la referencia completa.
context.scheduler
La API de scheduler es compartida entre todos los plugins de Nightbreak. Consulta context.scheduler para la referencia completa.
context.state
La API de state es compartida entre todos los plugins de Nightbreak. Consulta context.state para la referencia completa.
context.log
La API de logging es compartida entre todos los plugins de Nightbreak. Consulta context.log para la referencia completa.
Modelo de Ejecución
Un Runtime por Instancia de Script
Cada entidad prop que tiene scripts adjuntos obtiene su propia instancia de runtime Lua independiente. Cuando el prop aparece, FMM carga el código fuente Lua, lo evalúa en un entorno sandbox fresco y almacena la tabla devuelta. Cuando se elimina el prop, el runtime se cierra.
Para scripts de objeto, se crea un runtime por par (jugador, itemId). Cuando un jugador equipa un objeto personalizado, FMM crea una instancia de script para ese jugador y tipo de objeto. Cuando el objeto se desequipa, el runtime se cierra.
Esto significa:
- Las variables locales declaradas en el ámbito de archivo son privadas para esa instancia de script.
context.stateestá completamente aislado entre instancias, incluso si comparten el mismo archivo de script.
Propiedad de Tareas Programadas
Todas las tareas creadas a través de context.scheduler son propiedad del runtime que las creó. Cuando se elimina un prop:
- El runtime se cierra.
- Cada tarea propia -- tanto de una sola vez como recurrente -- se cancela automáticamente.
- Todas las observaciones de zona se limpian.
Alcance de los Cooldowns
El motor de scripting compartido expone context.cooldowns:set_local, :check_local, :set_global y :check_global (consulta la referencia de cooldowns de MagmaCore). FMM define el alcance de esos almacenes de la siguiente forma:
| Tipo de script | Alcance del store local | Alcance del store global |
|---|---|---|
| Script de prop | Por ScriptInstance (prop + archivo de script) | Por PropEntity (compartido entre todos los scripts vinculados a ese prop) |
| Script de objeto | Por triple (player, itemId, scriptFile) — persiste a través de reequipos aunque la instancia de script se derribe cada vez que el objeto sale de una ranura activa | Por jugador (compartido entre todos los scripts de objeto FMM que ese jugador ejecuta) |
Como los scripts de objeto se derriban y reconstruyen en cada ciclo de equip/unequip, los cooldowns de objeto se guardan en un mapa estático con clave por UUID de jugador en lugar de vivir en el ScriptInstance. Por eso un cooldown de objeto sigue aplicándose después de sacar el objeto del hotbar y volver a meterlo.
Presupuesto de Ejecución
Cada invocación de hook y cada invocación de callback se cronometra. Si una sola llamada tarda más de 50 milisegundos, el script se deshabilita con una advertencia en la consola:
[Lua] my_script.lua took 73ms in 'on_game_tick' (limit: 50ms) -- script disabled to prevent lag.
Para mantenerse dentro del presupuesto:
- Evita bucles sin límite dentro de hooks.
- Mantén los manejadores
on_game_tickligeros -- se ejecutan en cada tick. - Usa
context.scheduler:run_repeating(...)para repartir el trabajo entre ticks.
Referencia Completa de Hooks
Esta tabla lista todos los hooks disponibles tanto en scripts de prop como de objeto.
Hooks de Prop (8)
| Hook | Se dispara cuando | context.event |
|---|---|---|
on_spawn | El prop aparece en el mundo | nil |
on_game_tick | Cada tick del servidor (50ms) | nil |
on_destroy | El prop es eliminado | nil |
on_left_click | El jugador hace clic izquierdo en el prop | evento de daño |
on_right_click | El jugador hace clic derecho en el prop | evento de interacción |
on_projectile_hit | Un proyectil impacta en el prop | evento de impacto de proyectil |
on_zone_enter | El jugador entra en una zona observada | nil |
on_zone_leave | El jugador sale de una zona observada | nil |
Hooks de Objeto (22)
| Hook | Categoría | Se dispara cuando | context.event |
|---|---|---|---|
on_attack_entity | Combate | El jugador ataca una entidad | evento de daño |
on_kill_entity | Combate | El jugador mata una entidad | evento de muerte |
on_take_damage | Combate | El jugador recibe daño | evento de daño |
on_shield_block | Combate | El jugador bloquea con escudo | evento de daño |
on_shoot_bow | Combate | El jugador dispara un arco | evento de disparo de arco |
on_projectile_hit | Combate | El proyectil del jugador impacta | evento de impacto de proyectil |
on_projectile_launch | Combate | El jugador lanza un proyectil | evento de lanzamiento |
on_right_click | Interacción | El jugador hace clic derecho | evento de interacción |
on_left_click | Interacción | El jugador hace clic izquierdo | evento de interacción |
on_shift_right_click | Interacción | El jugador hace shift+clic derecho | evento de interacción |
on_shift_left_click | Interacción | El jugador hace shift+clic izquierdo | evento de interacción |
on_interact_entity | Interacción | El jugador hace clic derecho en una entidad | evento de interacción con entidad |
on_equip | Equipamiento | El objeto entra en ranura activa | nil |
on_unequip | Equipamiento | El objeto sale de ranura activa | nil |
on_swap_hands | Equipamiento | Intercambio entre mano principal/secundaria | evento de swap |
on_drop | Equipamiento | El jugador suelta el objeto | evento de drop |
on_break_block | Utilidad | El jugador rompe un bloque | evento de rotura de bloque |
on_consume | Utilidad | El jugador consume el objeto | evento de consumo |
on_item_damage | Utilidad | El objeto recibe daño de durabilidad | evento de daño de objeto |
on_fish | Utilidad | El jugador usa caña de pescar | evento de pesca |
on_death | Utilidad | El jugador muere mientras está equipado | evento de muerte |
on_game_tick | Ciclo de vida | Cada tick mientras está equipado | nil |
Siguientes Pasos
- Ejemplos y Patrones -- scripts completos y funcionales para props e ítems con recorridos guiados
- Solución de Problemas -- problemas comunes, consejos de depuración y una checklist de QC
- Primeros Pasos -- estructura de archivos, hooks, recorrido del primer script