SetsunaLUA DEVELOPER DOCS
返回首页

DEVELOPER / LUA API V2 / B4

Lua V2 开发文档

用 Lua 编写可进入 ClickGUI 与 Array List 的动态模块,并直接实现 2D HUD、3D 世界绘制、方块与实体查询、输入修改和受限游戏动作。

运行时
LuaJ 3.0.1
脚本目录
setsuna/scripts
目标版本
Minecraft 26.1.2
QUICK STARTCLIENT COMMAND
.lua folder
.lua reload

首次运行会生成 example.lua.disabled。改名为 example.lua 后执行重载,即可看到内置 HUD 与实体框示例。

01
OVERVIEW

概览

每个启用的 .lua 文件在独立沙箱中执行。一个文件可以声明多个模块;模块与原生 Java 模块共享注册、配置和事件系统。

VISUAL2D 与 3D 绘制

绘制矩形、圆形、渐变、裁剪区域、文本、实体屏幕框、世界方框、连线和追踪线。

FUNCTIONAL输入与玩家动作

读取完整鼠标输入、修改移动、管理客户端与服务端视角,并在限速保护下执行玩家动作。

NATIVE MODULE界面和配置接入

脚本可读取真实模块和设置快照,并通过受限接口开关模块或修改设置。

02
QUICK START

快速开始

  1. 01
    打开脚本目录

    在游戏聊天中执行 .lua folder,目录为当前游戏目录下的 setsuna/scripts

  2. 02
    创建 UTF-8 脚本

    新建以 .lua 结尾的普通文件。以 .disabled 结尾的示例不会自动加载。

  3. 03
    重载并启用模块

    执行 .lua reload,然后在对应 ClickGUI 分类中启用脚本模块。

hello.lua
local module = setsuna.module({
    id = "hello_lua",
    name = "Hello Lua",
    category = "misc"
})

module:on("enable", function()
    client:notify("模块已启用", "Hello Lua", "success")
end)

module:on("tick", function()
    if player:is_available() and input:is_down("left_alt") then
        action:sprint(true)
    end
end)
03
MODULE API

模块声明

setsuna.module(metadata) 创建动态模块并返回模块句柄。设置和事件都通过这个句柄注册。

setsuna.module(metadata: table) → Module
字段类型说明
idstring

稳定配置 ID,转为小写 ASCII slug,最长 64 字符;所有 Java/Lua 模块之间必须唯一。

namestring

ClickGUI 与 Array List 中的显示名,长度 1 至 96 字符。

categorystring

省略时为 misc,不区分大小写。

可用分类

combatmiscrendermovementplayerclient

内部 hud 分类不能用于 Lua 模块。同一脚本可多次调用 setsuna.module 声明多个模块。

04
CALLBACKS

事件回调

使用 module:on(event, callback) 注册回调。第一个参数始终是模块句柄;带上下文的事件会把第二个参数作为普通 Lua 表传入。

module:on(event: string, callback: function) → Module
事件上下文说明
enable / disable

模块启用或关闭时各调用一次。

tick

启用期间每个客户端游戏刻结束后调用。

render2dDraw2D

每帧 2D 覆盖层绘制,坐标已经换算为 GUI 缩放空间。

render3dDraw3D

每帧世界渲染后调用,使用绝对世界坐标。

key / char / mousetable

按键、Unicode 字符或鼠标按钮状态变化。将 event.cancel = true 可吞掉本次输入。

mouse_scrolltable

鼠标滚轮输入,提供水平/垂直滚动量以及光标坐标,可取消原版滚动。

inputtable

可改写 forwardstrafejumpsneaksprint

movetable

可改写移动向量 x/y/z;设置 cancel = true 会把本次移动归零。

attackEntity

本地玩家攻击前触发,第二个参数是目标实体快照。该回调内禁止再次发起攻击。

输入事件字段

key

keyscancodeactionmodifiersstatepressedreleasedrepeatcancel

mouse

buttonactionmodifiersstatepressedreleased、GUI 坐标 x/yraw_x/raw_ycancel

char

codepointtextallowedcancel

mouse_scroll

horizontalverticalx/yraw_x/raw_ycancel

input

移动值会限制在 -1 到 1;布尔字段必须保持为布尔值。

05
SETTINGS API

设置 API

设置必须在脚本加载阶段声明。它们自动显示在 ClickGUI 中,并按模块 ID 与设置名写入当前配置。

方法返回参数
module:booleanSetting

name, default[, label]

module:integerSetting

name, default, min, max[, step[, label]],步长必须大于 0。

module:numberSetting

name, default, min, max[, step[, label]],所有数值必须有限。

