跳至主要内容

Lua 腳本:Prop API

本頁涵蓋了 FreeMinecraftModels prop 腳本可用的所有 API:context.propcontext.eventcontext.worldcontext.zonescontext.schedulercontext.statecontext.log。如果您是 prop 腳本的新手,請先從入門指南開始。


context.prop

prop 表提供關於 prop 實體的資訊以及控制其動畫的方法。它在每次 hook 呼叫時重新建構。

欄位

欄位類型說明
prop.model_idstringblueprint 模型名稱(例如 "torch_01"
prop.current_locationlocation table建構上下文時 prop 的位置

location 表具有標準欄位:xyzworldyawpitch

範例:讀取 prop 資訊
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)

在 prop 模型上播放指定名稱的動畫。

參數類型預設值說明
namestring必填模型檔案中定義的動畫名稱
blendbooleantrue是否與目前動畫混合
loopbooleantrue動畫是否循環播放

如果找到並啟動了動畫則回傳 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()

停止 prop 上目前播放的所有動畫。

不接受任何參數。

範例
return {
api_version = 1,

on_right_click = function(context)
context.prop:stop_animation()
end
}

context.event

目前 hook 的事件資料。在 on_left_clickon_right_clickon_projectile_hit 中可用。在沒有關聯事件的 hook 中回傳 nilon_spawnon_game_tickon_destroyon_zone_enteron_zone_leave)。

欄位和方法

欄位或方法類型說明
event.is_cancelledboolean事件目前是否已被取消
event.cancel()function取消事件(例如阻止傷害或互動)
event.uncancel()function撤銷之前取消的事件
資訊

並非所有事件都可以取消。如果底層 Bukkit 事件未實作 Cancellable,則 event.cancel()event.uncancel() 不存在,event.is_cancelled 始終為 false

範例:使 prop 無敵

範例
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_laterscheduler:run_repeating),context.event 始終為 nil。事件修改只能在事件 hook 本身中進行。


context.world

world 表提供查詢和與 Minecraft 世界互動的方法。它基於 prop 目前所在的世界建構。

共用 API

context.world API 與 EliteMobs 共用。FMM prop 使用與 EliteMobs Boss 相同的 Magmacore world 表。此處記載的方法是 Magmacore 基礎實作中可用的方法。完整參考請查看 EliteMobs World & Environment 頁面——其中列出的作為核心 context.world API 一部分的方法在 FMM 中同樣可用。

world.name

包含世界名稱的 string 欄位。


world:get_block_at(x, y, z)

回傳給定座標處方塊的材質名稱,為小寫字串(例如 "stone""air")。

參數類型說明
xint方塊 X 座標
yint方塊 Y 座標
zint方塊 Z 座標
範例
return {
api_version = 1,

on_spawn = function(context)
local loc = context.prop.current_location
if loc then
local block = context.world:get_block_at(
math.floor(loc.x),
math.floor(loc.y) - 1,
math.floor(loc.z)
)
context.log:info("Prop is standing on: " .. block)
end
end
}

world:spawn_particle(particle, x, y, z, count, dx, dy, dz, speed)

在指定位置生成粒子。

