BattlePass
概述
BattlePass 为你的服务器增加了一条赛季制的成长轨道。一个赛季有开始和结束日期,并被划分为若干周;每一周会解锁一组任务。玩家完成其中一个任务时会获得经验值,而经验值阈值则对应等级。奖励被分组到**层级(tier)**中(例如一个免费层和一个由权限把守的高级层),并通过菜单领取。
一切都在网页面板中通过一个 Battle Pass Definition 条目来配置:层级、奖励、周、经验阈值、日程、菜单布局和按钮物品。奖励只是一组 TypeWriter 触发器,因此它可以给予物品、运行命令、授予装饰品,或做动作能做的任何其他事情。任务来自 TypeWriter 的 Quest 扩展。
该扩展运行于 TypeWriter 的 BTC 构建版(BTC Core,Paper/Folia),此处的文档仅供参考。进度通过 Battle Pass Data artifact 保存,并保留在内存缓存中,因此菜单和占位符永远不需要等待存储。
功能
- 赛季 — 可选的开始和结束日期、以天为单位的每周时长,以及 IANA 时区(默认为 UTC)。
- 每周任务 — 每一周会自动解锁或在选定日期解锁,每个任务在完成时给予固定数量的经验值。
- 经验与等级 — 一组经验阈值定义了各个等级,并可选择设置经验上限。
- 分层奖励 — 每个层级都有优先级、可选的权限,以及与所需等级绑定的奖励。
- 安全领取 — 领取会在触发器运行之前先预留,因此奖励不会被重复发放。
- 可配置菜单 — 槽位、大小以及每个按钮的物品、名称和 lore,或基于 GUI 扩展构建的完整自定义布局。
- 管理命令 — 为自己或其他玩家增加、移除或设置经验和等级,并读取某位玩家的进度。
- 占位符 — 用于计分板和菜单的等级、经验、奖励计数器和周信息。
- 可编辑的消息 — 每条聊天消息都可以在 BattlePass Messages 条目中修改。
- 支持网络环境 — 进度通过 MySQL 扩展存储,在可用时通过 Redis 使缓存失效。
安装
- 安装 TypeWriter 的 Quest 扩展、GUI 扩展(BTC 构建版中为
GuiAndDialogs)和 MySQL 扩展。没有它们,TypeWriter 不会加载 BattlePass。 - 将 BattlePass 的 JAR 放入
plugins/Typewriter/extensions/,然后重启服务器。 - 使用 Quest 扩展创建你想使用的任务。
- 如果你想要高级层,请用你的权限插件创建该权限(名称由你决定,在层级中输入它即可)。
快速上手
创建一个为期四周的赛季,并在 1 级提供一个免费奖励:
- 在 TypeWriter 网页面板中,打开一个 manifest 页面,添加一个 Battle Pass Data artifact。保持
artifactId为自动生成的值,并让storage.mode保持为PLAYER。 - 在同一个页面上添加一个 Battle Pass Definition 条目。为它设置
name,将data设为该 artifact,并选择一个icon,例如minecraft:book。 - 在
xp中,用递增的经验阈值填写levels(例如100、250、500),还可以选择设置max。 - 在
weeks中,添加一周,number为1,设置title,并在quests中选择一个 Quest 条目并为其设置xpReward。对接下来的几周重复此操作。 - 在
schedule中,设置start(例如2026-11-01T00:00:00)、weekDurationDays和timezone(例如Europe/Paris)。各周随后会依次解锁。 - 在
tiers中,添加一个level为1的层级,并在rewards中添加一个levelRequired为1并带有displayName的奖励。链接用于发放该奖励的triggers,例如一个给予物品的动作。 - 添加一个 Open Battle Pass 动作,在
battlePass中指向你的 definition,并通过 NPC、物品或菜单来触发它。玩家也可以输入/tw battlepass。 - 发布,完成该周的一个任务,然后打开菜单领取奖励。
层级的 level 是它在奖励菜单中的编号,并且在一个 definition 内必须唯一。领取奖励所需的玩家等级是该奖励自己的 levelRequired。层级可以带有 permission:没有该权限的玩家会看到它的奖励处于锁定状态,高级轨道就是这样构建的。
每个奖励都有一个 id。如果留空,扩展会根据层级的等级和奖励的位置生成一个(tier-1-reward-1),但如果你之后移动或插入奖励,生成的 id 就会发生偏移,玩家已领取的奖励将不再匹配。请在赛季开始之前为每个奖励设置明确的 id,并且永远不要更改它。
工作原理
只有当 definition 的某一周中所列的任务变为 COMPLETED、该周被标记为 available、该周已解锁并且赛季正在进行时,才会获得经验值。xpReward 为 0 的任务不会给予任何东西。等级就是玩家已达到的 xp.levels 阈值的数量。
当赛季已经开始(赛季结束后仍可领取)、玩家等级达到 levelRequired,并且在设置了层级 permission 时玩家拥有该权限,奖励才可以被领取。奖励只能领取一次。如果某个奖励的触发器失败,该奖励会保持待处理状态,并且不会自行重试,因为触发器可能带有副作用。
菜单
默认情况下,扩展会打开它自己的物品栏菜单:列出各周的主菜单、所选周的任务菜单,以及奖励(层级)菜单。
- 主菜单 — 每周一个按钮、上一周和下一周按钮、奖励按钮、信息按钮和关闭按钮。
- 任务菜单 — 该周的任务及其状态(锁定、可用、进行中、已完成)、翻页按钮、排序按钮和返回按钮。
- 奖励菜单 — 每个层级的奖励及其状态、翻页按钮和返回按钮;点击已解锁的奖励即可领取。
大小和位置来自 layout。每个大小必须是 9 到 54 之间的 9 的倍数,并且每个槽位都必须在其范围内。槽位接受单个数字或诸如 10-16 的范围。让槽位留空以使用默认位置(54 格布局,周位于第 2 行,任务位于第 2 到 4 行,关闭按钮位于第 49 格),或使用其 ...Enabled 字段关闭某个按钮。每个按钮在 buttons 中都有 item、name 和 lore,你可以在其中使用花括号中的占位符,例如 {week_title}、{quest_name}、{tier_level} 或 {reward_state}。面板中的字段帮助会列出每个按钮可用的占位符。
如果你设置了 baseMenuId、menuLayoutPool、menuViews 或 menuMainLayoutId,通行证会改为在你自己的 GUI 底板中打开,包含三个视图(主页、等级、任务),其 id 通过 menuHomeViewId、menuLevelsViewId 和 menuQuestsViewId 设置。GUI 编辑器随后会提供 battlepass_button: 物品:WEEK_SLOT、TIER_MENU、REWARD_SLOT、CLAIM、QUEST_SLOT、SORT、INFO、PAGE_NEXT、PAGE_PREV、BACK 和 CLOSE。编辑器中的按钮类型说明是法语的。
菜单交互属于 GUI 会话的内部机制:它们不是 Bukkit 命令,玩家无法输入。
命令
BattlePass 的命令是 TypeWriter 命令的子命令,因此以 /typewriter 或其别名 /tw 开头。基础权限是 typewriter.battlepass。<pass> 参数是 Battle Pass Definition 的 id 或名称,并支持自动补全。可选的 [targets] 参数是玩家选择器;不填时命令作用于发送者。
| 命令 | 说明 |
|---|---|
/tw battlepass | 打开按 id 排序后第一个 definition 的菜单。 |
/tw battlepass menu | 与 /tw battlepass 相同。 |
/tw battlepass open | 与 /tw battlepass 相同。 |
/tw battlepass <pass> xp add <amount> [targets] | 增加经验值(数量的正负号会被忽略)。 |
/tw battlepass <pass> xp remove <amount> [targets] | 移除经验值。 |
/tw battlepass <pass> xp set <amount> [targets] | 设置经验值(不低于零)。 |
/tw battlepass <pass> level add <amount> [targets] | 提升等级。 |
/tw battlepass <pass> level remove <amount> [targets] | 降低等级。 |
/tw battlepass <pass> level set <amount> [targets] | 设置等级。 |
/tw battlepass <pass> info [targets] | 显示某位玩家在该通行证中的经验值和等级。 |
权限
| 权限 | 授予 |
|---|---|
typewriter.battlepass | 所有 /tw battlepass 命令,包括菜单和管理子命令。 |
层级的 permission | 你自行选择、设置在某个层级上的权限,领取该层级的奖励时需要它。 |
占位符
这些是 battlepass expansion 的 MiniPlaceholders 标签,可用于任何支持占位符的 MiniMessage 文本。请将 def 替换为 Battle Pass Definition 条目的 id。计数器是数字;真或假的值会以 1 或 0 返回。
| 占位符 | 返回值 |
|---|---|
<battlepass_name:def> | 通行证的名称。 |
<battlepass_active:def> | 当玩家可以获得经验值(赛季进行中)时为 1,否则为 0。 |
<battlepass_level:def> | 玩家的等级。 |
<battlepass_xp:def> | 玩家的经验值。 |
<battlepass_xp_max:def> | 经验上限;未设置上限时为最高的阈值。 |
<battlepass_xp_next:def> | 下一等级的经验阈值。 |
<battlepass_xp_remaining:def> | 距离下一等级所缺少的经验值。 |
<battlepass_rewards:def> 和 <battlepass_rewards_total:def> | 奖励的总数。 |
<battlepass_rewards_claimed:def> | 已领取的奖励数。 |
<battlepass_rewards_available:def> | 玩家现在可以领取的奖励数。 |
<battlepass_rewards_unclaimed:def> | 奖励总数减去已领取的奖励数。 |
<battlepass_rewards_pending:def> | 已预留但尚未发放的奖励数。 |
<battlepass_week_state:def:N> | 第 N 周的状态标签。 |
<battlepass_week_active:def:N> | 当第 N 周既未锁定也不是不可用时为 1。 |
<battlepass_week_available:def:N> | 当该周被标记为 available 时为 1。 |
<battlepass_week_title:def:N> | 第 N 周的标题。 |
<battlepass_week_description:def:N> | 第 N 周的描述。 |
<battlepass_week_release:def:N> | 第 N 周的解锁日期。 |
<battlepass_week_release_in:def:N> | 第 N 周解锁前剩余的时间,解锁后为空。 |
条目
5 个条目,由扩展源码生成。
动作1
- Open Battle PassOpen a battle pass menu
事实1
- Battle Pass Quest ActiveCheck if a battle pass week is active
构件1
- Battle Pass Data ArtifactStore battle pass runtime data
清单1
- Battlepass DefinitionRegister a battle pass definition
其他条目1
- Battlepass MessagesBattlePass Messages
故障排查
扩展无法加载。 BattlePass 需要 Quest、GUI(GuiAndDialogs)和 MySQL 扩展。请检查 TypeWriter 的启动日志,查看是否缺少依赖。
日志显示 “Ignoring invalid battle pass definition”。 该 definition 未通过验证,因此没有被注册,/tw battlepass 会显示 “Aucun Battle Pass n'est actuellement chargé”。日志行会列出问题:空的 name、不是 9 到 54 之间 9 的倍数的菜单大小、超出菜单范围的槽位、重复的层级等级、周编号或奖励 id、未严格递增的 xp.levels,或者不早于 schedule.end 的 schedule.start。
完成任务没有获得经验值。 该任务必须列在 definition 的某一周中,且 xpReward 大于 0,该周必须是 available 并且已解锁,赛季必须处于进行状态,并且 definition 需要一个 data artifact(缺失时日志会给出警告)。未知的 timezone 会回退为 UTC,无法解析的日期字符串会被忽略。
某个奖励无法领取。 等级必须达到 levelRequired,玩家需要拥有层级的 permission,赛季必须已经开始,并且该奖励不能已被领取或已处于待处理状态。如果它的触发器失败了,日志会报告 “remains pending after delivery failure”,该奖励会一直保持待处理状态,直到管理员决定如何处理。
编辑奖励后,已领取的奖励又重新出现。 根据位置生成的奖励 id 发生了变化。请为每个奖励设置明确的 id 并保持不变。
进度没有被保存。 artifact 的 artifactId 必须保持为网页面板生成的有效 UUID;扩展拒绝使用其他任何值。请不要手动移动或重命名已存储的文件。