Party
概述
Party 让玩家组建短期的小队。队长创建队伍并按名称邀请玩家,被邀请的玩家用 /party join <leader> 接受。任务、地下城和 HUD 系统随后就可以询问“谁和这位玩家在同一个队伍中”。队长还可以把整支队伍传送到网络中的另一个服务器。
队伍不会保存到数据库:它们存在于内存中,并通过 Redis 复制到网络中的其他服务器。断开连接的成员仍然留在队伍中,因此队伍可以在服务器之间跳转后依然存在,只有当成员离开、被踢出,或队长解散时,队伍才会结束。重启所有服务器会解散所有队伍。
队伍菜单是你在网页面板中构建的 GUI 菜单。成员显示为玩家头像,待处理的邀请则显示为可点击的头像。
功能
- 创建、邀请、加入、离开、踢出、解散 — 可通过命令、TypeWriter 动作和菜单按钮使用。
- 队伍菜单 — 一个条目包含成员和邀请界面、分页和标签页。
- 邀请 — 通过聊天输入名称、带搜索过滤的加入界面,以及 60 秒的有效期。
- 人数上限 — 一个默认的最大值,并为诸如
typewriter.party.vip的权限提供更高的上限。 - 传送到某个服务器 — 队长把所有成员送到另一个后端服务器,无论他们在网络中的什么位置。
- 跨服务器队伍 — 成员、邀请和队伍聊天消息会同步到该组的每个服务器。
- 剧情钩子 — 一个 fact 用于判断玩家是否在队伍中。
- 占位符 — 用于 HUD 的队长、角色、人数、成员名称和成员生命值。
- 集成 — 其他 BTC 扩展(例如合作岛屿和地下城)会创建和读取队伍。
安装
- 安装负责绘制菜单的 GUI 扩展,以及 Party 声明为依赖的 Quest 扩展。
- 可选,适用于多个服务器:安装 MySQL 扩展,启用 Redis(或 Valkey),并在每个服务器上设置相同的
redis.group-id和唯一的redis.server-name。传送需要代理服务器处理btc:bridge通道。 - 将 Party 的 JAR 放入
plugins/Typewriter/extensions/,然后重启服务器。
party.use 默认授予所有人,party.admin 默认授予 OP。
快速上手
构建一个队伍菜单和一个人数上限:
- 在 TypeWriter 网页面板中,打开一个页面,添加一个 Party Menu Config 条目。只会用到它的限制(参见配置):设置
maxPartySize,还可以选择设置maxPartySizePermissions。 - 添加一个 Party Menu 条目。
/party会打开找到的第一个。 - 设置
inventoryTitle、inventoryRows和guiType,然后在layoutPool中构建布局并设置mainLayoutId。参见 GUI 指南。 - 在
views中声明界面(例如members和join)。将成员界面的 id 列入memberListViewIds,将邀请界面的 id 列入joinListViewIds。 - 添加带有
buttonType的物品:PARTY_MEMBERS、PARTY_JOIN、PAGE_NAV,以及运行命令的按钮(参见菜单)。 - 发布并运行
/party。
若要从任务中开始一个队伍,请使用 Create Party 动作。若要让玩家聚在一起,请使用带有 targetName 的 Invite Player(它接受占位符),以及带有 leaderName 的 Join Party。
使用 Warp Party to Server,并将 targetServer 设为代理服务器所知的后端名称,例如 dungeon-1。只有队长可以触发它。将其与 In Party fact 作为条件(criteria)结合使用,即可只向处于队伍中的玩家提供传送。
工作原理
队伍的每一次变更都会发送给其他服务器,由它们替换各自的副本。邀请在 60 秒后过期,每分钟检查一次,因此一次邀请的有效期介于 60 到 120 秒之间。当队长离开时,剩下的第一位成员成为队长。没有任何成员的队伍会被移除。
配置
Party Menu Config 条目是可选的。它只包含队伍人数上限,通过这些字段设置:
maxPartySize— 默认的最大成员数。默认值为5。maxPartySizePermissions— 权限到最大人数的映射。适用队长所拥有的匹配项中最高的人数。默认值是typewriter.party.vip对应 8,typewriter.party.mvp对应 12。
没有此条目时没有人数上限。队伍菜单本身不在这里配置,它来自 Party Menu 条目。
在此版本中,队伍服务不会读取或写入 Party Artifact,你也不需要创建它。
菜单
Party Menu 条目是一个 GUI 菜单,具有以下队伍专属的行为。
内容面板。 在 memberListViewIds 所列出的界面上,每位成员是一个显示角色和在线状态的玩家头像。如果你是队长,左键点击另一位成员会将其踢出。在 joinListViewIds 所列出的界面上,每个待处理的邀请是邀请者(队长)的头像:左键点击加入,右键点击拒绝。面板的位置由 contentX(默认 5)、contentY、contentColumns(默认 4)和 contentRows(默认 7)决定。
按钮。 这些 buttonType 值开箱即用:
buttonType | 点击 |
|---|---|
PARTY_MEMBERS | 打开 members 界面(party open members)。 |
PARTY_JOIN | 切换到同一菜单的 join 视图。 |
PAGE_NAV | 左键向前,右键向后;名称会显示页码计数器。当一页就够用时会隐藏。 |
这些值不会附加任何动作。请自行配置物品并为其设置命令:PARTY_INFO、PARTY_CREATE、PARTY_LEAVE、PARTY_DISBAND、PARTY_INVITE、PARTY_CLOSE、PARTY_ACCEPT_INVITE、PARTY_DECLINE_INVITE。例如,在相应的物品上运行 party create、party leave 或 party disband。邀请按钮需要输入名称:请给它一个 input 对话框,其 onInputCommands 运行 party invite {input}。
槽位命令。 物品可以运行 party open [view]、party page next|prev|<number>、party info、party create、party leave、party disband、party kick <name>、party invite <name>、party join <leader>、party declineinvite <leader> 和 party joinsearch <text>。它们会以点击的玩家身份运行。
头像的 lore 和某些管理消息是法语的。占位符 <party_role> 返回法语单词 Chef、Moderateur 和 Membre。如需标识符 LEADER、MODERATOR 和 MEMBER,请使用 <party_role_raw>。
命令
所有命令都需要 party.use。别名:/p。不带参数的命令会打开第一个 Party Menu,如果不存在则不输出任何内容。
| 命令 | 说明 |
|---|---|
/party | 打开队伍菜单。 |
/party create | 创建队伍并成为其队长。 |
/party invite | 关闭物品栏,并在聊天中输入玩家的名称。 |
/party invite <player> | 邀请一位玩家(仅限队长)。 |
/party join <leader> | 如果受到邀请,加入该队长的队伍。 |
/party accept <leader> | 与 join 相同。 |
/party leave | 离开你的队伍。 |
/party kick <player> | 踢出一位成员(仅限队长)。 |
/party disband | 解散队伍(仅限队长)。 |
/party info | 输出队长和成员。 |
/party admin list | 列出所有活动的队伍(需要 party.admin)。 |
/party admin info <player> | 显示某位玩家的队伍。 |
/party admin disband <player> | 解散某位玩家的队伍。其队长必须在线。 |
/party admin kick <player> | 将某位玩家从其队伍中移除。队伍的队长必须在线。 |
权限
| 权限 | 默认 | 授予 |
|---|---|---|
party.use | 所有人 | 每个 /party 命令。菜单点击会执行相同的动作,但不会检查它。 |
party.admin | OP | /party admin 命令。 |
typewriter.party.vip, typewriter.party.mvp | 无 | 更高的队伍人数上限,仅当它们列在配置条目的 maxPartySizePermissions 中时才生效。这些名称是默认值,可以更改。 |
占位符
用于 MiniMessage 文本的 MiniPlaceholders 标签,例如 <party_leader>。索引从 0 开始。
| 占位符 | 返回值 |
|---|---|
<party_in_party> | 玩家在队伍中时为 1,否则为 0。 |
<party_leader> | 队长的名称。 |
<party_role> | Chef、Moderateur 或 Membre。 |
<party_role_raw> | LEADER、MODERATOR 或 MEMBER。 |
<party_size> | 成员数量。 |
<party_members> | 成员数量。 |
<party_members:index> | 该位置的成员名称。 |
<party_members_exclude:index> | 该位置的成员名称,不包含查看者本人。 |
<party_list> | 以逗号分隔的成员名称。 |
<party_member_name:index> | 该位置的成员名称。 |
<party_member_uuid:index> | 该成员的 UUID。 |
<party_member_health:index> | 该成员在本服务器在线时的当前生命值,否则为 0.0。 |
<party_member_health_max:index> | 最大生命值,未知时为 20.0。 |
<party_member_health_percent:index> | 以百分比表示的生命值。 |
条目
10 个条目,由扩展源码生成。
动作7
- Create PartyCreate a new party
- Invite PlayerInvite a player to your party
- Join PartyJoin a party
- Kick Party MemberKick a member from your party
- Leave PartyLeave your current party
- Party MenuOpen Party Menu
- Warp Party to ServerWarp the player's party to a server
事实1
- In PartyCheck if player is in a party
构件1
- Party ArtifactArtifact for storing party and friend data
清单1
- Party size limitsMaximum party size, with optional permission-based overrides
故障排查
/party 没有任何反应。 没有发布 Party Menu 条目。诸如 /party create 的子命令在没有它时也能使用。
“You do not have an invite to this party.” 邀请在 60 到 120 秒后已过期,或者队长的名称拼写错误。请让队长重新邀请,然后使用 /party join <leader>。
“Party is full! Limit: N”。 队长已达到 Party Menu Config 的 maxPartySize。请提高它,或授予队长一个列在 maxPartySizePermissions 中的权限。没有配置条目时没有上限。
另一个服务器上的成员没有出现。 每个服务器都需要相同的非空 redis.group-id、唯一的 redis.server-name,以及已连接的 Redis。没有 group-id 就不会广播任何内容。
传送失败,提示 “Cross-server transport is unavailable.” Redis 未连接。请检查 MySQL 扩展的配置。targetServer 必须是代理服务器所知的后端名称,并且代理服务器必须接受 btc:bridge 通道。
在 Party Menu Config 中更改槽位、按钮、消息没有效果。 这些字段属于已不再注册的旧菜单。请使用 Party Menu 条目来设计菜单。
/party invite 之后的下一条聊天消息没有显示。 这是预期行为:不带名称的命令会等待一条聊天消息,并将其作为玩家名称,然后邀请该玩家。错误的名称只会得到一个错误提示。