module:stringSetting

name, default[, label],值最长 4096 字符。

setting:get()

读取当前设置值。

setting:set(value)

写入并返回最终值;数字自动限制在声明范围内。

setting:reset()

恢复脚本声明的默认值并返回结果。

settings.lua
local boxes = module:boolean("boxes", true, "显示方框")
local range = module:integer("range", 24, 4, 64, 1, "扫描范围")
local size = module:number("font_size", 14, 8, 32, 0.5, "字号")
local title = module:string("title", "Lua HUD", "标题")
06
COMMON API

通用 API

Client

方法返回说明
client:notify(message[, title[, type]])nil

发送客户端通知。类型支持 infosuccesswarningerror

client:username()string

当前会话用户名。

client:server()string

当前服务器地址,单人游戏返回 singleplayer

client:categories()Category[]

返回 ClickGUI 可见分类的 id/name 快照。

client:modules([category[, includeHidden]])Module[]

枚举真实模块;默认只含 GUI 分类,传具体分类 ID 可筛选。

client:module(id)Module | nil

读取一个模块及其完整设置快照。

Player

方法返回说明
player:is_available()boolean

玩家和客户端世界都已加载时为 true。

player:x() / y() / z()number | nil

本地玩家世界坐标。

player:health()number | nil

本地玩家生命值。

player:yaw() / pitch()number | nil

本地玩家当前视角。

player:server_yaw() / server_pitch()number | nil

旋转管理器将写入正常移动包的服务端视角。

player:rotation()table | nil

一次返回客户端与服务端 yaw/pitch 以及 silent 状态。

player:entity()Entity | nil

返回与世界查询相同格式的本地玩家快照。

颜色

setsuna.color(value) / setsuna.color(r, g, b[, a]) → packed ARGB integer

接受 #RRGGBB#AARRGGBB、32 位整数或 {r, g, b, a} 表。setsuna.color_table(color) 可拆回通道表。

colors.lua
local cyan = setsuna.color("#58DCE5")
local translucent = setsuna.color("#4058DCE5")
local red = setsuna.color(255, 70, 70, 220)
local channels = setsuna.color_table(cyan)
07
RENDER 2D

2D 绘制

render2d 的第二个参数是当帧有效的 Draw2D 表。坐标原点在左上角,单位为 GUI 缩放后的像素。

方法 / 字段返回说明
width / height / scalenumber

当前 GUI 画布尺寸与 GUI 缩放倍数;mouse_x/mouse_y/mouse_grabbed 是当帧鼠标快照。

draw:rect(x, y, w, h, color)nil

填充矩形。负宽高会自动翻转原点。

draw:rounded_rect(x, y, w, h, radius, color)nil

填充圆角矩形。

draw:outline_rect(x, y, w, h, color[, thickness[, radius]])nil

描边矩形,默认线宽 1、圆角 0。

draw:gradient_rect(x, y, w, h, start, end[, vertical[, radius]])nil

绘制水平或垂直双色渐变。

draw:circle(...) / circle_outline(...)nil

按圆心和半径绘制圆或圆环。

draw:line(x1, y1, x2, y2, color[, thickness])nil

绘制抗锯齿线段,默认线宽 1。

draw:text(text, x, y, color[, size[, shadow]])nil

绘制客户端字体,默认字号 14、阴影开启。

draw:text_width(text[, size])number

测量当前客户端字体宽度。

draw:bold_text(...) / bold_text_width(...)nil / number

粗体文字绘制与测量,参数顺序和普通文字一致。

draw:clip(x, y, w, h, callback)nil

只在指定矩形内执行绘制回调;裁剪状态即使报错也会恢复。

draw:world_to_screen(x, y, z)table | nil

投影世界坐标,返回 x/y/depth/visible;点在相机深度范围外时返回 nil。

draw:entity_bounds(entityId[, padding])table | nil

返回实体当前碰撞箱的屏幕 x/y/width/height/min/max/visible

hud.lua
local accent = setsuna.color("#58DCE5")
local panel = setsuna.color("#D9101519")

module:on("render2d", function(self, draw)
    local label = string.format("XYZ %.1f / %.1f / %.1f",
        player:x(), player:y(), player:z())
    local width = draw:text_width(label, 14) + 24

    draw:rounded_rect(12, 12, width, 38, 5, panel)
    draw:outline_rect(12, 12, width, 38, accent, 1, 5)
    draw:text(label, 24, 21, accent, 14, true)
end)
08
RENDER 3D

3D 绘制

render3d 使用绝对世界坐标,底层会自动转换为相机相对坐标。颜色可以传 nil,从而只绘制填充或描边。

