API y Guía para Desarrolladores de FreeMinecraftModels
FreeMinecraftModels es tanto un plugin independiente como una superficie de API para otros plugins.
Repositorio 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>
Dependencia
<dependency>
<groupId>com.magmaguy</groupId>
<artifactId>FreeMinecraftModels</artifactId>
<version>LATEST.VERSION.HERE</version>
<scope>provided</scope>
</dependency>
Úsalo como compileOnly/provided. No empaquetes el plugin dentro de tu propio jar.
Puntos de Entrada Principales
ModeledEntityManager.modelExists(String)ModeledEntityManager.reload()ModeledEntityManager.getAllEntities()ModeledEntityManager.getDynamicEntities()ModeledEntityManager.propEntities()
Tipos Principales del Runtime
ModeledEntityStaticEntityDynamicEntityPropEntity
Crear 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);
Todas las rutas de creación devuelven null si el ID de modelo solicitado no está cargado.
createWithInvisibility es una variante que aplica una poción de invisibilidad en lugar de ocultar la entidad de los clientes. Esto mantiene la entidad rastreada del lado del cliente, lo cual es necesario para la dirección de vehículos (usado internamente por /fmm mount).
Métodos Útiles del 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)DynamicEntity#setSyncMovement(boolean)Bone#getBoneLocation()
Superficie de Eventos
Eventos de interacción genéricos:
ModeledEntityLeftClickEventModeledEntityRightClickEventModeledEntityHitboxContactEventModeledEntityHitByProjectileEvent
También existen variantes tipadas para StaticEntity, DynamicEntity y PropEntity.
ModeledEntityHitByProjectileEvent y Detección de Proyectiles con OBB
FMM utiliza detección de impacto OBB (caja delimitadora orientada) para proyectiles contra entidades modeladas. Cuando un proyectil intersecta la hitbox OBB de una entidad modelada, FMM dispara un ModeledEntityHitByProjectileEvent. Este es un evento Bukkit cancelable estándar.
Detalles clave:
- El daño de flechas se calcula con soporte para el bonus del encantamiento
POWER - El encantamiento
PIERCINGes respetado -- las flechas pueden atravesar hacia objetivos adicionales - Cancela el evento para prevenir el daño y bloquear el impacto completamente
@EventHandler
public void onProjectileHitModel(ModeledEntityHitByProjectileEvent event) {
ModeledEntity target = event.getModeledEntity();
Projectile projectile = event.getProjectile();
// Cancelar para prevenir daño
event.setCancelled(true);
}
Utilidades de Ítems y Modelos
ModelItemFactory
Clase factory para crear ItemStacks relacionados con modelos programáticamente.
// Crear un ítem de colocación de prop (usa clave PDC "model_id")
ItemStack placementItem = ModelItemFactory.createModelItem("lamp_post", Material.STICK);
// Crear un ítem personalizado desde configuración (usa clave PDC "fmm_item_id")
PropScriptConfigFields config = ItemScriptManager.getItemDefinitions().get("magic_sword");
ItemStack customItem = ModelItemFactory.createCustomItem("magic_sword", config);
createModelItem(String modelId, Material material)-- crea un ítem de colocación para props. En 1.21.4+, aplica automáticamente el renderizado de display model si existe un JSON de display.createCustomItem(String itemId, PropScriptConfigFields config)-- crea un ítem personalizado con nombre, lore, encantamientos y display model desde la configuración unificada.formatModelName(String modelId)-- utilidad que convierte un ID de modelo como01_em_flame_swordenFlame Sword.
DisplayModelRegistry
Registro simple que rastrea qué modelos tienen un JSON de display disponible.
// Verificar si un modelo tiene un JSON de display model registrado
boolean has3D = DisplayModelRegistry.hasDisplayModel("magic_sword");
register(String modelId)-- registra un ID de modelo (llamado internamente durante la recarga)hasDisplayModel(String modelId)-- devuelvetruesi existe un.jsonde display model para este modeloshutdown()-- limpia todos los registros
ItemScriptManager
Gestiona el ciclo de vida de scripts Lua por jugador para ítems personalizados (modelos con material: establecido en su configuración YML).
// Obtener todas las definiciones de ítems personalizados registradas
Map<String, PropScriptConfigFields> items = ItemScriptManager.getItemDefinitions();
// Obtener la instancia de script Lua activa para un jugador + ítem
ScriptInstance instance = ItemScriptManager.getActiveScript(playerUUID, "magic_sword");
// Obtener todos los scripts activos para un jugador
Map<String, ScriptInstance> scripts = ItemScriptManager.getActiveScripts(playerUUID);
scanForCustomItems(File modelsFolder)-- escanea las configuraciones YML de modelos en busca de ítems personalizadosupdateEquippedScripts(Player player)-- compara los ítems equipados contra los scripts en ejecución, disparando hooks de equipar/desequiparremovePlayer(Player player)-- cierra todos los scripts para un jugador (llamar al desconectarse)getItemDefinitions()-- devuelve el mapa de ID de ítem aPropScriptConfigFields
ScriptedItemAPI
API pública para que plugins externos se integren con el sistema de ítems con scripts de FMM. Esto permite a otros plugins marcar sus propios ItemStacks con datos de ítems con scripts de FMM (etiqueta PDC + modelo de ítem) para que los hooks de scripts Lua de FMM se activen para esos ítems, sin que FMM sobrescriba el nombre, lore o encantamientos del ítem.
// Verificar si existe una definición de ítem con script
boolean exists = ScriptedItemAPI.isValidItemId("flame_blade");
// Aplicar datos de ítem con script de FMM a un ItemStack existente
// Esto establece:
// - La etiqueta PDC fmm_item_id (para que el sistema de scripts de FMM reconozca el ítem)
// - El modelo de ítem (1.21.4+) del registro de display model de FMM
// NO modifica nombre, lore, encantamientos ni ninguna otra propiedad del ítem.
boolean success = ScriptedItemAPI.applyScriptedItemData(itemStack, "flame_blade");
// Obtener la configuración de un ítem con script
PropScriptConfigFields config = ScriptedItemAPI.getItemConfig("flame_blade");
isValidItemId(String itemId)-- devuelvetruesi el ID de ítem está registrado en las definiciones de ítems de FMMapplyScriptedItemData(ItemStack itemStack, String itemId)-- marca la etiqueta PDC y el modelo de ítem en un ItemStack existente. Devuelvetrueen caso de éxito,falsesi el ID de ítem es inválido o el ItemStack no tiene meta. Nota para arco/ballesta: si elitemIddado no tiene un display model peroitemId + "_idle"sí (es decir, el ítem tiene modelos de estado de arco/ballesta), el método usa automáticamente el modelo_idlecomo display modelgetItemConfig(String itemId)-- devuelve elPropScriptConfigFieldspara el ID de ítem dado, onullsi no se encuentra
EliteMobs usa esta API internamente a través del campo de configuración scriptedItem. Cuando un ítem personalizado de EliteMobs establece scriptedItem: flame_blade, EliteMobs construye su ítem normalmente (nombre, lore, encantamientos, nivel) y luego llama a ScriptedItemAPI.applyScriptedItemData() para agregar el modelo y comportamiento de script de FMM encima.
PropScriptConfigFields
Clase de configuración unificada para archivos de configuración YML de modelos. Usada tanto por scripts de props como por ítems personalizados.
# Ejemplo: torch_01.yml
isEnabled: true
scripts:
- torch_glow.lua
material: STICK # Si se establece, el modelo se convierte en un ítem personalizado
name: "&eMagic Torch" # Nombre de visualización personalizado (opcional)
lore: # Líneas de lore personalizadas (opcional)
- "&7Glows in the dark"
enchantments: # Encantamientos (opcional, formato: NAME,LEVEL)
- "FIRE_ASPECT,1"
Métodos clave: isCustomItem(), getParsedMaterial(), getParsedEnchantments(), getScripts().
Scripting Lua
FreeMinecraftModels soporta scripts Lua tanto para props como para ítems personalizados a través del motor de scripting MagmaCore 2.0. Los archivos de script se colocan en plugins/FreeMinecraftModels/scripts/ y se vinculan a modelos mediante un archivo de configuración YML hermano al archivo del modelo.
Hooks de Scripts de Props
| Hook | Disparador |
|---|---|
on_spawn | El prop aparece en el mundo |
on_game_tick | Cada tick mientras el prop esté activo |
on_zone_enter | Un jugador entra en la zona del prop |
on_zone_leave | Un jugador sale de la zona del prop |
on_destroy | El prop es eliminado |
on_left_click | Un jugador hace clic izquierdo en el prop |
on_right_click | Un jugador hace clic derecho en el prop |
on_projectile_hit | Un proyectil impacta en el prop |
Hooks de Scripts de Ítems
Los ítems personalizados (modelos con material: establecido) soportan 22 hooks Lua:
| Hook | Disparador |
|---|---|
on_equip | El ítem entra en un slot de equipamiento rastreado |
on_unequip | El ítem sale de un slot de equipamiento rastreado |
on_game_tick | Cada tick mientras el ítem está equipado |
on_attack_entity | El jugador ataca una entidad mientras sostiene el ítem |
on_kill_entity | El jugador mata una entidad mientras sostiene el ítem |
on_take_damage | El jugador recibe daño mientras el ítem está equipado |
on_shield_block | El jugador bloquea con un escudo |
on_shoot_bow | El jugador dispara un arco |
on_projectile_hit | Un proyectil disparado por el jugador impacta algo |
on_projectile_launch | El jugador lanza un proyectil |
on_right_click | El jugador hace clic derecho con el ítem |
on_left_click | El jugador hace clic izquierdo con el ítem |
on_shift_right_click | El jugador hace shift+clic derecho con el ítem |
on_shift_left_click | El jugador hace shift+clic izquierdo con el ítem |
on_interact_entity | El jugador hace clic derecho en una entidad con el ítem |
on_swap_hands | El jugador intercambia el ítem entre manos |
on_drop | El jugador suelta el ítem |
on_break_block | El jugador rompe un bloque mientras sostiene el ítem |
on_consume | El jugador consume el ítem |
on_item_damage | El ítem recibe daño de durabilidad |
on_fish | El jugador usa una caña de pescar |
on_death | El jugador muere mientras el ítem está equipado |
Los scripts de ítems reciben context.item (con el ID del ítem e información del jugador) en lugar de context.prop.
Tabla de Contexto de Scripts de Props
Los scripts de props reciben una tabla context. Aquí hay un resumen de las APIs principales -- consulta API Lua de Props e Ítems para detalles completos.
context.prop:
model_id-- el nombre del modelo blueprintcurrent_location-- la ubicación actual del propplay_animation(name, blend, loop)-- reproduce la animación indicada (blend y loop por defecto entrue)stop_animation()-- detiene todas las animaciones actualeshurt_visual()-- reproduce el visual de daño (destello rojo) en el proppickup()-- elimina el prop y suelta su ítem de colocaciónmount(player)-- hace que un jugador monte el propdismount(player)-- desmonta a un jugador del propget_passengers()-- devuelve una lista de jugadores que actualmente montan el propspawn_elitemobs_boss(filename, x, y, z)-- genera un jefe de EliteMobs relativo al prop
context.event:
- Disponible en
on_left_click,on_right_clickyon_projectile_hit cancel(),uncancel(),is_cancelledplayer-- el jugador que activó el evento
context.world:
spawn_entity(entity_type, location)-- genera una entidad vanillaset_block_at(location, material)-- establece un bloque en el mundo- Además de partículas, sonidos, consultas de bloques, rayos y búsquedas de entidades cercanas
Objetos de jugador (de context.event.player):
get_held_item()-- devuelve el ítem que el jugador está sosteniendoconsume_held_item()-- elimina uno del ítem sostenidohas_item(material)-- verifica si el jugador tiene un ítemsend_message(text)-- envía un mensaje de chat al jugadorgame_mode-- el modo de juego actual del jugador
Ejemplo 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
Ejemplo de Script de Ítem
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 es una dependencia de plugin instalado, no una biblioteca para incrustar.
- Si tu plugin necesita modelos recién importados, llama a
ModeledEntityManager.reload()en lugar de intentar reconstruir el estado de FreeMinecraftModels por tu cuenta. - Todos los plugins del ecosistema Nightbreak ahora dependen de MagmaCore 2.0.0-SNAPSHOT, que incluye el motor de scripting Lua compartido utilizado por los scripts de props de FreeMinecraftModels y los poderes Lua de EliteMobs.