Saltar al contenido principal

Scripting Lua: Solución de problemas

Esta página cubre los problemas comunes que puedes encontrar al escribir o depurar scripts de props de FreeMinecraftModels, además de consejos para trabajar con el sistema de generación diferida de configuración. Si buscas ejemplos funcionales, consulta Ejemplos y patrones. Si recién estás comenzando, consulta Primeros pasos.


Problemas comunes

1. El archivo de configuración no se carga / El script no está asignado

Síntoma: El prop aparece pero no responde a clics ni a ningún hook.

Causas y soluciones:

  • Aún no existe un archivo de configuración .yml. FMM genera la configuración de forma diferida en el primer spawn del prop. La primera vez que se genera un modelo, FMM crea la configuración .yml de forma asíncrona con valores predeterminados (habilitado, sin scripts). Debes editar la configuración generada para agregar los nombres de tus archivos de script y luego volver a generar el prop.

  • La configuración tiene isEnabled: false. Abre el archivo .yml junto al archivo del modelo y establece isEnabled: true.

  • La lista scripts: está vacía. Agrega los nombres de tus archivos de script:

    isEnabled: true
    scripts:
    - my_script.lua
  • El nombre del archivo .yml no coincide con el nombre del archivo del modelo. La configuración debe tener el mismo nombre base que el archivo del modelo. Por ejemplo, torch_01.fmmodel necesita torch_01.yml en el mismo directorio.


2. Archivo de script no encontrado

Síntoma: La consola muestra: [FMM Scripts] Script 'my_script.lua' not found in scripts/ folder

Causas y soluciones:

  • Directorio incorrecto. Los archivos de script deben estar en plugins/FreeMinecraftModels/scripts/, no junto al archivo del modelo.

  • Nombre de archivo no coincide. El nombre en la configuración .yml debe coincidir exactamente con el nombre del archivo en la carpeta scripts/, incluyendo mayúsculas/minúsculas y la extensión .lua.

  • Archivo no presente. Verifica que el archivo .lua realmente exista en la carpeta scripts/.


3. El script no se carga en absoluto

Síntoma: No hay error en la consola, pero ningún hook se activa.

Revisa la consola del servidor en busca de errores de sintaxis Lua durante el inicio. Las causas más comunes son:

  • Falta end para cerrar una función o un bloque if
  • Paréntesis no emparejados
  • Falta coma entre definiciones de hooks en la tabla retornada
  • El archivo no termina con .lua

Si hay un error de Lua, la consola imprimirá un bloque de error [Lua] con el nombre del archivo, el número de línea y una descripción.


4. El hook nunca se activa

Síntoma: El script se carga (ves el mensaje [FMM Scripts] Bound script), pero un hook específico nunca se activa.

Verifica que el nombre del hook esté escrito exactamente como aparece en la referencia de hooks. Errores comunes:

Nombre incorrectoNombre correcto
on_clickon_right_click o on_left_click
on_interacton_right_click
on_hiton_left_click
on_tickon_game_tick
on_removeon_destroy
on_arrow_hiton_projectile_hit

Verifica también que el prop tenga realmente una entidad armor stand asociada. Algunas configuraciones de props pueden no producir una entidad que se pueda hacer clic.


5. Tiempo de espera agotado / Presupuesto de ejecución excedido

Síntoma: La consola muestra un mensaje como:

[Lua] my_script.lua took 73ms in 'on_game_tick' (limit: 50ms) -- script disabled to prevent lag.

El script estaba realizando demasiado trabajo en una sola llamada de hook. Causas comunes:

  • Iterar sobre demasiadas entidades en on_game_tick
  • Crear demasiadas partículas por tick
  • Ejecutar bucles costosos sin distribuir el trabajo entre ticks

Solución: Mueve el trabajo pesado detrás de un cooldown basado en estado o usa scheduler:run_repeating() con un intervalo razonable en lugar de on_game_tick.


6. context.event es nil en un hook de clic

Esto normalmente no debería ocurrir para on_left_click y on_right_click, pero siempre protégete con:

if context.event then
context.event.cancel()
end

Dentro de los callbacks del scheduler, context.event siempre es nil -- este es el comportamiento esperado. La modificación de eventos solo puede ocurrir dentro del hook del evento mismo.


7. La animación no se reproduce

Síntoma: play_animation() devuelve false, o no ocurre nada visible.

Causas y soluciones:

  • Nombre de animación incorrecto. El nombre debe coincidir exactamente con lo definido en el archivo del modelo. Revisa tu archivo .bbmodel o .fmmodel para obtener el nombre correcto de la animación.

  • El modelo no tiene animaciones. No todos los modelos tienen animaciones. Verifica que el archivo del modelo realmente contenga datos de animación.

  • Los jugadores no están en el rango del paquete de recursos. La animación es del lado del servidor, pero los jugadores necesitan tener cargado el paquete de recursos de FMM para ver el modelo.


8. Las partículas no aparecen

  • Verifica que el nombre de la partícula sea un valor válido del enum Particle de Bukkit en MAYÚSCULAS: "FLAME", no "flame".
  • Verifica que la ubicación esté en un chunk cargado. Si no hay jugadores cerca, el chunk puede estar descargado.
  • Verifica que count sea al menos 1.
  • Algunas partículas (como DUST) necesitan datos adicionales específicos que el spawn_particle() básico puede no soportar. Usa partículas estándar como FLAME, HEART, HAPPY_VILLAGER, NOTE, ENCHANT, etc.

9. El sonido no se reproduce

  • Verifica que el nombre del sonido sea una constante válida del enum Sound de Bukkit en MAYÚSCULAS. Ejemplo: "BLOCK_NOTE_BLOCK_HARP", no "block.note_block.harp".
  • Verifica que las coordenadas de ubicación sean correctas (no todas cero ni NaN).
  • Verifica que el volumen sea mayor que 0.

10. El estado se reinicia inesperadamente

context.state es por instancia de prop y persiste durante la vida del prop. Si el estado parece reiniciarse:

  • El prop puede haber sido eliminado y vuelto a generar (cada spawn crea una nueva instancia).
  • Puede que estés leyendo el estado en un callback del scheduler usando la variable de contexto incorrecta. Usa siempre el parámetro de contexto propio del callback.

Cómo funciona la generación diferida de configuración

Entender el sistema de configuración diferida ayuda a evitar confusión al configurar nuevos props:

  1. Primer spawn: Cuando un prop aparece y no existe un archivo .yml asociado, FMM crea la configuración de forma asíncrona. Esto significa que el archivo se escribe en un hilo de fondo y no está disponible inmediatamente.

  2. Valores predeterminados: La configuración generada tiene isEnabled: true y una lista vacía scripts: [].

  3. Sin scripts en el primer spawn: Como la configuración se crea después de que el prop ya ha aparecido (y no tiene scripts listados), el prop no tendrá scripts asignados en su primer spawn.

  4. Editar y volver a generar: Después de que FMM cree la configuración, la editas para agregar los nombres de tus archivos de script. La próxima vez que el prop aparezca, los scripts se cargarán.

  5. Ubicación de la configuración: El archivo .yml se crea en el mismo directorio que el archivo del modelo, con el mismo nombre base. Por ejemplo:

    • Modelo: plugins/FreeMinecraftModels/models/fountain.fmmodel
    • Configuración: plugins/FreeMinecraftModels/models/fountain.yml
Flujo de trabajo de configuración rápida
  1. Coloca el modelo en models/
  2. Coloca el script en scripts/
  3. Genera el prop una vez (genera el .yml)
  4. Edita el .yml para agregar scripts: [my_script.lua]
  5. Vuelve a generar el prop -- el script ahora está activo

Lectura de mensajes de error

Cuando algo sale mal en un script Lua de prop, la consola imprime un bloque de error [Lua]. Estos mensajes te indican exactamente qué archivo, qué línea, qué hook y qué salió mal en lenguaje claro.

Un error típico se ve así:

[Lua] Error in 'my_door.lua' at line 12 during 'on_right_click':
[Lua] -> You tried to call a method or function that doesn't exist.
[Lua] -> Check the method name for typos, or make sure you're using ':' (colon) for method calls, not '.' (dot).
[Lua] -> Script has been disabled for this entity to prevent further errors.

