Saltar al contenido principal

Lua Scripting: Primeros pasos

Esta pagina te ensena a escribir tu primer script Lua para un prop de FreeMinecraftModels, desde un archivo vacio hasta un prop interactivo funcional. Al finalizar, entenderas los hooks, el context, la Prop API y la estructura general de cada archivo de script de prop.

Una vez que te sientas comodo con lo basico, continua con las paginas complementarias:

  • Prop API -- las APIs de context.prop, context.event, context.world y otros context
  • Ejemplos y patrones -- scripts funcionales completos que puedes estudiar y adaptar
  • Solucion de problemas -- errores comunes, consejos de depuracion y la lista de verificacion QC
Funcion experimental

Los scripts Lua de props son actualmente experimentales. Los nombres de los hooks, los metodos auxiliares y el comportamiento aun pueden cambiar a medida que FreeMinecraftModels evoluciona, asi que prueba cuidadosamente antes de usarlos en un servidor de produccion.

Relacion con EliteMobs Lua

FreeMinecraftModels comparte el mismo motor Lua (Magmacore) que EliteMobs. Si ya escribes poderes Lua para EliteMobs, los conceptos fundamentales -- hooks, context, api_version, scheduler, zonas y la sandbox -- son identicos. La diferencia es:

  • Los scripts de EliteMobs se ejecutan en jefes y tienen hooks como on_boss_damaged_by_player, on_enter_combat, etc.
  • Los scripts de FMM se ejecutan en props y tienen hooks como on_right_click, on_left_click, on_projectile_hit, etc.

Las APIs context.world, context.zones, context.scheduler, context.state y context.log son las mismas en ambos plugins. Esta pagina solo cubre lo que es especifico de los props de FMM.


Que son los scripts de props

Los scripts de props son archivos .lua independientes que se encuentran en la carpeta plugins/FreeMinecraftModels/scripts/. Se referencian desde un archivo de config YAML que se ubica junto al archivo del modelo, y se ejecutan cada vez que el prop aparece en el mundo.

Para que son buenos los scripts de props

Los scripts de props destacan cuando necesitas:

  • Props interactivos que responden a los clics de los jugadores (puertas, palancas, botones)
  • Props decorativos invulnerables que no pueden ser destruidos por los jugadores
  • Disparadores de proximidad que detectan cuando los jugadores entran o salen de un area
  • Props animados que reproducen animaciones al interactuar o con un temporizador
  • Props emisores de sonido que reproducen sonidos al hacer clic o al acercarse
  • Cualquier comportamiento de prop que requiera logica mas alla de la decoracion estatica

Si tu prop es puramente decorativo y no necesita interaccion, no necesitas un script.


Para quien es esta pagina

Esta pagina esta escrita para tres tipos de lectores:

  • Alguien que ya conoce el scripting Lua de EliteMobs y quiere aprender los hooks y APIs especificos de FMM
  • Alguien que es nuevo en el scripting Lua y necesita una referencia completa con nombres exactos para props
  • Alguien que usa IA para redactar scripts de props y necesita suficiente detalle para saber cuando la IA invento algo falso

No necesitas convertirte en un desarrollador Lua completo antes de escribir scripts de props utiles. Para la mayoria de los scripts de props practicos, lo unico que realmente necesitas es:

  • Como colocar un hook valido en la tabla devuelta
  • Como leer valores de context
  • Como detener la ejecucion anticipadamente con if ... then return end
  • Como llamar a algunos metodos auxiliares de forma exacta

Introduccion rapida a Lua

Si eres completamente nuevo en Lua, aqui tienes la sintaxis minima que necesitas.

Variables

Usa local para almacenar un valor:

local animation_name = "open"
local sound_volume = 1.0

Funciones

Las funciones son bloques de logica reutilizables:

local function log_click(context)
context.log:info("Prop was clicked!")
end

Comprobaciones if

Usa if cuando algo solo debe ocurrir a veces:

if context.event == nil then
return
end

nil

nil significa "sin valor". Lo comprobaras frecuentemente:

