Pular para o conteúdo principal

API e Guia do Desenvolvedor do FreeMinecraftModels

FreeMinecraftModels é tanto um plugin standalone quanto uma superfície de API para outros plugins.

Repositório Maven

<repository>
<id>magmaguy-repo-releases</id>
<name>MagmaGuy's Repository</name>
<url>https://repo.magmaguy.com/releases</url>
</repository>
<repository>
<id>magmaguy-repo-snapshots</id>
<name>MagmaGuy's Snapshot Repository</name>
<url>https://repo.magmaguy.com/snapshots</url>
</repository>

Dependência

<dependency>
<groupId>com.magmaguy</groupId>
<artifactId>FreeMinecraftModels</artifactId>
<version>LATEST.VERSION.HERE</version>
<scope>provided</scope>
</dependency>

Use como compileOnly/provided. Não faça shade do plugin no seu próprio jar.

Pontos de Entrada Principais

  • ModeledEntityManager.modelExists(String)
  • ModeledEntityManager.reload()
  • ModeledEntityManager.getAllEntities()
  • ModeledEntityManager.getDynamicEntities()
  • ModeledEntityManager.propEntities()

Tipos de Runtime Principais

  • ModeledEntity
  • StaticEntity
  • DynamicEntity
  • PropEntity

Criando Entidades

StaticEntity preview = StaticEntity.create("example_model", location);
DynamicEntity mobModel = DynamicEntity.create("example_model", livingEntity);
DynamicEntity mount = DynamicEntity.createWithInvisibility("example_model", livingEntity);
PropEntity prop = PropEntity.spawnPropEntity("example_model", location);

Todos os caminhos de criação retornam null se o ID do modelo solicitado não estiver carregado.

createWithInvisibility é uma variante que aplica uma poção de invisibilidade em vez de esconder a entidade dos clientes. Isso mantém a entidade rastreada no lado do cliente, o que é necessário para a direção de veículos (usado internamente por /fmm mount).

Métodos Úteis de Runtime

  • ModeledEntity#setDisplayName(String)
  • ModeledEntity#setDisplayNameVisible(boolean)
  • ModeledEntity#setLeftClickCallback(...)
  • ModeledEntity#setRightClickCallback(...)
  • ModeledEntity#setHitboxContactCallback(...)
  • ModeledEntity#setModeledEntityHitByProjectileCallback(...)
  • ModeledEntity#playAnimation(String, boolean, boolean)
  • ModeledEntity#stopCurrentAnimations()
  • ModeledEntity#hasAnimation(String)
  • ModeledEntity#getEntityID() -- retorna a string do ID do modelo
  • ModeledEntity#getLocation() -- retorna a Location atual
  • ModeledEntity#getWorld() -- retorna o World
  • ModeledEntity#getViewers() -- retorna o HashSet<UUID> de jogadores que podem ver a entidade
  • ModeledEntity#getNametagBones() -- retorna List<Bone> de bones de nametag (útil para colocar texto adicional)
  • ModeledEntity#getScaleModifier() / setScaleModifier(double)
  • ModeledEntity#removeWithDeathAnimation() -- remove com a animação de morte (se existir)
  • ModeledEntity#removeWithMinimizedAnimation() -- remove com uma animação de redução de escala
  • ModeledEntity#remove() -- remove imediatamente a entidade e todos os bones
  • DynamicEntity#setSyncMovement(boolean)
  • DynamicEntity#isDamagesOnContact() / setDamagesOnContact(boolean) -- controla se a entidade causa dano a jogadores via contato de hitbox
  • Bone#getBoneLocation()

Superfície de Eventos

Eventos de interação genéricos:

  • ModeledEntityLeftClickEvent
  • ModeledEntityRightClickEvent
  • ModeledEntityHitboxContactEvent
  • ModeledEntityHitByProjectileEvent

Variantes tipadas também existem para StaticEntity, DynamicEntity e PropEntity.

Evento de ciclo de vida:

  • ResourcePackGenerationEvent -- dispara quando o FMM termina de gerar ou regenerar o resource pack (na inicialização e no /fmm reload). Ouça este evento para acionar pós-processamento no pack gerado.

ModeledEntityHitByProjectileEvent e Detecção de Projéteis com OBB

FMM usa detecção de acerto OBB (caixa delimitadora orientada) para projéteis contra entidades modeladas. Quando um projétil intersecta a hitbox OBB de uma entidade modelada, FMM dispara um ModeledEntityHitByProjectileEvent. Este é um evento Bukkit cancelável padrão.

Detalhes chave:

  • O dano de flechas é calculado com suporte ao bônus do encantamento POWER
  • O encantamento PIERCING é respeitado -- flechas podem atravessar para alvos adicionais
  • Cancele o evento para prevenir o dano e bloquear o acerto completamente
@EventHandler
public void onProjectileHitModel(ModeledEntityHitByProjectileEvent event) {
ModeledEntity target = event.getModeledEntity();
Projectile projectile = event.getProjectile();
// Cancelar para prevenir dano
event.setCancelled(true);
}

Utilitários de Itens e Modelos

ModelItemFactory

