# PlayDrop ゲームのオンラインパーティーとボイスチャット

友達どうしでオンラインで一緒に遊べるようにします。パーティーの人数を宣言し、PlayDrop のパーティー画面を開き、sdk.multiplayer.join で予約済みのルームに参加し、ルーム音声を制御します。

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

PlayDrop のパーティーは、一緒にゲームからゲームへ移動する友達のグループです。パーティーがあなたのゲームを始めると、PlayDrop はサーバーのルームの1つにメンバー分の席を予約するので、友達はバラバラにならずに同じ試合に参加できます。ボイスチャットはゲームではなく PlayDrop の中で動きます。

## 必要なもの

- [リアルタイムゲームサーバー](https://www.playdrop.ai/ja/create/learn/game-servers)：パーティーはあなたの Colyseus のルームで遊びます。
- サインイン中のプレイヤー：ルームはゲストを受け付けません。
- [catalogue.json](https://www.playdrop.ai/ja/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人は対象外です。これは参加するグループの人数で、ルームの定員ではありません。4人のパーティー2組が8席のルームを共有することもできます。`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" });
```

`join` は、PlayDrop がパーティーとして起動した場合はプレイヤーの予約済みの席を使い、そうでない場合は単独で参加します。パーティーの参加に失敗した場合は拒否され、プレイヤーを黙って別のルームに入れることは決してありません。ゲストには `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)` で読み取ります。`onPartyChange` は最初に現在の状態を届けます：`{ partyId, leaderUserId, revision, members, launch }`。パーティーがこのゲームを遊んでいるとき、`launch.status` は `joining` または `ready` です。メンバーであるだけでは、プレイヤーが同じルームにいるとは限りません。`join` を使ってください。

パーティーのメンバー管理は PlayDrop の役割です。ゲームはパーティーのメンバーを追加・削除したり、マイクを制御したりできません。プレイヤーはこの画面から友達をパーティーに招待します。ただし、ゲームは `sdk.social.sendMessage` を使って、独自の招待カードや挑戦カードを友達に送れます。[共有、フレンド、招待](https://www.playdrop.ai/ja/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)` は1人のプレイヤーの設定を上書きし、`updatePositions([{ player, position: { x, y, z } }])` は近接判定に位置を渡します。チームや上書きを解除するには `null` を渡します。誰の声を誰が聞けるかは PlayDrop が強制します。ブラウザの `sdk.multiplayer.voice.updateSpatialState({ listener: { position, forward, up }, speakers: [{ userId, position }] })` が調整するのは、音量と左右の定位だけです。

音声には、プレイヤーの同意、ミュート、ブロックが適用され、ホストのビルドや提供状況にも左右されます。

## 一時停止

パーティーのカプセル表示は、ゲームプレイを一時停止しません。PlayDrop の一時停止はクライアントを止めますが、ルームの接続は維持され、サーバーは動き続けます。1人のプレイヤーの一時停止で、ほかのプレイヤーの試合を止めてはいけません。試合の一時停止が必要なら、サーバー側で実装してください。

## テスト

非公開バージョンをアップロードし、[リアルタイムゲームサーバー](https://www.playdrop.ai/ja/create/learn/game-servers)で説明しているとおり、テスト用リンクを `player=1` と `player=2` で2つのウィンドウに開きます。コントローラーを使うローカルパーティーは別のモードです。[ローカルパーティーとコントローラー](https://www.playdrop.ai/ja/create/learn/local-party)をご覧ください。

## 関連ガイド

- [リアルタイムゲームサーバー](https://www.playdrop.ai/ja/create/learn/game-servers): MongoDB データベース付きのホスト型 Colyseus 0.17 サーバーでゲームを動かし、ブラウザから SDK で接続し、2人のプレイヤーでテストする方法と制限を説明します。
- [ローカルパーティーとコントローラー](https://www.playdrop.ai/ja/create/learn/local-party): sdk.device で物理ゲームパッドと PlayDrop のスマホコントローラーを読み取り、ローカルプレイヤーの枠を追跡し、コントローラー対応とローカルパーティーの人数を宣言します。
- [共有、フレンド、招待](https://www.playdrop.ai/ja/create/learn/social): 画像やクリップを添えてゲームを共有し、起動ペイロードを読み取り、フレンドを選んで PlayDrop Chat で招待カードや挑戦カードを送り、ほかのゲームをおすすめします。
