内置动作、日志与音效
ChaUI Script 的内置动作分为两类:客户端立即执行的本地动作,以及必须由服务端根据已保存页面确认后执行的服务端动作。
客户端只执行当前事件真实走到的分支,并把其中需要服务端参与的动作编号发出。服务端会用已经保存的页面事件和自定义方法重新确认编号,再执行对应动作;命令正文不会由客户端上传。页面 close 也遵循同样规则,reload 时使用旧页面快照确认关闭动作。
动作一览
| 函数 | 中文别名 | 执行位置 | 作用 |
|---|---|---|---|
log(message) | 日志(message) | 客户端本地 | 向当前玩家聊天栏发送一条调试消息 |
sound(path) | 音效(path) | 客户端本地 | 播放 ChaUI 资源目录中的 OGG 音效 |
moveWorld(x, y, z) | 移动世界页面(x, y, z) | 客户端本地 | 立即移动触发脚本的当前世界页面实例 |
moveWorld(x, y, z, milliseconds, type) | 移动世界页面(x, y, z, milliseconds, type) | 客户端本地 | 使用 linear 或 ease_in_out 插值移动当前世界页面实例 |
stopTimer(name) | 停止计时器(name) | 客户端本地 | 停止当前页面作用域内的同名计时器 |
close() | 关闭() | 服务端确认 | 关闭当前页面 |
close(pageId) | 关闭(pageId) | 服务端确认 | 关闭指定页面 |
open(pageId) | 打开(pageId) | 服务端确认 | 打开另一个已存在页面 |
openSub(pageId) | 打开子页面(pageId) | 服务端确认 | 在当前 GUI 上方打开一层子页面 |
closeAll() | 全部关闭() | 服务端确认 | 关闭当前 GUI 的整条父子页面链 |
cmd(command) | 指令(command) | 服务端确认 | 以玩家身份执行配置的业务动作 |
opcmd(command) | OP指令(command) | 服务端确认 | 临时使用更高权限执行配置的业务动作 |
consolecmd(command) | 控制台指令(command) | 服务端确认 | 由服务端控制台执行配置的业务动作 |
查询页面是否打开
isPageOpen(pageId) / 界面已打开(pageId) 是返回布尔值的客户端本地查询,可以直接用于条件或赋给变量:
vars.shopOpen = isPageOpen("shop")
if 界面已打开("detail_popup") {
log("详情子页面仍在显示")
}查询覆盖普通界面、容器替换界面、GUI 子页面、HUD 和世界页面;同一 pageId 只要还有任意活动实例就返回 true,世界页面不区分 instanceId。页面从执行 open 生命周期开始算作打开,直到 close 生命周期结束并释放资源后才变为关闭。查询只读取当前客户端的活动页面,不发包、不修改状态;空白、非法或运行时不是字符串的参数安全返回 false。编辑器编辑状态和隔离预览不计入活动页面。
输出本地调试日志
log 用于确认事件是否触发、条件是否进入预期分支,或查看变量当时的值。它只把消息显示在当前玩家的客户端聊天栏,不会发送给其他玩家,不会上传服务端,也不会写入服务端日志。
log("当前生命:{vals.player.health}/{vals.player.maxHealth}")
日志("当前计数:{vars.count + 1}")消息使用与响应式文字相同的花括号规则:{vars.xxx}、{vals.player.xxx} 和 {vals.papi.xxx} 会在动作执行时读取最新值,花括号内也可以进行四则运算。连续输入两个左花括号 可以输出普通花括号;未知变量或无效表达式会保留原占位内容,方便继续排查。
log 必须且只能填写一个带引号的字符串参数,解析后的单条消息最多显示 1024 个字符。它可以用于组件事件、页面打开/关闭事件、自定义方法、repeat、timer 和编辑器预览;当前客户端玩家尚未建立时会安全忽略。
组件布局值不能直接写进日志花括号。需要查看组件位置时,可以先把值保存到页面变量:
vars.currentY = component("player_name_value").layout.y
log("当前 Y:{vars.currentY}")播放本地音效
音效文件放在当前客户端游戏版本目录的 resourcepacks/ChaUI/ 下,脚本填写相对于该目录的路径。
sound("sounds/click.ogg")
音效("sounds/notice.ogg")第一版只支持 OGG。路径不能使用绝对路径、反斜杠、路径穿越、空白路径或控制字符。音效只在触发脚本的玩家客户端播放,不会把文件发送给其他玩家。
移动当前世界页面
世界页面脚本可以直接移动触发脚本的当前实例,不需要先关闭再重新打开:
moveWorld(120.5, 65, -30)
moveWorld(125, 66, -28, 800, "ease_in_out")
移动世界页面(130, 66, -25, 500, "linear")三参数形式立即移动。五参数形式的毫秒时长范围为 1 至 3600000,插值类型只支持匀速 linear 和平滑起停 ease_in_out。新移动会立即停止当前实例尚未完成的旧移动,并从屏幕中当时显示的位置开始。动作只修改当前会话,不写回页面 yml;普通 screen、HUD、容器页面和编辑器预览调用时会安全忽略。
打开和关闭页面
close()
close("detail_page")
open("detail_page")
openSub("detail_popup")
closeAll()关闭()
关闭("detail_page")
打开("detail_page")
打开子页面("detail_popup")
全部关闭()目标页面 ID 必须是服务端已经保存并可以正常加载的页面。页面 ID 建议只使用字母、数字、下划线、连字符或规范的 Unicode 字符,不要填写路径或文件扩展名。
openSub 只把 display.mode=screen 页面打开到当前普通 GUI 或容器替换 GUI 上方。父页面与子页面默认可以同时交互;若要阻止下层点击,请在子页面中放置全屏 rect 并设置 pointerEvents: block。close() 关闭触发它的当前页面,closeAll() 从栈顶到根页面关闭整条 GUI 链,但不会关闭 HUD 或世界页面。完整配置见在 GUI 上打开子页面。
执行业务动作
页面可以请求服务端以不同身份执行已经规划好的业务动作:
cmd("执行玩家确认动作")
opcmd("执行需要额外权限的页面动作")
consolecmd("执行服务端页面结算动作")这些示例中的文字代表需要由服务器作者替换的业务内容。不要把玩家输入内容直接拼接进高权限或控制台动作,也不要让普通页面触发未经过权限设计的管理功能。
close、open、openSub、closeAll、cmd、opcmd、consolecmd 不能写在 repeat 或 timer 块内,避免循环批量触发服务端动作。计时器的启动、停止、同名重启和页面关闭清理请阅读循环与计时器。
条件动作示例
events:
leftClick: |
if vars.ready == true {
sound("sounds/confirm.ogg")
open("result_page")
} else {
component("message").text.value = "请先完成选择"
sound("sounds/warning.ogg")
}本地文字和音效由当前客户端执行;open 则会提交事件触发意图,由服务端确认后打开页面。
服务端如何确认动作
客户端触发事件时,不会把指令内容或整段脚本作为可信动作直接交给服务端。服务端会校验玩家当前页面会话,再从已经保存的页面配置中找到对应组件和事件脚本,只执行其中允许的内置服务端动作。
因此,测试 close、open、cmd、opcmd、consolecmd 前必须先保存页面。编辑器中尚未保存的动作不会成为服务端执行依据。所有动作都必须使用本页列出的函数写法。
需要在编辑器单行输入框中执行多个动作时,可以使用分号:
sound("sounds/click.ogg"); open("detail_page")所有动作都使用“函数名 + 括号”的形式。文字参数放在引号中,无参数动作也保留空括号,这样编辑器才能准确识别动作边界。
需要与其他插件传递自定义数据时,可以在 packet() / 发包() 的数据参数中直接使用响应式模板:
packet("shop:select", "{vars.itemId}", "{vars.amount}", "{vals.player.health}")第一个包 ID 必须是固定的字面量字符串,不会执行变量替换;从第二个参数开始,会在发送前按与 log() 相同的规则展开页面变量、只读常量和表达式。需要输出普通左花括号时,连续写两个左花括号。完整限制和服务端校验方式请继续阅读自定义发包与安全边界。
猹件开发组