Scripts Lua: resolução de problemas
Esta página cobre problemas comuns ao escrever ou diagnosticar scripts de elementos decorativos FMM, incluindo a geração da configuração quando necessária. Para scripts funcionais, consulte Exemplos e padrões. Se está a começar, consulte Primeiros passos.
O FMM usa ScriptInstance do MagmaCore. Consulte Motor de scripts Lua do MagmaCore para o isolamento, agendamento, zonas, API do mundo, tabelas de entidades e métodos de interface para jogadores. Os poderes de bosses e scripts de NPC do EliteMobs reutilizam o isolamento Lua, mas expõem tabelas de contexto próprias.
Problemas comuns
1. Configuração não carregada ou script não associado
Sintoma: o elemento aparece, mas não responde a cliques nem a outros eventos.
Causas e soluções:
-
Ainda não existe um
.yml. O FMM tenta criá-lo de forma assíncrona na primeira criação do elemento, com valores predefinidos (ativo, sem scripts), sem substituir ficheiros existentes. Adicione os nomes dos scripts, execute/fmm reloadcom sucesso e coloque um novo elemento. Alterações a YAML e Lua exigem ambas uma recarga. -
A configuração contém
isEnabled: false. Abra o.ymljunto do modelo e definaisEnabled: true. -
A lista
scripts:está vazia. Adicione os nomes dos ficheiros:isEnabled: true
scripts:
- my_script.lua -
O nome do
.ymlnão corresponde ao modelo. Ambos devem ter o mesmo nome base e diretório. Por exemplo,torch_01.fmmodelprecisa detorch_01.yml.
2. Ficheiro de script não encontrado
Sintoma: a consola apresenta [FMM Scripts] Script 'my_script.lua' not found in scripts/ folder.
Causas e soluções:
-
Diretório errado. Coloque os scripts em
plugins/FreeMinecraftModels/scripts/, não junto do modelo. -
Nome diferente. O nome no
.ymldeve corresponder ao ficheiro emscripts/, incluindo maiúsculas e minúsculas. A extensão.luaé recomendada na configuração, mas opcional: o FMM acrescenta-a se faltar. -
Ficheiro ausente. Confirme que o
.luaexiste emscripts/. -
Definição em cache ou nomes repetidos. O FMM procura scripts recursivamente quando inicializa o fornecedor, mas associa-os pelo nome do ficheiro, não pelo caminho relativo. Use nomes únicos entre subpastas. Após adicionar ou editar um ficheiro Lua, execute
/fmm reloadcom sucesso; recriar o elemento não volta a ler o código Lua em cache.
3. O script não carrega
Sintoma: não vê erros na consola, mas nenhum evento executa o script.
Procure erros de sintaxe Lua no registo do arranque. As causas mais comuns são:
- Falta de
endpara terminar uma função ou condiçãoif. - Parênteses sem correspondência.
- Falta de uma vírgula entre funções de eventos na tabela devolvida.
- Ficheiro sem extensão
.lua.
As falhas de descoberta surgem como avisos de scripts inválidos ou retirados, ou como erros de carregamento. As falhas de eventos e funções agendadas usam um bloco [Lua] com o ficheiro e o contexto de execução; a linha só aparece se puder ser extraída da exceção.
4. Um evento nunca executa a função
Sintoma: a mensagem de arranque que adicionou aparece, mas uma função de evento nunca é executada.
Confirme o nome exato na referência de eventos. 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 (só é executado quando o elemento é removido definitivamente, não ao descarregar o chunk nem ao recarregar) |
on_arrow_hit | on_projectile_hit |
Confirme que o modelo foi carregado, tem uma hitbox utilizável e nenhum listener de proteção cancelou a interação antes da função do elemento. Um elemento criado usa um suporte de armadura; alterar uma opção não torna clicável um modelo inválido ou por carregar.
5. Limite de tempo ou execução excedido
Sintoma: a máquina virtual gera um erro Lua e interrompe uma chamada durante a execução, com uma destas mensagens:
Lua instruction budget exceeded (250000 instruction limit)
Lua CPU-time budget exceeded (50ms current-thread CPU limit)
Lua elapsed-time fallback budget exceeded (250ms fallback; current-thread CPU time unavailable)
Cada evento, função agendada ou avaliação de ficheiro pode executar até 250 000 instruções Lua ou consumir 50 ms de CPU da thread atual, conforme o primeiro limite atingido. As chamadas aninhadas partilham a mesma quota. A terceira mensagem só surge quando a JVM não disponibiliza medição de CPU por thread; nesse caso, o MagmaCore usa 250 ms de tempo decorrido. O script tentou fazer demasiado trabalho numa chamada. Causas comuns:
- Percorrer demasiadas entidades em
on_game_tick. - Criar demasiadas partículas por tick.
- Executar ciclos pesados sem distribuir o trabalho por vários ticks.
Solução: limite a frequência do trabalho com context.cooldowns ou use scheduler:run_repeating() com um intervalo adequado em vez de on_game_tick.
O limite de instruções restringe os ciclos Lua. O tempo é verificado a cada 1024 instruções Lua e no retorno; estas verificações não interrompem um método Java/Bukkit bloqueante durante a chamada. Limite também o trabalho dentro de cada função agendada.
6. context.event é nil num evento de clique
Isto não deve ocorrer normalmente em on_left_click e on_right_click, mas proteja sempre o acesso:
if context.event then
context.event.cancel()
end
Nas funções agendadas, context.event é sempre nil. Só pode modificar um evento dentro da própria função que o trata.
7. A animação não é reproduzida
Sintoma: play_animation() devolve false ou não há alteração visível.
Causas e soluções:
-
Nome incorreto. Deve corresponder exatamente à animação no
.bbmodelou.fmmodel. -
Modelo sem animações. Confirme que o ficheiro contém dados de animação.
-
Observador sem pacote ou fora do alcance. O jogador precisa do pacote de recursos atual e de estar dentro do alcance de visualização do modelo.
-
Pedido em espera ou suprimido. Passar
trueemblendusa uma única posição de espera, não uma transição gradual. Um pedido posterior pode substituí-lo e um ataque durante uma animação personalizada pode devolvertruesem a interromper. Use os argumentos posicionais indicados em Animações e distinga um pedido aceite de uma imagem apresentada.
8. As partículas não aparecem
- Os nomes aceitam
FLAMEouflame; a API normaliza maiúsculas e minúsculas antes de procurar a partícula Bukkit. - Confirme que a posição pertence a um chunk carregado. Sem jogadores próximos, o chunk pode estar descarregado.
- Confirme que
counté pelo menos 1. - Algumas partículas, como
DUST, exigem dados adicionais que ospawn_particle()base pode não suportar. Use partículas normais comoFLAME,HEART,HAPPY_VILLAGER,NOTEouENCHANT.
9. O som não é reproduzido
- São aceites nomes enum Bukkit, sem distinção de maiúsculas, ou chaves válidas como
minecraft:block.note_block.harpe chaves de pacotes personalizados. O cliente precisa de ter o som no pacote. - Confirme as coordenadas: não devem ser todas zero nem NaN.
- Confirme que o volume é superior a 0.
10. O estado é reiniciado inesperadamente
context.state pertence a uma instância de script. As entradas separadas de scripts: do mesmo elemento não o partilham. Mantém-se enquanto a instância está ativa. Se parecer reiniciar:
- O elemento pode ter sido removido e criado novamente, ou o seu chunk pode ter sido descarregado e carregado de novo. Cada criação ou carregamento do chunk produz uma nova instância. Guarde com
prop:set_persistent_dataos valores que tenham de sobreviver a isto. - Uma recarga bem-sucedida ou um erro de script pode ter encerrado a instância anterior. Consulte a consola; corrigir o ficheiro não reativa uma instância encerrada sem recarregar e voltar a associar o script.
- Pode estar a consultar a variável de contexto errada numa função agendada. Use o parâmetro de contexto da própria função.
11. A biblioteca os não está disponível
Sintoma: o script falha com um erro como attempt to index nil (os).
A biblioteca os foi completamente removida do ambiente isolado. Não pode usar os.time(), os.clock() nem outras funções os.
Solução: use context.world:get_time() para a hora do mundo ou conte o tempo decorrido com estado e contadores de ticks em on_game_tick. Para tempos de recarga, prefira context.cooldowns:check_local(key, ticks).
12. O script de item não é ativado
O formato de scripts de itens equipados foi removido. Um item personalizado com uma lista scripts: não vazia ou encantamentos antigos sem espaço de nomes é ignorado e produz um diagnóstico. Substitua-o por uma definição atual de item personalizado, com encantamentos com espaço de nomes. Os elementos decorativos continuam a usar scripts:.
13. A definição do item está indisponível
Procure o nome exato do ficheiro no aviso de arranque ou recarregamento. Um material indisponível, como um item de uma versão Minecraft mais recente, também faz ignorar a definição. Corrija-a ou substitua-a por uma compatível com a versão do servidor. O FMM não a reescreve nem inventa um material alternativo.
14. O evento funciona, mas os métodos de entidades falham
Sintoma: um evento como on_right_click funciona, mas uma função agendada falha com attempt to call nil ao chamar entity:damage() ou entity:push().
Causa: context.world:get_nearby_entities() devolve todas as entidades no alcance, incluindo itens no chão, orbes de experiência e nuvens de efeitos de área. As entidades não vivas não têm métodos de entidades vivas como damage(), push() ou add_potion_effect().
Solução: verifique if entity.damage then antes de chamar esses métodos:
local entities = context.world:get_nearby_entities(x, y, z, radius)
for _, entity in ipairs(entities) do
if entity.damage then
-- Safe to call living entity methods
entity:damage(5.0)
entity:push(0, 0.5, 0)
end
end
15. Faltam dados do evento nas funções agendadas
Sintoma: faltam dados do clique ou combate dentro de uma função de scheduler:run_later() ou scheduler:run_repeating().
Causa: as funções agendadas recebem um contexto novo, sem o evento Bukkit original nem o jogador do evento genérico de zona. context.event é sempre nil. Os scripts de elementos decorativos só recebem context.player nos eventos provocados por jogadores, como cliques e entrada/saída de zonas. Se precisarem do jogador mais tarde, devem guardá-lo a partir de context.player ou context.event.player durante o evento original.
Solução: use o contexto novo da função agendada para o estado e o mundo. Capture o jogador ou entidade antes do agendamento quando precisar daquele participante específico e confirme que continua válido.
on_right_click = function(context)
local clicked_player = context.player or (context.event and context.event.player)
context.scheduler:run_later(20, function(later_context)
-- Prop scripts should use a captured player when they need the clicker.
local player = later_context.player or clicked_player
if player and player.is_valid then
player:send_message("&aDelayed message!")
end
end)
end
Como é gerada a configuração quando necessária
O processo de geração ajuda a explicar o comportamento dos elementos novos:
-
Primeira criação: se não existir um
.ymlcorrespondente, o FMM cria-o numa thread em segundo plano. O ficheiro não fica disponível imediatamente. -
Predefinições: a configuração contém
isEnabled: trueescripts: []. -
Primeira criação sem scripts: o elemento já foi criado quando a configuração é escrita, e a lista ainda está vazia. Nenhum script é associado nessa primeira vez.
-
Editar, recarregar e recriar: adicione os nomes dos scripts e execute
/fmm reloadcom sucesso. As definições, verificações de colocação e listas de scripts do menu usam o mesmo catálogo preparado. Um novo elemento usa esse catálogo; não volta a ler o YAML editado. Alterações a Lua também exigem recarga. -
Localização: o
.ymlfica no mesmo diretório e usa o mesmo nome base do modelo. 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/. - Crie o elemento uma vez para gerar o
.yml. - Adicione
scripts: [my_script.lua]ao.yml. - Recarregue para descobrir o ficheiro Lua, coloque um elemento novo e confirme a sua própria mensagem de arranque.
Interpretar mensagens de erro
Os erros de eventos e funções agendadas produzem um bloco [Lua] com o ficheiro e o contexto de execução. A linha é incluída quando a exceção contém uma localização reconhecível no código. Os erros de descoberta e configuração podem usar outros avisos.
Exemplo:
[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 explica erros Lua comuns em linguagem simples:
| Erro Lua original | Significado da mensagem |
|---|---|
attempt to call nil | Tentou chamar um método ou função inexistente. Verifique o nome e o uso de : ou . |
index expected, got nil | Tentou aceder a um campo num valor nil. Confirme que foi inicializado anteriormente |
attempt to index | Tentou aceder a uma propriedade num valor nil ou inválido |
bad argument | A função recebeu um argumento do tipo errado. A mensagem compara o tipo esperado e o recebido |
| Limite excedido | Lua instruction budget exceeded (250000 instruction limit) ou Lua CPU-time budget exceeded (50ms current-thread CPU limit): a chamada foi interrompida e a instância do script desativada |
Leia todo o bloco [Lua] antes de alterar o código. Geralmente identifica diretamente a origem do problema.
Não invente nomes de métodos
A API Lua do FMM expõe um conjunto específico de métodos. Não pressuponha que existem abreviaturas ou nomes alternativos. Erros comuns:
context.prop:get_location()não existe. Use o campocontext.prop.current_location.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_global(...)não existe. Usecontext.cooldowns:global_ready()econtext.cooldowns:set_global(ticks)para tempos de recarga globais.context.playersó está definido nos eventos que envolvem um jogador, como cliques, entrada/saída de zonas eon_projectile_hitquando foi um jogador a disparar o projétil. Não representa um proprietário geral do elemento e énilnos eventos de ciclo de vida e nas funções agendadas.context.bosspertence ao EliteMobs. No FMM, usecontext.prop.
Consulte os métodos suportados na API de elementos decorativos e nas referências partilhadas que esta indica. Um nome plausível não prova que o método exista.
Sugestões de diagnóstico
1. Use context.log:info() em cada etapa
Adicione mensagens para observar a execução:
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. Consulte a consola no arranque
Adicione context.log:info("Prop script started") a on_spawn e coloque um elemento novo após recarregar. Procure a mensagem e eventuais erros de scripts ou configuração. O FMM não emite uma confirmação de sucesso para cada associação.
3. Confirme o caminho do modelo
A configuração deve estar no mesmo diretório do modelo, com o mesmo nome base. Confirme:
- Modelo:
plugins/FreeMinecraftModels/models/my_model.fmmodel - Configuração:
plugins/FreeMinecraftModels/models/my_model.yml
4. Verifique cada evento separadamente
Num script complexo, adicione uma função de evento de cada vez e confirme que é executada antes de avançar.
5. Procure erros nos nomes dos eventos
Um nome mal escrito é uma causa comum de falha. Um evento desconhecido faz rejeitar o script na validação. Consulte o erro na consola; não espere que as restantes funções desse ficheiro continuem a funcionar.
Percurso para principiantes
Para aprender desde o início:
- Escreva um ficheiro com
api_version = 1eon_spawnque registe uma mensagem. - Associe-o à configuração e confirme a mensagem.
- Adicione
on_right_clicke registe os cliques. - Adicione
on_left_clickcomcontext.event.cancel()para suprimir o dano predefinido do clique. - Reproduza uma animação com o clique direito.
- Acrescente um som ao clique direito.
- Adicione estado e um comportamento alternável.
- Observe uma zona para detetar proximidade.
- Depois avance para scripts com vários eventos e tarefas agendadas.
Cada passo usa o anterior e permite verificar o resultado antes de continuar.
Próximos passos
- Primeiros passos: estrutura de ficheiros, eventos, primeiro script e modelos para copiar.
- API de elementos decorativos: referência completa.
- Exemplos e padrões: scripts completos para estudar e adaptar.