if context.event ~= nil then
context.event.cancel()
end

Tablas

Lua usa tablas para objetos con claves nombradas y para la definicion del script devuelto:

return {
api_version = 1,

on_spawn = function(context)
end
}

Comentarios

Usa -- para notas:

-- Cancel the damage event so the prop cannot be broken
context.event.cancel()
tip

Para una introduccion mas completa a Lua, consulta la pagina Primeros pasos con EliteMobs. Los fundamentos de sintaxis son identicos.


Donde se ubican los archivos

Archivos de script

Coloca los archivos .lua en la carpeta central de scripts:

plugins/
FreeMinecraftModels/
scripts/
invulnerable.lua
interactive_door.lua
proximity_sound.lua

FMM detecta todos los archivos .lua en plugins/FreeMinecraftModels/scripts/ al iniciar.

Archivos de modelo y archivos de config

Cada archivo de modelo puede tener un archivo .yml de config asociado en el mismo directorio:

plugins/
FreeMinecraftModels/
models/
torch_01.fmmodel
torch_01.yml <-- config de script para torch_01
scripts/
invulnerable.lua <-- referenciado por torch_01.yml

El archivo .yml de config es lo que conecta un modelo con sus scripts.


Formato del archivo de config

El archivo de config YAML que se ubica junto a un archivo de modelo tiene dos campos:

isEnabled: true
scripts:
- invulnerable.lua
CampoTipoPredeterminadoNotas
isEnabledbooleantrueSi los scripts estan activos para este prop
scriptslista de strings[]Nombres de archivos .lua en la carpeta scripts/

Puedes adjuntar multiples scripts al mismo prop. Cada script es su propia instancia independiente.

Generacion diferida de config

Cuando un prop aparece y no existe un archivo .yml asociado, FMM crea automaticamente un archivo de config predeterminado con isEnabled: true y una lista scripts: vacia. Esto sucede de forma asincrona, por lo que el prop no tendra scripts en su primer spawn -- solo despues de que se cree la config y la edites para agregar nombres de archivos de script.

Esto significa:

  1. Coloca tu archivo de modelo en models/
  2. Genera el prop una vez (FMM crea el .yml automaticamente)
  3. Edita el .yml generado para agregar tus nombres de archivos de script
  4. Vuelve a generar el prop o recarga el servidor (los scripts ahora estan activos)

Referencia de hooks

Cada archivo de script Lua de prop devuelve una tabla. Cada clave en esa tabla (ademas de api_version y priority) debe ser uno de los hooks listados a continuacion. El runtime llama a la funcion correspondiente cada vez que se dispara el evento del juego asociado.

HookSe dispara cuandoNotas
on_spawnEl prop aparece en el mundoSe ejecuta una vez cuando el script se vincula
on_game_tickUna vez por tick del servidor (50 ms)Solo activo si el script define este hook
on_destroyEl prop se elimina del mundoHook de limpieza
on_left_clickUn jugador hace clic izquierdo (golpea) el propcontext.event es el evento de dano
on_right_clickUn jugador hace clic derecho en el propcontext.event es el evento de interaccion
on_projectile_hitUn proyectil golpea el propcontext.event es el evento de impacto de proyectil
on_zone_enterUn jugador entra en una zona vigiladaRequiere que se haya configurado una vigilancia de zona
on_zone_leaveUn jugador sale de una zona vigiladaRequiere que se haya configurado una vigilancia de zona

Contrato minimo del archivo

Cada script Lua de prop debe hacer return de una tabla.

Campos de nivel superior obligatorios y opcionales

CampoObligatorioTipoNotas
api_versionSiNumberActualmente debe ser 1
priorityNoNumberPrioridad de ejecucion. Los valores mas bajos se ejecutan primero. Por defecto 0
Claves de hook soportadasNoFunctionDebe usar uno de los nombres exactos de hook listados en la Referencia de hooks

