物品槽组件
物品槽组件用于显示并交互一份由服务端管理的物品状态。槽位身份固定由“玩家 + mode + bind”决定,不绑定页面或页面会话;不同页面、HUD 和世界页面只要打开了相同 mode + bind,就会自动显示并同步同一份槽位数据。客户端只提交点击意图,最终物品、光标、版本和背包变化都由服务端裁决。
物品槽默认不绘制底框、填充或边框。这样可以直接放到自定义界面素材上;如果需要独立槽位背景,可配置一张静态图片。
适用场景
- 临时合成、提交和操作槽
- 按玩家长期保存、可跨页面使用的物品槽
- 映射玩家真实背包位置
- 多个界面位置同步显示同一个槽位
服务端始终权威
客户端不能提交最终物品内容。过期版本、重复操作、伪造会话和无效映射都会被拒绝,避免不同步或重复物品。
通用配置
| 配置项 | 编辑器名称 | 类型 | 默认值 | 可选值或格式 | 说明 |
|---|---|---|---|---|---|
id | ID | 字符串 | 自动生成 item_slot_N | 页面内唯一 ID | 只标识页面组件本身,不等同于槽位绑定 ID。 |
type | 类型 | 只读字符串 | item_slot | 固定值 | 创建后不能修改。 |
parent | 父级 | 字符串 | 空 | 布局组件 ID | 为空表示根级元素。 |
z | 层级 | 整数 | 0 | 任意整数 | 控制槽位绘制顺序。 |
visible | 显示 | 布尔值 | true | true、false | 静态显隐开关。 |
enabled | 启用 | 布尔值 | true | true、false | 为假时不能进行槽位交互。 |
pointerEvents | 指针处理 | 枚举 | auto | auto、block、pass | 槽位在 auto 下天然参与命中;pass 会关闭槽位交互。 |
scale | 缩放 | 数字或公式 | 1 | 非负值 | 以槽位中心缩放画面和命中范围,不改变布局值。 |
opacity | 背景透明度 | 数字或公式 | 1 | 0 至 1 | 只影响槽位背景和边框,物品、数量与附魔效果保持不透明。 |
visibleWhen | 显示条件 | 条件表达式 | 空 | 只读条件 | 条件为假时隐藏。 |
enabledWhen | 启用条件 | 条件表达式 | 空 | 只读条件 | 条件为假时禁用。 |
containerBinding | 容器绑定 | 字符串 | 空 | 当前容器的语义槽位 ID | 仅容器替换页面使用;绑定后委托原版容器保留完整槽位交互。 |
containerTooltip | 容器提示 | 布尔值 | true | true、false | 是否显示绑定原版物品的完整提示。 |
layout.x | X | 数字或公式 | 创建时画布位置 | 合法布局公式 | 槽位左上角 X。 |
layout.y | Y | 数字或公式 | 创建时画布位置 | 合法布局公式 | 槽位左上角 Y。 |
layout.width | 宽 | 数字或公式 | 18 | 合法布局公式 | 推荐保持原版槽位附近尺寸。 |
layout.height | 高 | 数字或公式 | 18 | 合法布局公式 | 推荐保持原版槽位附近尺寸。 |
events.leftPress/rightPress/middlePress | 按下脚本 | ChaUI Script | 空 | 多行脚本 | 对应按键按下时触发。 |
events.leftRelease/rightRelease/middleRelease | 松开脚本 | ChaUI Script | 空 | 多行脚本 | 对应按键捕获仍有效并松开时触发。 |
events.leftClick | 左键脚本 | ChaUI Script | 空 | 多行脚本 | 组件左键事件;物品交换本身仍由槽位交互处理。 |
events.rightClick | 右键脚本 | ChaUI Script | 空 | 多行脚本 | 右键事件。 |
events.middleClick | 中键脚本 | ChaUI Script | 空 | 多行脚本 | 中键事件。 |
events.hoverEnter | 悬浮进入脚本 | ChaUI Script | 空 | 多行脚本 | 鼠标进入时触发。 |
events.hoverLeave | 悬浮离开脚本 | ChaUI Script | 空 | 多行脚本 | 鼠标离开时触发。 |
物品槽不支持自定义 tooltip。鼠标悬浮信息固定来自当前槽位物品自身,保存时写入 tooltip 会被拒绝。容器替换页面可用 containerTooltip: false 关闭绑定原版物品的提示。enabled: false 或 enabledWhen 结果为假时,槽内物品仍会绘制,但不会显示 Tooltip 或响应物品操作。
物品槽也不支持 dragMode。拖动物品、拆分堆叠和容器替换页面中的原版槽位操作都需要完整使用鼠标拖动手势;如果还允许拖动物品槽组件本体,两种行为会发生冲突。需要玩家移动一组槽位时,可以把它们放进可拖动的布局组件中,让布局负责整体移动。
专属配置
| 配置项 | 编辑器名称 | 类型 | 默认值 | 可选值或格式 | 说明 |
|---|---|---|---|---|---|
itemSlot.bind | 绑定 | 字符串 | 组件 ID | 安全绑定 ID | 标识槽位对应的物品状态;不同页面的相同 mode + bind 也会同步刷新。 |
itemSlot.mode | 模式 | 枚举 | temporary | persistent、temporary、mapped | 决定物品状态的存储和来源。 |
itemSlot.closePolicy | 关闭 | 枚举 | return_to_player | return_to_player、commit、discard | 仅 temporary 显示和生效;persistent、mapped 不允许配置。 |
itemSlot.check | 操作条件 | 条件表达式 | 空 | 与 visibleWhen 相同的只读条件语法 | 空白表示允许;结果为假、表达式无效或求值失败时不发送槽位操作包,但 events.leftClick 仍会执行。 |
itemSlot.allowPut | 放入 | 布尔值 | true | true、false | 是否允许把 ChaUI 会话光标中的物品放入槽位。 |
itemSlot.allowTake | 取出 | 布尔值 | true | true、false | 是否允许把槽位物品取到 ChaUI 会话光标。 |
itemSlot.path | 背景路径 | 字符串 | 空 | ChaUI 安全相对路径;仅 png、jpg、jpeg | 可使用 {vars.xxx} 等响应式路径模板;留空时槽位背景透明。 |
itemSlot.sourceX | 背景源X | 非负整数或公式 | 0 | 源图像素坐标或数字公式 | 背景选区左上角 X。 |
itemSlot.sourceY | 背景源Y | 非负整数或公式 | 0 | 源图像素坐标或数字公式 | 背景选区左上角 Y。 |
itemSlot.sourceWidth | 背景源宽 | 非负整数或公式 | 整张图片剩余宽度 | 像素尺寸或数字公式 | 背景选区宽度;为 0 时背景不绘制。 |
itemSlot.sourceHeight | 背景源高 | 非负整数或公式 | 整张图片剩余高度 | 像素尺寸或数字公式 | 背景选区高度;为 0 时背景不绘制。 |
背景选区公式每次渲染重新计算并向下取整。公式无效或越界时只隐藏槽位背景,槽位中的物品、数量、提示和交互仍然正常。
三种槽位模式
| 模式 | 状态位置 | 关闭后行为 | 常见用途 |
|---|---|---|---|
persistent | 服务端按玩家与 bind 保存 | 不执行关闭策略;之后打开任意相同 bind 页面都会恢复 | 长期存储、跨页面玩家专属槽位 |
temporary | 玩家当前 ChaUI 运行期,按 bind 保存 | 最后一个运行时页面关闭时执行关闭策略并清理 | 合成、提交、跨当前打开页面的临时操作 |
mapped | 服务端真实映射槽位 | 直接使用真实容器状态,无关闭策略 | backpack_0 等玩家背包映射 |
三种模式的数据、版本和收尾逻辑彼此独立。即使 persistent 与 temporary 使用完全相同的 bind,也不会读取或影响对方的物品。
临时槽位关闭策略
return_to_player:关闭时尝试返还玩家,背包满时必须使用安全保护,不能吞物品或刷物品。commit:把最终物品交给其他业务逻辑处理。discard:明确丢弃,适合受控的特殊页面,使用前应确认业务风险。
同一个 temporary + bind 如果出现在多个已保存页面中,这些页面必须配置相同的 closePolicy,否则页面加载或保存会被拒绝。临时槽位会一直保留到玩家最后一个 ChaUI 运行时页面关闭;只关闭其中一个页面不会提前收尾。
操作条件
“操作条件”是客户端发包前的便捷判断,适合根据当前页面变量或只读常量暂时禁止槽位交换。没配置或留空时直接允许;条件为假、语法无效或运行时求值失败时,只阻止内置槽位操作包,组件自己的 events.leftClick 仍按原顺序执行。
这个字段不能替代服务端权限和物品安全校验。客户端状态可能被修改,真正的权限、物品合法性和业务条件仍应在服务端事件中检查。
背包映射
mapped 使用显式白名单。backpack_0~backpack_35 映射 36 格主背包,另外支持 backpack_mainhand、backpack_offhand、backpack_helmet、backpack_chestplate、backpack_leggings 与 backpack_boots。点击时服务端会用 ChaUI 会话光标与真实背包槽执行权威交换。
完整编号、动态主手语义和只读背包常量见背包映射表。
配置示例
- id: submit_slot
type: item_slot
parent: ""
visible: true
enabled: true
pointerEvents: auto
scale: 1
opacity: 0.85
z: 10
layout:
x: 40
y: 40
width: 18
height: 18
itemSlot:
bind: quest_submit
mode: temporary
closePolicy: return_to_player
check: vars.questReady && vals.player.health > 0 # 操作条件:任务就绪且玩家存活
allowPut: true
allowTake: true
path: gui/item_slot.png # 可选;不写时背景完全透明
sourceX: 0
sourceY: 0
sourceWidth: 18
sourceHeight: 18
events: {}槽位对象的配置可以安全读取,但物品交换结果仍由服务端裁决。下面的事件只读取绑定 ID,不会直接修改槽位物品:
events:
rightClick: |-
vars.slotBind = component("submit_slot").itemSlot.bind
log("当前槽位绑定:{vars.slotBind}")映射背包示例:
itemSlot:
bind: backpack_0
mode: mapped
allowPut: true
allowTake: truemapped 模式不要写 closePolicy。
相同 bind、不同模式仍是两份独立数据:
- id: saved_reward
type: item_slot
layout: {x: 20, y: 20, width: 18, height: 18}
itemSlot:
bind: reward
mode: persistent
- id: current_reward
type: item_slot
layout: {x: 44, y: 20, width: 18, height: 18}
itemSlot:
bind: reward
mode: temporary
closePolicy: return_to_player上面的两个槽位虽然都叫 reward,但永久槽位和临时槽位不会互相显示、覆盖或同步物品。
背景图片只负责装饰,不参与服务端物品裁决,也不会改变槽位的点击区域。物品槽背景不支持 GIF。
常见问题
两个槽位为什么同时变化
它们使用了相同的 itemSlot.mode + itemSlot.bind,因此绑定同一份玩家级服务端状态。这个规则也适用于不同页面、HUD 和世界页面。不需要同步时请更换 bind;需要同名但数据隔离时请使用不同 mode。
操作条件没通过,为什么左键脚本还执行
itemSlot.check 只控制内置槽位操作是否发包,不控制组件事件。这样可以在禁止交换时仍播放提示、修改页面变量或记录本地日志。需要阻止脚本逻辑时,请在 events.leftClick 内使用同样的条件自行分支。
点击后提示版本过期
服务端状态已经变化,客户端提交的是旧版本操作。等待最新同步结果后重新操作,不要让客户端自行构造物品结果。
mapped 为什么只能使用白名单 bind
真实容器映射必须经过服务端白名单,避免客户端构造危险槽位地址。未记录的映射会被拒绝。
创建事件
item_slot 支持 events.create,可在槽位组件实例创建时设置说明变量、显隐或周边组件状态。初始槽位和动态槽位实例各触发一次,但脚本不能伪造最终物品结果;槽位内容仍以服务端同步为准,关闭或 reload 时继续执行既定的持久化、返还或映射策略。
猹件开发组