Classe factory para criar ItemStacks relacionados a modelos programaticamente.

// Criar um item de colocação de prop (usa chave PDC "model_id")
ItemStack placementItem = ModelItemFactory.createModelItem("lamp_post", Material.STICK);

// Criar um item personalizado a partir da configuração (usa chave PDC "fmm_item_id")
PropScriptConfigFields config = ItemScriptManager.getItemDefinitions().get("magic_sword");
ItemStack customItem = ModelItemFactory.createCustomItem("magic_sword", config);
  • createModelItem(String modelId, Material material) -- cria um item de colocação para props. Em 1.21.4+, aplica automaticamente a renderização de display model se um JSON de display existir.
  • createCustomItem(String itemId, PropScriptConfigFields config) -- cria um item personalizado com nome, lore, encantamentos e display model da configuração unificada.
  • formatModelName(String modelId) -- utilitário que converte um ID de modelo como 01_em_flame_sword em Flame Sword.

DisplayModelRegistry

Registro simples que rastreia quais modelos têm um JSON de display disponível.

// Verificar se um modelo tem um JSON de display model registrado
boolean has3D = DisplayModelRegistry.hasDisplayModel("magic_sword");
  • register(String modelId) -- registra um ID de modelo (chamado internamente durante o reload)
  • hasDisplayModel(String modelId) -- retorna true se um .json de display model existir para este modelo
  • getRegisteredModels() -- retorna um Set<String> imutável de todos os IDs de modelo que possuem display models registrados
  • shutdown() -- limpa todos os registros

ItemScriptManager

Gerencia o ciclo de vida de scripts Lua por jogador para itens personalizados (modelos com material: definido em sua configuração YML).

// Obter todas as definições de itens personalizados registradas
Map<String, PropScriptConfigFields> items = ItemScriptManager.getItemDefinitions();

// Obter a instância de script Lua ativa para um jogador + item
ScriptInstance instance = ItemScriptManager.getActiveScript(playerUUID, "magic_sword");

// Obter todos os scripts ativos para um jogador
Map<String, ScriptInstance> scripts = ItemScriptManager.getActiveScripts(playerUUID);
  • scanForCustomItems(File modelsFolder) -- escaneia configurações YML de modelos em busca de itens personalizados
  • updateEquippedScripts(Player player) -- compara itens equipados com scripts em execução, disparando hooks de equipar/desequipar
  • removePlayer(Player player) -- encerra todos os scripts para um jogador (chamar ao desconectar)
  • getItemDefinitions() -- retorna o mapa de ID de item para PropScriptConfigFields

ScriptedItemAPI

API pública para plugins externos se integrarem com o sistema de itens com script do FMM. Isso permite que outros plugins marquem seus próprios ItemStacks com dados de itens com script do FMM (tag PDC + modelo de item) para que os hooks de script Lua do FMM disparem para esses itens, sem que o FMM sobrescreva o nome, lore ou encantamentos do item.

// Verificar se uma definição de item com script existe
boolean exists = ScriptedItemAPI.isValidItemId("flame_blade");

// Aplicar dados de item com script do FMM a um ItemStack existente
// Isso define:
// - A tag PDC fmm_item_id (para que o sistema de script do FMM reconheça o item)
// - O modelo de item (1.21.4+) do registro de display model do FMM
// NÃO modifica nome, lore, encantamentos ou qualquer outra propriedade do item.
boolean success = ScriptedItemAPI.applyScriptedItemData(itemStack, "flame_blade");

// Obter a configuração de um item com script
PropScriptConfigFields config = ScriptedItemAPI.getItemConfig("flame_blade");
  • isValidItemId(String itemId) -- retorna true se o ID do item estiver registrado nas definições de itens do FMM
  • applyScriptedItemData(ItemStack itemStack, String itemId) -- marca a tag PDC e o modelo de item em um ItemStack existente. Retorna true em caso de sucesso, false se o ID do item for inválido ou o ItemStack não tiver meta. Nota para arco/besta: se o itemId dado não tiver um display model mas itemId + "_idle" tiver (ou seja, o item tem modelos de estado de arco/besta), o método automaticamente usa o modelo _idle como display model
  • getItemConfig(String itemId) -- retorna o PropScriptConfigFields para o ID de item dado, ou null se não encontrado
Integração com EliteMobs

EliteMobs usa esta API internamente através do campo de configuração scriptedItem. Quando um item personalizado do EliteMobs define scriptedItem: flame_blade, EliteMobs constrói seu item normalmente (nome, lore, encantamentos, nível) e então chama ScriptedItemAPI.applyScriptedItemData() para adicionar o modelo e comportamento de script do FMM por cima.

PropScriptConfigFields

Classe de configuração unificada para arquivos de configuração YML de modelos. Usada tanto por scripts de props quanto por itens personalizados.

# Exemplo: torch_01.yml
isEnabled: true
scripts:
- torch_glow.lua
material: STICK # Se definido, modelo se torna um item personalizado
name: "&eMagic Torch" # Nome de exibição personalizado (opcional)
lore: # Linhas de lore personalizadas (opcional)
- "&7Glows in the dark"
enchantments: # Encantamentos (opcional, formato: NAME,LEVEL)
- "FIRE_ASPECT,1"

