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
ModeledEntityStaticEntityDynamicEntityPropEntity
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 modeloModeledEntity#getLocation()-- retorna aLocationatualModeledEntity#getWorld()-- retorna oWorldModeledEntity#getViewers()-- retorna oHashSet<UUID>de jogadores que podem ver a entidadeModeledEntity#getNametagBones()-- retornaList<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 escalaModeledEntity#remove()-- remove imediatamente a entidade e todos os bonesDynamicEntity#setSyncMovement(boolean)DynamicEntity#isDamagesOnContact()/setDamagesOnContact(boolean)-- controla se a entidade causa dano a jogadores via contato de hitboxBone#getBoneLocation()
Superfície de Eventos
Eventos de interação genéricos:
ModeledEntityLeftClickEventModeledEntityRightClickEventModeledEntityHitboxContactEventModeledEntityHitByProjectileEvent
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 como01_em_flame_swordemFlame 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)-- retornatruese um.jsonde display model existir para este modelogetRegisteredModels()-- retorna umSet<String>imutável de todos os IDs de modelo que possuem display models registradosshutdown()-- 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 personalizadosupdateEquippedScripts(Player player)-- compara itens equipados com scripts em execução, disparando hooks de equipar/desequiparremovePlayer(Player player)-- encerra todos os scripts para um jogador (chamar ao desconectar)getItemDefinitions()-- retorna o mapa de ID de item paraPropScriptConfigFields
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)-- retornatruese o ID do item estiver registrado nas definições de itens do FMMapplyScriptedItemData(ItemStack itemStack, String itemId)-- marca a tag PDC e o modelo de item em um ItemStack existente. Retornatrueem caso de sucesso,falsese o ID do item for inválido ou o ItemStack não tiver meta. Nota para arco/besta: se oitemIddado não tiver um display model masitemId + "_idle"tiver (ou seja, o item tem modelos de estado de arco/besta), o método automaticamente usa o modelo_idlecomo display modelgetItemConfig(String itemId)-- retorna oPropScriptConfigFieldspara o ID de item dado, ounullse não encontrado
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
| Hook | Acionamento |
|---|---|
on_spawn | Prop é spawnado no mundo |
on_game_tick | A cada tick enquanto o prop está vivo |
on_zone_enter | Um jogador entra na zona do prop |
on_zone_leave | Um jogador sai da zona do prop |
on_destroy | Prop é removido |
on_left_click | Jogador clica com botão esquerdo no prop |
on_right_click | Jogador clica com botão direito no prop |
on_projectile_hit | Um projétil atinge o prop |
Hooks de Scripts de Itens
Itens personalizados (modelos com material: definido) suportam 22 hooks Lua:
| Hook | Acionamento |
|---|---|
on_equip | Item entra em um slot de equipamento rastreado |
on_unequip | Item sai de um slot de equipamento rastreado |
on_game_tick | A cada tick enquanto o item está equipado |
on_attack_entity | Jogador ataca uma entidade enquanto segura o item |
on_kill_entity | Jogador mata uma entidade enquanto segura o item |
on_take_damage | Jogador recebe dano enquanto item está equipado |
on_shield_block | Jogador bloqueia com um escudo |
on_shoot_bow | Jogador dispara um arco |
on_projectile_hit | Um projétil disparado pelo jogador atinge algo |
on_projectile_launch | Jogador lança um projétil |
on_right_click | Jogador clica com botão direito com o item |
on_left_click | Jogador clica com botão esquerdo com o item |
on_shift_right_click | Jogador faz shift+clique direito com o item |
on_shift_left_click | Jogador faz shift+clique esquerdo com o item |
on_interact_entity | Jogador clica com botão direito em uma entidade com o item |
on_swap_hands | Jogador troca o item entre as mãos |
on_drop | Jogador solta o item |
on_break_block | Jogador quebra um bloco enquanto segura o item |
on_consume | Jogador consome o item |
on_item_damage | Item recebe dano de durabilidade |
on_fish | Jogador usa uma vara de pescar |
on_death | Jogador 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 blueprintcurrent_location-- a localização atual do propplay_animation(name, blend, loop)-- reproduz a animação nomeada (blend e loop padrãotrue)stop_animation()-- para todas as animações atuaishurt_visual()-- reproduz o visual de dano (flash vermelho) no proppickup()-- remove o prop e dropa seu item de colocaçãomount(player)-- faz um jogador montar o propdismount(player)-- remove um jogador do propget_passengers()-- retorna uma lista de jogadores atualmente montando o propspawn_elitemobs_boss(filename, x, y, z)-- spawna um boss EliteMobs relativo ao prop
context.event:
- Disponível em
on_left_click,on_right_clickeon_projectile_hit cancel(),uncancel(),is_cancelledplayer-- o jogador que acionou o evento
context.world:
spawn_entity(entity_type, location)-- spawna uma entidade vanillaset_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á segurandoconsume_held_item()-- remove um do item seguradohas_item(material)-- verifica se o jogador tem um itemsend_message(text)-- envia uma mensagem de chat para o jogadorgame_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.