Rewards
概览
Rewards 为每位玩家维护一个队列,存放已经获得但尚未领取的奖励。你不再当场给予物品或运行命令,而是把奖励推入队列。玩家稍后在线并且物品栏有空位时,可从菜单中领取。即使奖励发放时玩家离线或物品栏已满,也不会丢失任何东西。
奖励是你只需定义一次的模板(一个奖励定义:展示物品、lore、所需空槽位数、领取时运行的动作)。发放它会向队列添加一条小记录;领取它会移除该记录,并触发你链接到该定义的 TypeWriter 动作。由于领取效果是一组 TypeWriter 动作,奖励可以给予物品、金钱、任务步骤,或 TypeWriter 能触发的任何其他内容。
队列存储在单个构件中。当 MySQL 扩展提供 Redis 时,共用同一存储的服务器会在每次保存后被通知重新加载该构件,因此在一台服务器上发放的奖励可以在另一台服务器上领取。
功能
- 延迟领取 — 奖励在队列中等待,直到玩家领取。
- 奖励定义 — 每种奖励类型一个可重复使用的模板,包含展示物品、名称、lore 和空槽位要求。
- 领取动作 — 领取会触发任意 TypeWriter 动作列表,而不是控制台命令。
- 独立的领取菜单 — 带有奖励槽位、信息槽位、翻页按钮、批量领取和返回按钮的分页物品栏。
- 可嵌入的按钮 — 奖励槽位和批量领取按钮可通过按钮类型放置在任意 GUI 页面上。
- Cron 发放 —
btc_give_reward可以在每个 cron 周期内为每位玩家最多发放一次奖励(每日、每周奖励)。 - 领取事件 — 每次领取时,事件条目都会触发,并带有奖励 id、自定义数据和计数器。
- 待领取数量事实与占位符 — 在条件、计分板和菜单中使用该队列。
- 防刷屏 — 同一玩家两次领取之间有 500 毫秒的冷却。
安装
- 安装 GUI 扩展(其在构建中的插件名称为
GuiAndDialogs)和 MySQL 扩展,两者都被声明为 Rewards 的依赖项。Redis 仅用于跨服务器刷新,在单台服务器上不需要。 - 将 Rewards 的 JAR 放入
plugins/Typewriter/extensions/并重启服务器。 - 可选:安装 MiniPlaceholders,以便在 MiniMessage 文本中使用
rewards占位符。
快速上手
发放一份玩家从菜单中领取的每日登录奖励。
- 在 TypeWriter 网页面板中,打开一个**静态(static)**页面,添加一个 Rewards Artifact。只添加一个:占位符和嵌入式按钮会使用它们找到的第一个。
- 添加一个 Rewards Config 条目(同样只添加一个),用于调整消息和奖励 lore 的布局。
- 添加一个 Reward Definition。将
rewardId设为daily_login,source设为daily_login,选择一个displayItem,并在onClaimActions中链接给予奖励的动作。 - 创建一个 Give Reward 动作。链接
artifact和reward,启用useCron,并将cronExpression设为0 0 0 * * *表示每天一次。通过加入事件或 NPC 触发它。 - 创建一个使用相同
artifact的 Open Rewards Menu 动作,并通过命令或 NPC 触发它。 - 发布。触发发放的玩家会获得一个待领取的奖励;在菜单中点击它即可领取。
在条件中使用 Has Pending Rewards,使通知只在玩家有东西可领取时才显示。
工作原理
队列只存储 rewardId、发放时间和自定义数据。菜单中显示的物品以及要运行的动作,始终是在显示或领取的那一刻从定义中读取的。其定义已被删除的队列奖励不会显示,也无法领取。
菜单
Rewards 可以通过两种共用同一套领取逻辑的方式显示。
独立菜单。 Open Rewards Menu 会打开自己的物品栏,rows 为 1 到 6。待领取的奖励按顺序填入 rewardSlotsConfig(一个范围,或在 useRange 关闭时使用显式的槽位列表)。当奖励数量多于槽位时,菜单会通过可选的 previousPageButton 和 nextPageButton 分页。可选的 infoSlot、bulkClaimButton 和 backButton 接受槽位编号、物品、MiniMessage 名称和 lore。backButton.command 以玩家身份运行(不带开头的斜杠);将其留空则只关闭菜单。设置了 backgroundItem 时,空槽位会用它填充。槽位编号从 0(左上角)到第一行的 8,然后是 9 到 17,依此类推。
任意 GUI 页面上的按钮。 在 GUI 菜单中,将某个物品的 buttonType 设为 Rewards 标记之一。你配置的物品会保留其位置和样式;对于奖励槽位,它会被该奖励自己的展示物品替换。
| 按钮类型 | 行为 |
|---|---|
rewards_button:REWARD_SLOT#<n> | 显示查看者的第 n 个待领取奖励(从 0 开始计数);左键点击领取。超过最后一个奖励后,槽位为空。 |
rewards_button:BULK_CLAIM | 左键点击会领取玩家有空位容纳的所有待领取奖励。 |
两种模式下的领取规则:
- 奖励需要玩家物品栏中有
requiredInventorySlots个空槽位(0 表示不检查)。如果空间不足,领取会被拒绝,并发送inventoryFullMessage。 - 领取会触发定义的
onClaimActions,然后触发每一个 Reward Claimed 事件条目。批量领取从最后加入队列的奖励到第一个,并以奖励 idbulk_claim触发一次事件。 - 成功消息和批量消息来自 Rewards Config 条目。对于嵌入式按钮,会使用找到的第一个 Rewards Config 条目。
奖励物品的 lore 由定义的 additionalLore 构建,然后是一条分隔线以及来源和空槽位行,最后是一条收尾提示;标签来自 Rewards Config 条目。
占位符
MiniPlaceholders 扩展 rewards,可在 MiniMessage 文本中作为标签使用。
| 占位符 | 返回 |
|---|---|
<rewards_pending> | 玩家待领取的奖励数量。 |
<rewards_pending:rewardId> | 具有该 rewardId 的待领取奖励数量。 |
<rewards_source:source> | 其定义具有该 source 的待领取奖励数量(不区分大小写)。定义已被删除的奖励不会被计入。 |
<rewards_claimed_total> | 玩家累计已领取的奖励数量。 |
奖励 id 是标签的参数:请写 <rewards_pending:daily_login>,而不是 <rewards_pending_daily_login>。如果不存在 Rewards Artifact,所有占位符都不返回任何内容。
条目
7 个条目,由扩展源码生成。
动作2
- BTC Give RewardAdds a reward to a player's pending queue (with optional cron scheduling)
- BTC Open Rewards MenuOpens the rewards queue menu for a player
事件1
- BTC Reward Claimed EventTriggered when a player successfully claims a reward
事实1
- BTC Has Pending RewardsReturns the count of pending rewards for a player
构件1
- BTC Rewards ArtifactStores pending rewards and claim history for all players
清单2
- BTC Reward DefinitionDefines a reward type that can be given and claimed by players
- BTC Rewards ConfigGlobal configuration for the rewards system (sounds, toasts, messages)
故障排查
菜单没有打开,且日志提示未安装 GUI Extension。 btc_open_rewards_menu 在运行时需要 GUI 扩展。请安装它并重启。当其 artifact 字段为空时,该动作同样不会执行任何操作,并给出警告。
Give Reward 没有任何作用。 当动作没有 artifact、没有 reward,或所链接的定义的 rewardId 为空时,日志会显示警告。请填写这三个字段。
Cron 奖励只发放了一次。 开启 useCron 时,上次发放时间按玩家和动作条目存储。只有在那之后 cron 表达式下一次匹配时,才会进行下一次发放。请使用较短的表达式进行测试,或为每个计划使用不同的动作条目。
待领取的奖励不可见或无法领取。 菜单会跳过无法通过 rewardId 找到其定义的队列奖励。在已经发放奖励之后,请勿更改定义的 rewardId。
领取被拒绝,并显示物品栏已满的消息。 玩家的空槽位少于 requiredInventorySlots。请注意,该检查会统计玩家物品栏对象的每一个空槽位,包括盔甲和副手槽位。
Toast、音效、noRewardsMessage 和 onClaimFailActions 没有效果。 这些字段存在于 Rewards Config 和 Reward Definition 中,但此版本的代码从不读取它们。只有领取消息、物品栏已满消息、批量消息以及 lore 布局会被应用。
奖励没有出现在另一台服务器上。 跨服务器刷新依赖于 MySQL 扩展提供的 Redis,并且两台服务器必须读取相同的构件存储。没有 Redis 时,每台服务器只能看到自己的副本,直到重启。