MagmaCore Lua 脚本引擎
MagmaCore 提供了一个共享的 Lua 脚本引擎,供多个 Nightbreak 插件使用。该引擎处理沙盒、调度、区域管理、世界交互、实体表和玩家界面——所有这些都具有跨插件的一致 API。
目前,以下插件使用此引擎:
- EliteMobs -- 自定义 Boss 的 Lua 技能(钩子如
on_boss_damaged_by_player、on_enter_combat等) - FreeMinecraftModels -- 道具和自定义物品的 Lua 脚本(钩子如
on_right_click、on_left_click、on_equip等)
本页面介绍共享引擎功能。有关插件特定的钩子、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
这表示"如果此钩子没有对应的玩家,则在此停止"。
nil
nil 表示"没有值"。它是 Lua 中"这里什么都没有"的表达。
你经常会用以下方式检查 nil:
if context.event ~= nil then
-- do something with the event
end
~= 表示"不等于"。
表
Lua 使用表(table)完成多种功能:
- 列表
- 带命名键的对象
- 最终返回的脚本定义
带命名键的表示例:
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,不可使用:
| 已移除 | 原因 |
|---|---|
debug | 暴露内部虚拟机状态 |
dofile | 文件系统访问 |
io | 文件系统访问 |
load | 任意代码加载 |
loadfile | 文件系统访问 |
luajava | 直接 Java 类访问 |
module | 模块系统(不需要) |
os | 操作系统访问 |
package | 模块系统(不需要) |
require | 模块系统 / 文件系统访问 |
可用的标准库
Lua 标准库的其余部分正常工作:
| 类别 | 函数 |
|---|---|
| 数学 | math.abs、math.ceil、math.floor、math.max、math.min、math.random、math.sin、math.cos、math.sqrt、math.pi 以及所有其他 math.* 函数 |
| 字符串 | string.byte、string.char、string.find、string.format、string.gsub、string.len、string.lower、string.match、string.rep、string.sub、string.upper 以及所有其他 string.* 函数 |
| 表 | table.insert、table.remove、table.sort、table.concat 以及所有其他 table.* 函数 |
| 迭代器 | pairs、ipairs、next |
| 类型 | type、tostring、tonumber、select、unpack |
| 错误处理 | pcall、xpcall、error、assert |
| 其他 | print、rawget、rawset、rawequal、rawlen、setmetatable、getmetatable |
os 库不可用os 库已从沙盒中完全移除。如果你需要计时信息,请使用 context.world:get_time() 获取世界时间,或使用 on_tick / on_game_tick 中的 tick 计数器在 context.state 中存储时间戳。
print 会输出到服务器控制台,但建议使用 context.log:info(msg) 进行输出。日志消息会以脚本文件名作为前缀,更容易追踪是哪个脚本产生的消息。
文件规范
每个 Lua 脚本必须 return 一个表。该表有严格的格式要求。
必需和可选的顶层字段
| 字段 | 必需 | 类型 | 说明 |
|---|---|---|---|
api_version | 是 | Number | 当前必须为 1 |
priority | 否 | Number | 执行优先级。值越小越先执行。默认为 0 |
| 支持的钩子键 | 否 | Function | 必须使用插件支持的确切钩子名称 |
验证规则
- 文件必须返回一个表。
api_version是必需的,当前必须为1。priority如果存在必须为数值。- 每个额外的顶层键必须是支持的钩子名称。
- 每个钩子键必须指向一个函数。
- 未知的顶层键会被拒绝。
辅助函数和局部常量应放在最终 return 之前,而不是在返回的表内部(除非它们是实际的钩子)。
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
}
方法语法:: 与 .
在 Lua 中,object:method(arg) 是 object.method(object, arg) 的简写。MagmaCore API 接受两种形式,因此以下写法都可以:
context.log:info("hello")
context.log.info("hello") -- same thing
所有文档统一使用 : 形式。
执行预算
每次钩子调用和每次回调调用都会计时。如果单次调用超过 50 毫秒,脚本将被禁用并在控制台输出警告:
[Lua] my_script.lua took 73ms in 'on_game_tick' (limit: 50ms) -- script disabled to prevent lag.
保持在预算内的建议:
- 避免在钩子内使用无限循环。
- 保持
on_game_tick/on_tick处理程序轻量——它们每个 tick 都会运行。 - 使用
context.scheduler:run_repeating(...)将工作分散到多个 tick。 - 将耗时操作放在基于状态的冷却或合理间隔之后。
context.state
一个普通的 Lua 表,在脚本实例的整个生命周期中持续存在。用它来存储标记、计数器、任务 ID、切换状态以及你需要在钩子之间共享的任何数据。
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 在钩子调用之间持续存在。所有其他 context 表(context.prop、context.world、context.event 等)每次都会重新构建。context.state 不会重建——它从脚本实例创建的那一刻起一直存在,直到实例被销毁。
context.log
控制台日志方法。消息在服务器控制台中以脚本文件名作为前缀。
| 方法 | 说明 |
|---|---|
log:info(message) | 信息消息 |
log:warn(message) | 警告消息 |
log:error(message) | 警告级别消息(以 WARN 级别记录,与 log:warn 相同) |
log:debug(message) | 调试消息(以 info 级别显示,带有调试前缀) |
context.log:info("Script loaded!")
context.log:warn("Something unexpected happened")
context.log:error("Critical failure in zone setup")
context.log:debug("State value: " .. tostring(context.state.counter))
context.cooldowns
冷却表管理脚本的时间冷却。有两种作用域:
- 本地冷却 是按脚本实例的,由字符串键标识。如果未提供键,则使用脚本文件名作为默认键。
- 全局冷却 在同一实体所有者的所有脚本之间共享(例如同一道具的所有脚本,或同一 Boss 的所有 Lua 技能)。
cooldowns:check_local(key?, duration)
最常用的方法。检查冷却是否就绪,如果是则启动冷却并返回 true。如果未就绪,返回 false。这是原子性的检查并设置操作——没有竞态条件。
| 参数 | 类型 | 说明 |
|---|---|---|
key | string(可选) | 冷却标识符。默认为脚本文件名。 |
duration | int | 冷却持续时间(tick 为单位,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?)
设置本地冷却而不检查是否已有冷却在运行。用于无条件的冷却重置。
| 参数 | 类型 | 说明 |
|---|---|---|
duration | int | 持续时间(tick)。传入 0 或负数可清除冷却。 |
key | string(可选) | 冷却标识符。默认为脚本文件名。 |
cooldowns:global_ready()
如果全局冷却(在同一实体的所有脚本之间共享)已过期,返回 true。
cooldowns:set_global(duration)
设置全局冷却。
| 参数 | 类型 | 说明 |
|---|---|---|
duration | int | 持续时间(tick) |
在 EliteMobs 技能脚本中,global_ready() 和 set_global() 使用 Boss 内置的技能冷却系统,该系统在同一 Boss 的所有 Lua 技能之间共享。EliteMobs 中的本地冷却也在同一 Boss 实体的所有技能之间共享(由你选择的字符串键标识)。
context.scheduler
调度器允许你运行延迟和重复任务。所有任务属于脚本实例,当脚本实例被销毁时自动取消(例如道具被移除或 Boss 死亡时)。
scheduler:run_later(ticks, callback)
在延迟后运行一次回调。返回数值类型的任务 ID。
| 参数 | 类型 | 说明 |
|---|---|---|
ticks | int | 延迟的服务器 tick 数(20 tick = 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。
| 参数 | 类型 | 说明 |
|---|---|---|
delay | int | 首次运行前的初始延迟(tick) |
interval | int | 每次后续运行之间的 tick 数 |
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 取消已调度的任务。
| 参数 | 类型 | 说明 |
|---|---|---|
taskId | int | 由 run_later 或 run_repeating 返回的任务 ID |
如果你启动了重复任务,务必在清理钩子中取消它(道具用 on_destroy,Boss 用 on_exit_combat / on_death,物品用 on_unequip)。忘记取消会导致后台任务一直运行到脚本实例被销毁,浪费性能并可能导致错误。
已调度的回调接收一个全新的 context 作为参数。务必使用回调自身的 context 参数,而不是创建回调的钩子中的外层 context。外层 context 可能包含过期的引用。
context.world
世界表提供了查询和交互 Minecraft 世界的方法。它基于实体当前所在的世界构建。
EliteMobs 扩展了 context.world,增加了生成 Boss、增援、下落方块、烟花、喷溅药水和临时方块的方法。完整的扩展 API 请参阅 EliteMobs 世界与环境。此处记录的方法在所有插件中可用。
world.name
包含世界名称的字符串字段。
world:get_block_at(x, y, z)
返回给定坐标处方块的材料名称,为小写字符串(例如 "stone"、"air")。
| 参数 | 类型 | 说明 |
|---|---|---|
x | int | 方块 X 坐标 |
y | int | 方块 Y 坐标 |
z | int | 方块 Z 坐标 |
world:set_block_at(x, y, z, material)
在给定坐标处设置方块。在主线程上运行。
| 参数 | 类型 | 说明 |
|---|---|---|
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)
在指定位置生成粒子。
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
particle | string | 必填 | Bukkit Particle 枚举名称,大写(例如 "FLAME"、"DUST") |
x | number | 必填 | X 坐标 |
y | number | 必填 | Y 坐标 |
z | number | 必填 | 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)
在指定位置播放声音。
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
sound | string | 必填 | Bukkit Sound 枚举名称,大写(例如 "ENTITY_EXPERIENCE_ORB_PICKUP") |
x | number | 必填 | X 坐标 |
y | number | 必填 | Y 坐标 |
z | number | 必填 | Z 坐标 |
volume | number | 1.0 | 音量 |
pitch | number | 1.0 | 音调 |
world:strike_lightning(x, y, z)
在指定位置劈下闪电(视觉效果和伤害)。
| 参数 | 类型 | 说明 |
|---|---|---|
x | number | X 坐标 |
y | number | Y 坐标 |
z | number | Z 坐标 |
world:get_time()
返回当前世界时间(以 tick 为单位)。
world:set_time(ticks)
设置世界时间。
| 参数 | 类型 | 说明 |
|---|---|---|
ticks | int | 世界时间(0 = 黎明,6000 = 正午,13000 = 夜晚,18000 = 午夜) |
world:get_nearby_entities(x, y, z, radius)
返回以给定坐标为中心的边界框内所有实体的实体包装表数组。
| 参数 | 类型 | 说明 |
|---|---|---|
x | number | 中心 X |
y | number | 中心 Y |
z | number | 中心 Z |
radius | number | 搜索半径(在三个轴上用作半范围) |
这会返回范围内的所有实体,包括非生物实体(盔甲架、掉落物等)。在调用生物实体方法前,始终使用 if entity.damage then 进行防护检查。
world:get_nearby_players(x, y, z, radius)
返回以给定坐标为中心的边界框内所有玩家的玩家包装表数组。
| 参数 | 类型 | 说明 |
|---|---|---|
x | number | 中心 X |
y | number | 中心 Y |
z | number | 中心 Z |
radius | number | 搜索半径 |
world:spawn_entity(entity_type, x, y, z)
在给定位置生成原版 Minecraft 实体。
| 参数 | 类型 | 说明 |
|---|---|---|
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 坐标。
| 参数 | 类型 | 说明 |
|---|---|---|
x | int | 方块 X 坐标 |
z | int | 方块 Z 坐标 |
world:raycast(from_x, from_y, from_z, dir_x, dir_y, dir_z, [max_distance])
从一个点沿方向投射射线,返回命中信息。
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
from_x | number | 必填 | 起点 X |
from_y | number | 必填 | 起点 Y |
from_z | number | 必填 | 起点 Z |
dir_x | number | 必填 | 方向 X 分量 |
dir_y | number | 必填 | 方向 Y 分量 |
dir_z | number | 必填 | 方向 Z 分量 |
max_distance | number | 50 | 最大射线距离 |
返回包含以下字段的表:
| 字段 | 类型 | 说明 |
|---|---|---|
hit_entity | entity table 或 nil | 射线命中的第一个实体,如果没有则为 nil |
hit_location | location table 或 nil | 射线命中的精确位置 |
hit_block | table 或 nil | 命中方块的 {x, y, z, material},如果未命中方块则为 nil |
world:spawn_firework(x, y, z, colors, [type], [power])
在给定位置生成烟花火箭。
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
x | number | 必填 | X 坐标 |
y | number | 必填 | Y 坐标 |
z | number | 必填 | Z 坐标 |
colors | table | 必填 | 颜色字符串数组,例如 {"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])
放置一个在延迟后自动恢复为原始状态的方块。
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
x | int | 必填 | 方块 X 坐标 |
y | int | 必填 | 方块 Y 坐标 |
z | int | 必填 | 方块 Z 坐标 |
material | string | 必填 | Bukkit Material 名称(例如 "stone"、"ice") |
ticks | int | 0 | 方块恢复前的持续时间(tick)。0 表示永久。 |
require_air | boolean | false | 如果为 true,仅在目标为空气时放置方块 |
方块放置成功返回 true,材料无效或空气要求未满足返回 false。
world:drop_item(x, y, z, material, [amount])
在指定位置以自然散布方式掉落物品实体。
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
x | number | 必填 | X 坐标 |
y | number | 必填 | Y 坐标 |
z | number | 必填 | Z 坐标 |
material | string | 必填 | Bukkit Material 名称 |
amount | int | 1 | 堆叠大小 |
返回掉落物品的实体表,如果材料无效则返回 nil。
context.zones
区域表允许你创建空间区域并监听玩家进入/离开事件。区域绑定到脚本实例,当脚本实例被销毁时自动清理。
zones:create_sphere(x, y, z, radius)
创建以给定坐标为中心的球形区域。返回数值类型的区域句柄。
| 参数 | 类型 | 说明 |
|---|---|---|
x | number | 中心 X |
y | number | 中心 Y |
z | number | 中心 Z |
radius | number | 球体半径 |
zones:create_cylinder(x, y, z, radius, height)
创建圆柱体区域。返回数值类型的区域句柄。
| 参数 | 类型 | 说明 |
|---|---|---|
x | number | 中心 X |
y | number | 中心 Y(底部) |
z | number | 中心 Z |
radius | number | 圆柱体半径 |
height | number | 圆柱体高度 |
zones:create_cuboid(x, y, z, xSize, ySize, zSize)
创建长方体区域。返回数值类型的区域句柄。
| 参数 | 类型 | 说明 |
|---|---|---|
x | number | 中心 X |
y | number | 中心 Y |
z | number | 中心 Z |
xSize | number | X 半范围 |
ySize | number | Y 半范围 |
zSize | number | Z 半范围 |
zones:watch(handle, onEnterCallback, onLeaveCallback)
开始监听区域的玩家进入/离开事件。当玩家进入或离开区域时,相应的回调会触发(如果定义了 on_zone_enter / on_zone_leave 钩子也会触发)。
| 参数 | 类型 | 说明 |
|---|---|---|
handle | int | 来自 create_* 调用的区域句柄 |
onEnterCallback | function 或 nil | 玩家进入区域时调用 |
onLeaveCallback | function 或 nil | 玩家离开区域时调用 |
成功设置监听时返回 true,如果区域句柄无效则返回 nil。
区域监听每个服务器 tick 针对同一世界中的所有玩家进行检查。保持区域数量合理以避免性能开销。
zones:unwatch(handle)
停止监听区域并清理其资源。
| 参数 | 类型 | 说明 |
|---|---|---|
handle | int | 要停止监听的区域句柄 |
示例:接近触发区域
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)
context.zones:watch(
handle,
function(player)
context.log:info("Player entered zone!")
end,
function(player)
context.log:info("Player left zone!")
end
)
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.event
当当前钩子由游戏事件触发时(例如 on_right_click、on_zone_enter),事件表会存在。在 on_tick 或已调度的回调中不存在。
| 字段 / 方法 | 类型 | 说明 |
|---|---|---|
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 参考。
em 辅助命名空间
em 表在文件加载时可用(在任何钩子运行之前)。它提供了辅助构造函数,用于构建整个 API 中使用的位置表、向量表和区域定义。
| 函数 | 用途 |
|---|---|
em.create_location(x, y, z [, 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) | 创建平移射线区域定义 |
区域构建器返回可链式调用的表,带有 :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(...) 方法更常用于简单的基于监听的区域。
实体表
实体表从世界查询、事件数据和区域回调中返回。它们根据实体类型提供分层的字段和方法集。
实体基础字段
| 字段 | 类型 | 说明 |
|---|---|---|
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 | 实体所在的世界名称 |
实体基础方法
| 方法 | 返回值 | 说明 |
|---|---|---|
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 | 切换实体的发光轮廓效果。 |
生物实体字段
生物实体(玩家、怪物等)拥有所有实体基础字段,加上:
| 字段 | 类型 | 说明 |
|---|---|---|
health | number | 当前生命值 |
maximum_health | number | 最大生命值 |
name | string | 显示名称 |
is_alive | boolean | 实体是否存活 |
生物实体方法
| 方法 | 返回值 | 说明 |
|---|---|---|
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 以 tick 为单位。amplifier 为效果等级减 1(0 = I 级)。 |
remove_potion_effect(effect) | void | 按名称移除药水效果 |
并非 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 时可用。
| 字段 | 类型 | 说明 |
|---|---|---|
is_elite | boolean | 实体是否是 EliteMobs 精英 |
is_custom_boss | boolean | 实体是否是 EliteMobs 自定义 Boss(也可在 elite 子表中获取) |
is_significant_boss | boolean | 实体是否是生命值倍率超过 1 的自定义 Boss(即设计好的遭遇战,而非填充精英) |
elite | table 或 nil | 精英信息子表(见下方)。如果实体不是精英则为 nil。 |
elite 子表包含:
| 字段 | 类型 | 说明 |
|---|---|---|
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 时可用。
| 字段 | 类型 | 说明 |
|---|---|---|
is_modeled | boolean | 实体是否附加了 FMM 模型(DynamicEntity 或 PropEntity) |
is_prop | boolean | 实体是否是 FMM 道具(静态装饰实体) |
model | table 或 nil | 模型信息子表(见下方)。如果实体没有模型则为 nil。 |
model 子表包含:
| 字段 | 类型 | 说明 |
|---|---|---|
model.model_id | string | 模型蓝图 ID(例如 "torch_01") |
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
玩家特有字段
玩家实体拥有所有实体和生物实体字段,加上:
| 字段 | 类型 | 说明 |
|---|---|---|
game_mode | string | 玩家的游戏模式("creative"、"survival"、"adventure"、"spectator") |
玩家特有方法
| 方法 | 返回值 | 说明 |
|---|---|---|
send_message(msg) | void | 向玩家发送聊天消息。支持 & 颜色代码。 |
get_held_item() | table 或 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 或 nil | 通过射线检测返回玩家正在看的实体,如果没有则返回 nil。默认范围为 50。 |
get_eye_location() | location table | 返回玩家眼睛高度的位置表 |
get_look_direction() | table | 返回玩家视线方向的 {x, y, z} 方向向量 |
send_block_change(x, y, z, material, [ticks]) | void | 发送仅对此玩家可见的假方块。如果提供了 ticks,假方块会在该时长后自动恢复。 |
reset_block(x, y, z) | void | 为此玩家将假方块恢复为真实方块 |
sleep(x, y, z) | void | 使玩家在给定坐标处进入床上睡眠动画。玩家停止睡眠时方块会自动恢复。 |
wake_up() | void | 唤醒正在睡觉的玩家。 |
玩家 UI 方法
这些方法可在任何玩家实体表上使用,提供通过 Minecraft 内置 UI 元素向玩家显示信息的方式。
player:show_boss_bar(text, [color], progress, [ticks])
向玩家显示 Boss 血条。
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
text | string | 必填 | 显示的文本。支持 & 颜色代码。 |
color | string | "WHITE" | 血条颜色。可选:"RED"、"BLUE"、"GREEN"、"YELLOW"、"PURPLE"、"PINK"、"WHITE" |
progress | number | 必填 | 填充量,从 0.0(空)到 1.0(满) |
ticks | int | nil | 可选的自动消失延迟(tick)。如果省略,血条会一直显示直到手动隐藏。 |
player:hide_boss_bar()
从玩家屏幕上移除 Boss 血条。不需要参数。
player:show_action_bar(text, [ticks])
在操作栏区域(快捷栏上方)显示文本。
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
text | string | 必填 | 显示的文本。支持 & 颜色代码。 |
ticks | int | nil | 可选的持续时间(tick)。如果提供,消息每 40 tick 重新发送一次以在整个时间内保持可见。 |
player:show_title(title, [subtitle], fade_in, stay, fade_out)
向玩家显示标题屏幕。
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
title | string | 必填 | 主标题文本。支持 & 颜色代码。 |
subtitle | string | "" | 主标题下方的副标题文本。可选。 |
fade_in | int | 必填 | 淡入持续时间(tick) |
stay | int | 必填 | 标题在屏幕上停留的时间(tick) |
fade_out | int | 必填 | 淡出持续时间(tick) |
后续步骤
有关插件特定的钩子、API 和工作流程: