# PlayDrop 游戏中的在线队伍和语音聊天

让朋友们在线一起玩你的游戏：声明队伍人数，打开 PlayDrop 的队伍窗口，用 sdk.multiplayer.join 加入预留的房间，并控制房间语音。

Source: https://www.playdrop.ai/zh-hans/create/learn/online-party

PlayDrop 队伍是一群一起在游戏之间移动的朋友。当一支队伍启动你的游戏时，PlayDrop 会在你服务器的某个房间里为队伍成员预留席位，让朋友们进入同一场对局，而不是被分开。语音聊天在 PlayDrop 中运行，而不是在你的游戏中。

## 你需要什么

- 一个[实时游戏服务器](https://www.playdrop.ai/zh-hans/create/learn/game-servers)：队伍在你的 Colyseus 房间中游玩。
- 已登录的玩家：房间会拒绝访客。
- [catalogue.json](https://www.playdrop.ai/zh-hans/create/learn/catalogue-json) 中的以下声明：

```json
{
  "types": ["solo", "online", "party"],
  "party": { "online": [2, 3, 4] },
  "roomVoice": true,
  "server": { "entry": "server/index.mjs", "rooms": ["game"] }
}
```

`party.online` 列出可以一起进入的确切队伍人数，最多 4 人；`[2, 4]` 不包括 3 人。它是一起进入的队伍人数，不是房间容量：两支四人队伍可以共用一个八人房间。`party` 需要 `party` 类型，`party.online` 需要 `online`。`roomVoice: true` 会开启房间语音，并且需要 `online`。

## 加入正确的房间

```js
if (!sdk.me.isLoggedIn) {
  await sdk.me.promptLogin();
}
const room = await sdk.multiplayer.join("game", { mode: "versus" });
```

当 PlayDrop 以队伍方式启动游戏时，`join` 会使用玩家预留的队伍席位，否则就独立加入。如果队伍加入失败，它会拒绝；绝不会悄悄把玩家放进另一个房间。访客会收到 `authentication_required`，PlayDrop 会显示登录；请在 `sdk.me.onAuthChange` 中再次加入。在各局之间保持同一个房间。

重新加载后，`sdk.multiplayer.reconnect(roomName, token)` 会用你为这款游戏、这个版本和这位用户私下保存的重连令牌恢复预留的席位。遇到 `multiplayer_reconnect_expired`、`multiplayer_reconnect_unavailable` 或 `party_reconnect_mismatch` 时，丢弃该令牌并调用 `join`。

## 队伍窗口

从一个按钮调用 `sdk.social.openParty({ mode: "online" })`，可以打开 PlayDrop 的队伍窗口，玩家可以在其中邀请朋友，并开启或关闭语音。已有的队伍会被沿用。`openParty()` 会打开队伍菜单，`openParty({ section: "voice" })` 会打开语音设置；不要同时使用 `mode` 和 `section`。窗口关闭时 promise 就会完成，包括取消的情况。

用 `sdk.social.getParty()` 或 `sdk.social.onPartyChange(callback)` 读取队伍，后者会先发送当前状态：`{ partyId, leaderUserId, revision, members, launch }`。当队伍正在玩这款游戏时，`launch.status` 为 `joining` 或 `ready`。仅仅是队伍成员，并不表示玩家在同一个房间；请使用 `join`。

队伍成员由 PlayDrop 管理：游戏不能添加或移除队伍成员，也不能控制麦克风；玩家通过这个窗口邀请朋友加入队伍。游戏仍然可以用 `sdk.social.sendMessage` 向朋友发送自己的邀请卡或挑战卡；请参阅[分享、好友和邀请](https://www.playdrop.ai/zh-hans/create/learn/social)。

## 房间语音

设置 `roomVoice: true` 后，房间里的每个人都可以说话，无需服务器代码。要改变谁能听到谁，请在服务器上绑定房间并设置策略：

```js
import { playdrop } from "@playdrop/server";

const platform = playdrop.multiplayer.forRoom(this);
platform.voice.setPolicy("team");
platform.voice.setTeam(client.auth, "red");
```

策略有 `all`、`team`、`proximity`（附带 `{ range }`）和 `off`。`setAudience(player, audience)` 可以单独覆盖一位玩家的设置，`updatePositions([{ player, position: { x, y, z } }])` 为近距离模式提供位置；传入 `null` 可清除队伍分配或覆盖设置。谁能听到谁由 PlayDrop 强制执行。在浏览器中，`sdk.multiplayer.voice.updateSpatialState({ listener: { position, forward, up }, speakers: [{ userId, position }] })` 只调整音量和声像。

语音受玩家同意、静音和屏蔽的约束，并取决于宿主版本和功能推出进度。

## 暂停

队伍胶囊不会暂停游戏。PlayDrop 的暂停会让你的客户端停下，但房间保持连接，你的服务器也会继续运行。一位玩家暂停不能让其他人的对局停下；如需暂停对局，请在服务器上实现。

## 测试

上传一个私密版本，然后在两个窗口中分别用 `player=1` 和 `player=2` 打开测试链接，方法见[实时游戏服务器](https://www.playdrop.ai/zh-hans/create/learn/game-servers)。使用控制器的本地队伍是另一种模式：请参阅[本地队伍和控制器](https://www.playdrop.ai/zh-hans/create/learn/local-party)。

## 相关指南

- [实时游戏服务器](https://www.playdrop.ai/zh-hans/create/learn/game-servers): 为你的游戏运行托管的 Colyseus 0.17 服务器和 MongoDB 数据库，用 SDK 从浏览器连接，用两位玩家测试，并了解各项限制。
- [本地队伍和控制器](https://www.playdrop.ai/zh-hans/create/learn/local-party): 通过 sdk.device 读取实体手柄和 PlayDrop 手机控制器，跟踪本地玩家槽位，并声明控制器支持和本地队伍人数。
- [分享、好友和邀请](https://www.playdrop.ai/zh-hans/create/learn/social): 带图片或短片分享游戏，读取启动数据，选择好友，在 PlayDrop Chat 中发送邀请卡和挑战卡，并推荐其他游戏。
