Lua 腳本:道具與物品 API
本頁涵蓋 FreeMinecraftModels 道具和物品腳本可用的所有 API:context.prop、context.item、context.event、context.player、context.world、context.zones、context.scheduler、context.state 和 context.log。如果你是腳本新手,請先從入門指南開始。
context.prop
道具表提供關於道具實體的資訊以及控制其動畫的方法。它在每次鉤子呼叫時重新建構。
欄位
| 欄位 | 類型 | 說明 |
|---|---|---|
prop.model_id | string | 藍圖模型名稱(例如 "torch_01") |
prop.current_location | location table | 建構上下文時道具的位置 |
location 表具有標準欄位:x、y、z、world、yaw、pitch。
範例:讀取道具資訊
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)
在道具模型上播放指定名稱的動畫。
| 參數 | 類型 | 預設值 | 說明 |
|---|---|---|---|
name | string | 必填 | 模型檔案中定義的動畫名稱 |
blend | boolean | true | 是否與目前動畫混合 |
loop | boolean | true | 動畫是否循環播放 |
如果找到並啟動了動畫則回傳 true,否則回傳 false。
範例
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()
停止道具上目前播放的所有動畫。
不接受任何參數。
範例
return {
api_version = 1,
on_right_click = function(context)
context.prop:stop_animation()
end
}
prop:hurt_visual()
在道具上播放視覺受傷動畫(紅色閃爍),不會造成任何實際傷害。
不接受任何參數。
範例
return {
api_version = 1,
on_left_click = function(context)
-- 被攻擊時閃紅,但不實際受到傷害
if context.event then
context.event.cancel()
end
context.prop:hurt_visual()
end
}
prop:pickup()
從世界中移除道具並在其位置掉落一個放置用的紙張物品。掉落的物品可以右鍵點擊方塊來重新放置道具。
不接受任何參數。
範例
return {
api_version = 1,
on_right_click = function(context)
-- 讓玩家透過右鍵點擊拾取道具
context.prop:pickup()
end
}
prop:mount(player)
將玩家掛載到道具上第一個可用的騎乘點座位。模型必須定義了騎乘點骨骼。
| 參數 | 類型 | 說明 |
|---|---|---|
player | entity table | 玩家實體表(例如來自 context.event.player) |
範例
return {
api_version = 1,
on_right_click = function(context)
local player = context.event and context.event.player
if player then
context.prop:mount(player)
end
end
}
prop:dismount(player)
將玩家從道具的騎乘點座位上移除。
| 參數 | 類型 | 說明 |
|---|---|---|
player | entity table | 玩家實體表 |
範例
return {
api_version = 1,
on_right_click = function(context)
local player = context.event and context.event.player
if player then
-- 切換上下坐騎
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()
回傳道具上所有當前乘客的實體表的 Lua 陣列。
不接受任何參數。
範例
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()
回傳此道具的模型是否定義了騎乘點骨骼。
不接受任何參數。回傳 true 或 false。
範例
return {
api_version = 1,
on_right_click = function(context)
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)
在指定位置生成 EliteMobs 自訂 Boss。需要伺服器上安裝了 EliteMobs。
| 參數 | 類型 | 說明 |
|---|---|---|
filename | string | 自訂 Boss 檔名(例如 "my_boss.yml") |
x | number | X 座標 |
y | number | Y 座標 |
z | number | Z 座標 |
如果 EliteMobs 未安裝或 Boss 檔案不存在,回傳 nil;否則回傳生成的 Boss 的生物實體表。
範例
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)
為玩家開啟一個持久化的箱子物品欄 GUI。內容在物品欄關閉時儲存到道具的 PersistentDataContainer 中,再次開啟時恢復。
| 參數 | 類型 | 預設值 | 說明 |
|---|---|---|---|
player | entity table | 必填 | 要顯示物品欄的玩家 |
title | string | 必填 | 物品欄標題(支援 & 顏色代碼) |
rows | int | 3 | 列數(1-6,其中 6 = 54 格 = 大箱子) |
如果物品欄已開啟則回傳 true,否則回傳 false。
prop:is_viewing_inventory(player)
回傳給定玩家目前是否開啟了此道具的物品欄。
| 參數 | 類型 | 說明 |
|---|---|---|
player | entity table | 要檢查的玩家 |
回傳 true 或 false。
範例:物品欄關閉時播放關閉動畫
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)
從玩家的主手取走已書寫或可書寫的書並儲存在道具上。
| 參數 | 類型 | 說明 |
|---|---|---|
player | entity table | 持有書的玩家 |
成功時回傳 true。
prop:read_book(player)
為玩家開啟儲存的書供其閱讀。
| 參數 | 類型 | 說明 |
|---|---|---|
player | entity table | 要顯示書的玩家 |
如果成功開啟了書則回傳 true。
prop:take_book(player)
將儲存的書歸還到玩家的物品欄並從道具上移除。
| 參數 | 類型 | 說明 |
|---|---|---|
player | entity table | 要給予書的玩家 |
成功時回傳 true。
prop:has_book()
回傳此道具上是否儲存了一本書。不接受任何參數。
prop:drop_inventory()
將所有儲存的物品欄內容作為物品實體掉落在道具位置,然後清除儲存資料。會自動關閉目前正在檢視物品欄的玩家的介面。
不接受任何參數。成功時回傳 true。
prop:drop_book()
將儲存的書作為物品實體掉落在道具位置,並清除儲存的書資料。
不接受任何參數。成功時回傳 true。
prop:set_persistent_data(key, value)
在道具的盔甲架 PersistentDataContainer 上儲存一個字串值。此資料在伺服器重啟和區塊卸載後仍然保留。
| 參數 | 類型 | 說明 |
|---|---|---|
key | string | 唯一的鍵名(內部儲存為 fmm_lua_<key>) |
value | string | 要儲存的值。對於數字和布林值使用 tostring()。 |
成功時回傳 true,如果道具沒有支撐的盔甲架則回傳 false。
prop:get_persistent_data(key)
取得之前透過 set_persistent_data 儲存的字串值。如果鍵未被設定則回傳 nil。
| 參數 | 類型 | 說明 |
|---|---|---|
key | string | set_persistent_data 中使用的鍵名 |
範例:持久化的切換狀態
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
}
context.item
物品表僅在物品腳本中可用(不在道具腳本中)。它提供關於自訂物品的資訊以及操作它的方法。此表在每次鉤子呼叫時重新建構。
欄位
| 欄位 | 類型 | 說明 |
|---|---|---|
item.id | string | 物品類型 ID(YML 設定中的 fmm_item_id) |
item:material()
回傳物品的材質名稱字串(例如 "DIAMOND_SWORD"、"STICK")。
item:get_amount() / item:set_amount(n)
取得或設定物品的堆疊數量。
| 參數 | 類型 | 說明 |
|---|---|---|
n | int | 新的堆疊數量 |
item:consume(n)
將物品的堆疊數量減少 n(預設 1)。如果結果數量為 0 或更少,物品將從玩家的物品欄中移除。
| 參數 | 類型 | 預設值 | 說明 |
|---|---|---|---|
n | int | 1 | 要消耗的數量 |
item:get_uses() / item:set_uses(n)
取得或設定儲存在物品 PersistentDataContainer 中的自訂使用次數計數器。這獨立於原版耐久度,可用於實現自訂耐久或充能系統。
| 參數 | 類型 | 說明 |
|---|---|---|
n | int | 新的使用次數 |
item:get_name() / item:set_name(s)
取得或設定物品的顯示名稱。支援 & 顏色代碼。
| 參數 | 類型 | 說明 |
|---|---|---|
s | string | 新的顯示名稱(例如 "&b&lFrost Sword") |
item:get_lore() / item:set_lore(table)
取得或設定物品的說明。get_lore() 回傳字串表(每行一個)。set_lore() 接受字串表。
| 參數 | 類型 | 說明 |
|---|---|---|
table | table | 字串陣列,每行說明一個 |
範例:追蹤使用次數的物品腳本
return {
api_version = 1,
on_right_click = function(context)
local uses = context.item:get_uses()
if uses <= 0 then
context.player:send_message("&cThis item is out of charges!")
return
end
context.item:set_uses(uses - 1)
context.player:send_message("&aUsed! Charges remaining: " .. (uses - 1))
end
}
item:get_durability()
回傳一個包含 current 和 max 欄位的表,表示物品的原版耐久度。如果物品沒有耐久條則回傳 nil。
範例
local dur = context.item:get_durability()
if dur then
context.player:send_message("Durability: " .. dur.current .. "/" .. dur.max)
end
item:get_durability_percentage()
回傳剩餘耐久度,為 0.0 到 1.0 的分數。如果物品沒有耐久條則回傳 nil。
item:use_durability(amount, can_break)
減少物品的原版耐久度一個固定數量。
| 參數 | 類型 | 預設值 | 說明 |
|---|---|---|---|
amount | int | 必填 | 要消耗的耐久點數 |
can_break | boolean | false | 如果為 true,耐久耗盡時物品會被銷毀。如果為 false,耐久會停在 1。 |
item:use_durability_percentage(fraction, can_break)
按最大值的百分比減少物品的原版耐久度。
| 參數 | 類型 | 預設值 | 說明 |
|---|---|---|---|
fraction | number | 必填 | 要消耗的最大耐久度的分數(例如 0.1 = 10%) |
can_break | boolean | false | 如果為 true,耐久耗盡時物品會被銷毀。如果為 false,耐久會停在 1。 |
context.event
當前鉤子的事件資料。在道具和物品腳本的點擊、戰鬥和互動鉤子中可用。在沒有關聯事件的鉤子中回傳 nil(on_spawn、on_game_tick、on_destroy、on_zone_enter、on_zone_leave、on_equip)。
欄位和方法
| 欄位或方法 | 類型 | 說明 |
|---|---|---|
event.player | 玩家實體表 | 觸發事件的玩家。在 on_left_click、on_right_click 和 on_projectile_hit(如果射手是玩家)中可用。所有欄位和方法請參見玩家實體方法。 |
event.is_cancelled | boolean | 事件目前是否已被取消 |
event.cancel() | function | 取消事件(例如阻止傷害或互動) |
event.uncancel() | function | 撤銷之前取消的事件 |
並非所有事件都可以取消。如果底層 Bukkit 事件未實作 Cancellable,則 event.cancel() 和 event.uncancel() 不存在,event.is_cancelled 始終為 false。
範例:使道具無敵
範例
return {
api_version = 1,
on_left_click = function(context)
if context.event then
context.event.cancel()
end
end
}
範例:檢查取消狀態
範例
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
}
在排程器回呼中(scheduler:run_later、scheduler:run_repeating),context.event 始終為 nil。事件修改只能在事件鉤子本身中進行。
context.world
world API 在所有 Nightbreak 插件中共享。完整參考請參見 context.world。
FMM 道具使用與 EliteMobs Boss 相同的 MagmaCore world 表。全域頁面上記載的所有方法(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、spawn_firework)在 FMM 中均可用。有關 world:raycast()(投射射線並偵測命中的實體/方塊)和 world:spawn_firework()(生成具有自訂顏色和形狀的煙火火箭)的完整詳情,請參見 MagmaCore world API。EliteMobs 使用額外方法擴展了 world 表用於生成 Boss、增援等 -- 參見 EliteMobs World & Environment。
玩家實體方法
玩家實體表從 context.event.player、context.world:get_nearby_players() 和區域回呼中回傳。
實體表、生物實體方法、玩家特定方法和玩家 UI 方法在所有 Nightbreak 插件中共享。完整參考涵蓋實體基礎欄位、生物實體欄位和方法、玩家特定欄位和方法以及玩家 UI 方法,請參見 MagmaCore Lua 腳本引擎。新的玩家方法包括 player:get_target_entity()(射線投射瞄準)、player:get_eye_location()、player:get_look_direction()、player:send_block_change()(每玩家假方塊)和 player:reset_block() -- 詳情請參見玩家特定方法。
context.zones
zones API 在所有 Nightbreak 插件中共享。完整參考請參見 context.zones。
context.scheduler
scheduler API 在所有 Nightbreak 插件中共享。完整參考請參見 context.scheduler。
context.state
state API 在所有 Nightbreak 插件中共享。完整參考請參見 context.state。
context.log
日誌 API 在所有 Nightbreak 插件中共享。完整參考請參見 context.log。
運行時模型
每個腳本實例一個運行時
每個附帶腳本的道具實體都會獲得自己獨立的 Lua 運行時實例。當道具生成時,FMM 載入 Lua 原始碼,在新的沙盒環境中執行,並儲存回傳的表。當道具被移除時,運行時關閉。
對於物品腳本,每個(玩家,itemId)對建立一個運行時。當玩家裝備自訂物品時,FMM 為該玩家和物品類型建立腳本實例。當物品被卸下時,運行時關閉。
這意味著:
- 在檔案作用域宣告的區域變數對該腳本實例是私有的。
context.state在實例間完全隔離,即使它們共享同一腳本檔案。
排程任務所有權
透過 context.scheduler 建立的所有任務歸建立它們的運行時所有。當道具被移除時:
- 運行時關閉。
- 所有擁有的任務 -- 一次性和重複性的 -- 都自動取消。
- 所有區域監視被清除。
執行預算
每次鉤子呼叫和每次回呼呼叫都會計時。如果單次呼叫超過 50 毫秒,腳本會被停用並顯示主控台警告:
[Lua] my_script.lua took 73ms in 'on_game_tick' (limit: 50ms) -- script disabled to prevent lag.
為保持在預算內:
- 避免鉤子內的無限迴圈。
- 保持
on_game_tick處理程式輕量 -- 它們每個 tick 都運行。 - 使用
context.scheduler:run_repeating(...)將工作分散到多個 tick。
完整鉤子參考
此表列出了道具和物品腳本中所有可用的鉤子。
道具鉤子(8)
| 鉤子 | 觸發時機 | context.event |
|---|---|---|
on_spawn | 道具生成到世界中 | nil |
on_game_tick | 每個伺服器 tick(50ms) | nil |
on_destroy | 道具被移除 | nil |
on_left_click | 玩家左鍵點擊道具 | 傷害事件 |
on_right_click | 玩家右鍵點擊道具 | 互動事件 |
on_projectile_hit | 拋射物命中道具 | 拋射物命中事件 |
on_zone_enter | 玩家進入被監視的區域 | nil |
on_zone_leave | 玩家離開被監視的區域 | nil |
物品鉤子(22)
| 鉤子 | 類別 | 觸發時機 | context.event |
|---|---|---|---|
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_equip | 裝備 | 物品進入活動欄位 | nil |
on_unequip | 裝備 | 物品離開活動欄位 | nil |
on_swap_hands | 裝備 | 主/副手交換 | 交換事件 |
on_drop | 裝備 | 玩家丟棄物品 | 丟棄事件 |
on_break_block | 實用 | 玩家破壞方塊 | 方塊破壞事件 |
on_consume | 實用 | 玩家消耗物品 | 消耗事件 |
on_item_damage | 實用 | 物品受到耐久損耗 | 物品損耗事件 |
on_fish | 實用 | 玩家使用釣魚竿 | 釣魚事件 |
on_death | 實用 | 裝備時玩家死亡 | 死亡事件 |
on_game_tick | 生命週期 | 裝備期間每個 tick | nil |