Lua Scripting: Primeiros passos
Esta página ensina a escrever o seu primeiro script Lua para um prop do FreeMinecraftModels, desde um ficheiro vazio até um prop interativo funcional. No final, vai compreender hooks, context, a Prop API e a estrutura geral de cada ficheiro de script de prop.
Assim que estiver confortável com o básico, continue com as páginas complementares:
- Prop API -- as APIs de
context.prop,context.event,context.worlde outros context - Exemplos e padrões -- scripts completos e funcionais que pode estudar e adaptar
- Resolução de problemas -- erros comuns, dicas de depuração e a checklist de QC
Os scripts Lua de props são atualmente experimentais. Os nomes dos hooks, métodos auxiliares e comportamento ainda podem mudar à medida que o FreeMinecraftModels evolui, por isso teste cuidadosamente antes de os usar num servidor de produção.
O FreeMinecraftModels partilha o mesmo motor Lua (Magmacore) que o EliteMobs. Se já escreve poderes Lua para o EliteMobs, os conceitos fundamentais -- hooks, context, api_version, scheduler, zonas e a sandbox -- são idênticos. A diferença é:
- Os scripts do EliteMobs executam em bosses e têm hooks como
on_boss_damaged_by_player,on_enter_combat, etc. - Os scripts do FMM executam em props e têm hooks como
on_right_click,on_left_click,on_projectile_hit, etc.
As APIs context.world, context.zones, context.scheduler, context.state e context.log são as mesmas em ambos os plugins. Esta página cobre apenas o que é específico para props do FMM.
O que são scripts de props
Scripts de props são ficheiros .lua independentes que se encontram na pasta plugins/FreeMinecraftModels/scripts/. São referenciados a partir de um ficheiro de config YAML que fica ao lado do ficheiro de modelo, e executam sempre que o prop é gerado no mundo.
Para que são bons os scripts de props
Os scripts de props destacam-se quando precisa de:
- Props interativos que respondem a cliques dos jogadores (portas, alavancas, botões)
- Props decorativos invulneráveis que não podem ser destruídos pelos jogadores
- Gatilhos de proximidade que detetam quando jogadores entram ou saem de uma área
- Props animados que reproduzem animações na interação ou com um temporizador
- Props emissores de som que reproduzem sons quando clicados ou quando alguém se aproxima
- Qualquer comportamento de prop que exija lógica além da decoração estática
Se o seu prop é puramente decorativo e não precisa de interação, não precisa de um script.
Para quem é esta página
Esta página foi escrita para três tipos de leitores:
- Alguém que já conhece o scripting Lua do EliteMobs e quer aprender os hooks e APIs específicos do FMM
- Alguém que é novo no scripting Lua e precisa de uma referência completa com nomes exatos para props
- Alguém que usa IA para redigir scripts de props e precisa de detalhe suficiente para saber quando a IA inventou algo falso
Não precisa de se tornar um programador Lua completo antes de escrever scripts de props úteis. Para a maioria dos scripts de props práticos, as únicas coisas que realmente precisa são:
- Como colocar um hook válido na tabela retornada
- Como ler valores do
context - Como parar cedo com
if ... then return end - Como chamar alguns métodos auxiliares exatamente
Mini-introdução ao Lua
Se é completamente novo no Lua, aqui está a sintaxe mínima de que precisa.
Variáveis
Use local para armazenar um valor:
local animation_name = "open"
local sound_volume = 1.0
Funções
Funções são blocos de lógica reutilizáveis:
local function log_click(context)
context.log:info("Prop was clicked!")
end
Verificações if
Use if quando algo só deve acontecer por vezes:
if context.event == nil then
return
end
nil
nil significa "sem valor". Vai verificá-lo frequentemente:
if context.event ~= nil then
context.event.cancel()
end
Tabelas
O Lua usa tabelas para objetos com chaves nomeadas e para a definição do script retornado:
return {
api_version = 1,
on_spawn = function(context)
end
}
Comentários
Use -- para notas:
-- Cancel the damage event so the prop cannot be broken
context.event.cancel()
Para uma introdução mais completa ao Lua, consulte a página Primeiros passos com EliteMobs. Os fundamentos de sintaxe são idênticos.
Onde ficam os ficheiros
Ficheiros de script
Coloque os ficheiros .lua na pasta central de scripts:
plugins/
FreeMinecraftModels/
scripts/
invulnerable.lua
interactive_door.lua
proximity_sound.lua
O FMM descobre todos os ficheiros .lua em plugins/FreeMinecraftModels/scripts/ ao iniciar.
Ficheiros de modelo e ficheiros de config
Cada ficheiro de modelo pode ter um ficheiro .yml de config associado no mesmo diretório:
plugins/
FreeMinecraftModels/
models/
torch_01.fmmodel
torch_01.yml <-- config de script para torch_01
scripts/
invulnerable.lua <-- referenciado por torch_01.yml
O ficheiro .yml de config é o que liga um modelo aos seus scripts.
Formato do ficheiro de config
O ficheiro de config YAML que fica ao lado de um ficheiro de modelo tem dois campos:
isEnabled: true
scripts:
- invulnerable.lua
| Campo | Tipo | Predefinido | Notas |
|---|---|---|---|
isEnabled | boolean | true | Se os scripts estão ativos para este prop |
scripts | lista de strings | [] | Nomes de ficheiros .lua na pasta scripts/ |
Pode anexar múltiplos scripts ao mesmo prop. Cada script é a sua própria instância independente.
Geração diferida de config
Quando um prop é gerado e não existe um ficheiro .yml associado, o FMM cria automaticamente um ficheiro de config predefinido com isEnabled: true e uma lista scripts: vazia. Isto acontece de forma assíncrona, portanto o prop não terá scripts na sua primeira geração -- só depois de a config ser criada e de a editar para adicionar nomes de ficheiros de script.
Isto significa:
- Coloque o seu ficheiro de modelo em
models/ - Gere o prop uma vez (o FMM cria o
.ymlautomaticamente) - Edite o
.ymlgerado para adicionar os seus nomes de ficheiros de script - Regere o prop ou recarregue o servidor (os scripts estão agora ativos)
Referência de hooks
Cada ficheiro de script Lua de prop retorna uma tabela. Cada chave nessa tabela (além de api_version e priority) deve ser um dos hooks listados abaixo. O runtime chama a função correspondente sempre que o evento de jogo associado é disparado.
| Hook | Dispara quando | Notas |
|---|---|---|
on_spawn | O prop é gerado no mundo | Executa uma vez quando o script é vinculado |
on_game_tick | Uma vez por tick do servidor (50 ms) | Só ativo se o script definir este hook |
on_destroy | O prop é removido do mundo | Hook de limpeza |
on_left_click | Um jogador clica com o botão esquerdo (ataca) o prop | context.event é o evento de dano |
on_right_click | Um jogador clica com o botão direito no prop | context.event é o evento de interação |
on_projectile_hit | Um projétil atinge o prop | context.event é o evento de impacto de projétil |
on_zone_enter | Um jogador entra numa zona vigiada | Requer que uma vigilância de zona esteja configurada |
on_zone_leave | Um jogador sai de uma zona vigiada | Requer que uma vigilância de zona esteja configurada |
Contrato mínimo do ficheiro
Cada script Lua de prop deve fazer return de uma tabela.
Campos de nível superior obrigatórios e opcionais
| Campo | Obrigatório | Tipo | Notas |
|---|---|---|---|
api_version | Sim | Number | Atualmente deve ser 1 |
priority | Não | Number | Prioridade de execução. Valores mais baixos executam primeiro. Predefinido 0 |
| Chaves de hook suportadas | Não | Function | Deve usar um dos nomes exatos de hook listados na Referência de hooks |
Regras de validação
- O ficheiro deve retornar uma tabela.
api_versioné obrigatório e atualmente deve ser1.prioritydeve ser numérico se presente.- Cada chave de nível superior adicional deve ser um nome de hook suportado.
- Cada chave de hook deve apontar para uma função.
- Chaves de nível superior desconhecidas são rejeitadas.
Funções auxiliares e constantes locais devem ficar acima do return final, não dentro da tabela retornada.
O seu primeiro script de prop funcional, construído passo a passo
Antes do passo 1: Configurar a config
- Coloque o seu ficheiro de modelo (ex.:
my_prop.fmmodel) emplugins/FreeMinecraftModels/models/ - Gere o prop uma vez para criar a config
.yml - Crie o seu ficheiro de script em
plugins/FreeMinecraftModels/scripts/first_test.lua - Edite
plugins/FreeMinecraftModels/models/my_prop.yml:
isEnabled: true
scripts:
- first_test.lua
- Regere o prop ou recarregue o servidor
Passo 1: Fazer o ficheiro carregar
return {
api_version = 1,
on_spawn = function(context)
end
}
Se isto carregar sem erros na consola, provou:
- O ficheiro é Lua válido
- O FMM encontrou-o na pasta
scripts/ - A config referencia-o corretamente
- A forma da tabela retornada está correta
Passo 2: Fazer o prop fazer algo visível
return {
api_version = 1,
on_spawn = function(context)
context.log:info("Prop script loaded for: " .. (context.prop.model_id or "unknown"))
end
}
Verifique a consola do servidor. Se vir a mensagem de log, o seu hook está a disparar.
Passo 3: Reagir a um clique do jogador
return {
api_version = 1,
on_right_click = function(context)
context.log:info("Prop was right-clicked!")
end
}
Clique com o botão direito no prop no jogo. Se a consola mostrar a mensagem, o hook de clique está a funcionar.
Passo 4: Cancelar dano para tornar o prop invulnerável
return {
api_version = 1,
on_left_click = function(context)
if context.event then
context.event.cancel()
end
end
}
Este é o padrão usado pelo script predefinido invulnerable.lua. Cancela o evento de dano para que o armor stand que suporta o prop não possa ser destruído.
Passo 5: Reproduzir uma animação ao clicar
return {
api_version = 1,
on_right_click = function(context)
context.prop:play_animation("open", true, false)
end
}
Isto reproduz a animação "open" no modelo do prop, com mistura e sem loop.
O que é context?
Cada função de hook recebe um argumento chamado context. Pense nele como uma caixa de ferramentas que o FMM lhe entrega cada vez que algo acontece -- contém tudo o que precisa para interagir com o prop, o mundo, zonas e mais.
on_right_click = function(context)
-- context.prop = o prop que foi clicado
-- context.event = o evento de clique (pode ser cancelado)
-- context.world = ferramentas para partículas, sons, consultas de blocos
-- context.state = o seu próprio armazenamento persistente
-- context.log = registo na consola
-- context.scheduler = tarefas diferidas e repetitivas
-- context.zones = criação e vigilância de zonas espaciais
end
Não cria context -- o FMM cria-o e passa-o ao seu hook.
context é criado de novo para cada chamada de hook, exceto context.state que persiste durante toda a vida do prop. Isto significa que pode armazenar dados em context.state e lê-los mais tarde num hook diferente.
APIs chave de context
Aqui está um resumo do que está disponível. Para detalhes completos, consulte Prop API.
-
context.prop-- A entidade do prop. Fornecemodel_id,current_location,play_animation()estop_animation(). -
context.event-- O evento Bukkit que acionou este hook. Disponível emon_left_click,on_right_clickeon_projectile_hit. Fornececancel(),uncancel()eis_cancelled. Énilem hooks sem evento (comoon_spawneon_game_tick). -
context.state-- Uma tabela Lua simples que persiste durante a vida do prop. Use-a para armazenar flags, estados de alternância, IDs de tarefas e qualquer coisa que precise de lembrar entre hooks. -
context.log-- Registo na consola comlog:info(msg),log:warn(msg)elog:error(msg). -
context.scheduler-- Tarefas diferidas e repetitivas comscheduler:run_later(ticks, callback)escheduler:run_repeating(delay, interval, callback). Os callbacks recebem um context novo. Cancele tarefas comscheduler:cancel(taskId). -
context.world-- Interação com o mundo: partículas, sons, consultas de blocos, relâmpagos, entidades próximas. Consulte Prop API para a lista completa de métodos. -
context.zones-- Criação e vigilância de zonas espaciais (esferas, cilindros, cuboides). Consulte Prop API para a lista completa de métodos.
Sintaxe de métodos: : vs .
Em Lua, object:method(arg) é uma abreviação de object.method(object, arg). A API do FMM aceita ambas as formas:
context.log:info("hello")
context.log.info("hello") -- a mesma coisa
Toda a documentação usa : de forma consistente.
Modelos prontos para copiar e colar
Menor script de prop válido
return {
api_version = 1,
on_spawn = function(context)
end
}
Modelo de prop invulnerável
return {
api_version = 1,
on_left_click = function(context)
if context.event then
context.event.cancel()
end
end
}
Modelo de prop interativo
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
}
Layout de ficheiro maior
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
}
Primeiro fluxo de trabalho real
Ao construir um script de prop completamente novo, use esta ordem:
- Crie o ficheiro
.luae façaon_spawnfuncionar. - Adicione o nome do ficheiro de script à config
.ymldo prop. - Mude para o hook que realmente quer (ex.:
on_right_click). - Adicione primeiro uma mensagem de log, antes de animações ou efeitos.
- Adicione um efeito real (animação, som, partícula).
- Só depois disso, adicione funções auxiliares, state, lógica de scheduler ou zonas.
Essa ordem torna a depuração dramaticamente mais fácil porque só uma coisa muda de cada vez.
Scripts predefinidos
O FMM vem com um script Lua predefinido:
invulnerable.lua-- Cancela eventos de dano por clique esquerdo, tornando o prop indestrutível. Este é o script de prop útil mais simples.
Pode encontrar mais exemplos na página Exemplos e padrões.
Lua Sandbox
Os scripts de props executam dentro do mesmo ambiente LuaJ sandboxed que o EliteMobs. As restrições da sandbox são idênticas. Para a lista completa de globais removidos e funções da biblioteca padrão disponíveis, consulte a página EliteMobs Hooks & Lifecycle.
Em resumo:
- Removidos:
debug,dofile,io,load,loadfile,luajava,module,os,package,require - Disponíveis: Todas as funções
math.*,string.*,table.*,pairs,ipairs,type,tostring,tonumber,pcall,printe mais
print escreve na consola do servidor, mas prefira context.log:info(msg) para output. As mensagens de log são prefixadas com o nome do ficheiro de script, facilitando o rastreio de qual script produziu a mensagem.
Próximos passos
- Prop API -- referência completa de
context.prop,context.event,context.world,context.zonesecontext.scheduler - Exemplos e padrões -- scripts completos e funcionais com explicações
- Resolução de problemas -- problemas comuns, dicas de depuração e uma checklist de QC
Se também escreve poderes Lua para o EliteMobs, as APIs partilhadas (context.world, context.zones, context.scheduler, context.state, context.log) funcionam de forma idêntica. Consulte a documentação Lua do EliteMobs para as APIs específicas de bosses.