Métodos chave: isCustomItem(), getParsedMaterial(), getParsedEnchantments(), getScripts().

Scripting Lua

FreeMinecraftModels suporta scripts Lua tanto para props quanto para itens personalizados através do motor de scripting MagmaCore 2.0. Arquivos de script são colocados em plugins/FreeMinecraftModels/scripts/ e são vinculados a modelos via um arquivo de configuração YML irmão ao lado do arquivo de modelo.

Hooks de Scripts de Props

HookAcionamento
on_spawnProp é spawnado no mundo
on_game_tickA cada tick enquanto o prop está vivo
on_zone_enterUm jogador entra na zona do prop
on_zone_leaveUm jogador sai da zona do prop
on_destroyProp é removido
on_left_clickJogador clica com botão esquerdo no prop
on_right_clickJogador clica com botão direito no prop
on_projectile_hitUm projétil atinge o prop

Hooks de Scripts de Itens

Itens personalizados (modelos com material: definido) suportam 22 hooks Lua:

HookAcionamento
on_equipItem entra em um slot de equipamento rastreado
on_unequipItem sai de um slot de equipamento rastreado
on_game_tickA cada tick enquanto o item está equipado
on_attack_entityJogador ataca uma entidade enquanto segura o item
on_kill_entityJogador mata uma entidade enquanto segura o item
on_take_damageJogador recebe dano enquanto item está equipado
on_shield_blockJogador bloqueia com um escudo
on_shoot_bowJogador dispara um arco
on_projectile_hitUm projétil disparado pelo jogador atinge algo
on_projectile_launchJogador lança um projétil
on_right_clickJogador clica com botão direito com o item
on_left_clickJogador clica com botão esquerdo com o item
on_shift_right_clickJogador faz shift+clique direito com o item
on_shift_left_clickJogador faz shift+clique esquerdo com o item
on_interact_entityJogador clica com botão direito em uma entidade com o item
on_swap_handsJogador troca o item entre as mãos
on_dropJogador solta o item
on_break_blockJogador quebra um bloco enquanto segura o item
on_consumeJogador consome o item
on_item_damageItem recebe dano de durabilidade
on_fishJogador usa uma vara de pescar
on_deathJogador morre enquanto item está equipado

Scripts de itens recebem context.item (com o ID do item e informações do jogador) em vez de context.prop.

Tabela Context de Scripts de Props

Scripts recebem uma tabela context. Aqui está um resumo das APIs principais -- veja API Lua de Props e Itens para detalhes completos.

context.prop:

  • model_id -- o nome do modelo blueprint
  • current_location -- a localização atual do prop
  • play_animation(name, blend, loop) -- reproduz a animação nomeada (blend e loop padrão true)
  • stop_animation() -- para todas as animações atuais
  • hurt_visual() -- reproduz o visual de dano (flash vermelho) no prop
  • pickup() -- remove o prop e dropa seu item de colocação
  • mount(player) -- faz um jogador montar o prop
  • dismount(player) -- remove um jogador do prop
  • get_passengers() -- retorna uma lista de jogadores atualmente montando o prop
  • spawn_elitemobs_boss(filename, x, y, z) -- spawna um boss EliteMobs relativo ao prop

context.event:

  • Disponível em on_left_click, on_right_click e on_projectile_hit
  • cancel(), uncancel(), is_cancelled
  • player -- o jogador que acionou o evento

context.world:

  • spawn_entity(entity_type, location) -- spawna uma entidade vanilla
  • set_block_at(location, material) -- define um bloco no mundo
  • Mais partículas, sons, consultas de bloco, raios e buscas de entidades próximas

Objetos de jogador (de context.event.player):

  • get_held_item() -- retorna o item que o jogador está segurando
  • consume_held_item() -- remove um do item segurado
  • has_item(material) -- verifica se o jogador tem um item
  • send_message(text) -- envia uma mensagem de chat para o jogador
  • game_mode -- o modo de jogo atual do jogador

Exemplo de Script de Prop

function on_spawn(context)
context.prop.play_animation("idle", true, true)
end

function on_right_click(context)
context.prop.play_animation("activate", false, false)
end

Exemplo de Script de Item

function on_equip(context)
context.event.player.send_message("&6You equipped the Flame Blade!")
end

function on_attack_entity(context)
-- Fire effect on hit
context.event.player.send_message("&cBurn!")
end

function on_unequip(context)
context.event.player.send_message("&7Flame Blade sheathed.")
end

Notas

  • FreeMinecraftModels é uma dependência de plugin instalado, não uma biblioteca embutível.
  • Se seu plugin precisa de modelos recém-importados, chame ModeledEntityManager.reload() em vez de tentar reconstruir o estado do FreeMinecraftModels você mesmo.
  • Todos os plugins no ecossistema Nightbreak agora dependem do MagmaCore 2.0.0-SNAPSHOT, que inclui o motor de scripting Lua compartilhado usado pelos scripts de props do FreeMinecraftModels e pelos poderes Lua do EliteMobs.