方法返回说明
draw:filled_box(minX, minY, minZ, maxX, maxY, maxZ, color)nil

绘制填充世界方框。

draw:outline_box(..., color[, thickness])nil

绘制方框轮廓,默认线宽 1.5。

draw:box(..., fill, outline[, thickness])nil

一次绘制填充和轮廓,任一颜色可为 nil。

draw:gradient_box(..., bottom, top[, outline[, thickness]])nil

绘制上下双色渐变世界方框,可附加轮廓。

draw:block_box(x, y, z, fill, outline[, thickness])nil

绘制一个完整方块空间。

draw:entity_box(entityId, fill, outline[, thickness])boolean

按实体 ID 绘制当前碰撞箱;实体已消失时返回 false。

draw:entity_gradient_box(entityId, bottom, top[, outline[, thickness]])boolean

按实体 ID 绘制上下渐变碰撞箱。

draw:line(x1, y1, z1, x2, y2, z2, color[, thickness])nil

绘制世界空间线段。

draw:tracer(entityId, color[, thickness])boolean

从当前相机连接到实体碰撞箱中心。

09
WORLD & ENTITY

世界与实体

世界 API 是只读接口,只能在模块回调内调用。未加载区块不会被强制加载,单点方块查询会返回 nil。

方法返回说明
world:block(x, y, z)Block | nil

返回 x/y/z/id/air/solid/replaceable/fluid

world:block_id(x, y, z)string | nil

返回完整方块 ID,例如 minecraft:diamond_ore

world:is_air(x, y, z)boolean | nil

判断已加载位置是否为空气。

world:entities(radius[, filter[, limit]])Entity[]

枚举本地玩家附近实体。半径最多 256、结果最多 512,默认上限 128。

world:entity(id)Entity | nil

按运行时实体 ID 获取最新快照。

world:find_blocks(idOrList[, radius[, limit]])Block[]

在玩家周围立方体搜索一个或多个方块 ID;半径最大 16、结果最多 512。

world:dimension()string | nil

当前维度 ID。

world:time()integer | nil

当前主世界时钟时间。

实体筛选与快照

allplayerslivingmobsanimalsminecraft:zombie

Entity 包含 iduuidnametype、坐标、视角、尺寸、速度、碰撞箱、距离和类型标记;生物额外包含 healthmax_healtharmor

world-query.lua
module:on("tick", function()
    local ores = world:find_blocks({
        "diamond_ore", "deepslate_diamond_ore"
    }, 12, 64)

    local targets = world:entities(32, "players", 32)
    if #ores > 0 and #targets > 0 then
        print(ores[1].id, targets[1].name)
    end
end)
10
INPUT & ACTION

输入与动作

输入状态

方法返回说明
input:is_down(key)boolean

读取 GLFW 键。可传数字或名称,例如 spaceleft_shiftF6

input:mouse_down(button)boolean

读取 GLFW 鼠标按钮,左键为 0、右键为 1。

input:cursor()table

返回 GUI x/yraw_x/raw_ygrabbedinside

input:cursor_grabbed()boolean

鼠标当前是否被游戏视角抓取。

input:key_code(name)integer

把键名转换为 GLFW 键码。该纯转换方法可在脚本加载阶段缓存。

受限动作

方法返回说明
action:jump()boolean

触发本地玩家起跳。

action:rotate(yaw, pitch)boolean

设置视角;pitch 自动限制到 -90 至 90。

action:rotate_silent(yaw, pitch[, priority])boolean

通过旋转管理器把视角写入下一次正常移动包,不改变相机;持续旋转应每 tick 续约。

action:send_rotation(yaw, pitch[, onGround[, collision]])boolean

立即发送一个旋转包。它不会代替正常移动同步,不应在同 tick 重复调用。

action:look_at(x, y, z[, mode[, priority]])boolean

朝向世界坐标;模式为 clientsilentpacket

action:release_rotation()boolean

释放当前 Lua 模块持有的静默旋转。

action:cursor_grab([grabbed])boolean

抓取或释放鼠标;模块关闭、报错和重载时自动清理所有权。

action:set_velocity(x, y, z)boolean

设置速度,每个分量限制到 -10 至 10。

action:sprint([enabled])boolean

开启或关闭疾跑,省略参数时开启。

action:swing([hand]) / use([hand])boolean

挥动或使用 main/off 手。

action:attack(entityId)boolean

攻击已加载且存活的实体,并挥动主手。

action:select_slot(slot)boolean

选择 Lua 风格热栏槽位 1 至 9。

action:send_chat(message)boolean

发送一行聊天,最长 256 字符。

