Scripting Lua: Solução de Problemas
Esta página cobre problemas comuns que você pode encontrar ao escrever ou depurar scripts de props do FreeMinecraftModels, além de dicas para trabalhar com o sistema de geração preguiçosa de configuração. Se você está procurando exemplos funcionais, veja Exemplos e Padrões. Se está apenas começando, veja Primeiros Passos.
Problemas Comuns
1. Arquivo de configuração não carrega / Script não vinculado
Sintoma: O prop spawna mas não responde a cliques ou quaisquer hooks.
Causas e soluções:
-
Nenhum arquivo de configuração
.ymlexiste ainda. O FMM gera a configuração de forma preguiçosa no primeiro spawn do prop. Na primeira vez que um modelo é spawnado, o FMM cria o arquivo de configuração.ymlde forma assíncrona com valores padrão (habilitado, sem scripts). Você deve editar a configuração gerada para adicionar os nomes dos seus scripts e então respawnar o prop. -
A configuração tem
isEnabled: false. Abra o arquivo.ymlao lado do arquivo de modelo e definaisEnabled: true. -
A lista
scripts:está vazia. Adicione os nomes dos seus scripts:isEnabled: true
scripts:
- my_script.lua -
O nome do arquivo
.ymlnão corresponde ao nome do arquivo de modelo. A configuração deve ter o mesmo nome base que o arquivo de modelo. Por exemplo,torch_01.fmmodelprecisa detorch_01.ymlno mesmo diretório.
2. Arquivo de script não encontrado
Sintoma: O console mostra: [FMM Scripts] Script 'my_script.lua' not found in scripts/ folder
Causas e soluções:
-
Diretório errado. Arquivos de script devem estar em
plugins/FreeMinecraftModels/scripts/, não ao lado do arquivo de modelo. -
Nome de arquivo diferente. O nome na configuração
.ymldeve corresponder exatamente ao nome do arquivo na pastascripts/, incluindo maiúsculas/minúsculas e a extensão.lua. -
Arquivo não presente. Verifique novamente se o arquivo
.luarealmente existe na pastascripts/.
3. Script não carrega de forma alguma
Sintoma: Nenhum erro no console, mas nenhum hook dispara.
Verifique o console do servidor para erros de sintaxe Lua durante a inicialização. As causas mais comuns são:
endfaltando para fechar uma função ou blocoif- Parênteses não correspondentes
- Vírgula faltando entre definições de hooks na tabela retornada
- Arquivo não termina com
.lua
Se houver um erro Lua, o console imprimirá um bloco de erro [Lua] com o nome do arquivo, número da linha e uma descrição.
4. Hook nunca dispara
Sintoma: O script carrega (você vê a mensagem [FMM Scripts] Bound script), mas um hook específico nunca é acionado.
Verifique se o nome do hook está escrito exatamente como listado na referência de hooks. Erros comuns:
| Nome errado | Nome correto |
|---|---|
on_click | on_right_click ou on_left_click |
on_interact | on_right_click |
on_hit | on_left_click |
on_tick | on_game_tick |
on_remove | on_destroy |
on_arrow_hit | on_projectile_hit |
Verifique também se o prop realmente tem uma entidade armor stand de suporte. Algumas configurações de prop podem não produzir uma entidade clicável.
5. Timeout / orçamento de execução excedido
Sintoma: O console mostra uma mensagem como:
[Lua] my_script.lua took 73ms in 'on_game_tick' (limit: 50ms) -- script disabled to prevent lag.
O script estava fazendo trabalho demais em uma única chamada de hook. Causas comuns:
- Iterando sobre muitas entidades em
on_game_tick - Criando muitas partículas por tick
- Executando loops caros sem distribuir o trabalho entre ticks
Solução: Mova trabalho pesado para trás de um cooldown baseado em estado ou use scheduler:run_repeating() com um intervalo razoável em vez de on_game_tick.
6. context.event é nil em um hook de clique
Isso não deveria acontecer normalmente para on_left_click e on_right_click, mas sempre proteja com:
if context.event then
context.event.cancel()
end
Dentro de callbacks de scheduler, context.event é sempre nil -- este é o comportamento esperado. Modificação de evento só pode acontecer dentro do próprio hook de evento.
7. Animação não reproduz
Sintoma: play_animation() retorna false, ou nada visível acontece.
Causas e soluções:
-
Nome de animação errado. O nome deve corresponder exatamente ao que está definido no arquivo de modelo. Verifique seu
.bbmodelou.fmmodelpara o nome correto da animação. -
Modelo não tem animações. Nem todos os modelos têm animações. Verifique se o arquivo de modelo realmente contém dados de animação.
-
Jogadores não estão no alcance do resource pack. A animação é server-side, mas jogadores precisam do resource pack do FMM carregado para ver o modelo.
8. Partículas não aparecem
- Verifique se o nome da partícula é um valor válido do enum
Particledo Bukkit em MAIÚSCULAS:"FLAME", não"flame". - Verifique se a localização está em um chunk carregado. Se nenhum jogador está por perto, o chunk pode estar descarregado.
- Verifique se
counté pelo menos 1. - Algumas partículas (como
DUST) precisam de dados extras específicos que ospawn_particle()base pode não suportar. Use partículas padrão comoFLAME,HEART,HAPPY_VILLAGER,NOTE,ENCHANT, etc.
9. Som não toca
- Verifique se o nome do som é uma constante válida do enum
Sounddo Bukkit em MAIÚSCULAS. Exemplo:"BLOCK_NOTE_BLOCK_HARP", não"block.note_block.harp". - Verifique se as coordenadas de localização estão corretas (não todos zeros ou NaN).
- Verifique se o volume é maior que 0.
10. Estado reseta inesperadamente
context.state é por instância de prop e persiste durante a vida do prop. Se o estado parece resetar:
- O prop pode ter sido removido e respawnado (cada spawn cria uma nova instância).
- Você pode estar lendo estado em um callback de scheduler usando a variável de context errada. Sempre use o próprio parâmetro de context do callback.
11. Biblioteca os não está disponível
Sintoma: Script crasha com um erro como attempt to index nil (os).
A biblioteca os é completamente removida do sandbox Lua. Você não pode usar os.time(), os.clock() ou qualquer outra função os.
Solução: Use context.world:get_time() para o tempo do mundo, ou rastreie o tempo decorrido manualmente usando flags de estado e contadores de tick em on_game_tick. Para cooldowns, use flags de context.state com scheduler:run_later().
12. Script de item não ativando
Sintoma: O item customizado está na mão do jogador, mas nenhum hook de item dispara.
Causas e soluções:
-
Sem campo
material:na configuração YML. Scripts de item só funcionam em modelos que têmmaterial:definido na sua configuração. Sem este campo, o FMM trata o modelo como prop, não como item customizado. -
Chave PDC
fmm_item_idausente. O item no inventário do jogador deve ter a chave PersistentDataContainerfmm_item_id. Itens obtidos através de comandos vanilla ou plugins de terceiros podem não ter esta tag. Use/fmm giveitem <id>ou o menu de admin para obter um item com as tags corretas. -
Nome do arquivo de script não listado na configuração. Verifique se a configuração
.ymldo item tem o nome do arquivo de script na listascripts:, assim como os props.
13. Script de item ativando e desativando imediatamente
Sintoma: Você vê o script vincular e desvincular em rápida sucessão no console, ou on_equip dispara seguido imediatamente por on_unequip.
Causa: O rastreamento de equipamento de itens dispara em eventos de mudança de slot. Se você se der um item com um comando e ele for para um slot não-ativo, ou se seu slot ativo mudar durante o give, o ciclo de equipar/desequipar pode disparar em rápida sucessão.
Solução: Depois de se dar o item com /fmm giveitem <id>, certifique-se de trocar manualmente para o slot de inventário contendo o item. O script ativa baseado em qual slot está atualmente selecionado, não apenas se o item está no inventário.
14. Hook dispara mas script crasha em métodos de entidade
Sintoma: Um hook como on_shift_right_click funciona, mas o script crasha dentro de um callback agendado com erros como attempt to call nil ao chamar entity:damage() ou entity:push().
Causa: context.world:get_nearby_entities() retorna TODAS as entidades no alcance, incluindo entidades não-vivas (armor stands, itens dropados, orbes de experiência, nuvens de efeito de área). Essas entidades não possuem métodos de entidades vivas como damage(), push() ou add_potion_effect().
Solução: Sempre proteja com if entity.damage then antes de chamar métodos de entidades vivas:
local entities = context.world:get_nearby_entities(x, y, z, radius)
for _, entity in ipairs(entities) do
if entity.damage then
-- Seguro chamar métodos de entidades vivas
entity:damage(5.0)
entity:push(0, 0.5, 0)
end
end
15. context.player é nil em callbacks agendados
Sintoma: context.player é nil dentro de um callback scheduler:run_later() ou scheduler:run_repeating(), mesmo estando disponível no hook que criou o callback.
Causa: O context é reconstruído preguiçosamente para cada invocação de callback. Em alguns casos, especialmente se o jogador desconectar ou o item for desequipado entre o agendamento e a execução, context.player pode não estar disponível.
Solução: Capture a referência do jogador de uma variável de closure antes de agendar:
on_right_click = function(context)
local player = context.player
local player_loc = player.current_location
context.scheduler:run_later(20, function()
-- Use a variável 'player' capturada, não context.player
if player.is_valid then
player:send_message("&aDelayed message!")
end
end)
end
Como a Geração Preguiçosa de Configuração Funciona
Entender o sistema de configuração preguiçosa ajuda a evitar confusão ao configurar novos props:
-
Primeiro spawn: Quando um prop spawna e nenhum arquivo
.ymlirmão existe, o FMM cria a configuração de forma assíncrona. Isso significa que o arquivo é escrito em uma thread em segundo plano e não está imediatamente disponível. -
Valores padrão: A configuração gerada tem
isEnabled: truee uma lista vaziascripts: []. -
Sem scripts no primeiro spawn: Como a configuração é criada depois que o prop já spawnou (e não tem scripts listados), o prop não terá scripts vinculados no seu primeiro spawn.
-
Edite e respawne: Depois que o FMM cria a configuração, você a edita para adicionar os nomes dos seus scripts. Na próxima vez que o prop spawnar, os scripts serão carregados.
-
Localização da configuração: O arquivo
.ymlé criado no mesmo diretório que o arquivo de modelo, com o mesmo nome base. Por exemplo:- Modelo:
plugins/FreeMinecraftModels/models/fountain.fmmodel - Configuração:
plugins/FreeMinecraftModels/models/fountain.yml
- Modelo:
- Coloque o modelo em
models/ - Coloque o script em
scripts/ - Spawne o prop uma vez (gera o
.yml) - Edite o
.ymlpara adicionarscripts: [my_script.lua] - Respawne o prop -- script agora está ativo
Lendo Mensagens de Erro
Quando algo dá errado em um script Lua de prop, o console imprime um bloco de erro [Lua]. Essas mensagens dizem exatamente qual arquivo, qual linha, qual hook e o que deu errado em linguagem simples.
Um erro típico se parece com isto:
[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.
O sistema traduz erros comuns de Lua para linguagem simples:
| Erro Lua bruto | O que o console diz |
|---|---|
attempt to call nil | Você tentou chamar um método ou função que não existe. Verifique erros de digitação e uso de : vs .. |
index expected, got nil | Você tentou acessar um campo em algo que é nil. Verifique se o código anterior o inicializou. |
attempt to index | Você tentou acessar uma propriedade em um valor nil ou inválido. |
bad argument | Uma função recebeu o tipo errado de argumento. A mensagem mostra o tipo esperado vs. real. |
| Timeout | Seu script levou Xms em 'hook_name' (limite: 50ms) -- script desabilitado para evitar lag. |
Sempre leia a mensagem de erro [Lua] completa antes de mergulhar no código. Ela geralmente aponta diretamente para a solução.
Não Assuma que Métodos Não Documentados Existem
A API Lua do FMM expõe um conjunto específico de métodos. Não assuma que abreviações ou nomes alternativos existem. Erros comuns:
context.prop:get_location()-- não existe. Usecontext.prop.current_location(um campo, não um método).context.prop:set_animation("open")-- não existe. Usecontext.prop:play_animation("open", true, true).context.event:setCancelled(true)-- não existe. Usecontext.event.cancel().context.cooldowns:check_local(...)-- não existe no FMM. Usecontext.statecomscheduler:run_later()para cooldowns.context.player-- não existe em scripts de props do FMM. Usecontext.world:get_nearby_players()para encontrar jogadores perto do prop.context.boss-- não existe. Isso é do EliteMobs. Usecontext.propno FMM.
Na dúvida, consulte a página API de Props. Se não está documentado lá, não existe.
Dicas de Depuração
1. Use context.log:info() generosamente
Adicione mensagens de log em cada etapa ao 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. Verifique o console na inicialização
O FMM registra [FMM Scripts] Bound script 'X' to prop 'Y' para cada vinculação bem-sucedida. Se você não vê esta mensagem, a configuração ou script não foi carregado.
3. Verifique o caminho do arquivo de modelo
A configuração .yml deve ser irmã do arquivo de modelo (mesmo diretório, mesmo nome base). Verifique isto checando:
- Caminho do arquivo de modelo:
plugins/FreeMinecraftModels/models/my_model.fmmodel - Caminho do arquivo de configuração:
plugins/FreeMinecraftModels/models/my_model.yml
4. Teste hooks individualmente
Ao construir um script complexo, comece testando cada hook isoladamente. Adicione um hook de cada vez e verifique se ele dispara antes de passar para o próximo.
5. Verifique erros de digitação em nomes de hooks
A razão mais comum para um hook não disparar é um nome de hook mal escrito. O script carregará sem erros, mas a função de hook mal escrita será rejeitada durante a validação.
Caminho de Progressão para Iniciantes
Se você quer aprender este sistema do zero, esta progressão funciona bem:
- Escreva um arquivo com apenas
api_version = 1eon_spawnque registra uma mensagem. - Adicione o script a uma configuração de prop e verifique se a mensagem de log aparece.
- Adicione
on_right_clicke registre quando o prop é clicado. - Adicione
on_left_clickcomcontext.event.cancel()para invulnerabilidade. - Reproduza uma animação ao clicar com botão direito.
- Adicione um som ao clicar com botão direito.
- Adicione estado e comportamento de alternância.
- Adicione um monitoramento de zona para detecção de proximidade.
- Só então passe para scripts complexos multi-hook com schedulers.
Cada passo se baseia no anterior, e você pode testar em cada etapa.
Próximos Passos
- Primeiros Passos -- estrutura de arquivos, hooks, passo a passo do primeiro script, templates para copiar e colar
- API de Props -- referência completa da API
- Exemplos e Padrões -- scripts completos e funcionais que você pode estudar e adaptar