Reglas de validacion

  • El archivo debe devolver una tabla.
  • api_version es obligatorio y actualmente debe ser 1.
  • priority debe ser numerico si esta presente.
  • Cada clave de nivel superior adicional debe ser un nombre de hook soportado.
  • Cada clave de hook debe apuntar a una funcion.
  • Las claves de nivel superior desconocidas son rechazadas.

Las funciones auxiliares y las constantes locales deben estar encima del return final, no dentro de la tabla devuelta.


Tu primer script de prop funcional, paso a paso

Antes del paso 1: Configurar la config

  1. Coloca tu archivo de modelo (ej. my_prop.fmmodel) en plugins/FreeMinecraftModels/models/
  2. Genera el prop una vez para crear la config .yml
  3. Crea tu archivo de script en plugins/FreeMinecraftModels/scripts/first_test.lua
  4. Edita plugins/FreeMinecraftModels/models/my_prop.yml:
isEnabled: true
scripts:
- first_test.lua
  1. Vuelve a generar el prop o recarga el servidor

Paso 1: Hacer que el archivo se cargue

return {
api_version = 1,

on_spawn = function(context)
end
}

Si esto se carga sin errores en la consola, has demostrado:

  • El archivo es Lua valido
  • FMM lo encontro en la carpeta scripts/
  • La config lo referencia correctamente
  • La forma de la tabla devuelta es correcta

Paso 2: Hacer que el prop haga algo visible

return {
api_version = 1,

on_spawn = function(context)
context.log:info("Prop script loaded for: " .. (context.prop.model_id or "unknown"))
end
}

Revisa la consola del servidor. Si ves el mensaje de log, tu hook se esta ejecutando.

Paso 3: Reaccionar al clic de un jugador

return {
api_version = 1,

on_right_click = function(context)
context.log:info("Prop was right-clicked!")
end
}

Haz clic derecho en el prop en el juego. Si la consola muestra el mensaje, el hook de clic esta funcionando.

Paso 4: Cancelar el dano para hacer el prop invulnerable

return {
api_version = 1,

on_left_click = function(context)
if context.event then
context.event.cancel()
end
end
}

Este es el patron utilizado por el script predefinido invulnerable.lua. Cancela el evento de dano para que el armor stand que respalda al prop no pueda ser destruido.

Paso 5: Reproducir una animacion al hacer clic

return {
api_version = 1,

on_right_click = function(context)
context.prop:play_animation("open", true, false)
end
}

Esto reproduce la animacion "open" en el modelo del prop, mezclada y sin bucle.


Que es context?

Cada funcion de hook recibe un argumento llamado context. Piensa en el como una caja de herramientas que FMM te entrega cada vez que algo sucede -- contiene todo lo que necesitas para interactuar con el prop, el mundo, las zonas y mas.

on_right_click = function(context)
-- context.prop = el prop que fue clicado
-- context.event = el evento de clic (puede ser cancelado)
-- context.world = herramientas para particulas, sonidos, consultas de bloques
-- context.state = tu propio almacenamiento persistente
-- context.log = registro en consola
-- context.scheduler = tareas diferidas y repetitivas
-- context.zones = creacion y vigilancia de zonas espaciales
end

Tu no creas context -- FMM lo crea y lo pasa a tu hook.

info

context se crea nuevo para cada llamada de hook, excepto context.state que persiste durante toda la vida del prop. Esto significa que puedes almacenar datos en context.state y leerlos despues en un hook diferente.


APIs clave de context

Aqui tienes un resumen de lo que esta disponible. Para detalles completos, consulta Prop API.

  • context.prop -- La entidad del prop. Proporciona model_id, current_location, play_animation() y stop_animation().

  • context.event -- El evento Bukkit que activo este hook. Disponible en on_left_click, on_right_click y on_projectile_hit. Proporciona cancel(), uncancel() e is_cancelled. Es nil en hooks sin evento (como on_spawn y on_game_tick).

  • context.state -- Una tabla Lua simple que persiste durante la vida del prop. Usala para almacenar flags, estados de alternancia, IDs de tareas y cualquier cosa que necesites recordar entre hooks.

  • context.log -- Registro en consola con log:info(msg), log:warn(msg) y log:error(msg).

  • context.scheduler -- Tareas diferidas y repetitivas con scheduler:run_later(ticks, callback) y scheduler:run_repeating(delay, interval, callback). Los callbacks reciben un context nuevo. Cancela tareas con scheduler:cancel(taskId).

  • context.world -- Interaccion con el mundo: particulas, sonidos, consultas de bloques, rayos, entidades cercanas. Consulta Prop API para la lista completa de metodos.

  • context.zones -- Creacion y vigilancia de zonas espaciales (esferas, cilindros, cuboides). Consulta Prop API para la lista completa de metodos.


Sintaxis de metodos: : vs .

En Lua, object:method(arg) es una forma abreviada de object.method(object, arg). La API de FMM acepta ambas formas:

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

Toda la documentacion usa : de forma consistente.


Plantillas listas para copiar y pegar

Script de prop valido mas pequeno

return {
api_version = 1,

on_spawn = function(context)
end
}

Plantilla de prop invulnerable

return {
api_version = 1,

on_left_click = function(context)
if context.event then
context.event.cancel()
end
end
}

Plantilla de prop interactivo

return {
api_version = 1,

on_spawn = function(context)
context.state.is_active = false
end,

on_right_click = function(context)
context.state.is_active = not context.state.is_active

if context.state.is_active then
context.prop:play_animation("activate", true, true)
else
context.prop:stop_animation()
end
end
}

Disposicion de archivo mas grande

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)
context.state.task_id = nil
end,

on_right_click = function(context)
do_something(context)
end,

on_destroy = function(context)
if context.state.task_id ~= nil then
context.scheduler:cancel(context.state.task_id)
end
end
}

Primer flujo de trabajo real

Al construir un script de prop completamente nuevo, usa este orden:

  1. Crea el archivo .lua y haz que on_spawn funcione.
  2. Agrega el nombre del archivo de script a la config .yml del prop.
  3. Cambia al hook que realmente deseas (ej. on_right_click).
  4. Agrega un mensaje de log primero, antes de animaciones o efectos.
  5. Agrega un efecto real (animacion, sonido, particula).
  6. Solo despues de eso, agrega funciones auxiliares, state, logica de scheduler o zonas.

Ese orden facilita enormemente la depuracion porque solo cambia una cosa a la vez.


Scripts predefinidos

FMM viene con un script Lua predefinido:

  • invulnerable.lua -- Cancela los eventos de dano por clic izquierdo, haciendo el prop indestructible. Este es el script de prop util mas simple.

Puedes encontrar mas ejemplos en la pagina Ejemplos y patrones.


Lua Sandbox

Los scripts de props se ejecutan dentro del mismo entorno LuaJ sandboxed que EliteMobs. Las restricciones de la sandbox son identicas. Para la lista completa de globals eliminados y funciones de la biblioteca estandar disponibles, consulta la pagina EliteMobs Hooks & Lifecycle.

En resumen:

  • Eliminados: debug, dofile, io, load, loadfile, luajava, module, os, package, require
  • Disponibles: Todas las funciones math.*, string.*, table.*, pairs, ipairs, type, tostring, tonumber, pcall, print y mas
tip

print escribe en la consola del servidor, pero es preferible usar context.log:info(msg) para la salida. Los mensajes de log llevan el prefijo del nombre del archivo de script, lo que facilita rastrear que script produjo el mensaje.


Proximos pasos

  • Prop API -- referencia completa de context.prop, context.event, context.world, context.zones y context.scheduler
  • Ejemplos y patrones -- scripts funcionales completos con explicaciones
  • Solucion de problemas -- problemas comunes, consejos de depuracion y una lista de verificacion QC

Si tambien escribes poderes Lua para EliteMobs, las APIs compartidas (context.world, context.zones, context.scheduler, context.state, context.log) funcionan de forma identica. Consulta la documentacion Lua de EliteMobs para las APIs especificas de jefes.