El sistema traduce los errores comunes de Lua a lenguaje claro:

Error Lua sin procesarLo que la consola te indica
attempt to call nilIntentaste llamar a un método o función que no existe. Revisa errores tipográficos y el uso de : vs. ..
index expected, got nilIntentaste acceder a un campo en algo que es nil. Verifica que el código anterior lo haya inicializado.
attempt to indexIntentaste acceder a una propiedad en un valor nil o inválido.
bad argumentUna función recibió el tipo de argumento incorrecto. El mensaje muestra el tipo esperado vs. el real.
TimeoutTu script tardó Xms en 'hook_name' (límite: 50ms) -- script deshabilitado para prevenir lag.
tip

Siempre lee el mensaje de error [Lua] completo antes de sumergirte en el código. Generalmente te señala directamente la solución.


No asumas que existen métodos no documentados

La API Lua de FMM expone un conjunto específico de métodos. No asumas que existen nombres abreviados o alternativos. Errores comunes:

  • context.prop:get_location() -- no existe. Usa context.prop.current_location (un campo, no un método).
  • context.prop:set_animation("open") -- no existe. Usa context.prop:play_animation("open", true, true).
  • context.event:setCancelled(true) -- no existe. Usa context.event.cancel().
  • context.cooldowns:check_local(...) -- no existe en FMM. Usa context.state con scheduler:run_later() para cooldowns.
  • context.player -- no existe en los scripts de props de FMM. Usa context.world:get_nearby_players() para encontrar jugadores cerca del prop.
  • context.boss -- no existe. Eso es de EliteMobs. Usa context.prop en FMM.

En caso de duda, consulta la página de API de Props. Si no está documentado allí, no existe.


Consejos de depuración

1. Usa context.log:info() con frecuencia

Agrega mensajes de registro en cada paso al depurar:

on_right_click = function(context)
context.log:info("Right click received!")
context.log:info("Event present: " .. tostring(context.event ~= nil))
context.log:info("State is_open: " .. tostring(context.state.is_open))
end

2. Revisa la consola al inicio

FMM registra [FMM Scripts] Bound script 'X' to prop 'Y' por cada vinculación exitosa. Si no ves este mensaje, la configuración o el script no se cargaron.

3. Verifica la ruta del archivo del modelo

La configuración .yml debe ser un archivo hermano del archivo del modelo (mismo directorio, mismo nombre base). Verifícalo revisando:

  • Ruta del archivo del modelo: plugins/FreeMinecraftModels/models/my_model.fmmodel
  • Ruta del archivo de configuración: plugins/FreeMinecraftModels/models/my_model.yml

4. Prueba los hooks individualmente

Al construir un script complejo, comienza probando cada hook por separado. Agrega un hook a la vez y verifica que se active antes de pasar al siguiente.

5. Busca errores tipográficos en los nombres de hooks

La razón más común por la que un hook no se activa es un nombre de hook mal escrito. El script se cargará sin errores, pero la función de hook mal escrita será rechazada durante la validación.


Ruta de progresión para principiantes

Si quieres aprender este sistema desde cero, esta progresión funciona bien:

  1. Escribe un archivo con solo api_version = 1 y on_spawn que registre un mensaje.
  2. Agrega el script a una configuración de prop y verifica que aparezca el mensaje de registro.
  3. Agrega on_right_click y registra cuando se hace clic en el prop.
  4. Agrega on_left_click con context.event.cancel() para invulnerabilidad.
  5. Reproduce una animación al hacer clic derecho.
  6. Agrega un sonido al hacer clic derecho.
  7. Agrega estado y comportamiento de alternancia.
  8. Agrega una vigilancia de zona para detección de proximidad.
  9. Solo entonces pasa a scripts complejos con múltiples hooks y schedulers.

Cada paso se basa en el anterior, y puedes probar en cada etapa.


Próximos pasos

  • Primeros pasos -- estructura de archivos, hooks, tutorial del primer script, plantillas para copiar y pegar
  • API de Props -- referencia completa de la API
  • Ejemplos y patrones -- scripts funcionales completos que puedes estudiar y adaptar