要钥匙才能开
这一页讲怎么让玩家必须拿着特定物品才能打开宝箱。
先理解它的工作方式
这个插件的钥匙不是虚拟货币,也不是次数。它直接检查玩家主手拿着的物品长什么样。
所以流程是这样的:
- 你规定"手上拿着 10 张名字带'钥匙'的纸才能开"
- 玩家手里拿着符合条件的纸,右键宝箱
- 插件检查主手物品,通过就开箱并扣掉 10 张
- 不通过就发一条提示,宝箱保持原样
钥匙物品本身可以由任何方式发放:商店卖、任务奖励、活动赠送,插件不管它从哪来。
钥匙检查只读主手的物品,副手放着不算。这一点经常被玩家误解,写公告时最好说明清楚。
最简单的配置
settings:
open_key:
deny: |-
tell "&c你需要一把钥匙才能打开"
key:
- check:
material: "tripwire_hook"
consume: true
意思是:手上拿着绊线钩就能开,开完扣掉 1 个。
三个部分:
deny:不满足条件时执行的脚本key:可接受的钥匙列表check:具体的检查条件consume:是否扣除
check:能检查什么
- check:
material: "paper"
name: "钥匙"
lore:
- "这是个钥匙"
amount: 10
consume: true
| 条件 | 怎么匹配 | 说明 |
|---|---|---|
material | 完全相同 | 物品材质,比如 paper、diamond |
name | 包含就行 | 物品名字里含有这段文字即可 |
lore | 每条都要有 | 你写的每一条都必须能在物品描述里找到 |
custom_model_data | 完全相同 | 模型数据,需要 1.14+ |
amount | 至少这么多 | 需要的数量,默认 1 |
所有写了的条件必须同时满足。上面那个例子要求:材质是纸、名字里有"钥匙"、描述里有"这是个钥匙"、数量至少 10 个。
不需要检查的条件直接不写就行。
name 是包含匹配
name: "钥匙"
这样配的话,下面这些物品名都能通过:
钥匙每日钥匙&6黄金钥匙宝箱钥匙 x1
比较之前会去掉颜色代码,所以物品名带颜色不影响匹配。
想精确一点就把名字写全:
name: "每日宝箱钥匙"
lore 是"每条都要有"
这一点容易搞反。假设你这样配:
lore:
- "限时活动"
- "不可交易"
物品的描述必须同时包含"限时活动"和"不可交易"两句才算通过。只有其中一句是不行的。
物品自己有多余的描述行不影响匹配。
amount 是最低数量
amount: 10
玩家手上至少要有 10 个。有 15 个也能开,扣的时候只扣 10 个。
必须是大于 0 的整数。
低于 1.14 的服务端不支持这个属性。如果你配了,插件启动时会警告说这个条件永远不会匹配,等于把宝箱锁死了。
默认的 def.yml 里这一行是注释状态,就是这个原因。
consume:扣不扣
consume: true # 扣掉(默认)
consume: false # 只检查,不扣
false 适合做"通行证"类型的钥匙:需要持有,但不会消耗。
配置多种钥匙
key 是一个列表,可以放多个条目。玩家满足任意一个就能开箱:
settings:
open_key:
deny: |-
tell "&c你没有合适的钥匙"
key:
# 方案一:10 张普通钥匙,会扣
- check:
material: "paper"
name: "普通钥匙"
amount: 10
consume: true
# 方案二:1 个 VIP 令牌,不扣
- check:
material: "gold_ingot"
name: "VIP令牌"
consume: false
插件从上往下检查,用第一个满足条件的方案。所以把消耗少的、优先级高的放前面。
deny:拒绝时的提示
deny: |-
tell inline "&c钥匙不够 {{ &has_amount }} / {{ &required_amount }}"
可用的变量:
| 变量 | 含义 |
|---|---|
&has_amount | 玩家手上有几个(空手时是 0) |
&required_amount | 这次需要几个 |
&consume | 是否需要消耗 |
注意 tell inline 和 tell 的区别:用了变量就必须写 tell inline,并且变量要用 {{ }} 包起来。
不用变量的话简单写就行:
deny: |-
tell "&c你需要一把钥匙"
玩家空手右键时,插件没法知道他想用哪种钥匙,此时 &required_amount 取所有方案里要求数量最少的那个值。
检查和扣除的时机
这个顺序能解释很多疑问,值得看一下:
- 玩家右键宝箱,第一次检查钥匙
- 不通过 → 执行
deny,立即把宝箱重新发给玩家,不扣钥匙 - 通过 → 执行
events.open脚本和插件事件 - 第二次检查钥匙(因为上一步的脚本可能改了玩家手上的东西)
- 构建界面并打开,确认玩家真的看到了界面
- 再确认一次这个坐标对玩家还是可见的
- 全部通过 → 这时才扣钥匙,然后移除宝箱、播放动画
几个由此得出的结论:
- 钥匙不足时宝箱不会消失。插件会立即重发一次、1 tick 后再补发一次
- 任何一步失败都不会扣钥匙,不存在"扣了钥匙但没开箱"
- 如果玩家在开箱瞬间把钥匙丢掉,第 5 步会检测到并取消开箱
用命令测试时的注意点
/tsl open mychest
这个命令也会检查钥匙。测试配了钥匙的宝箱时,手上也得拿着钥匙,否则会直接触发 deny。
想跳过钥匙测试奖励配置的话,临时把 open_key 整段注释掉。
不要钥匙
不写 settings.open_key 节点,宝箱就是直接能开的。
如果 open_key 存在,但 key 下面是空的、或者所有条目都因为格式问题被跳过,插件会输出 该宝箱将拒绝开启,谁都打不开这个箱子。
注意默认的 skull_test.yml 里就有一个 key: 后面什么都不写的例子,那是测试用的。
配错了怎么发现
启动或 /tsl reload 时,插件会逐条检查钥匙配置并输出提示:
| 控制台提示 | 原因 |
|---|---|
宝箱 X 已加载 N 个钥匙条件 | 正常,N 是实际生效的条数 |
open_key.key[N] 不是对象,已跳过 | 那一条没写成 - check: 的结构 |
open_key.key[N].check 缺失或格式错误,已跳过 | 少了 check 或者缩进不对 |
open_key.key[N].check.amount 不是整数,已跳过 | amount 写了非整数 |
open_key.key[N].check.amount 必须大于 0,已跳过 | amount 填了 0 或负数 |
open_key.key[N].check 没有可识别条件,已跳过 | check 下面一个有效条件都没有 |
配置了 custom_model_data,但当前服务端低于 1.14 | 该条件不会匹配 |
序号从 0 开始,key[1] 指的是第二条。
想看每次匹配的细节就开 /tsl debug,能看到命中了第几个条件、持有多少、需要多少、扣完剩多少。
完整示例
一个需要钥匙的每日宝箱:
title: "&6&l每日宝箱"
layout:
- '#########'
- ' 1111111 '
- '#########'
settings:
block: "TRAPPED_CHEST"
lock_inventory: true
open_key:
deny: |-
tell inline "&c需要每日钥匙 &7({{ &has_amount }}/{{ &required_amount }})"
key:
# 普通玩家:3 个钥匙
- check:
material: "tripwire_hook"
name: "每日钥匙"
amount: 3
consume: true
# VIP:持有令牌即可,不消耗
- check:
material: "nether_star"
name: "VIP令牌"
consume: false
events:
close: |-
tsl-claim
claim:
key: 1
amount: 3~5
layout: random
generator:
iron:
chance: 70
give: source
material: "iron_ingot"
amount: 3~8
gold:
chance: 30
give: source
material: "gold_ingot"
amount: 2~4
icons:
'#':
material: "GRAY_STAINED_GLASS_PANE"
name: " "
怎么给玩家发钥匙
插件本身不负责发钥匙。常见做法:
- 用其他插件的商店卖(比如 Malkuth)
- 用 CDK 兑换码发放(比如 CDKLite)
- 每日签到插件当奖励发
- 管理员用原版
/give命令直接发
原版命令的写法在不同版本差别很大,按你的服务端版本选:
# 1.13 ~ 1.20.4
/give <玩家> tripwire_hook{display:{Name:'{"text":"每日钥匙"}'}} 3
# 1.20.5 及以上(改成了组件格式)
/give <玩家> tripwire_hook[custom_name='{"text":"每日钥匙"}'] 3
# 1.12.2
/give <玩家> tripwire_hook 3 0 {display:{Name:"每日钥匙"}}
原版命令对引号和格式很敏感,写错一个字符就会失败。更稳的做法是自己在游戏里做好一个钥匙物品,然后用带物品库的插件(Zaphkiel、NeigeItems、ItemsAdder 等)保存成模板来发放。
不管用哪种方式,只要物品的材质、名字、描述符合你配的 check 条件就行,插件不关心它从哪来。