action:send_command(command)boolean

发送命令,可带或不带开头的斜杠。

action:module_toggle(id) / module_set(id, enabled)boolean

触发或设置真实客户端模块。

action:setting_set(moduleId, settingId, value)boolean

按快照中的稳定设置 ID 写入经类型与范围校验的值。

action:setting_cycle(...) / setting_press(...)boolean

切换布尔/枚举/字体、步进数值或执行按钮设置。

key-action.lua
local jumpKey = input:key_code("J")
local targetKey = input:key_code("R")

module:on("key", function(self, event)
    if not event.pressed then return end

    if event.key == jumpKey then
        event.cancel = true
        action:jump()
    elseif event.key == targetKey then
        local targets = world:entities(6, "living", 1)
        if targets[1] then action:attack(targets[1].id) end
    end
end)

module:on("input", function(self, movement)
    if input:is_down("left_alt") then
        movement.sprint = true
    end
end)
11
COMMANDS

管理命令

.lua list

列出成功加载的脚本及各自模块数量。

.lua reload

保存配置、卸载并重新加载所有脚本,然后恢复配置状态。

.lua errors

显示最近的脚本加载或回调错误,聊天中最多显示最近 10 条。

.lua folder

在系统文件管理器中打开脚本目录。

12
SECURITY & LIMITS

安全与限制

所有新运行时 API 只能在模块回调内使用;保存上下文并在后续回调重用会被拒绝。限制按回调或按脚本计算。

SANDBOX禁用危险全局

io · os · package · debug · luajava · dofile · loadfile · require

RENDER QUOTA每次回调硬上限

2D 最多 4096 次绘制,3D 最多 2048 次绘制;单个 3D 方框边长最多 512。

QUERY QUOTA最多 4 次高开销查询

entitiesfind_blocks 共用回调限额;方块搜索半径最多 16,结果最多 512。

ACTION RATE动作和消息限速

每回调最多 64 个动作;每脚本每秒最多 80 个动作、20 次攻击、5 条聊天或命令。

13
COMPLETE EXAMPLE

完整视觉脚本

这个示例每 10 tick 缓存附近生物,每帧只使用实体 ID 绘制方框,同时显示玩家坐标 HUD。它与首次生成的示例结构一致。

visual_example.lua
local module = setsuna.module({
    id = "lua_visual_example",
    name = "Lua 视觉示例",
    category = "render"
})

local showBoxes = module:boolean("show_boxes", true, "显示实体方框")
local range = module:integer("range", 24, 4, 64, 1, "扫描范围")

local accent = setsuna.color("#58DCE5")
local fill = setsuna.color("#2458DCE5")
local background = setsuna.color("#D914191E")
local ticks = 0
local nearby = {}

module:on("enable", function()
    client:notify("视觉示例已启用", "Lua", "success")
end)

module:on("tick", function()
    ticks = ticks + 1
    if ticks % 10 == 0 and player:is_available() then
        nearby = world:entities(range:get(), "living", 64)
    end
end)

module:on("render2d", function(self, draw)
    if not player:is_available() then return end
    local label = string.format("Lua HUD | XYZ %.1f %.1f %.1f",
        player:x(), player:y(), player:z())
    local width = draw:text_width(label, 14) + 24

    draw:rounded_rect(12, 12, width, 38, 5, background)
    draw:outline_rect(12, 12, width, 38, accent, 1, 5)
    draw:text(label, 24, 21, accent, 14, true)
end)

module:on("render3d", function(self, draw)
    if not showBoxes:get() then return end
    for _, entity in ipairs(nearby) do
        draw:entity_box(entity.id, fill, accent, 1.5)
    end
end)
14
TROUBLESHOOTING

问题排查

脚本没有出现在 ClickGUI

确认文件以 .lua 结尾、至少调用一次 setsuna.module,然后执行 .lua errors 查看加载错误。

模块启用后立即关闭+

某个回调抛出了错误。执行 .lua errors,阶段名会显示为 模块ID.事件名

提示 API 只能在回调中使用+

world、运行时 inputaction 不能在脚本顶层执行。把调用移入模块回调;只有 input:key_code 可在顶层缓存。

渲染回调提示禁止游戏动作+

渲染回调只负责绘制。记录状态或目标 ID,再在 tick 或输入回调中调用 action。

实体框偶尔返回 false+

缓存期间实体可能死亡、卸载或更换 ID。这是正常情况;下一次 world 查询会刷新列表。

重载后设置值丢失+

保持模块 id 与设置 name 不变,它们是配置恢复使用的稳定键;显示用 label 可以修改。

已复制到剪贴板