參數類型預設值說明
particlestring必填Bukkit Particle 列舉名稱,大寫(例如 "FLAME""DUST"
xnumber必填X 座標
ynumber必填Y 座標
znumber必填Z 座標
countint1粒子數量
dxnumber0X 擴散/偏移
dynumber0Y 擴散/偏移
dznumber0Z 擴散/偏移
speednumber0粒子速度
範例
return {
api_version = 1,

on_right_click = function(context)
local loc = context.prop.current_location
if loc then
context.world:spawn_particle("HEART", loc.x, loc.y + 1, loc.z, 5, 0.3, 0.3, 0.3, 0)
end
end
}

world:play_sound(sound, x, y, z, volume, pitch)

在指定位置播放聲音。

參數類型預設值說明
soundstring必填Bukkit Sound 列舉名稱,大寫(例如 "ENTITY_EXPERIENCE_ORB_PICKUP"
xnumber必填X 座標
ynumber必填Y 座標
znumber必填Z 座標
volumenumber1.0音量
pitchnumber1.0音調
範例
return {
api_version = 1,

on_right_click = function(context)
local loc = context.prop.current_location
if loc then
context.world:play_sound("BLOCK_NOTE_BLOCK_PLING", loc.x, loc.y, loc.z, 1.0, 1.2)
end
end
}

world:strike_lightning(x, y, z)

在指定位置劈下閃電(視覺效果並造成傷害)。

參數類型說明
xnumberX 座標
ynumberY 座標
znumberZ 座標
範例
return {
api_version = 1,

on_projectile_hit = function(context)
local loc = context.prop.current_location
if loc then
context.world:strike_lightning(loc.x, loc.y, loc.z)
end
end
}

world:get_time()

回傳目前世界時間(以 tick 為單位)。


world:set_time(ticks)

設定世界時間。

參數類型說明
ticksint世界時間(0 = 黎明,6000 = 正午,13000 = 夜晚,18000 = 午夜)

world:get_nearby_entities(x, y, z, radius)

回傳以給定座標為中心的邊界框內所有存活實體的實體包裝表陣列。

參數類型說明
xnumber中心 X
ynumber中心 Y
znumber中心 Z
radiusnumber搜尋半徑(在三個軸上均用作半範圍)
範例
return {
api_version = 1,

on_right_click = function(context)
local loc = context.prop.current_location
if loc then
local entities = context.world:get_nearby_entities(loc.x, loc.y, loc.z, 10)
context.log:info("Found " .. #entities .. " entities nearby")
end
end
}

world:get_nearby_players(x, y, z, radius)

回傳以給定座標為中心的邊界框內所有玩家的玩家包裝表陣列。

參數類型說明
xnumber中心 X
ynumber中心 Y
znumber中心 Z
radiusnumber搜尋半徑
範例
return {
api_version = 1,

on_right_click = function(context)
local loc = context.prop.current_location
if loc then
local players = context.world:get_nearby_players(loc.x, loc.y, loc.z, 20)
for i = 1, #players do
context.log:info("Nearby player: " .. (players[i].name or "unknown"))
end
end
end
}

context.zones

zones 表允許您建立空間區域並監視玩家進入/離開事件。區域繫結到腳本實例,並在 prop 被移除時自動清理。

zones:create_sphere(x, y, z, radius)

在給定座標處建立球形區域。回傳一個數字區域控制代碼。

參數類型說明
xnumber中心 X
ynumber中心 Y
znumber中心 Z
radiusnumber球體半徑

zones:create_cylinder(x, y, z, radius, height)

建立圓柱形區域。回傳一個數字區域控制代碼。

參數類型說明
xnumber中心 X
ynumber中心 Y(底部)
znumber中心 Z
radiusnumber圓柱半徑
heightnumber圓柱高度

zones:create_cuboid(x, y, z, xSize, ySize, zSize)

建立長方體區域。回傳一個數字區域控制代碼。

參數類型說明
xnumber中心 X
ynumber中心 Y
znumber中心 Z
xSizenumberX 方向半範圍
ySizenumberY 方向半範圍
zSizenumberZ 方向半範圍

zones:watch(handle, onEnterCallback, onLeaveCallback)

開始監視區域的玩家進入/離開事件。當玩家進入或離開區域時,相應的 hook 會觸發(on_zone_enteron_zone_leave)。

參數類型說明
handleint來自 create_* 呼叫的區域控制代碼
onEnterCallbackfunction 或 nil當玩家進入區域時呼叫
onLeaveCallbackfunction 或 nil當玩家離開區域時呼叫

如果監視設定成功則回傳 true,如果區域控制代碼無效則回傳 nil

資訊

區域監視在每個伺服器 tick 對同一世界中的所有玩家進行檢查。請保持合理的區域數量以避免效能開銷。


zones:unwatch(handle)

停止監視區域並清理其資源。

參數類型說明
handleint要停止監視的區域控制代碼

範例:近距離觸發區域

範例
return {
api_version = 1,

on_spawn = function(context)
local loc = context.prop.current_location
if loc == nil then return end

-- Create a sphere zone around the prop
local handle = context.zones:create_sphere(loc.x, loc.y, loc.z, 5)

-- Watch for player enter/leave
context.zones:watch(
handle,
function(player)
context.log:info("Player entered zone!")
end,
function(player)
context.log:info("Player left zone!")
end
)

-- Store handle so we can clean up later if needed
context.state.zone_handle = handle
end,

on_destroy = function(context)
if context.state.zone_handle then
context.zones:unwatch(context.state.zone_handle)
end
end
}

context.scheduler

scheduler 允許您執行延遲和重複任務。所有任務歸腳本實例所有,並在 prop 被移除時自動取消。

scheduler:run_later(ticks, callback)

延遲後執行一次回呼。回傳一個數字任務 ID。

參數類型說明
ticksint以伺服器 tick 為單位的延遲(20 tick = 1 秒)
callbackfunction延遲到期時以新的 context 呼叫
範例
return {
api_version = 1,

on_right_click = function(context)
context.log:info("Something will happen in 2 seconds...")

context.scheduler:run_later(40, function(delayed_context)
local loc = delayed_context.prop.current_location
if loc then
delayed_context.world:spawn_particle("EXPLOSION_EMITTER", loc.x, loc.y, loc.z, 1)
end
end)
end
}

scheduler:run_repeating(delay, interval, callback)

以固定間隔重複執行回呼。回傳一個數字任務 ID。

參數類型說明
delayint第一次執行前的初始延遲(tick)
intervalint每次後續執行之間的 tick 數
callbackfunction每個間隔以新的 context 呼叫
範例
return {
api_version = 1,

on_spawn = function(context)
-- Emit particles every second
context.state.particle_task = context.scheduler:run_repeating(0, 20, function(tick_context)
local loc = tick_context.prop.current_location
if loc then
tick_context.world:spawn_particle("FLAME", loc.x, loc.y + 1, loc.z, 3, 0.1, 0.1, 0.1, 0.02)
end
end)
end,

on_destroy = function(context)
if context.state.particle_task then
context.scheduler:cancel(context.state.particle_task)
end
end
}

scheduler:cancel(taskId)

透過 ID 取消已排程的任務。

參數類型說明
taskIdintrun_laterrun_repeating 回傳的任務 ID
務必取消重複任務

如果您啟動了重複任務,務必在 on_destroy 中(或不再需要時)取消它。忘記取消會導致背景任務一直執行直到 prop 從伺服器移除,浪費效能並可能導致錯誤。


context.state

一個在 prop 整個生命週期內持久化的普通 Lua 表。用於儲存旗標、計數器、任務 ID、切換狀態以及需要在 hook 之間共用的任何資料。

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.propcontext.worldcontext.event 等)每次都會重新建構。


context.log

主控台日誌方法。訊息在伺服器主控台中以腳本檔案名稱為前綴。

方法說明
log:info(message)資訊訊息
log:warn(message)警告訊息
log:error(message)錯誤訊息(功能上與 warn 相同)
範例
return {
api_version = 1,

on_spawn = function(context)
context.log:info("Script loaded!")
end,

on_right_click = function(context)
context.log:warn("Prop was clicked -- this is a debug warning")
end
}

執行階段模型

每個 prop 一個執行階段

每個附加了腳本的 prop 實體都會取得自己獨立的 Lua 執行階段實例。當 prop 生成時,FMM 載入 Lua 原始碼,在新的沙盒環境中執行,並儲存回傳的表。當 prop 被移除時,執行階段會關閉。

這意味著:

  • 在檔案作用域宣告的區域變數對該 prop 實例是私有的。
  • context.state 在 prop 實例之間完全隔離,即使它們共用相同的腳本檔案。

任務擁有權

透過 context.scheduler 建立的所有任務歸建立它們的執行階段所有。當 prop 被移除時:

  1. 執行階段關閉。
  2. 所有擁有的任務——無論是一次性的還是重複的——都會自動取消。
  3. 所有區域監視都會被清除。

執行預算

每次 hook 呼叫和每次回呼呼叫都會計時。如果單次呼叫超過 50 毫秒,腳本將被停用並在主控台顯示警告:

[Lua] my_script.lua took 73ms in 'on_game_tick' (limit: 50ms) -- script disabled to prevent lag.

為了保持在預算內:

  • 避免在 hook 中使用無限迴圈。
  • 保持 on_game_tick 處理程式輕量——它們每個 tick 都會執行。
  • 使用 context.scheduler:run_repeating(...) 將工作分散到多個 tick 中。

後續步驟