Scripting Lua: API de Props
Esta página cubre todas las API disponibles para los scripts de props de FreeMinecraftModels: context.prop, context.event, context.world, context.zones, context.scheduler, context.state y context.log. Si eres nuevo en el scripting de props, comienza primero con Primeros pasos.
context.prop
La tabla prop proporciona información sobre la entidad del prop y métodos para controlar sus animaciones. Se reconstruye desde cero en cada llamada de hook.
Campos
| Campo | Tipo | Notas |
|---|---|---|
prop.model_id | string | El nombre del modelo blueprint (ej. "torch_01") |
prop.current_location | location table | 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: leer información 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 con nombre en el modelo del prop.
| Parámetro | Tipo | Por defecto | Notas |
|---|---|---|---|
name | string | requerido | El nombre de la animación tal como está definido en el archivo del modelo |
blend | boolean | true | Si se debe mezclar con la animación actual |
loop | boolean | true | Si la animación se repite en bucle |
Devuelve true si la animación fue encontrada e iniciada, 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 requiere parámetros.
Ejemplo
return {
api_version = 1,
on_right_click = function(context)
context.prop:stop_animation()
end
}
context.event
Datos del evento para el hook actual. Disponible en on_left_click, on_right_click y on_projectile_hit. Devuelve nil en hooks que no tienen un evento asociado (on_spawn, on_game_tick, on_destroy, on_zone_enter, on_zone_leave).
Campos y métodos
| Campo o método | Tipo | Notas |
|---|---|---|
event.is_cancelled | boolean | Si el evento está actualmente cancelado |
event.cancel() | function | Cancela el evento (ej. previene daño o interacción) |
event.uncancel() | function | Revierte la cancelación de un evento previamente cancelado |
No todos los eventos son cancelables. Si el evento subyacente de Bukkit 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: Verificar 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 de eventos solo puede ocurrir durante el propio hook del evento.
context.world
La tabla world proporciona métodos para consultar e interactuar con el mundo de Minecraft. Se construye a partir del mundo actual del prop.
La API context.world se comparte con EliteMobs. Los props de FMM usan la misma tabla world de Magmacore que los jefes de EliteMobs. Los métodos documentados aquí son los disponibles en la implementación base de Magmacore. Para la referencia completa, consulta la página EliteMobs World & Environment -- los métodos listados allí como parte de la API base context.world también están disponibles en FMM.
world.name
Un campo de tipo string 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 un string en minúsculas (ej. "stone", "air").
| Parámetro | Tipo | Notas |
|---|---|---|
x | int | Coordenada X del bloque |
y | int | Coordenada Y del bloque |
z | int | Coordenada Z del bloque |
Ejemplo
return {
api_version = 1,
on_spawn = function(context)
local loc = context.prop.current_location
if loc then
local block = context.world:get_block_at(
math.floor(loc.x),
math.floor(loc.y) - 1,
math.floor(loc.z)
)
context.log:info("Prop is standing on: " .. block)
end
end
}
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, MAYÚSCULAS (ej. "FLAME", "DUST") |
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/desplazamiento en X |
dy | number | 0 | Dispersión/desplazamiento en Y |
dz | number | 0 | Dispersión/desplazamiento en Z |
speed | number | 0 | Velocidad de las partículas |
Ejemplo
return {
api_version = 1,
on_right_click = function(context)
local loc = context.prop.current_location
if loc then
context.world:spawn_particle("HEART", loc.x, loc.y + 1, loc.z, 5, 0.3, 0.3, 0.3, 0)
end
end
}
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, MAYÚSCULAS (ej. "ENTITY_EXPERIENCE_ORB_PICKUP") |
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 |
Ejemplo
return {
api_version = 1,
on_right_click = function(context)
local loc = context.prop.current_location
if loc then
context.world:play_sound("BLOCK_NOTE_BLOCK_PLING", loc.x, loc.y, loc.z, 1.0, 1.2)
end
end
}
world:strike_lightning(x, y, z)
Invoca un rayo en una ubicación (visual y con daño).
| Parámetro | Tipo | Notas |
|---|---|---|
x | number | Coordenada X |
y | number | Coordenada Y |
z | number | Coordenada Z |
Ejemplo
return {
api_version = 1,
on_projectile_hit = function(context)
local loc = context.prop.current_location
if loc then
context.world:strike_lightning(loc.x, loc.y, loc.z)
end
end
}
world:get_time()
Devuelve la hora actual del mundo en ticks.
world:set_time(ticks)
Establece la hora del mundo.
| Parámetro | Tipo | Notas |
|---|---|---|
ticks | int | Hora del mundo (0 = amanecer, 6000 = mediodía, 13000 = noche, 18000 = medianoche) |
world:get_nearby_entities(x, y, z, radius)
Devuelve un array de tablas wrapper de entidades para todas las entidades vivas dentro de un cuadro delimitador centrado en las coordenadas dadas.
| Parámetro | Tipo | Notas |
|---|---|---|
x | number | Centro X |
y | number | Centro Y |
z | number | Centro Z |
radius | number | Radio de búsqueda (usado como media extensión en los tres ejes) |
Ejemplo
return {
api_version = 1,
on_right_click = function(context)
local loc = context.prop.current_location
if loc then
local entities = context.world:get_nearby_entities(loc.x, loc.y, loc.z, 10)
context.log:info("Found " .. #entities .. " entities nearby")
end
end
}
world:get_nearby_players(x, y, z, radius)
Devuelve un array de tablas wrapper de jugadores para todos los jugadores dentro de un cuadro delimitador centrado en las coordenadas dadas.
| Parámetro | Tipo | Notas |
|---|---|---|
x | number | Centro X |
y | number | Centro Y |
z | number | Centro Z |
radius | number | Radio de búsqueda |
Ejemplo
return {
api_version = 1,
on_right_click = function(context)
local loc = context.prop.current_location
if loc then
local players = context.world:get_nearby_players(loc.x, loc.y, loc.z, 20)
for i = 1, #players do
context.log:info("Nearby player: " .. (players[i].name or "unknown"))
end
end
end
}
context.zones
La tabla zones permite crear zonas espaciales y vigilarlas para eventos de entrada/salida de jugadores. Las zonas están vinculadas a la instancia del script y se limpian automáticamente cuando se elimina el prop.
zones:create_sphere(x, y, z, radius)
Crea una zona esférica centrada en las coordenadas dadas. Devuelve un identificador numérico de zona.
| 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 de zona.
| 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 de forma cuboide. Devuelve un identificador numérico de zona.
| Parámetro | Tipo | Notas |
|---|---|---|
x | number | Centro X |
y | number | Centro Y |
z | number | Centro Z |
xSize | number | Media extensión en X |
ySize | number | Media extensión en Y |
zSize | number | Media extensión en Z |
zones:watch(handle, onEnterCallback, onLeaveCallback)
Comienza a vigilar una zona para eventos de entrada/salida de jugadores. Cuando un jugador entra o sale de la zona, se dispara el hook correspondiente (on_zone_enter u on_zone_leave).
| Parámetro | Tipo | Notas |
|---|---|---|
handle | int | Identificador de zona de una llamada create_* |
onEnterCallback | function o nil | Se llama cuando un jugador entra en la zona |
onLeaveCallback | function o nil | Se llama cuando un jugador sale de la zona |
Devuelve true si la vigilancia se configuró correctamente, nil si el identificador de zona era inválido.
Las vigilancias de zona se verifican cada tick del servidor contra todos los jugadores en el mismo mundo. Mantén la cantidad de zonas razonable para evitar sobrecarga de rendimiento.
zones:unwatch(handle)
Detiene la vigilancia de una zona y limpia sus recursos.
| Parámetro | Tipo | Notas |
|---|---|---|
handle | int | Identificador de zona a dejar de vigilar |
Ejemplo: Zona de activación por proximidad
Ejemplo
return {
api_version = 1,
on_spawn = function(context)
local loc = context.prop.current_location
if loc == nil then return end
-- Create a sphere zone around the prop
local handle = context.zones:create_sphere(loc.x, loc.y, loc.z, 5)
-- Watch for player enter/leave
context.zones:watch(
handle,
function(player)
context.log:info("Player entered zone!")
end,
function(player)
context.log:info("Player left zone!")
end
)
-- Store handle so we can clean up later if needed
context.state.zone_handle = handle
end,
on_destroy = function(context)
if context.state.zone_handle then
context.zones:unwatch(context.state.zone_handle)
end
end
}
context.scheduler
El scheduler permite ejecutar tareas retrasadas y repetitivas. Todas las tareas pertenecen a la instancia del script y se cancelan automáticamente cuando se elimina el prop.
scheduler:run_later(ticks, callback)
Ejecuta un callback una vez después de un retraso. Devuelve un ID de tarea numérico.
| Parámetro | Tipo | Notas |
|---|---|---|
ticks | int | Retraso en ticks del servidor (20 ticks = 1 segundo) |
callback | function | Se llama con un context nuevo cuando expira el retraso |
Ejemplo
return {
api_version = 1,
on_right_click = function(context)
context.log:info("Something will happen in 2 seconds...")
context.scheduler:run_later(40, function(delayed_context)
local loc = delayed_context.prop.current_location
if loc then
delayed_context.world:spawn_particle("EXPLOSION_EMITTER", loc.x, loc.y, loc.z, 1)
end
end)
end
}
scheduler:run_repeating(delay, interval, callback)
Ejecuta un callback repetidamente a un intervalo fijo. Devuelve un ID de tarea numérico.
| Parámetro | Tipo | Notas |
|---|---|---|
delay | int | Retraso inicial en ticks antes de la primera ejecución |
interval | int | Ticks entre cada ejecución subsiguiente |
callback | function | Se llama con un context nuevo en cada intervalo |
Ejemplo
return {
api_version = 1,
on_spawn = function(context)
-- Emit particles every second
context.state.particle_task = context.scheduler:run_repeating(0, 20, function(tick_context)
local loc = tick_context.prop.current_location
if loc then
tick_context.world:spawn_particle("FLAME", loc.x, loc.y + 1, loc.z, 3, 0.1, 0.1, 0.1, 0.02)
end
end)
end,
on_destroy = function(context)
if context.state.particle_task then
context.scheduler:cancel(context.state.particle_task)
end
end
}
scheduler:cancel(taskId)
Cancela una tarea programada por su ID.
| Parámetro | Tipo | Notas |
|---|---|---|
taskId | int | El ID de tarea devuelto por run_later o run_repeating |
Si inicias una tarea repetitiva, cancélala siempre en on_destroy (o cuando ya no sea necesaria). Olvidar cancelarla deja una tarea ejecutándose en segundo plano hasta que el prop se elimine del servidor, lo que desperdicia rendimiento y puede causar errores.
context.state
Una tabla Lua simple que persiste durante toda la vida del prop. Ú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
Solo context.state persiste entre llamadas de hooks. Todas las demás tablas de contexto (context.prop, context.world, context.event, etc.) se reconstruyen desde cero cada vez.
context.log
Métodos de registro en consola. Los mensajes se muestran con el nombre del archivo del script como prefijo en la consola del servidor.
| Método | Notas |
|---|---|
log:info(message) | Mensaje informativo |
log:warn(message) | Mensaje de advertencia |
log:error(message) | Mensaje de error (funcionalmente igual que warn) |
Ejemplo
return {
api_version = 1,
on_spawn = function(context)
context.log:info("Script loaded!")
end,
on_right_click = function(context)
context.log:warn("Prop was clicked -- this is a debug warning")
end
}
Modelo de ejecución
Un entorno de ejecución por prop
Cada entidad prop que tiene scripts asignados obtiene su propia instancia independiente de entorno de ejecución Lua. Cuando el prop aparece, FMM carga el código fuente Lua, lo evalúa en un entorno sandbox nuevo y almacena la tabla devuelta. Cuando se elimina el prop, el entorno de ejecución se cierra.
Esto significa:
- Las variables locales declaradas a nivel de archivo son privadas para esa instancia de prop.
context.stateestá completamente aislado entre instancias de prop, incluso si comparten el mismo archivo de script.
Propiedad de tareas
Todas las tareas creadas a través de context.scheduler pertenecen al entorno de ejecución que las creó. Cuando se elimina un prop:
- El entorno de ejecución se cierra.
- Todas las tareas -- tanto las de una sola vez como las repetitivas -- se cancelan automáticamente.
- Todas las vigilancias de zonas se limpian.
Presupuesto de ejecución
Cada invocación de hook y cada invocación de callback se mide en tiempo. Si una sola llamada tarda más de 50 milisegundos, el script se desactiva con una advertencia en consola:
[Lua] my_script.lua took 73ms in 'on_game_tick' (limit: 50ms) -- script disabled to prevent lag.
Para mantenerte dentro del presupuesto:
- Evita bucles sin límite dentro de hooks.
- Mantén los handlers de
on_game_tickligeros -- se ejecutan en cada tick. - Usa
context.scheduler:run_repeating(...)para distribuir el trabajo entre ticks.
Próximos pasos
- Ejemplos y patrones -- scripts de props completos y funcionales con explicaciones
- Solución de problemas -- problemas comunes, consejos de depuración y lista de verificación de QC
- Primeros pasos -- estructura de archivos, hooks, tutorial del primer script