Saltar al contenido principal

Scripting Lua: Primeros Pasos

Esta página te enseña a escribir tu primer script Lua para un prop de FreeMinecraftModels, desde un archivo vacío hasta un prop interactivo funcional. Al finalizar, entenderás los hooks, el context, la Prop API y la estructura general de cada archivo de script de prop.

Una vez que te sientas cómodo con lo básico, continúa con las páginas 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
  • Solución de Problemas -- errores comunes, consejos de depuración y la lista de verificación QC
Función Experimental

Los scripts Lua de props son actualmente experimentales. Los nombres de los hooks, los métodos auxiliares y el comportamiento aún pueden cambiar a medida que FreeMinecraftModels evoluciona, así que prueba cuidadosamente antes de usarlos en un servidor de producción.

Relación 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 idénticos. 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 página solo cubre lo que es específico de los props de FMM.


Qué 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 configuración YAML que se ubica junto al archivo del modelo, y se ejecutan cada vez que el prop aparece en el mundo.

Para Qué 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 área
  • 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 lógica más allá de la decoración estática

Si tu prop es puramente decorativo y no necesita interacción, no necesitas un script.


Para Quién Es Esta Página

Esta página está escrita para tres tipos de lectores:

  • Alguien que ya conoce el scripting Lua de EliteMobs y quiere aprender los hooks y APIs específicos 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 cuándo la IA inventó algo falso

No necesitas convertirte en un desarrollador Lua completo antes de escribir scripts de props útiles. Para la mayoría de los scripts de props prácticos, lo único que realmente necesitas es:

  • Cómo colocar un hook válido en la tabla devuelta
  • Cómo leer valores de context
  • Cómo detener la ejecución anticipadamente con if ... then return end
  • Cómo llamar a algunos métodos auxiliares de forma exacta

Introducción Rápida a Lua

Si eres completamente nuevo en Lua, aquí tienes la sintaxis mínima que necesitas.

Variables

Usa local para almacenar un valor:

local animation_name = "open"
local sound_volume = 1.0

Funciones

Las funciones son bloques de lógica 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 comprobarás frecuentemente:

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

Tablas

Lua usa tablas para objetos con claves nombradas y para la definición 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 introducción más completa a Lua, consulta la página Primeros pasos con EliteMobs. Los fundamentos de sintaxis son idénticos.


Dónde 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 Configuración

Cada archivo de modelo puede tener un archivo .yml de configuración 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 configuración es lo que conecta un modelo con sus scripts.


Formato del Archivo de Configuración

El archivo de configuración YAML que se ubica junto a un archivo de modelo tiene dos campos:

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

Puedes adjuntar múltiples scripts al mismo prop. Cada script es su propia instancia independiente.

Generación Diferida de Configuración

Cuando un prop aparece y no existe un archivo .yml asociado, FMM crea automáticamente un archivo de configuración predeterminado con isEnabled: true y una lista scripts: vacía. Esto sucede de forma asíncrona, por lo que el prop no tendrá scripts en su primer spawn -- solo después de que se cree la configuración 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 automáticamente)
  3. Edita el .yml generado para agregar tus nombres de archivos de script
  4. Vuelve a generar el prop o recarga (los scripts ahora están activos)

Referencia de Hooks

Cada archivo de script Lua de prop devuelve una tabla. Cada clave en esa tabla (además de api_version y priority) debe ser uno de los hooks listados a continuación. El runtime llama a la función 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 daño
on_right_clickUn jugador hace clic derecho en el propcontext.event es el evento de interacción
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 Mínimo del Archivo

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

Campos de Nivel Superior Obligatorios y Opcionales

CampoObligatorioTipoNotas
api_versionNumberActualmente debe ser 1
priorityNoNumberPrioridad de ejecución. Los valores más 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 Validación

  • El archivo debe devolver una tabla.
  • api_version es obligatorio y actualmente debe ser 1.
  • priority debe ser numérico si está presente.
  • Cada clave de nivel superior adicional debe ser un nombre de hook soportado.
  • Cada clave de hook debe apuntar a una función.
  • 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 generar la configuración .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 válido
  • FMM lo encontró en la carpeta scripts/
  • La configuración 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 está 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 está funcionando.

Paso 4: Cancelar el Daño 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 patrón utilizado por el script predefinido invulnerable.lua. Cancela el evento de daño para que el armor stand que respalda al prop no pueda ser destruido.

Paso 5: Reproducir una Animación al Hacer Clic

return {
api_version = 1,

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

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


¿Qué Es context?

Cada función de hook recibe un argumento llamado context. Piensa en él 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 más.

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 partículas, sonidos, consultas de bloques
-- context.state = tu propio almacenamiento persistente
-- context.log = registro en consola
-- context.scheduler = tareas diferidas y repetitivas
-- context.zones = creación y vigilancia de zonas espaciales
end

Tú 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 después en un hook diferente.


APIs Clave de context

Aquí tienes un resumen de lo que está 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 activó 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. Úsala 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 -- Interacción con el mundo: partículas, sonidos, consultas de bloques, rayos, entidades cercanas. Consulta Prop API para la lista completa de métodos.

  • context.zones -- Creación y vigilancia de zonas espaciales (esferas, cilindros, cuboides). Consulta Prop API para la lista completa de métodos.


Sintaxis de Métodos: : 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 documentación usa : de forma consistente.


Plantillas Listas para Copiar y Pegar

Script de Prop Válido Más Pequeño

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
}

Disposición de Archivo Más 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 configuración .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 (animación, sonido, partícula).
  6. Solo después de eso, agrega funciones auxiliares, state, lógica de scheduler o zonas.

Ese orden facilita enormemente la depuración porque solo cambia una cosa a la vez.


Scripts Predefinidos

FMM viene con dos scripts Lua predefinidos:

  • invulnerable.lua -- Cancela los eventos de daño por clic izquierdo, haciendo el prop indestructible. Este es el script de prop útil más simple.
  • pickupable.lua -- Permite a los jugadores recoger un prop golpeándolo tres veces. Cada golpe reproduce una animación de daño en el prop, y al tercer golpe el prop se elimina y suelta su ítem de colocación para que el jugador lo recoja.

Puedes encontrar más ejemplos en la página 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 idénticas. Para la lista completa de globals eliminados y funciones de la biblioteca estándar disponibles, consulta la página 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 más
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 qué script produjo el mensaje.


Próximos 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
  • Solución de Problemas -- problemas comunes, consejos de depuración y una lista de verificación QC

Si también escribes poderes Lua para EliteMobs, las APIs compartidas (context.world, context.zones, context.scheduler, context.state, context.log) funcionan de forma idéntica. Consulta la documentación Lua de EliteMobs para las APIs específicas de jefes.