Scripts Lua: API de elementos decorativos
Esta página cobre as APIs disponíveis nos scripts de elementos decorativos FMM: context.prop, context.event, context.player, context.projectile, context.world, context.zones, context.scheduler, context.state, context.cooldowns e context.log. Se está a começar, consulte primeiro Primeiros passos.
context.prop
A tabela fornece informações sobre o elemento e métodos para controlar as animações. O FMM mantém uma cópia em cache por elemento para reduzir trabalho. Campos como current_location são consultados quando lidos e refletem o estado atual.
Campos
| Campo | Tipo | Notas |
|---|---|---|
prop.model_id | Cadeia | Nome do modelo da definição, como "torch_01" |
prop.current_location | Tabela de posição | Posição atual, consultada ao ler o campo; não é uma cópia fixa |
A tabela de posição contém x, y, z, world, yaw e pitch.
Exemplo: consultar informações do elemento
return {
api_version = 1,
on_spawn = function(context)
context.log:info("Prop spawned: " .. (context.prop.model_id or "unknown"))
local loc = context.prop.current_location
if loc then
context.log:info("Location: " .. loc.x .. ", " .. loc.y .. ", " .. loc.z)
end
end
}
prop:play_animation(name, blend, loop)
Reproduz uma animação pelo nome no modelo do elemento.
| Parâmetro | Tipo | Predefinição | Notas |
|---|---|---|---|
name | Cadeia | Obrigatório | Nome da animação no ficheiro do modelo |
blend | Booleano | true | Com true, aguarda o fim do tick do estado atual; com false, interrompe imediatamente. Não faz uma transição gradual |
loop | Booleano | true | Repetição de uma animação personalizada; os estados integrados usam a sua própria regra |
Devolve true quando aceita o pedido, mesmo que fique em espera ou seja suprimido, e false quando não o pode aceitar. O estado terminal death recusa novos pedidos. Durante uma animação personalizada, um pedido de ataque é aceite sem a interromper. Só cabe um pedido na fila; um novo pedido em espera substitui o anterior. A aceitação não prova reprodução visível. Consulte Animações.
Exemplo
return {
api_version = 1,
on_right_click = function(context)
local success = context.prop:play_animation("open", true, false)
if not success then
context.log:warn("Animation 'open' not found on this model!")
end
end
}
prop:stop_animation()
Limpa os pedidos em espera e regressa a idle, se existir. Caso contrário, termina o estado atual do motor de animação partilhado. O estado terminal death mantém-se, embora a implementação Bedrock receba um pedido de paragem.
Não recebe parâmetros.
Exemplo
return {
api_version = 1,
on_right_click = function(context)
context.prop:stop_animation()
end
}
prop:hurt_visual()
Apresenta o flash vermelho de dano sem causar dano real ao elemento.
Não recebe parâmetros.
Exemplo
return {
api_version = 1,
on_left_click = function(context)
-- Flash red when punched, but don't actually take damage
if context.event then
context.event.cancel()
end
context.prop:hurt_visual()
end
}
prop:pickup()
Remove o elemento do mundo e deixa cair o item de papel de colocação na sua posição. Esse item permite voltar a colocá-lo com um clique direito num bloco.
Não recebe parâmetros nem devolve valores. A remoção e a queda do item são agendadas na thread principal Bukkit. Não verifica permissões nem transfere os dados guardados do inventário ou livro para o papel. Verifique o acesso e trate dos conteúdos guardados antes de recolher o elemento. Não repita pickup() enquanto uma recolha já estiver agendada.
Exemplo
return {
api_version = 1,
on_right_click = function(context)
-- Let players pick up the prop by right-clicking it
context.prop:pickup()
end
}
prop:mount(player)
Monta um jogador no primeiro assento disponível. O modelo precisa de ossos de pontos de montada.
| Parâmetro | Tipo | Notas |
|---|---|---|
player | Tabela de entidade | Jogador, por exemplo de context.player ou context.event.player |
Devolve true quando o jogador foi encontrado, o elemento tem pontos de montada e a ação foi agendada. Devolve false se essas referências não forem válidas. true não garante que exista um assento disponível no momento em que a ação for executada.
Quando um script de clique direito controla os assentos, cancele context.event para impedir que o comportamento predefinido do FMM também tente sentar o jogador.
Exemplo
return {
api_version = 1,
on_right_click = function(context)
if context.event then context.event.cancel() end
local player = context.event and context.event.player
if player then
context.prop:mount(player)
end
end
}
prop:dismount(player)
Retira um jogador do assento no elemento.
| Parâmetro | Tipo | Notas |
|---|---|---|
player | Tabela de entidade | Jogador a desmontar |
Devolve true quando o jogador foi encontrado, o elemento tem um gestor de montadas e a verificação foi agendada. Devolve false se essas referências não forem válidas.
Exemplo
return {
api_version = 1,
on_right_click = function(context)
if context.event then context.event.cancel() end
local player = context.event and context.event.player
if player then
-- Toggle mount/dismount
local passengers = context.prop:get_passengers()
for i = 1, #passengers do
if passengers[i].uuid == player.uuid then
context.prop:dismount(player)
return
end
end
context.prop:mount(player)
end
end
}
prop:get_passengers()
Devolve um vetor Lua de tabelas de entidades com todos os passageiros atuais.
Não recebe parâmetros.
Exemplo
return {
api_version = 1,
on_game_tick = function(context)
local passengers = context.prop:get_passengers()
if #passengers > 0 then
context.log:info("Prop has " .. #passengers .. " passenger(s)")
end
end
}
prop:has_mount_points()
Indica se o modelo tem ossos de pontos de montada.
Não recebe parâmetros. Devolve true ou false.
Exemplo
return {
api_version = 1,
on_right_click = function(context)
if context.event then context.event.cancel() end
local player = context.event and context.event.player
if player and context.prop:has_mount_points() then
context.prop:mount(player)
end
end
}
prop:spawn_elitemobs_boss(filename, x, y, z)
Cria um boss personalizado EliteMobs na posição indicada. Exige EliteMobs instalado.
| Parâmetro | Tipo | Notas |
|---|---|---|
filename | Cadeia | Ficheiro do boss, como "my_boss.yml" |
x | Número | Coordenada X |
y | Número | Coordenada Y |
z | Número | Coordenada Z |
Devolve uma tabela de entidade viva para o boss criado, ou nil quando a integração não consegue devolver um boss vivo. Isso inclui plugin indisponível, configuração em falta ou falha na criação. nil não identifica a causa.
Exemplo
return {
api_version = 1,
on_right_click = function(context)
local loc = context.prop.current_location
if loc then
local boss = context.prop:spawn_elitemobs_boss("dungeon_guardian.yml", loc.x, loc.y + 1, loc.z)
if boss then
context.log:info("Spawned boss: " .. (boss.name or "unknown"))
else
context.log:warn("Could not spawn boss -- is EliteMobs installed?")
end
end
end
}
prop:open_inventory(player, title, rows)
Agenda a abertura de um inventário de baú para o jogador. Cada elemento tem um único inventário partilhado: a primeira abertura constrói-o a partir dos dados guardados no PersistentDataContainer do elemento, e as aberturas seguintes mostram esse mesmo inventário em tempo real a todos os jogadores. O FMM guarda-o de volta no elemento quando o último jogador o fecha, quando o chunk do elemento é descarregado e antes de drop_inventory() o ler.
| Parâmetro | Tipo | Predefinição | Notas |
|---|---|---|---|
player | Tabela de entidade | Obrigatório | Jogador a quem mostrar o inventário |
title | Cadeia | Obrigatório | Título; aceita códigos de cor & |
rows | Inteiro | 3 | De 1 a 6 linhas; 6 equivalem a 54 posições, um baú duplo |
Devolve true se as referências do elemento e jogador forem válidas e a abertura tiver sido agendada; caso contrário, false. O número de linhas é limitado ao intervalo 1–6 antes de criar o inventário.
O tamanho e o título vêm da chamada que constrói o inventário; enquanto estiver aberto, as chamadas seguintes reutilizam-no tal como está. Quando o conteúdo guardado ocupa mais posições do que as linhas pedidas, o inventário cresce para as acomodar, pelo que um valor rows menor nunca descarta itens guardados. Se os dados guardados não puderem ser lidos, o inventário não abre. A ação é ignorada se o elemento tiver sido removido antes de ser executada. true não garante que o inventário tenha aberto.
prop:is_viewing_inventory(player)
Indica se o listener de inventário acompanha o jogador como utilizador deste elemento. Não garante que a interface continue realmente aberta.
| Parâmetro | Tipo | Notas |
|---|---|---|
player | Tabela de entidade | Jogador a verificar |
Devolve true ou false.
Exemplo: animação ao fechar o inventário
context.state["task_" .. player.uuid] = context.scheduler:run_repeating(5, 5, function(tick_context)
if not tick_context.prop:is_viewing_inventory(player) then
tick_context.prop:play_animation("close", true, false)
tick_context.scheduler:cancel(tick_context.state["task_" .. player.uuid])
end
end)
prop:place_book(player)
Retira o livro escrito ou editável da mão principal do jogador e guarda-o no elemento.
| Parâmetro | Tipo | Notas |
|---|---|---|
player | Tabela de entidade | Jogador com o livro na mão |
Devolve true se as referências forem válidas e a ação tiver sido agendada. A ação posterior, na thread principal, só coloca o livro se o jogador tiver um livro editável ou escrito e o elemento ainda não tiver um.
prop:read_book(player)
Abre o livro guardado para o jogador ler.
| Parâmetro | Tipo | Notas |
|---|---|---|
player | Tabela de entidade | Jogador a quem mostrar o livro |
Devolve true se as referências forem válidas e a leitura tiver sido agendada. A ação posterior exige um WRITTEN_BOOK guardado e desserializável. Um WRITABLE_BOOK guardado não é aberto.
prop:take_book(player)
Devolve o livro guardado ao inventário do jogador e remove-o do elemento.
| Parâmetro | Tipo | Notas |
|---|---|---|
player | Tabela de entidade | Jogador que recebe o livro |
Devolve true se as referências forem válidas e a ação tiver sido agendada. Não garante que exista um livro guardado.
Garanta espaço livre no inventário do jogador. O registo guardado é removido antes de adicionar o livro; os itens que não couberem não são deixados cair. place_book serializa toda a pilha da mão e depois retira um item. Use livros individuais normais.
prop:has_book()
Verifica apenas se existe a chave do livro no PDC do suporte de armadura. Não valida o conteúdo serializado. Não recebe parâmetros.
prop:drop_inventory()
Agenda a gravação do inventário aberto, se existir, e o seu fecho para todos os jogadores; depois lê o conteúdo guardado, remove o registo do PDC e deixa cair os itens na posição do elemento. As alterações feitas no inventário aberto até esse momento são incluídas. Uma falha de descodificação após a remoção do registo pode não deixar itens para cair.
Não recebe parâmetros. Devolve true se o suporte de armadura for válido e a ação tiver sido agendada. Não garante que existam itens guardados.
prop:drop_book()
Agenda a queda do livro guardado na posição do elemento. A ação remove o registo antes de descodificar; uma falha de descodificação pode perder o livro.
Não recebe parâmetros. Devolve true se o suporte de armadura for válido e a ação tiver sido agendada. Não garante que exista um livro guardado.
prop:set_persistent_data(key, value)
Guarda uma cadeia de texto no PersistentDataContainer do suporte de armadura. Os dados acompanham esse suporte durante a gravação normal do mundo e o descarregamento de chunks. Remover definitivamente o elemento ou substituí-lo por um papel de colocação não transfere esses dados.
| Parâmetro | Tipo | Notas |
|---|---|---|
key | Cadeia | Sufixo de chave Bukkit válido, com letras minúsculas, algarismos e ._-/. Guardado como fmm_lua_<key>; caracteres inválidos provocam um erro |
value | Cadeia | Valor a guardar. Use tostring() para números e booleanos |
Devolve true em caso de sucesso e false se não houver suporte de armadura.
prop:get_persistent_data(key)
Lê uma cadeia guardada por set_persistent_data. Devolve nil se a chave não tiver sido definida.
| Parâmetro | Tipo | Notas |
|---|---|---|
key | Cadeia | Chave usada em set_persistent_data |
Exemplo: estado alternável persistente
return {
api_version = 1,
on_spawn = function(context)
local saved = context.prop:get_persistent_data("active")
context.state.active = saved == "true"
end,
on_right_click = function(context)
context.state.active = not context.state.active
context.prop:set_persistent_data("active", tostring(context.state.active))
end
}
Efeitos de itens
A API context.item de itens equipados foi removida. Defina efeitos com encantamentos personalizados e associe-os pela lista enchantments: do item, com espaço de nomes.
context.event
Dados do evento atual, disponíveis em cliques, impactos de projéteis e eventos genéricos de zonas. É nil quando não há evento nem jogador associado, como em on_spawn, on_game_tick e on_destroy.
Os cliques FMM usam uma opção própria de cancelamento do comportamento predefinido. A tabela Lua expõe apenas os campos e métodos aqui indicados.
Campos e métodos
| Campo ou método | Tipo | Notas |
|---|---|---|
event.player | Tabela de jogador | Jogador que clicou ou atravessou a fronteira da zona. Disponível em on_left_click, on_right_click, on_zone_enter e on_zone_leave. Em on_projectile_hit é a entidade viva que disparou o projétil, que pode ser um mob, e está ausente quando o atirador não é uma entidade viva. Consulte Métodos de jogadores |
event.is_cancelled | Booleano | Estado de cancelamento quando o contexto foi construído. Não é atualizado após cancel() ou uncancel() |
event.cancel() | Função | Cancela o evento, por exemplo, para impedir o dano ou interação |
event.uncancel() | Função | Retira o cancelamento de um evento |
cancel e uncancel ignoram os argumentos recebidos. Assim, context.event.cancel() e context.event:cancel() são equivalentes. Esta página usa ponto; ambas as formas funcionam.
Os eventos genéricos de zona fornecem um jogador, sem opção de cancelamento. Nesses eventos não existem event.cancel() nem event.uncancel(), e event.is_cancelled é false. Nos cliques, o cancelamento impede a ação predefinida correspondente do FMM.
Trate event.is_cancelled como uma cópia do estado inicial. Se chamar cancel() ou uncancel() e precisar de recordar a alteração na mesma função, guarde um indicador local.
A tabela não expõe campos específicos Bukkit como target, block, projectile ou item. Para contexto adicional, use context.player, context.event.player, context.projectile (em on_projectile_hit), player:get_target_entity(range), context.world:raycast(...) ou consultas de entidades próximas.
on_projectile_hit
É acionado quando um projétil atinge a hitbox do elemento, uma vez por projétil.
| Valor do contexto | Notas |
|---|---|
context.projectile | Tabela de entidade do projétil (flecha, tridente, bola de neve, etc.). Só é definido neste evento |
context.event.player | A entidade viva que disparou o projétil, se existir |
context.player | O atirador quando é um jogador; caso contrário, nil |
O evento é executado depois de o FMM ter tratado o impacto, e o tratamento predefinido de projéteis do FMM não faz nada nos elementos decorativos. Chamar context.event.cancel() aqui não impede que um projétil não perfurante seja consumido pelo impacto. O evento não é acionado quando outro plugin já cancelou o impacto.
return {
api_version = 1,
on_projectile_hit = function(context)
local shooter = context.player
if shooter then
shooter:send_message("&eYou hit the target!")
end
context.prop:play_animation("hit", false, false)
end
}
Exemplo: cancelar dano do clique esquerdo
Exemplo
return {
api_version = 1,
on_left_click = function(context)
if context.event then
context.event.cancel()
end
end
}
Exemplo: consultar o estado de cancelamento
Exemplo
return {
api_version = 1,
on_left_click = function(context)
if context.event and not context.event.is_cancelled then
context.event.cancel()
context.log:info("Damage cancelled!")
end
end
}
Nas funções agendadas de scheduler:run_later e scheduler:run_repeating, context.event é sempre nil. Só pode modificar o evento durante a própria função que o trata.
context.world
Esta é a API do mundo FreeMinecraftModels/MagmaCore. Consulte context.world para a referência completa.
Todos os métodos da página global estão disponíveis no FMM: get_block_at, set_block_at, spawn_particle, play_sound, strike_lightning, get_time, set_time, get_nearby_entities, get_nearby_players, spawn_entity, get_highest_block_y, raycast, place_temporary_block, drop_item e spawn_firework. Consulte a API do mundo MagmaCore para world:raycast(), que deteta entidades e blocos ao longo de um raio, world:place_temporary_block(), que substitui blocos temporariamente, e world:spawn_firework(), que cria fogos de artifício personalizados. Os poderes de bosses EliteMobs partem da mesma base e acrescentam métodos com tabelas de posição para bosses, reforços, blocos em queda, blocos temporários e outras operações. Consulte Mundo e ambiente EliteMobs.
Adições ao mundo específicas do FMM
O FreeMinecraftModels acrescenta três auxiliares opcionais de saque EliteMobs a context.world. Estão sempre presentes, mas devolvem false sem fazer nada se o EliteMobs não estiver instalado:
| Método | Notas |
|---|---|
world:drop_elitemobs_procedural_loot(player, level, location?) | Gera saque procedural EliteMobs. Respeita a configuração de entrega direta ao inventário, deixando cair junto do jogador o que não couber; caso contrário, usa a posição escolhida. Devolve false se esse tipo de saque estiver desativado |
world:drop_elitemobs_random_loot(player, level, location?) | Sorteia as tabelas de saque EliteMobs para o jogador ao nível indicado |
world:drop_elitemobs_custom_loot(player, file, level, location?) | Deixa cair um item personalizado EliteMobs específico. Devolve false se o ficheiro não for encontrado |
As assinaturas completas estão na Referência da API Lua. Para criar bosses através do elemento, use prop:spawn_elitemobs_boss(...), descrito acima.
Métodos de jogadores
As tabelas de jogadores vêm de context.player, context.event.player e context.world:get_nearby_players(). Os eventos genéricos MagmaCore on_zone_enter e on_zone_leave colocam o jogador que entrou ou saiu em ambos os campos do contexto.
O FMM usa as tabelas de entidades, métodos de entidades vivas, métodos específicos de jogadores e métodos de interface descritos na página global. Os poderes EliteMobs expõem tabelas semelhantes, mas específicas de bosses, em Bosses e entidades. Consulte Motor de scripts Lua do MagmaCore para os campos e métodos das entidades e jogadores, incluindo Métodos de interface para jogadores. Os métodos novos incluem player:get_target_entity() para selecionar alvos por raio, player:get_eye_location(), player:get_look_direction(), player:send_block_change() para blocos falsos por jogador e player:reset_block(). Consulte Métodos específicos de jogadores.
Campos de entidades específicos do FMM
Todas as tabelas de entidades criadas num script FMM recebem automaticamente estes campos através de LuaEntityEnricher. Os indicadores e a referência ao modelo são cópias do momento de construção da tabela. Obtenha uma nova tabela após alterar o modelo associado. has_permission consulta as permissões atuais do jogador; is_op é uma cópia fixa.
| Campo | Tipo | Notas |
|---|---|---|
entity.is_modeled | Booleano | true se a entidade Bukkit for a entidade subjacente de uma ModeledEntity |
entity.is_prop | Booleano | true se for um suporte de armadura de uma PropEntity |
entity.model | Tabela ou nil | Preenchido apenas com is_modeled = true |
Quando existe, entity.model disponibiliza:
| Campo ou método | Notas |
|---|---|
model.model_id | Nome do modelo da definição, como "dragon" |
model.is_dynamic | true para uma DynamicEntity, ligada a uma entidade viva |
model:play_animation(name, blend, loop) | Pede uma animação. Nesta integração, blend e loop têm predefinição false. true significa pedido aceite, sem provar reprodução visível |
model:stop_animations() | Limpa a reprodução em espera e regressa a idle se existir; não interrompe a morte terminal |
model:remove() | Remove imediatamente a entidade com modelo e todos os ossos |
on_right_click = function(context)
local player = context.event and context.event.player
if not player then return end
local target = player:get_target_entity(8)
if target and target.is_modeled then
target.model:play_animation("hurt", true, false)
end
end
Campos de entidades EliteMobs
Com EliteMobs instalado, o FMM também usa o seu enriquecimento de entidades para acrescentar:
| Campo | Tipo | Notas |
|---|---|---|
entity.is_elite | Booleano | true se a entidade for acompanhada pelo EliteMobs |
entity.is_custom_boss | Booleano | true se usar uma configuração de boss personalizado |
entity.is_significant_boss | Booleano | true para bosses personalizados com healthMultiplier > 1, excluindo mobs comuns com nome |
entity.elite | Tabela ou nil | Preenchido apenas com is_elite = true. Contém level, name, health, max_health, health_multiplier, damage_multiplier, is_custom_boss e elite:remove() |
Os indicadores e a maioria dos campos elite são cópias fixas; health e max_health são consultados ao ler. Com EliteMobs ativo, entity:can_receive_hostile_effect(player_uuid) também aplica a autorização de alvos mágicos do EliteMobs depois da verificação partilhada de alvos hostis. Se o adaptador estiver indisponível, a verificação recusa o alvo em vez de tratar aliados como alvos independentes.
context.zones
Esta é a API de zonas FreeMinecraftModels/MagmaCore. Consulte context.zones. Os poderes de bosses usam outra tabela, com definições nativas de zonas EliteMobs; consulte Zonas e seleção de alvos EliteMobs.
context.scheduler
É o agendador MagmaCore usado pelos scripts FMM e NPC EliteMobs. Os nomes de estilo EliteMobs run_after, run_every e cancel_task são aliases do agendador partilhado, pelo que ambos os estilos funcionam. Os poderes de bosses expõem os mesmos aliases através do contexto próprio. Consulte context.scheduler.
context.state
A API de estado é partilhada pelos scripts FMM, poderes de bosses e scripts de NPC EliteMobs. Consulte context.state.
context.log
O registo FreeMinecraftModels/MagmaCore oferece info, warn e error. Os NPC EliteMobs usam o mesmo registo; os poderes de bosses expõem info, warn e debug. Consulte context.log.
context.cooldowns
A API usa a ordem partilhada MagmaCore/FMM, também usada pelos NPC EliteMobs: check_local(key?, duration). Os poderes de bosses usam a mesma ordem de argumentos, com armazenamento próprio. Consulte context.cooldowns.
| Método | Notas |
|---|---|
local_ready(key?) | Verifica se o tempo de recarga local terminou |
local_remaining(key?) | Devolve os ticks restantes ou 0 |
check_local(key?, duration) | Verifica e inicia atomicamente um tempo de recarga local |
set_local(duration, key?) | Define um tempo de recarga local sem verificar |
global_ready() | Consulta o tempo de recarga global partilhado do proprietário do script |
set_global(duration) | Define esse tempo de recarga global |
Use context.cooldowns:check_local("my_key", 40) para limitar a frequência normal de ações do elemento.
Modelo de execução
Um ambiente por instância de script
Cada entrada na lista scripts: de um elemento recebe um ambiente Lua independente. O FMM descobre e valida o código ao registar o fornecedor, depois avalia o código em cache num ambiente isolado novo para cada associação. Alterar ou adicionar um ficheiro Lua exige um recarregamento bem-sucedido antes de novas associações o usarem. As funções dos scripts executam pela ordem da lista configurada; o valor priority é lido mas não altera essa ordem. Ao remover o elemento, as suas instâncias de scripts são encerradas.
Os encantamentos de itens têm um ciclo de vida separado; não criam uma instância de script de elemento decorativo para um item equipado.
Assim:
- As variáveis locais declaradas ao nível do ficheiro são privadas da instância.
context.stateé completamente isolado entre instâncias, mesmo usando o mesmo ficheiro.
Responsabilidade pelas tarefas agendadas
Todas as tarefas de context.scheduler pertencem ao ambiente que as criou. Ao remover o elemento:
- O ambiente é encerrado.
- Todas as suas tarefas, únicas ou repetidas, são canceladas automaticamente.
- Todas as observações de zonas são limpas.
on_destroy só é executado primeiro quando o elemento é removido definitivamente: recolhido, partido, eliminado com /fmm deleteall ou removido por um plugin. Quando o chunk ou o mundo do elemento é descarregado, ou quando o FMM recarrega ou encerra, o ambiente termina sem chamar on_destroy. O elemento regressa com um novo ambiente, e um novo on_spawn, quando o seu chunk volta a carregar.
Âmbito dos tempos de recarga
O motor partilhado oferece auxiliares locais local_ready, local_remaining, check_local e set_local, e globais global_ready e set_global. No FMM, o armazenamento tem este âmbito:
| Tipo de script | Armazenamento local | Armazenamento global |
|---|---|---|
| Elemento decorativo | Por ScriptInstance, elemento e ficheiro de script | Por PropEntity, partilhado por todos os scripts associados ao elemento |
Os tempos de recarga globais são limpos ao retirar o registo do elemento ou encerrar o gestor durante um recarregamento bem-sucedido ou desativação. Uma preparação de recarregamento rejeitada mantém o ambiente atual. As durações usam tempo decorrido monotónico, com 50 ms por tick pedido. Os atrasos do agendador seguem ticks do servidor; podem divergir quando há atraso no servidor.
Limites de execução
Cada evento, função agendada e avaliação inicial de ficheiro tem um limite rígido. É imposto dentro da máquina virtual Lua, durante a execução.
| Limite | Valor |
|---|---|
| Tempo de CPU da thread atual | 50 milissegundos |
| Instruções Lua executadas | 250 000 |
O primeiro limite atingido interrompe a chamada com um erro Lua e desativa a instância. As mensagens são:
Lua instruction budget exceeded (250000 instruction limit)
Lua CPU-time budget exceeded (50ms current-thread CPU limit)
O contador de instruções limita ciclos exclusivamente Lua, como while true do end. O tempo é verificado a cada 1 024 instruções Lua e no regresso da chamada. O mecanismo não interrompe um método Java/Bukkit bloqueante enquanto este está a executar.
O tempo medido é o de CPU da thread atual. O script não é penalizado pelo tempo em que a thread do servidor não esteve a executar. Se a JVM não disponibilizar essa medição, o MagmaCore usa 250 milissegundos de tempo decorrido, com Lua elapsed-time fallback budget exceeded (250ms fallback; current-thread CPU time unavailable), mantendo o limite de 250 000 instruções.
As chamadas aninhadas partilham uma quota única. Se um evento chamar uma função que chama outra, toda a cadeia tem 50 ms de CPU ou 250 000 instruções.
A avaliação durante a descoberta do fornecedor rejeita definições inválidas antes do registo. O código em cache volta a ser avaliado para cada nova instância, com os mesmos limites.
Para respeitar os limites:
- Evite ciclos sem limite nos eventos.
- Mantenha
on_game_tickleve, pois executa em cada tick. - Distribua o trabalho por ticks com
context.scheduler:run_repeating(...).
Referência completa de eventos
A tabela seguinte contém os eventos ativos de elementos decorativos.
A coluna context.event descreve a opção de cancelamento FMM ou o jogador da zona. A tabela Lua expõe event.player, event.is_cancelled, event.cancel() e event.uncancel() quando aplicáveis.
Oito eventos ativos de elementos decorativos
| Evento | Quando ocorre | context.event |
|---|---|---|
on_spawn | Criação no mundo ou novo carregamento com o seu chunk | nil |
on_game_tick | Cada tick do servidor, 50 ms a 20 TPS | nil |
on_destroy | Remoção definitiva do elemento (não ao descarregar o chunk nem ao recarregar) | nil |
on_left_click | Clique esquerdo de um jogador | Opção de cancelamento do dano predefinido |
on_right_click | Clique direito de um jogador | Opção de cancelamento da interação predefinida |
on_zone_enter | Entrada de um jogador numa zona observada | Jogador em context.player / context.event.player; não cancelável |
on_zone_leave | Saída de um jogador de uma zona observada | Jogador em context.player / context.event.player; não cancelável |
on_projectile_hit | Um projétil atinge o elemento | Evento de impacto de projétil; event.player é o atirador. Consulte on_projectile_hit |
Efeitos de itens
Use Encantamentos personalizados para efeitos de itens de mão. A antiga tabela de 22 eventos de itens já não descreve um sistema em execução.
Próximos passos
- Exemplos e padrões: scripts de elementos decorativos, com explicações e notas de configuração.
- Resolução de problemas: problemas comuns, diagnóstico e verificação de qualidade.
- Primeiros passos: ficheiros, eventos e primeiro script.
Transporte EliteMobs
context.world:start_elitemobs_transport(player, route_id) inicia uma rota guardada do EliteMobs para um jogador no mundo do contexto. Devolve se o pedido foi aceite e exige EliteMobs com essa rota carregada. O ID não inclui .yml. Consulte Rotas de transporte.