# PlayDrop 게임의 온라인 파티와 음성 채팅

친구들이 온라인에서 함께 플레이하게 하세요. 파티 인원수를 선언하고, PlayDrop 파티 창을 열고, sdk.multiplayer.join으로 예약된 방에 참가하고, 방 음성 채팅을 제어하세요.

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

PlayDrop 파티는 여러 게임을 함께 옮겨 다니는 친구 그룹입니다. 파티가 내 게임을 시작하면 PlayDrop이 서버의 방 하나에 멤버들의 자리를 예약하므로, 친구들이 흩어지지 않고 같은 경기에 들어옵니다. 음성 채팅은 게임이 아니라 PlayDrop에서 실행됩니다.

## 필요한 것

- [실시간 게임 서버](https://www.playdrop.ai/ko/create/learn/game-servers): 파티는 내 Colyseus 방에서 플레이합니다.
- 로그인한 플레이어: 방은 게스트를 받지 않습니다.
- [catalogue.json](https://www.playdrop.ai/ko/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명 파티 두 개가 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" });
```

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)`으로 읽으세요. `onPartyChange`는 현재 상태를 먼저 전달합니다: `{ partyId, leaderUserId, revision, members, launch }`. 파티가 이 게임을 플레이 중이면 `launch.status`는 `joining` 또는 `ready`입니다. 멤버라는 사실만으로 플레이어들이 같은 방에 있다는 뜻은 아니니 `join`을 사용하세요.

파티 멤버 구성은 PlayDrop이 관리합니다. 게임은 파티 멤버를 추가하거나 제거할 수 없고 마이크를 제어할 수도 없으며, 플레이어는 이 창에서 친구를 파티에 초대합니다. 그래도 게임은 `sdk.social.sendMessage`로 친구에게 자체 초대 카드나 도전 카드를 보낼 수 있습니다. [공유, 친구, 초대](https://www.playdrop.ai/ko/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이 일시 정지하면 클라이언트는 멈추지만, 방은 연결된 상태로 남고 서버는 계속 실행됩니다. 한 플레이어의 일시 정지로 다른 플레이어의 경기가 멈추면 안 됩니다. 경기 일시 정지가 필요하면 서버에 구현하세요.

## 테스트하기

비공개 버전을 업로드한 다음, [실시간 게임 서버](https://www.playdrop.ai/ko/create/learn/game-servers)에서 설명한 대로 테스트 링크를 `player=1`과 `player=2`로 두 창에서 여세요. 컨트롤러를 쓰는 로컬 파티는 별개의 모드입니다. [로컬 파티와 컨트롤러](https://www.playdrop.ai/ko/create/learn/local-party)를 참고하세요.

## 관련 가이드

- [실시간 게임 서버](https://www.playdrop.ai/ko/create/learn/game-servers): MongoDB 데이터베이스가 있는 호스팅 Colyseus 0.17 서버를 게임에 쓰고, SDK로 브라우저에서 연결하고, 플레이어 2명으로 테스트하고, 제한 사항을 알아보세요.
- [로컬 파티와 컨트롤러](https://www.playdrop.ai/ko/create/learn/local-party): sdk.device로 실제 게임패드와 PlayDrop 휴대폰 컨트롤러를 읽고, 로컬 플레이어 슬롯을 따르고, 컨트롤러 지원과 로컬 파티 인원수를 선언하세요.
- [공유, 친구, 초대](https://www.playdrop.ai/ko/create/learn/social): 이미지나 클립과 함께 게임을 공유하고, 실행 페이로드를 읽고, 친구를 고르고, PlayDrop Chat으로 초대·도전 카드를 보내고, 다른 게임을 추천하세요.
