FreeMinecraftModels API 與開發者指南
FreeMinecraftModels 既是一個獨立插件,也是提供給其他插件使用的 API 介面。
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>
依賴
<dependency>
<groupId>com.magmaguy</groupId>
<artifactId>FreeMinecraftModels</artifactId>
<version>LATEST.VERSION.HERE</version>
<scope>provided</scope>
</dependency>
請將它作為 compileOnly/provided 使用。不要將插件打包進你自己的 jar 中。
核心入口點
ModeledEntityManager.modelExists(String)ModeledEntityManager.reload()ModeledEntityManager.getAllEntities()ModeledEntityManager.getDynamicEntities()ModeledEntityManager.propEntities()
核心運行時類型
ModeledEntityStaticEntityDynamicEntityPropEntity
建立實體
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);
如果請求的模型 ID 未載入,所有建立方式都會回傳 null。
createWithInvisibility 是一個變體,它使用隱身藥水而非從客戶端隱藏實體。這使實體在客戶端保持被追蹤狀態,這對於載具轉向是必需的(由 /fmm mount 內部使用)。
實用運行時方法
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()
事件介面
通用互動事件:
ModeledEntityLeftClickEventModeledEntityRightClickEventModeledEntityHitboxContactEventModeledEntityHitByProjectileEvent
同時也提供 StaticEntity、DynamicEntity 和 PropEntity 的型別化版本。
ModeledEntityHitByProjectileEvent 與 OBB 拋射物偵測
FMM 使用 OBB(定向邊界框)碰撞偵測來檢測拋射物與建模實體的碰撞。當拋射物與建模實體的 OBB 碰撞箱相交時,FMM 會觸發 ModeledEntityHitByProjectileEvent。這是一個標準的可取消 Bukkit 事件。
關鍵細節:
- 箭矢傷害的計算支援
POWER附魔加成 PIERCING附魔被尊重 -- 箭矢可以穿透並命中額外目標- 取消事件可以阻止傷害並完全阻擋命中
@EventHandler
public void onProjectileHitModel(ModeledEntityHitByProjectileEvent event) {
ModeledEntity target = event.getModeledEntity();
Projectile projectile = event.getProjectile();
// 取消以阻止傷害
event.setCancelled(true);
}
物品與模型實用工具
ModelItemFactory
用於以程式方式建立與模型相關的 ItemStack 的工廠類別。
// 建立道具放置物品(使用 "model_id" PDC 鍵)
ItemStack placementItem = ModelItemFactory.createModelItem("lamp_post", Material.STICK);
// 從設定建立自訂物品(使用 "fmm_item_id" PDC 鍵)
PropScriptConfigFields config = ItemScriptManager.getItemDefinitions().get("magic_sword");
ItemStack customItem = ModelItemFactory.createCustomItem("magic_sword", config);
createModelItem(String modelId, Material material)-- 為道具建立放置物品。在 1.21.4+ 上,如果存在展示 JSON,會自動套用展示模型渲染。createCustomItem(String itemId, PropScriptConfigFields config)-- 使用統一設定建立帶有名稱、說明、附魔和展示模型的自訂物品。formatModelName(String modelId)-- 將模型 ID(如01_em_flame_sword)轉換為Flame Sword的實用方法。
DisplayModelRegistry
簡單的登錄表,追蹤哪些模型有可用的展示 JSON。
// 檢查模型是否有已登錄的展示模型 JSON
boolean has3D = DisplayModelRegistry.hasDisplayModel("magic_sword");
register(String modelId)-- 登錄一個模型 ID(在重新載入期間內部呼叫)hasDisplayModel(String modelId)-- 如果此模型存在.json展示模型,則回傳trueshutdown()-- 清除所有登錄
ItemScriptManager
管理自訂物品(YML 設定中設定了 material: 的模型)的每玩家 Lua 腳本的生命週期。
// 取得所有已登錄的自訂物品定義
Map<String, PropScriptConfigFields> items = ItemScriptManager.getItemDefinitions();
// 取得玩家 + 物品的活躍 Lua 腳本實例
ScriptInstance instance = ItemScriptManager.getActiveScript(playerUUID, "magic_sword");
// 取得玩家的所有活躍腳本
Map<String, ScriptInstance> scripts = ItemScriptManager.getActiveScripts(playerUUID);
scanForCustomItems(File modelsFolder)-- 掃描模型 YML 設定以尋找自訂物品updateEquippedScripts(Player player)-- 比較已裝備物品與運行中的腳本,觸發 equip/unequip 鉤子removePlayer(Player player)-- 關閉玩家的所有腳本(退出時呼叫)getItemDefinitions()-- 回傳物品 ID 到PropScriptConfigFields的對應
ScriptedItemAPI
外部插件用於與 FMM 腳本物品系統整合的公開 API。允許其他插件在自己的 ItemStack 上標記 FMM 腳本物品資料(PDC 標籤 + 物品模型),使 FMM 的 Lua 腳本鉤子能夠對這些物品觸發,而 FMM 不會覆蓋物品的名稱、說明或附魔。
// 檢查腳本物品定義是否存在
boolean exists = ScriptedItemAPI.isValidItemId("flame_blade");
// 將 FMM 腳本物品資料套用到現有 ItemStack
// 設定內容:
// - fmm_item_id PDC 標籤(使 FMM 的腳本系統辨識該物品)
// - 物品模型(1.21.4+)來自 FMM 的展示模型登錄表
// 不會修改名稱、說明、附魔或任何其他物品屬性。
boolean success = ScriptedItemAPI.applyScriptedItemData(itemStack, "flame_blade");
// 取得腳本物品的設定
PropScriptConfigFields config = ScriptedItemAPI.getItemConfig("flame_blade");
isValidItemId(String itemId)-- 如果物品 ID 在 FMM 的物品定義中已登錄,則回傳trueapplyScriptedItemData(ItemStack itemStack, String itemId)-- 在現有 ItemStack 上標記 PDC 標籤和物品模型。成功回傳true,物品 ID 無效或 ItemStack 無 meta 時回傳false。**弓/弩注意:**如果給定的itemId沒有展示模型但itemId + "_idle"有(即該物品有弓/弩狀態模型),方法會自動使用_idle模型作為展示模型getItemConfig(String itemId)-- 回傳給定物品 ID 的PropScriptConfigFields,未找到時回傳null
EliteMobs 透過 scriptedItem 設定欄位在內部使用此 API。當 EliteMobs 自訂物品設定 scriptedItem: flame_blade 時,EliteMobs 會正常建構物品(名稱、說明、附魔、等級),然後呼叫 ScriptedItemAPI.applyScriptedItemData() 來加入 FMM 的模型和腳本行為。
PropScriptConfigFields
模型 YML 設定檔的統一設定類別。道具腳本和自訂物品都使用此類別。
# 範例: torch_01.yml
isEnabled: true
scripts:
- torch_glow.lua
material: STICK # 設定後,模型成為自訂物品
name: "&eMagic Torch" # 自訂顯示名稱(可選)
lore: # 自訂說明行(可選)
- "&7Glows in the dark"
enchantments: # 附魔(可選,格式: NAME,LEVEL)
- "FIRE_ASPECT,1"
關鍵方法:isCustomItem()、getParsedMaterial()、getParsedEnchantments()、getScripts()。
Lua 腳本
FreeMinecraftModels 透過 MagmaCore 2.0 腳本引擎支援道具和自訂物品的 Lua 腳本。腳本檔案放置在 plugins/FreeMinecraftModels/scripts/ 中,並透過模型檔案旁的 YML 設定檔繫結到模型。
道具腳本鉤子
| 鉤子 | 觸發條件 |
|---|---|
on_spawn | 道具被生成到世界中 |
on_game_tick | 道具存在期間的每個 tick |
on_zone_enter | 玩家進入道具的區域 |
on_zone_leave | 玩家離開道具的區域 |
on_destroy | 道具被移除 |
on_left_click | 玩家左鍵點擊道具 |
on_right_click | 玩家右鍵點擊道具 |
on_projectile_hit | 拋射物命中道具 |
物品腳本鉤子
自訂物品(設定了 material: 的模型)支援 22 個 Lua 鉤子:
| 鉤子 | 觸發條件 |
|---|---|
on_equip | 物品進入被追蹤的裝備欄位 |
on_unequip | 物品離開被追蹤的裝備欄位 |
on_game_tick | 物品裝備期間的每個 tick |
on_attack_entity | 玩家手持物品攻擊實體 |
on_kill_entity | 玩家手持物品擊殺實體 |
on_take_damage | 物品裝備時玩家受到傷害 |
on_shield_block | 玩家用盾牌格擋 |
on_shoot_bow | 玩家射箭 |
on_projectile_hit | 玩家發射的拋射物命中目標 |
on_projectile_launch | 玩家發射拋射物 |
on_right_click | 玩家右鍵點擊物品 |
on_left_click | 玩家左鍵點擊物品 |
on_shift_right_click | 玩家 Shift+右鍵點擊物品 |
on_shift_left_click | 玩家 Shift+左鍵點擊物品 |
on_interact_entity | 玩家用物品右鍵點擊實體 |
on_swap_hands | 玩家在雙手間交換物品 |
on_drop | 玩家丟棄物品 |
on_break_block | 玩家手持物品破壞方塊 |
on_consume | 玩家消耗物品 |
on_item_damage | 物品受到耐久損耗 |
on_fish | 玩家使用釣魚竿 |
on_death | 物品裝備時玩家死亡 |
物品腳本接收 context.item(包含物品 ID 和玩家資訊)而非 context.prop。
道具腳本上下文表
腳本會接收一個 context 表。以下是關鍵 API 的摘要——完整詳情請參見 Lua Prop API。
context.prop:
model_id-- 藍圖模型名稱current_location-- 道具的當前位置play_animation(name, blend, loop)-- 播放指定動畫(blend 和 loop 預設為true)stop_animation()-- 停止所有當前動畫hurt_visual()-- 在道具上播放受傷(紅色閃爍)視覺效果pickup()-- 移除道具並掉落其放置物品mount(player)-- 讓玩家騎上道具dismount(player)-- 將玩家從道具上移除get_passengers()-- 回傳目前騎在道具上的玩家列表spawn_elitemobs_boss(filename, x, y, z)-- 在道具相對位置生成 EliteMobs Boss
context.event:
- 在
on_left_click、on_right_click和on_projectile_hit中可用 cancel()、uncancel()、is_cancelledplayer-- 觸發事件的玩家
context.world:
spawn_entity(entity_type, location)-- 生成原版實體set_block_at(location, material)-- 在世界中設定方塊- 另外還有粒子、聲音、方塊查詢、閃電和附近實體查找
玩家物件(來自 context.event.player):
get_held_item()-- 回傳玩家手持的物品consume_held_item()-- 移除一個手持物品has_item(material)-- 檢查玩家是否擁有某物品send_message(text)-- 向玩家傳送聊天訊息game_mode-- 玩家當前的遊戲模式
道具腳本範例
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
物品腳本範例
function on_equip(context)
context.event.player.send_message("&6You equipped the Flame Blade!")
end
function on_attack_entity(context)
-- 命中時的火焰效果
context.event.player.send_message("&cBurn!")
end
function on_unequip(context)
context.event.player.send_message("&7Flame Blade sheathed.")
end
備註
- FreeMinecraftModels 是已安裝插件的依賴,不是可嵌入的函式庫。
- 如果你的插件需要剛匯入的模型,請呼叫
ModeledEntityManager.reload(),而不是嘗試自行重建 FreeMinecraftModels 的內部狀態。 - Nightbreak 生態系統中的所有插件現在都依賴於 MagmaCore 2.0.0-SNAPSHOT,其中包含 FreeMinecraftModels 道具腳本和 EliteMobs Lua 能力所使用的共享 Lua 腳本引擎。