虚拟宝箱
工作原理
TreasuresLite 的宝箱基于 NMS 数据包实现。插件通过 sendBlockChange 向玩家客户端发送虚拟方块,不会在世界中放置实体方块。
- 宝箱仅在客户端渲染,服务端世界数据不受影响
- 每个玩家看到的宝箱状态完全独立(是否可领取、是否在冷却)
- 通过数据包拦截玩家右键点击虚拟方块的事件来触发开箱
方块外观配置
在宝箱配置文件的 settings 节点下配置方块外观。支持三种配置方式:
简化配置(仅指定材质)
settings:
block: "CHEST"
支持的材质:CHEST、TRAPPED_CHEST、ENDER_CHEST、BARREL 等所有 Bukkit Material。
CraftEngine 自定义方块(简化)
settings:
block: "craftengine:custom_chest"
# 或简写
block: "ce:my_custom_block"
详细配置(支持完整 BlockData 属性)
settings:
block:
# 方块材质类型(必填)
material: "CHEST"
# 方块朝向(可选,默认 NORTH)
# 可选值:NORTH, SOUTH, EAST, WEST, UP, DOWN
facing: "NORTH"
# 方块是否包含水源(可选,默认 false)
waterlogged: false
# 箱子类型(可选,默认 SINGLE)
# 可选值:SINGLE, LEFT, RIGHT
type: "SINGLE"
旧配置中的 settings.type 仍会被读取,但只在没有 settings.block 时才生效。两者同时存在时以 block 为准。
默认的 def.yml 就同时写了 type: trapped_chest 和 block: {material: "CHEST"},实际显示的是普通箱子。想要陷阱箱请改 block,改 type 没有效果。
头颅方块
支持使用自定义材质的头颅方块,有多种配置方式:
settings:
# 使用玩家名
block: "player_head:Notch"
# 使用 Base64 材质
block: "player_head:base64:eyJ0ZXh0dXJlcyI6..."
# 使用材质 URL
block: "player_head:url:http://textures.minecraft.net/texture/abc123..."
# 使用纯材质值
block: "player_head:texture:eyJ0ZXh0dXJlcyI6..."
头颅详细配置:
settings:
block:
material: "PLAYER_HEAD"
facing: "NORTH"
# 使用 Base64 材质
texture: "eyJ0ZXh0dXJlcyI6..."
# 或使用玩家名
owner: "Notch"
# 或使用材质 URL
texture_url: "http://textures.minecraft.net/texture/abc123..."
# 可选:自定义 UUID
uuid: "069a79f4-44e9-4726-a5be-fca90e38aaf5"
支持的头颅类型:PLAYER_HEAD、SKELETON_SKULL、WITHER_SKELETON_SKULL、ZOMBIE_HEAD、CREEPER_HEAD、DRAGON_HEAD、PIGLIN_HEAD(1.16+)
带 WALL 的墙头材质(如 PLAYER_WALL_HEAD)会按墙头形态贴在方块侧面,其余按站立头处理。
头颅方块通过发包实现,不会真实修改世界方块。如果同时提供 texture 和 owner,优先使用 texture。
箱盖开合动画只对 CHEST、TRAPPED_CHEST、ENDER_CHEST 生效。头颅、木桶和 CraftEngine 自定义方块能正常开箱,但不会有开合动画。
生成模式
固定坐标模式(Normal)
在 location.yml 中定义坐标分组,然后将宝箱绑定到坐标组:
# location.yml
location:
def1:
- 'world, 0, 80, 0, east'
- 'world1, 0, 80, 0, south'
generator:
normal:
period: 1800000
treasure:
def:
def1: "true"
坐标写法必须是 世界名, X, Y, Z, 朝向 五段,缺少朝向会导致该行被跳过。
每个坐标组可以设置独立的冷却时间,也可以配置为公共宝箱(一人领取后所有人消失)。period 和 cooldown 的单位都是毫秒。
随机坐标模式(Random)
在指定区域内随机生成宝箱坐标:
# location.yml
generator:
random:
period: 1800000
treasure:
- location: "world: 50,100 ~ -50,-100: ground#255: random"
max: 5
chest: def
ground#255 表示从 Y=255 往下找到第一个非空气方块上方放置宝箱。range#0~40 表示在 Y=0~40 范围内随机选择高度。
同一个宝箱配置多条随机规则时,结果会按顺序合并,并跨规则按坐标去重。
显示与坐标优先级
每个玩家的宝箱坐标来自三个来源,按物理坐标(世界 + XYZ,不含朝向)去重,冲突时优先级为:
| 优先级 | 来源 | 产生方式 |
|---|---|---|
| 高 | 临时(Temp) | Kether 动作 tsl-put 放入 |
| 中 | 固定(Normal) | generator.normal 坐标组 |
| 低 | 随机(Random) | generator.random 区域抽取 |
显示采用差集对账:插件会比较"现在应该显示什么"和"上次已经发给这个玩家什么",只补发变化的部分,并把不该再显示的坐标恢复成真实方块。开启 /tsl debug 可以看到每次对账的统计,包括候选数、实际发送数、恢复数、因世界不匹配或超出距离被跳过的数量。
其他设置
settings:
# 上锁玩家背包,无法点击背包内物品
lock_inventory: true
开启 lock_inventory 后,config.yml 里的 view.virtualize_ui 对该宝箱不再生效。