MagmaCore Lua 腳本引擎
MagmaCore 提供了一個共用的 Lua 腳本引擎,供多個 Nightbreak 外掛使用。該引擎處理沙盒、排程、區域管理、世界互動、實體表與玩家 UI —— 並在各個外掛之間提供一致的 API。
目前使用此引擎的外掛包含:
- EliteMobs —— 自訂 Boss 的 Lua 能力(如
on_boss_damaged_by_player、on_enter_combat等 hooks) - FreeMinecraftModels —— 道具與自訂物品的 Lua 腳本(如
on_right_click、on_left_click、on_equip等 hooks)
本頁說明共用引擎功能。如需各外掛特有的 hooks、API 與工作流程,請參閱上方連結的外掛頁面。
Lua 簡易入門
如果你完全沒接觸過 Lua,以下是為任何 Nightbreak 外掛撰寫腳本所需的最少語法。
變數
使用 local 儲存一個值:
local cooldown_key = "fire_burst"
local damage_multiplier = 1.5
local 表示該變數僅屬於這個檔案或區塊。
函式
函式是可重複使用的邏輯區塊:
local function warn_player(player)
player:send_message("&cMove!")
end
稍後可以這樣呼叫:
warn_player(some_player)
if 判斷
當某件事只應在某些情況下發生時,使用 if:
if context.player == nil then
return
end
意思是「如果這個 hook 沒有玩家,就到此停止」。
nil
nil 表示「沒有值」。它是 Lua 對「什麼都沒有」的表達方式。
你會經常用以下方式檢查 nil:
if context.event ~= nil then
-- do something with the event
end
~= 表示「不等於」。
表(Tables)
Lua 將表用於多種用途:
- 清單
- 帶有命名鍵的物件
- 最後回傳的腳本定義
帶有命名鍵的表範例:
local particle = {
particle = "FLAME",
amount = 1,
speed = 0.05
}
回傳腳本定義
在每個腳本檔案的結尾,你會回傳一張表:
return {
api_version = 1,
on_spawn = function(context)
end
}
那張回傳的表就是該腳本檔案。
註解
使用 -- 為人類撰寫註解:
-- This cooldown stops the attack from firing every hit
context.cooldowns:set_local(60, "fire_burst")
Lua 沙盒
所有 Lua 腳本皆在沙盒化的 LuaJ 環境中執行。多個可能存取檔案系統或 Java 執行環境的全域物件已被移除。沙盒規則在所有使用 MagmaCore 的外掛之間都相同。
被移除的全域
下列標準 Lua 全域已被設為 nil,無法使用:
| Removed | Why |
|---|---|
debug | 暴露內部 VM 狀態 |
dofile | 檔案系統存取 |
io | 檔案系統存取 |
load | 任意程式碼載入 |
loadfile | 檔案系統存取 |
luajava | 直接存取 Java 類別 |
module | 模組系統(不需要) |
os | 作業系統存取 |
package | 模組系統(不需要) |
require | 模組系統/檔案系統存取 |
可用的標準函式庫
Lua 標準函式庫的其他部分皆可正常運作:
| Category | Functions |
|---|---|
| Math | math.abs、math.ceil、math.floor、math.max、math.min、math.random、math.sin、math.cos、math.sqrt、math.pi,以及所有其他 math.* 函式 |
| String | string.byte、string.char、string.find、string.format、string.gsub、string.len、string.lower、string.match、string.rep、string.sub、string.upper,以及所有其他 string.* 函式 |
| Table | table.insert、table.remove、table.sort、table.concat,以及所有其他 table.* 函式 |
| Iterators | pairs、ipairs、next |
| Type | type、tostring、tonumber、select、unpack |
| Error handling | pcall、xpcall、error、assert |
| Other | print、rawget、rawset、rawequal、rawlen、setmetatable、getmetatable |
os 函式庫無法使用os 函式庫已從沙盒中完全移除。若需要計時資訊,請使用 context.world:get_time() 取得世界時間,或在 context.state 中透過 on_game_tick hook 以 tick 計數器儲存時間戳。
print 會寫入伺服器主控台,但建議使用 context.log:info(msg) 進行輸出。日誌訊息會帶有腳本檔名前綴,便於追蹤訊息來源。
檔案約定
每個 Lua 腳本必須 return 一張表。該表的結構刻意採嚴格規範。
必要與可選的頂層欄位
| Field | Required | Type | Notes |
|---|---|---|---|
api_version | Yes | Number | 目前必須為 1 |
priority | No | Number | 執行優先順序。數值較低者先執行。預設為 0 |
| supported hook keys | No | Function | 必須使用該外掛所支援的 hook 名稱 |
驗證規則
- 檔案必須回傳一張表。
api_version為必要欄位,目前必須為1。- 若提供
priority,必須為數字。 - 每個額外的頂層鍵都必須是受支援的 hook 名稱。
- 每個 hook 鍵都必須指向一個函式。
- 不認識的頂層鍵會被拒絕。
輔助函式與本地常數應放在最後 return 的上方,而不是放在回傳的表中(除非它們真的是 hook)。
local ANIMATION_NAME = "idle"
local function do_something(context)
context.log:info("Doing something!")
end
return {
api_version = 1,
priority = 0,
on_spawn = function(context)
do_something(context)
end
}
共用引擎 Hooks
下列 hooks 可供所有使用 MagmaCore 腳本引擎的外掛使用。各外掛會在這些之上新增自己的 hooks。
| Hook | When it fires |
|---|---|
on_spawn | 當腳本實例建立時呼叫一次(實體生成或道具放置) |
on_game_tick | 在實體存活/啟用時,每個伺服器 tick 呼叫一次 |
on_zone_enter | 當玩家進入受監控區域時呼叫 |
on_zone_leave | 當玩家離開受監控區域時呼叫 |
方法語法:: 與 .
在 Lua 中,object:method(arg) 是 object.method(object, arg) 的簡寫。MagmaCore API 兩種形式都接受,所以任一寫法皆可:
context.log:info("hello")
context.log.info("hello") -- same thing
所有文件皆統一使用 :。
執行預算
每次 hook 呼叫與每次回呼呼叫都會計時。若單次呼叫耗時超過 50 毫秒,腳本會被停用並在主控台輸出警告:
[Lua] my_script.lua took 73ms in 'on_game_tick' (limit: 50ms) -- script disabled to prevent lag.
要維持在預算內:
- 避免 hooks 內無界限的迴圈。
- 讓
on_game_tick處理函式保持輕量 —— 它們每個 tick 都會執行。 - 使用
context.scheduler:run_repeating(...)將工作分散到多個 tick。 - 將昂貴的工作放在基於狀態的冷卻或合理的間隔背後。
若 Lua 腳本在任何 hook 或排程回呼中拋出執行階段錯誤,該腳本實例會立即且永久地對該實體停用。請在腳本檔案中修正錯誤 —— 腳本會在實體下次生成時重新初始化。
context.state
一張在腳本實例整個生命週期中保持的純 Lua 表。用來儲存旗標、計數器、任務 ID、切換狀態,以及任何需要在 hooks 之間共享的資料。
on_spawn = function(context)
context.state.is_open = false
context.state.click_count = 0
context.state.task_id = nil
end,
on_right_click = function(context)
context.state.click_count = (context.state.click_count or 0) + 1
end
只有 context.state 會在 hook 呼叫之間保留。所有其他 context 表(context.prop、context.world、context.event 等)每次都會重新建立。context.state 不會被重建 —— 它會從腳本實例建立的那一刻起一直存在,直到被銷毀。
context.log
主控台日誌方法。訊息會在伺服器主控台中帶有腳本檔名前綴。
| Method | Notes |
|---|---|
log:info(message) | 資訊訊息 |
log:warn(message) | 警告訊息 |
log:error(message) | 警告等級訊息(以 WARN 等級記錄,與 log:warn 相同) |
EliteMobs 的 context.log 註冊的是 debug 而非 error。使用 log:debug(message) 輸出除錯訊息(以 info 等級顯示並帶有 debug 前綴)。
context.log:info("Script loaded!")
context.log:warn("Something unexpected happened")
context.log:error("Critical failure in zone setup")
context.cooldowns
cooldowns 表用來管理腳本中基於時間的冷卻。有兩種範圍:
- 本地冷卻屬於各個腳本實例,並以字串鍵識別。若未提供 key,腳本檔名會作為預設 key。
- 全域冷卻由同一擁有者實體上的所有腳本共享(例如,同一個道具上的所有腳本,或同一個 Boss 上的所有 Lua 能力)。
cooldowns:check_local(key?, duration)
最常用的方法。檢查冷卻是否就緒,若已就緒則啟動冷卻並回傳 true。若未就緒則回傳 false。此操作為原子檢查與設定 —— 沒有競爭條件。
| Parameter | Type | Notes |
|---|---|---|
key | string (optional) | 冷卻識別碼。預設為腳本檔名。 |
duration | int | 以 ticks 計的冷卻時間(20 = 1 秒) |
on_right_click = function(context)
-- Only allow this action once every 3 seconds
if not context.cooldowns:check_local("interact", 60) then
return
end
-- ... do the action
end
cooldowns:local_ready(key?)
若本地冷卻已過期(或從未設定)則回傳 true,仍在進行中則回傳 false。
cooldowns:local_remaining(key?)
回傳本地冷卻剩餘的 tick 數,若已就緒則為 0。
cooldowns:set_local(duration, key?)
設定本地冷卻,不檢查是否已有冷卻在進行中。可用於無條件重設冷卻。
| Parameter | Type | Notes |
|---|---|---|
duration | int | 以 ticks 計的時間。傳入 0 或負數則清除。 |
key | string (optional) | 冷卻識別碼。預設為腳本檔名。 |
cooldowns:global_ready()
若全域冷卻(同一實體上所有腳本共享)已過期則回傳 true。
cooldowns:set_global(duration)
設定全域冷卻。
| Parameter | Type | Notes |
|---|---|---|
duration | int | 以 ticks 計的時間 |
全域冷卻的「擁有者」依腳本類型而定:
- EliteMobs Lua 能力 — 依
EliteEntity共享(每個 Boss 一個槽位)。global_ready()/set_global()使用 Boss 內建的能力冷卻系統;本地冷卻也會在同一 Boss 上的所有能力之間共享。 - FMM 道具腳本 — 依
PropEntity共享(每個放置的道具一個槽位)。 - FMM 物品腳本 — 依玩家 UUID 共享(每位玩家一個槽位)。物品上的本地冷卻會在裝備/卸下之間持久化,key 為
playerUUID → "itemId:scriptFile" → key,因此即使玩家把物品從快捷欄拿出再放回去,冷卻仍會保留。
context.scheduler
排程器讓你執行延遲或重複的任務。所有任務皆由腳本實例擁有,當腳本實例被銷毀時(例如道具被移除或 Boss 死亡)會自動取消。
scheduler:run_later(ticks, callback)
延遲一段時間後執行一次回呼。回傳數字任務 ID。
| Parameter | Type | Notes |
|---|---|---|
ticks | int | 以伺服器 ticks 計的延遲(20 ticks = 1 秒) |
callback | function | 延遲結束時以全新的 context 呼叫 |
context.scheduler:run_later(40, function(delayed_context)
delayed_context.log:info("2 seconds have passed!")
end)
scheduler:run_repeating(delay, interval, callback)
以固定間隔重複執行回呼。回傳數字任務 ID。
| Parameter | Type | Notes |
|---|---|---|
delay | int | 第一次執行前的初始延遲(ticks) |
interval | int | 後續每次執行間隔的 ticks |
callback | function | 每次間隔以全新的 context 呼叫 |
context.state.particle_task = context.scheduler:run_repeating(0, 20, function(tick_context)
tick_context.log:info("Another second passed!")
end)
scheduler:cancel(taskId)
依任務 ID 取消已排程的任務。
| Parameter | Type | Notes |
|---|---|---|
taskId | int | 由 run_later 或 run_repeating 回傳的任務 ID |
若啟動了重複任務,務必在清理 hook 中將其取消(道具用 on_destroy、Boss 用 on_exit_combat / on_death、物品用 on_unequip)。忘記取消會留下背景任務一直執行直到腳本實例被銷毀,浪費效能並可能導致錯誤。
排程回呼會收到一個全新的 context 作為參數。永遠使用回呼自己的 context 參數,而非建立該回呼的外層 hook 中的 context。外層 context 可能含有過時的參考。
context.world
world 表提供查詢與互動 Minecraft 世界的方法。它由實體當前所在的世界建立。
EliteMobs 為 context.world 擴充了額外方法,用於生成 Boss、增援、掉落方塊、煙火、濺射藥水與暫時方塊。完整擴充 API 請參見 EliteMobs World & Environment。此處記載的方法在所有外掛中皆可使用。
world.name
包含世界名稱的字串欄位。
world:get_block_at(x, y, z)
回傳指定座標方塊的材質名稱(小寫字串,如 "stone"、"air")。
| Parameter | Type | Notes |
|---|---|---|
x | int | 方塊 X 座標 |
y | int | 方塊 Y 座標 |
z | int | 方塊 Z 座標 |
world:set_block_at(x, y, z, material)
設定指定座標的方塊。在主執行緒上執行。
| Parameter | Type | Notes |
|---|---|---|
x | int | 方塊 X 座標 |
y | int | 方塊 Y 座標 |
z | int | 方塊 Z 座標 |
material | string | Bukkit Material 名稱,小寫(例如 "stone"、"air"、"oak_planks") |
若方塊成功設定則回傳 true,否則為 false。
world:spawn_particle(particle, x, y, z, count, dx, dy, dz, speed)
於指定位置生成粒子。
| Parameter | Type | Default | Notes |
|---|---|---|---|
particle | string | required | Bukkit Particle 列舉名稱,大寫(例如 "FLAME"、"DUST") |
x | number | required | X 座標 |
y | number | required | Y 座標 |
z | number | required | Z 座標 |
count | int | 1 | 粒子數量 |
dx | number | 0 | X 分散/偏移 |
dy | number | 0 | Y 分散/偏移 |
dz | number | 0 | Z 分散/偏移 |
speed | number | 0 | 粒子速度 |
某些粒子類型需要方塊或物品資料,而這個簡易 API 並不支援。BLOCK_CRACK、FALLING_DUST、BLOCK_DUST 與 ITEM_CRACK 會失敗或無可見效果。請改用無需資料的替代品:CLOUD、SMOKE、CAMPFIRE_COSY_SMOKE、SNOWFLAKE、FLAME、DUST 等。
world:play_sound(sound, x, y, z, volume, pitch)
於指定位置播放音效。
| Parameter | Type | Default | Notes |
|---|---|---|---|
sound | string | required | Bukkit Sound 列舉名稱,大寫(例如 "ENTITY_EXPERIENCE_ORB_PICKUP") |
x | number | required | X 座標 |
y | number | required | Y 座標 |
z | number | required | Z 座標 |
volume | number | 1.0 | 音量 |
pitch | number | 1.0 | 音高 |
world:strike_lightning(x, y, z)
於指定位置降下閃電(具視覺效果並造成傷害)。
| Parameter | Type | Notes |
|---|---|---|
x | number | X 座標 |
y | number | Y 座標 |
z | number | Z 座標 |
world:get_time()
回傳目前世界時間(ticks)。
world:set_time(ticks)
設定世界時間。
| Parameter | Type | Notes |
|---|---|---|
ticks | int | 世界時間(0 = 日出,6000 = 中午,13000 = 夜晚,18000 = 午夜) |
world:get_nearby_entities(x, y, z, radius)
回傳指定座標為中心、在邊界盒內所有實體的包裝表陣列。
| Parameter | Type | Notes |
|---|---|---|
x | number | 中心 X |
y | number | 中心 Y |
z | number | 中心 Z |
radius | number | 搜尋半徑(在三軸上皆作為半延伸值使用) |
此方法會回傳範圍內所有實體,包括非生物實體(盔甲架、掉落物品等)。在呼叫生物實體方法前,請永遠先用 if entity.damage then 加以判斷。
world:get_nearby_players(x, y, z, radius)
回傳指定座標為中心、在邊界盒內所有玩家的包裝表陣列。
| Parameter | Type | Notes |
|---|---|---|
x | number | 中心 X |
y | number | 中心 Y |
z | number | 中心 Z |
radius | number | 搜尋半徑 |
world:spawn_entity(entity_type, x, y, z)
於指定位置生成原版 Minecraft 實體。
| Parameter | Type | Notes |
|---|---|---|
entity_type | string | Bukkit 實體類型名稱,小寫(例如 "zombie"、"skeleton"、"pig") |
x | number | X 座標 |
y | number | Y 座標 |
z | number | Z 座標 |
回傳所生成實體的實體表(若為生物實體則含生物實體方法),若實體類型無效則回傳 nil。
world:get_highest_block_y(x, z)
回傳指定 X/Z 位置最高非空氣方塊的 Y 座標。
| Parameter | Type | Notes |
|---|---|---|
x | int | 方塊 X 座標 |
z | int | 方塊 Z 座標 |
world:raycast(from_x, from_y, from_z, dir_x, dir_y, dir_z, [max_distance])
從一個點朝一個方向射出射線,並回傳所擊中物的資訊。
| Parameter | Type | Default | Notes |
|---|---|---|---|
from_x | number | required | 起點 X |
from_y | number | required | 起點 Y |
from_z | number | required | 起點 Z |
dir_x | number | required | 方向 X 分量 |
dir_y | number | required | 方向 Y 分量 |
dir_z | number | required | 方向 Z 分量 |
max_distance | number | 50 | 射線最大距離 |
回傳含下列欄位的表:
| Field | Type | Notes |
|---|---|---|
hit_entity | entity table or nil | 射線擊中的第一個實體,若無則為 nil |
hit_location | location table or nil | 射線擊中物的精確位置 |
hit_block | table or nil | 擊中方塊的 {x, y, z, material},若未擊中方塊則為 nil |
world:spawn_firework(x, y, z, colors, [type], [power])
於指定位置生成煙火火箭。
| Parameter | Type | Default | Notes |
|---|---|---|---|
x | number | required | X 座標 |
y | number | required | Y 座標 |
z | number | required | Z 座標 |
colors | table | required | 顏色字串陣列,例如 {"RED", "BLUE", "WHITE"} |
type | string | "BALL" | 煙火形狀:"BALL"、"BALL_LARGE"、"STAR"、"BURST"、"CREEPER" |
power | int | 1 | 飛行高度,0-127 |
-- Example: red and gold firework burst
context.world:spawn_firework(loc.x, loc.y, loc.z, {"RED", "GOLD"}, "BURST", 2)
world:place_temporary_block(x, y, z, material, [ticks], [require_air])
放置一個會在延遲後自動還原為原本狀態的方塊。
| Parameter | Type | Default | Notes |
|---|---|---|---|
x | int | required | 方塊 X 座標 |
y | int | required | 方塊 Y 座標 |
z | int | required | 方塊 Z 座標 |
material | string | required | Bukkit Material 名稱(例如 "stone"、"ice") |
ticks | int | 0 | 方塊還原前的時間(ticks)。0 表示永久。 |
require_air | boolean | false | 若為 true,僅在目標為空氣時放置方塊 |
若方塊成功放置則回傳 true,若材質無效或未滿足空氣需求則回傳 false。
world:drop_item(x, y, z, material, [amount])
於指定位置自然散落物品實體。
| Parameter | Type | Default | Notes |
|---|---|---|---|
x | number | required | X 座標 |
y | number | required | Y 座標 |
z | number | required | Z 座標 |
material | string | required | Bukkit Material 名稱 |
amount | int | 1 | 堆疊大小 |
回傳所掉落物品的實體表,若材質無效則回傳 nil。
context.zones
zones 表讓你建立空間區域,並監控玩家進入/離開事件。區域會綁定至腳本實例,當腳本實例被銷毀時會自動清理。
zones:create_sphere(x, y, z, radius)
於指定座標為中心建立球形區域。回傳數字區域 handle。
| Parameter | Type | Notes |
|---|---|---|
x | number | 中心 X |
y | number | 中心 Y |
z | number | 中心 Z |
radius | number | 球體半徑 |
zones:create_cylinder(x, y, z, radius, height)
建立圓柱區域。回傳數字區域 handle。
| Parameter | Type | Notes |
|---|---|---|
x | number | 中心 X |
y | number | 中心 Y(底部) |
z | number | 中心 Z |
radius | number | 圓柱半徑 |
height | number | 圓柱高度 |
zones:create_cuboid(x, y, z, xSize, ySize, zSize)
建立長方體區域。回傳數字區域 handle。
| Parameter | Type | Notes |
|---|---|---|
x | number | 中心 X |
y | number | 中心 Y |
z | number | 中心 Z |
xSize | number | X 軸半延伸 |
ySize | number | Y 軸半延伸 |
zSize | number | Z 軸半延伸 |
zones:watch(handle, onEnterCallback, onLeaveCallback)
開始監控區域的玩家進入/離開事件。回呼參數作為布林訊號 —— 傳入非 nil 值(例如函式或 true)會啟用腳本上對應的 hook。回呼本身不會被直接呼叫;進入/離開的邏輯會透過腳本的 on_zone_enter / on_zone_leave hooks 觸發。
| Parameter | Type | Notes |
|---|---|---|
handle | int | 從 create_* 呼叫取得的區域 handle |
onEnterCallback | any non-nil or nil | 非 nil 會為此區域啟用 on_zone_enter hook |
onLeaveCallback | any non-nil or nil | 非 nil 會為此區域啟用 on_zone_leave hook |
若監控設定成功則回傳 true,若區域 handle 無效則回傳 nil。
區域監控會在每個伺服器 tick 對同世界內所有玩家進行檢查。請將區域數量控制在合理範圍,以避免效能負擔。
zones:unwatch(handle)
停止監控區域,並清理其資源。
| Parameter | Type | Notes |
|---|---|---|
handle | int | 要停止監控的區域 handle |
範例:接近觸發區域
return {
api_version = 1,
on_spawn = function(context)
local loc = context.prop.current_location -- or context.boss:get_location()
if loc == nil then return end
local handle = context.zones:create_sphere(loc.x, loc.y, loc.z, 5)
-- Pass non-nil values to enable on_zone_enter and on_zone_leave hooks.
-- These are boolean signals, not callbacks — the actual logic goes in the hooks below.
context.zones:watch(handle, true, true)
context.state.zone_handle = handle
end,
on_zone_enter = function(context)
context.log:info("Player entered zone!")
end,
on_zone_leave = function(context)
context.log:info("Player left zone!")
end,
on_destroy = function(context)
if context.state.zone_handle then
context.zones:unwatch(context.state.zone_handle)
end
end
}
context.event
當前 hook 由遊戲事件觸發時(例如 on_right_click、on_zone_enter)會出現 event 表。在 on_game_tick 或排程回呼期間不會出現。
| Field / Method | Type | Notes |
|---|---|---|
is_cancelled | boolean | 事件是否已被取消 |
cancel() | method | 取消事件(阻止預設行為) |
uncancel() | method | 解除先前取消的事件 |
player | entity table | 事件中涉及的玩家(若有) |
on_right_click = function(context)
if context.event then
context.event:cancel() -- prevent the default right-click interaction
end
end
EliteMobs 能力腳本擁有更詳盡的事件表,包含傷害量、傷害原因、傷害者參考與傷害修改方法。完整 EliteMobs 事件欄位請參見 Lua API Reference。
em 輔助命名空間
em 表在檔案載入時就可使用(在任何 hook 執行之前)。它提供建立位置表、向量表與區域定義(在整個 API 中使用)的輔助建構函式。
| Function | Purpose |
|---|---|
em.create_location(x, y, z [, world, yaw, pitch]) | 建立位置表,可選 world 名稱、yaw 與 pitch。回傳的表還有一個 .add(dx, dy, dz) 方法,可就地偏移位置並回傳自身以便鏈式呼叫。 |
em.create_vector(x, y, z) | 建立向量表 |
em.zone.create_sphere_zone(radius) | 建立球形區域定義 |
em.zone.create_dome_zone(radius) | 建立穹頂區域定義 |
em.zone.create_cylinder_zone(radius, height) | 建立圓柱區域定義 |
em.zone.create_cuboid_zone(x, y, z) | 建立長方體區域定義 |
em.zone.create_cone_zone(length, radius) | 建立錐形區域定義 |
em.zone.create_static_ray_zone(length, thickness) | 建立靜態射線區域定義 |
em.zone.create_rotating_ray_zone(length, point_radius, animation_duration) | 建立旋轉射線區域定義 |
em.zone.create_translating_ray_zone(length, point_radius, animation_duration) | 建立平移射線區域定義 |
em.location.is_in_dungeon(loc) | 檢查位置是否位於任何已註冊的地下城區域內 |
em.location.is_protected(loc) | 檢查位置是否位於任何受保護的區域內(WorldGuard、GriefPrevention、EM 區域等) |
em.location.owned_by(loc, namespace) | 檢查特定外掛命名空間是否擁有該位置(例如 "EliteMobs") |
em.location.owners(loc) | 擁有該位置的命名空間字串陣列 |
em.location.kinds_at(loc) | 該位置的種類標籤陣列("elitemobs"、"world_package"、"open_world_dungeon"、地下城大小分類) |
em.location.has_kind(loc, kind) | 檢查位置是否帶有指定種類的標籤 |
區域建構函式會回傳可鏈式呼叫的表,具有 :set_center(loc)(或依區域類型不同的 :set_origin(loc) / :set_destination(loc))方法:
-- At file scope: create a reusable zone shape
local blast_zone = em.zone.create_sphere_zone(5)
return {
api_version = 1,
on_spawn = function(context)
-- Anchor the zone at call time
blast_zone:set_center(context.boss:get_location())
local entities = context.zones:get_entities_in_zone(blast_zone)
-- ...
end
}
em 命名空間在 EliteMobs 中特別有用,因為區域定義會與 context.zones:get_entities_in_zone() 及 context.script 一同使用。在 FreeMinecraftModels 中,context.zones:create_sphere(...) / create_cylinder(...) / create_cuboid(...) 方法更常用於簡單的監控型區域。
實體表
實體表會從世界查詢、事件資料與區域回呼中回傳。它們依實體類型提供分層的欄位與方法。
實體基本欄位
| Field | Type | Notes |
|---|---|---|
uuid | string | 實體的 UUID |
entity_type | string | 實體類型(例如 "player"、"zombie"、"skeleton"、"villager") |
is_valid | boolean | 實體參考是否仍有效 |
is_dead | boolean | 實體是否已死亡 |
is_player | boolean | 實體是否為玩家 |
is_hostile | boolean | 實體是否為敵對生物(殭屍、骷髏等) |
is_passive | boolean | 實體是否為被動生物(牛、豬、雞等) |
current_location | location table | 實體當前位置(x、y、z、world、yaw、pitch) |
world | string | 實體所在的世界名稱 |
實體基本方法
| Method | Returns | Notes |
|---|---|---|
teleport(location_table) | void | 傳送實體。位置表需包含 x、y、z、world 欄位;yaw 與 pitch 為可選。 |
remove() | void | 從世界中移除實體。僅在實體仍有效時生效。 |
set_silent(flag) | void | 抑制或重新啟用實體聲音。 |
set_invulnerable(flag) | void | 使實體無敵或可受傷。 |
set_gravity(flag) | void | 啟用或停用實體重力。 |
set_glowing(flag) | void | 切換實體的發光輪廓效果。 |
生物實體欄位
生物實體(玩家、生物等)擁有所有實體基本欄位之外,還包括:
| Field | Type | Notes |
|---|---|---|
health | number | 當前生命值 |
maximum_health | number | 最大生命值 |
name | string | 顯示名稱 |
is_alive | boolean | 實體是否存活 |
生物實體方法
| Method | Returns | Notes |
|---|---|---|
damage(amount) | void | 對實體造成指定數量的傷害 |
push(x, y, z) | void | 套用速度衝量 |
set_facing(x, y, z) | void | 設定實體面朝方向 |
add_potion_effect(effect, duration, amplifier) | void | 加上藥水效果。effect 為字串(如 "speed"、"slowness"、"regeneration")。duration 以 ticks 計。amplifier 為效果等級減 1(0 = 等級 I)。 |
remove_potion_effect(effect) | void | 依名稱移除藥水效果 |
get_scale() | number | 回傳當前實體縮放比例(在沒有 generic.scale 屬性的伺服器上預設為 1.0) |
set_scale(value) | void | 透過 generic.scale 屬性設定實體縮放比例。在 1.20.5 之前的伺服器上無作用。 |
並非所有由 get_nearby_entities() 回傳的實體都是生物實體。可以使用 entity.is_player、entity.is_hostile 或 entity.is_passive 依分類過濾,或在呼叫 damage()、push()、add_potion_effect() 等生物實體方法前以 if entity.damage then 加以判斷。
外掛整合欄位
實體表會自動包含偵測與互動其他 Nightbreak 外掛所管理之實體的欄位。這些欄位僅在對應外掛安裝時才會被填入 —— 否則預設為 false / nil 並無額外開銷。
EliteMobs 欄位
當 EliteMobs 已安裝時可用。
| Field | Type | Notes |
|---|---|---|
is_elite | boolean | 實體是否為 EliteMobs 精英 |
is_custom_boss | boolean | 實體是否為 EliteMobs 自訂 Boss(也可在 elite 子表中取得) |
is_significant_boss | boolean | 實體是否為生命值倍率超過 1 的自訂 Boss(即設計過的戰鬥,而非普通的精英) |
elite | table or nil | 精英資訊子表(見下)。若實體非精英則為 nil。 |
elite 子表包含:
| Field | Type | Notes |
|---|---|---|
elite.level | int | 精英的等級 |
elite.name | string | 精英的顯示名稱 |
elite.health | number | 當前生命值 |
elite.max_health | number | 最大生命值 |
elite.is_custom_boss | boolean | 是否為自訂 Boss(相對於天然精英) |
elite.health_multiplier | number | 設定檔定義的生命值倍率 |
elite.damage_multiplier | number | 設定檔定義的傷害倍率 |
elite:remove() | void | 透過 EliteMobs 的標準移除流程移除精英(清理追蹤、戰利品等) |
範例:對精英採用不同傷害
local entities = context.world:get_nearby_entities(x, y, z, 5)
for _, entity in ipairs(entities) do
if entity.is_elite then
-- Deal double damage to elites
entity:damage(20)
context.log:info("Hit elite: " .. entity.elite.name .. " (level " .. entity.elite.level .. ")")
elseif entity.is_hostile then
entity:damage(10)
end
end
FreeMinecraftModels 欄位
當 FreeMinecraftModels 已安裝時可用。
| Field | Type | Notes |
|---|---|---|
is_modeled | boolean | 實體是否附加 FMM 模型(DynamicEntity 或 PropEntity) |
is_prop | boolean | 實體是否為 FMM 道具(靜態裝飾用實體) |
model | table or nil | 模型資訊子表(見下)。若實體未附帶模型則為 nil。 |
model 子表包含:
| Field | Type | Notes |
|---|---|---|
model.model_id | string | 模型藍圖 ID(例如 "torch_01") |
model.is_dynamic | boolean | 帶模型的實體是否為 DynamicEntity(生物/Boss 模型)而非靜態道具 |
model:play_animation(name, [blend], [loop]) | boolean | 播放命名動畫。blend 預設為 false,loop 預設為 false。若找到動畫則回傳 true。 |
model:stop_animations() | void | 停止模型上目前所有正在播放的動畫。 |
model:remove() | void | 透過 FMM 的標準移除流程移除帶模型的實體。 |
模型橋接(在任何實體上皆可用)預設 blend 與 loop 為 false。道具表 的 play_animation 預設兩者皆為 true,因為道具通常會希望使用混合且循環的動畫。
範例:依類型過濾實體
local entities = context.world:get_nearby_entities(x, y, z, 10)
for _, entity in ipairs(entities) do
if entity.is_prop then
-- Skip props
elseif entity.is_player then
entity:damage(5)
elseif entity.entity_type == "villager" then
-- Don't hurt villagers
elseif entity.is_elite then
entity:damage(20)
elseif entity.is_hostile then
entity:damage(10)
end
end
玩家專屬欄位
玩家實體在所有實體與生物實體欄位之外還包含:
| Field | Type | Notes |
|---|---|---|
game_mode | string | 玩家的遊戲模式("creative"、"survival"、"adventure"、"spectator") |
玩家專屬方法
| Method | Returns | Notes |
|---|---|---|
send_message(msg) | void | 對玩家傳送聊天訊息。支援 & 色碼。 |
get_held_item() | table or nil | 回傳 {type, amount, display_name}(對應玩家主手物品),若空手則回傳 nil |
consume_held_item(amount?) | void | 消耗玩家主手物品。amount 預設為 1 |
has_item(material, amount?) | boolean | 若玩家物品欄任何位置至少有 amount(預設 1)數量的指定材質則回傳 true |
get_target_entity([range]) | entity table or nil | 透過射線回傳玩家正注視的實體,若無則為 nil。預設範圍為 50。 |
get_eye_location() | location table | 回傳玩家眼睛高度的位置表 |
get_look_direction() | table | 回傳玩家視線方向的 {x, y, z} 方向向量 |
send_block_change(x, y, z, material, [ticks]) | boolean | 傳送僅該玩家可見的虛擬方塊。若提供 ticks,虛擬方塊會在該時間後自動還原。成功回傳 true,材質無效則為 false。 |
reset_block(x, y, z) | boolean | 為該玩家將虛擬方塊還原為實際方塊。永遠回傳 true。 |
sleep(x, y, z) | void | 讓玩家於指定座標進入床上睡眠動畫。玩家停止睡眠時方塊會自動還原。 |
wake_up() | void | 喚醒正在睡眠的玩家。 |
玩家 UI 方法
下列方法可用於任何玩家實體表,提供透過 Minecraft 內建 UI 元素向玩家顯示資訊的方式。
player:show_boss_bar(text, [color], progress, [ticks])
對玩家顯示 Boss 血條。
| Parameter | Type | Default | Notes |
|---|---|---|---|
text | string | required | 要顯示的文字。支援 & 色碼。 |
color | string | "WHITE" | 血條顏色。可為:"RED"、"BLUE"、"GREEN"、"YELLOW"、"PURPLE"、"PINK"、"WHITE" |
progress | number | required | 填充量,從 0.0(空)到 1.0(滿) |
ticks | int | nil | 可選的自動關閉延遲(ticks)。若省略,血條會持續顯示直到手動隱藏。 |
player:hide_boss_bar()
從玩家畫面上移除 Boss 血條。不需參數。
player:show_action_bar(text, [ticks])
於動作列區域(快捷欄上方)顯示文字。
| Parameter | Type | Default | Notes |
|---|---|---|---|
text | string | required | 要顯示的文字。支援 & 色碼。 |
ticks | int | nil | 可選的持續時間(ticks)。若提供,訊息會每 40 ticks 重新傳送,以維持整段時間的可見性。 |
player:show_title(title, [subtitle], fade_in, stay, fade_out)
向玩家顯示標題畫面。
| Parameter | Type | Default | Notes |
|---|---|---|---|
title | string | required | 主標題文字。支援 & 色碼。 |
subtitle | string | "" | 主標題下方的副標題。可選。 |
fade_in | int | required | 淡入持續 ticks |
stay | int | required | 標題在畫面上停留的 ticks |
fade_out | int | required | 淡出持續 ticks |
下一步
各外掛專屬的 hooks、API 與工作流程:
- EliteMobs: 開始使用 | Hooks 與生命週期 | Boss 與實體 | 世界與環境 | 區域與目標
- FreeMinecraftModels: 開始使用 | Prop 與 Item API | 範例