Scripting Lua: Primeiros Passos
Esta página ensina você a escrever seu primeiro script Lua para um prop do FreeMinecraftModels, de um arquivo vazio até um prop interativo funcional. Ao final, você entenderá hooks, context, a API de props e a forma geral de cada arquivo de script de prop.
Quando estiver confortável com o básico, continue com as páginas complementares:
- API de Props -- as APIs
context.prop,context.event,context.worlde outros contexts - Exemplos e Padrões -- scripts completos e funcionais que você pode estudar e adaptar
- Solução de Problemas -- erros comuns, dicas de depuração e checklist de QC
Scripts Lua para props são atualmente experimentais. Nomes de hooks, métodos auxiliares e comportamentos ainda podem mudar conforme o FreeMinecraftModels evolui, então teste cuidadosamente antes de usá-los em um servidor de produção.
FreeMinecraftModels compartilha o mesmo motor Lua (Magmacore) que o EliteMobs. Se você já escreve poderes Lua para EliteMobs, os conceitos centrais -- hooks, context, api_version, scheduler, zones e o sandbox -- são idênticos. A diferença é:
- Scripts EliteMobs rodam em bosses e têm hooks como
on_boss_damaged_by_player,on_enter_combat, etc. - Scripts FMM rodam 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 documentadas aqui são as versões do FreeMinecraftModels/MagmaCore. Scripts de NPC do EliteMobs usam as mesmas tabelas genéricas do MagmaCore mais context.npc; poderes de boss do EliteMobs usam variantes específicas de boss para várias tabelas. Esta página cobre o que é específico para props e itens do FMM.
O Que São Scripts de Props
Scripts de props são arquivos .lua independentes que ficam na pasta plugins/FreeMinecraftModels/scripts/. Eles são referenciados a partir de um arquivo de configuração YAML que fica ao lado do arquivo de modelo, e rodam sempre que o prop é spawnado no mundo.
Para Que Scripts de Props São Bons
Scripts de props brilham quando você precisa de:
- Props interativos que respondem a cliques de jogadores (portas, alavancas, botões)
- Props decorativos invulneráveis que não podem ser quebrados por jogadores
- Gatilhos de proximidade que detectam quando jogadores entram ou saem de uma área
- Props animados que reproduzem animações por interação ou por timer
- Props emissores de som que tocam sons quando clicados ou quando alguém se aproxima
- Qualquer comportamento de prop que requer lógica além de decoração estática
Se seu prop é puramente decorativo e não precisa de interação, você não precisa de um script.
O Que São Scripts de Item
Scripts de item usam o mesmo formato de arquivo .lua e a mesma pasta scripts/ que scripts de prop. A diferença é que são vinculados a itens customizados -- modelos que têm um campo material: definido no seu arquivo de configuração YML. Enquanto scripts de prop rodam quando uma entidade prop é spawnada no mundo, scripts de item rodam quando um jogador equipa o item customizado (mão principal, mão secundária ou slot de armadura) e param quando o item é desequipado.
Como Scripts de Item Funcionam
- Ativação: Uma instância de script é criada quando um jogador equipa um item customizado do FMM. Scripts são por-jogador por-tipo-de-item -- uma
ScriptInstancepor par (jogador, itemId). - Desativação: A instância de script é destruída quando o item é desequipado (movido para fora do slot ativo, dropado, ou o jogador desconecta).
- Identificação de itens: Itens customizados são identificados pela chave PDC (PersistentDataContainer)
fmm_item_id, que é diferente domodel_iddo prop. Para obter um item com as tags corretas, use/fmm giveitem <id>ou o menu de admin. - Contexto: Hooks de item recebem
contextcomcontext.player,context.item,context.world,context.state,context.scheduler,context.log, e (onde aplicável)context.event.
Para Que Scripts de Item São Bons
Scripts de item brilham quando você precisa de:
- Armas customizadas com habilidades especiais (espadas de gelo, varinhas mágicas)
- Ferramentas com ações únicas de clique direito ou shift+clique
- Itens consumíveis com efeitos customizados
- Armaduras com efeitos passivos enquanto usadas
- Itens que rastreiam uso ou têm durabilidade limitada
- Qualquer comportamento de item segurado além das mecânicas vanilla
Para Quem Esta Página É
Esta página é escrita para três tipos de leitores:
- Alguém que já conhece scripting Lua do EliteMobs e quer aprender os hooks e APIs específicos do FMM
- Alguém que é novo em scripting Lua e precisa de uma referência completa com nomes exatos para props
- Alguém usando IA para redigir scripts de props e precisando de detalhes suficientes para saber quando a IA inventou algo falso
Você não precisa se tornar um desenvolvedor Lua completo antes de escrever scripts úteis para props. Para a maioria dos scripts práticos de props, as únicas coisas que você realmente precisa são:
- Como colocar um hook válido na tabela retornada
- Como ler valores de
context - Como parar antecipadamente com
if ... then return end - Como chamar alguns métodos auxiliares exatamente
Mini Primer de Lua
Você não precisa ser um especialista em Lua para escrever scripts do FMM. A maioria dos scripts usa apenas um punhado de conceitos: variáveis (local x = 5), funções (function foo() end), verificações if (if x then ... end), tabelas ({key = value}) e nil (o valor "nada" do Lua). A sintaxe é leve — sem ponto e vírgula, sem chaves, apenas end para fechar blocos.
Para um passo a passo completo com exemplos, veja o Motor de Scripts Lua do MagmaCore — Mini-introdução ao Lua. Esse primer é compartilhado entre todos os plugins do Nightbreak, então aprendê-lo uma vez vale para todos.
Onde os Arquivos Ficam
Arquivos de Script
Coloque arquivos .lua na pasta central de scripts:
plugins/
FreeMinecraftModels/
scripts/
invulnerable.lua
interactive_door.lua
proximity_sound.lua
O FMM descobre todos os arquivos .lua em plugins/FreeMinecraftModels/scripts/ na inicialização.
Arquivos de Modelo e Arquivos de Configuração
Cada arquivo de modelo pode ter um arquivo de configuração .yml irmão no mesmo diretório:
plugins/
FreeMinecraftModels/
models/
torch_01.fmmodel
torch_01.yml <-- script config for torch_01
scripts/
invulnerable.lua <-- referenced by torch_01.yml
O arquivo de configuração .yml é o que conecta um modelo aos seus scripts.
Formato do Arquivo de Configuração
O arquivo de configuração YAML que fica ao lado de um arquivo de modelo tem estes campos:
isEnabled: true
voxelize: false
solidify: false
scripts:
- invulnerable.lua
Para itens personalizados (modelos que os jogadores podem segurar ou equipar), você também define o campo material e, opcionalmente, name, lore e enchantments:
isEnabled: true
material: DIAMOND_SWORD
name: "&bFrost Blade"
lore:
- "&7A sword forged in eternal ice"
- "&7Slows enemies on hit"
enchantments:
- "SHARPNESS,5"
- "UNBREAKING,3"
scripts:
- frost_sword.lua
| Campo | Tipo | Padrão | Notas |
|---|---|---|---|
isEnabled | boolean | true | Se os scripts estão ativos para este prop/item |
scripts | lista de strings | [] | Nomes de arquivos .lua de scripts na pasta scripts/ |
voxelize | boolean | false | Alinha a colocação a rotações de 90 graus e à grade de blocos |
solidify | boolean | false | Coloca blocos de barreira apenas por pacote na área ocupada pelo prop (requer voxelize) |
material | string | "" | Um nome válido de Bukkit Material (ex.: DIAMOND_SWORD). Definir isso transforma o modelo em um item personalizado que os jogadores podem segurar ou equipar, o que ativa o sistema de scripting de itens |
name | string | "" | Nome de exibição do item personalizado. Suporta códigos de cor & |
lore | lista de strings | [] | Linhas de lore mostradas no tooltip do item. Suporta códigos de cor & |
enchantments | lista de strings | [] | Encantamentos aplicados ao item. Formato: "ENCHANTMENT_NAME,LEVEL" (ex.: "SHARPNESS,5") |
Você pode anexar múltiplos scripts ao mesmo prop. Cada script é sua própria instância independente.
- O ID do item é derivado do nome do arquivo YML sem a extensão. Por exemplo,
frost_sword.ymlproduz um ID de itemfrost_sword. É esse o ID usado por/fmm giveiteme pela chave PDCfmm_item_id. - Itens usam apenas o primeiro script da lista
scripts:. Diferente dos props, que executam todos os scripts listados como instâncias independentes, itens personalizados ignoram quaisquer scripts após a primeira entrada. - A extensão
.luaé anexada automaticamente aos nomes de arquivo de script se você a omitir, entãofrost_swordefrost_sword.luasão equivalentes na listascripts:.
Geração Preguiçosa de Configuração
Quando um prop spawna e nenhum arquivo .yml irmão existe, o FMM cria automaticamente um arquivo de configuração padrão com isEnabled: true e uma lista vazia scripts:. Isso acontece de forma assíncrona, então o prop não terá scripts no seu primeiro spawn -- apenas depois que a configuração é criada e você a edita para adicionar nomes de arquivo de scripts.
Isso significa:
- Coloque seu arquivo de modelo em
models/ - Spawne o prop uma vez (FMM cria o
.ymlautomaticamente) - Edite o
.ymlgerado para adicionar os nomes dos seus scripts - Respawne o prop ou recarregue (scripts agora estão ativos)
Referência de Hooks
Cada arquivo 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 correspondente é disparado.
| Hook | Dispara quando | Notas |
|---|---|---|
on_spawn | O prop é spawnado no mundo | Roda uma vez quando o script é vinculado |
on_game_tick | Uma vez a cada tick do servidor (50 ms) | Apenas ativo se o script definir este hook |
on_destroy | O prop é removido do mundo | Hook de limpeza |
on_left_click | Um jogador clica com botão esquerdo (ataca) o prop | context.event é o evento de dano |
on_right_click | Um jogador clica com 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 em uma zona monitorada | Requer que um monitoramento de zona esteja configurado |
on_zone_leave | Um jogador sai de uma zona monitorada | Requer que um monitoramento de zona esteja configurado |
O validador de scripts atual aceita on_projectile_hit para scripts de prop, mas o runtime atual ainda não despacha impactos de projétil para scripts de prop. Use o on_projectile_hit de item para comportamento de projétil ligado a um item com script, ou a API Bukkit ModeledEntityHitByProjectileEvent para tratamento de projéteis em entidades modeladas do lado do plugin.
Referência de Hooks de Item
Scripts de item retornam uma tabela assim como scripts de prop, com api_version = 1 e funções de hook. Os seguintes hooks estão disponíveis para scripts de item. Todos os hooks de item recebem context com context.player, context.item e (onde aplicável) context.event.
A coluna de notas nomeia a família de eventos Bukkit subjacente. O wrapper Lua não expõe campos brutos específicos do Bukkit como target, block, projectile ou item; use context.player, context.event.player e consultas auxiliares de entidade/mundo quando precisar de contexto extra.
Hooks de Combate
| Hook | Dispara quando | Notas |
|---|---|---|
on_attack_entity | O jogador ataca uma entidade enquanto segura o item | context.event é o evento de dano |
on_kill_entity | O jogador mata uma entidade enquanto segura o item | context.event é o evento de morte |
on_take_damage | O jogador recebe dano enquanto o item está equipado | context.event é o evento de dano |
on_shield_block | O jogador bloqueia dano com um escudo | context.event é o evento de dano |
on_shoot_bow | O jogador dispara um arco | context.event é o evento de disparo de arco |
on_projectile_hit | Um projétil disparado pelo jogador atinge algo | context.event é o evento de impacto de projétil |
on_projectile_launch | O jogador lança um projétil | context.event é o evento de lançamento de projétil |
Hooks de Interação
| Hook | Dispara quando | Notas |
|---|---|---|
on_right_click | O jogador clica com botão direito enquanto segura o item | context.event é o evento de interação |
on_left_click | O jogador clica com botão esquerdo enquanto segura o item | context.event é o evento de interação |
on_shift_right_click | O jogador faz shift+clique direito enquanto segura o item | context.event é o evento de interação |
on_shift_left_click | O jogador faz shift+clique esquerdo enquanto segura o item | context.event é o evento de interação |
on_interact_entity | O jogador clica com botão direito em uma entidade enquanto segura o item | context.event é o evento de interação com entidade |
Hooks de Equipamento
| Hook | Dispara quando | Notas |
|---|---|---|
on_equip | O item é equipado (movido para um slot ativo) | Bom lugar para inicializar estado |
on_unequip | O item é desequipado (movido para fora de um slot ativo) | Bom lugar para limpeza |
on_swap_hands | O jogador troca o item entre mão principal e secundária | context.event é o evento de troca |
on_drop | O jogador dropa o item | context.event é o evento de drop |
Hooks Utilitários
| Hook | Dispara quando | Notas |
|---|---|---|
on_break_block | O jogador quebra um bloco enquanto segura o item | context.event é o evento de quebra de bloco |
on_consume | O jogador consome o item (comida/poção) | context.event é o evento de consumo |
on_item_damage | O item sofre dano de durabilidade | context.event é o evento de dano ao item |
on_fish | O jogador usa uma vara de pescar | context.event é o evento de pesca |
on_death | O jogador morre enquanto o item está equipado | context.event é o evento de morte |
Hook de Ciclo de Vida
| Hook | Dispara quando | Notas |
|---|---|---|
on_game_tick | A cada tick do servidor enquanto o item está equipado | Use com moderação -- roda 20 vezes por segundo |
Contrato Mínimo do Arquivo
Cada script Lua de prop deve return 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 menores rodam primeiro. Padrão 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 arquivo deve retornar uma tabela.
api_versioné obrigatório e atualmente deve ser1.prioritydeve ser numérico se presente.- Cada chave extra de nível superior 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.
Seu Primeiro Script de Prop Funcional, Construído Devagar
Antes do Passo 1: Configure a Configuração
- Coloque seu arquivo de modelo (ex:
my_prop.fmmodel) emplugins/FreeMinecraftModels/models/ - Spawne o prop uma vez para gerar a configuração
.yml - Crie seu arquivo de script em
plugins/FreeMinecraftModels/scripts/first_test.lua - Edite
plugins/FreeMinecraftModels/models/my_prop.yml:
isEnabled: true
scripts:
- first_test.lua
- Respawne o prop ou recarregue o servidor
Passo 1: Faça o Arquivo Carregar
return {
api_version = 1,
on_spawn = function(context)
end
}
Se isso carregar sem erros no console, você provou:
- O arquivo é Lua válido
- O FMM o encontrou na pasta
scripts/ - A configuração o referencia corretamente
- A forma da tabela retornada está correta
Passo 2: Faça o Prop Fazer Uma Coisa 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 o console do servidor. Se você vir a mensagem de log, seu hook está disparando.
Passo 3: Reaja ao Clique de um 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 o console mostrar a mensagem, o hook de clique está funcionando.
Passo 4: Cancele 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 pré-fabricado invulnerable.lua. Ele cancela o evento de dano para que o armor stand de suporte do prop não possa ser destruído.
Passo 5: Reproduza uma Animação ao Clicar
return {
api_version = 1,
on_right_click = function(context)
context.prop:play_animation("open", true, false)
end
}
Isso reproduz a animação "open" no modelo do prop, com blending 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 te entrega cada vez que algo acontece -- ele contém tudo que você precisa para interagir com o prop, o mundo, zonas e mais.
Você não cria context você mesmo -- o FMM o cria e o passa para seu hook. Para detalhes completos sobre as APIs de contexto compartilhadas (context.state, context.log, context.cooldowns, context.scheduler, context.world, context.zones), veja a página Motor de Scripts Lua do MagmaCore.
APIs Principais do context
Aqui está um resumo do que está disponível. Para detalhes completos, veja API de Props.
-
context.prop-- (Apenas scripts de prop) A entidade prop. Fornecemodel_id,current_location,play_animation()estop_animation(). -
context.item-- (Apenas scripts de item) O item personalizado. Forneceid,material(),get_amount(),set_amount(),consume(),get_uses(),set_uses(),get_name(),set_name(),get_lore(),set_lore(),get_durability(),get_durability_percentage(),use_durability()euse_durability_percentage(). Veja API de Props e Itens para detalhes completos. -
context.player-- O jogador nos hooks acionados por jogador. Scripts de item resolvem isso a partir do dono do item; hooks de clique em prop e hooks genéricos de zona resolvem a partir do jogador que acionou. Énilem hooks de ciclo de vida do prop, em callbacks agendados de prop e em hooks que não envolvem um jogador. -
context.event-- Um pequeno wrapper para o evento Bukkit ou o ator jogador que acionou este hook. Disponível em hooks de clique, combate, interação e zona genérica. Forneceevent.player,is_cancellede, quando o evento Bukkit subjacente é cancelável,cancel()/uncancel(); ele não expõe campos específicos do Bukkit comotarget,block,projectileouitem. Énilem hooks que não têm evento nem ator jogador (comoon_spawn,on_game_tickeon_equip). -
context.state-- Uma tabela Lua simples que persiste durante a vida da instância do script. Veja context.state. -
context.cooldowns-- Auxiliares de cooldown local e global. Usecontext.cooldowns:check_local("key", ticks)para cooldowns normais por script. Veja context.cooldowns. -
context.log-- Logging no console. Veja context.log. -
context.scheduler-- Tarefas atrasadas e repetitivas. Veja context.scheduler. -
context.world-- Interação com o mundo: partículas, sons, consultas de blocos, raios, entidades próximas. Veja context.world. -
context.zones-- Crie e monitore zonas espaciais (esferas, cilindros, cuboides). Veja context.zones.
Sintaxe de Método: : vs .
Para uma explicação da sintaxe de método : vs . em Lua, veja a página Motor de Scripts Lua do MagmaCore. Ambas as formas são aceitas pela API do FMM.
Templates Iniciais para Copiar e Colar
Menor Script de Prop Válido
return {
api_version = 1,
on_spawn = function(context)
end
}
Template de Prop Invulnerável
return {
api_version = 1,
on_left_click = function(context)
if context.event then
context.event.cancel()
end
end
}
Template 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
}
Menor Script de Item Válido
return {
api_version = 1,
on_equip = function(context)
end
}
Template de Item com Ação de Clique Direito
return {
api_version = 1,
on_right_click = function(context)
if not context.cooldowns:check_local("activate", 40) then return end
-- Your action here
context.player:send_message("&aItem activated!")
end
}
Layout de Arquivo 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 novo script de prop do zero, use esta ordem:
- Crie o arquivo
.luae façaon_spawnfuncionar. - Adicione o nome do script à configuração
.ymldo prop. - Mude para o hook real que deseja (ex:
on_right_click). - Adicione uma mensagem de log primeiro, antes de animações ou efeitos.
- Adicione um efeito real (animação, som, partícula).
- Só depois disso, adicione auxiliares, state, lógica de scheduler ou zonas.
Essa ordem torna a depuração dramaticamente mais fácil porque apenas uma coisa muda de cada vez.
Scripts Pré-fabricados
O FMM vem com quatro scripts Lua pré-fabricados:
invulnerable.lua-- Cancela eventos de dano de clique esquerdo, tornando o prop indestrutível. Este é o script de prop útil mais simples.pickupable.lua-- Permite que jogadores peguem um prop ao acertá-lo três vezes. Cada acerto reproduz uma animação de dano no prop, e no terceiro acerto o prop é removido e dropa seu item de colocação para o jogador coletar.storage_double.lua-- Transforma um prop em um baú duplo (54 slots). Clicar com o botão direito abre uma GUI de inventário persistente. Reproduz animações e sons de abrir/fechar. O conteúdo é salvo no prop e sobrevive a reinícios do servidor. Ao ser destruído, todo o conteúdo é dropado.storage_single.lua-- Igual aostorage_double, mas com 3 linhas (27 slots) em vez de 6.
Você pode encontrar mais exemplos na página Exemplos e Padrões.
Sandbox Lua
Scripts de props e de itens rodam dentro do mesmo ambiente LuaJ sandboxado que o EliteMobs. As restrições do sandbox são idênticas. Para a lista completa de globais removidos e funções de biblioteca padrão disponíveis, veja a página Motor de Scripting Lua do MagmaCore.
Próximos Passos
- API de Props e Itens -- referência completa de
context.prop,context.item,context.event,context.world,context.zonesecontext.scheduler - Exemplos e Padrões -- scripts completos e funcionais para props e itens, com explicações passo a passo
- Solução de Problemas -- problemas comuns, dicas de depuração e checklist de QC
Se você também escreve poderes Lua de chefe para o EliteMobs, o sandbox, o api_version, a tabela de estado, os conceitos de cooldown e a estrutura orientada a hooks são familiares, mas o contexto de chefe usa nomes de método específicos do EliteMobs. Veja a documentação Lua do EliteMobs para as APIs exatas de chefes.