본문으로 건너뛰기

SDK 사용법

Connect Base 게임 서버를 클라이언트에서 사용하는 방법입니다.

설치

bash
npm install connectbase-client

초기화

typescript
import { ConnectBase, GameRoom } from 'connectbase-client'

// SDK 초기화
const cb = new ConnectBase({
    appId: 'YOUR_APP_ID',
    publicKey: 'cb_pk_...'
})

// 게임 룸 클라이언트 생성
const game = cb.game.createClient({
    clientId: 'unique-player-id'  // 고유 클라이언트 ID
})

GameRoom 옵션

typescript
interface GameRoomOptions {
    clientId: string           // 필수: 고유 클라이언트 ID
    publicKey: string          // 필수: Public Key (cb_pk_*)
    userId?: string            // 선택: 인증된 사용자 ID
    serverUrl?: string         // 선택: 커스텀 서버 URL
    reconnect?: boolean        // 선택: 자동 재연결 (기본 true)
    reconnectDelay?: number    // 선택: 재연결 딜레이 (기본 1000ms)
    maxReconnectAttempts?: number  // 선택: 최대 재연결 시도 (기본 5)
}

연결 및 룸 관리

typescript
// 서버에 연결
await game.connect()

// 룸 생성
const state = await game.createRoom({
    roomId: 'my-room-123',
    maxPlayers: 10,
    tickRate: 64,
    metadata: {
        gameMode: 'deathmatch',
        map: 'arena'
    }
})

// 룸 참가
const state = await game.joinRoom('room-id', {
    nickname: 'Player1',
    team: 'red'
})

// 룸 퇴장
await game.leaveRoom()

// 룸 목록 조회
const rooms = await game.listRooms()

이벤트 핸들링

typescript
// 연결 이벤트
game.on('onConnect', () => console.log('연결됨'))
game.on('onDisconnect', (reason) => console.log('연결 해제:', reason))
game.on('onReconnecting', (attempt) => console.log('재연결 중...'))

// 플레이어 이벤트
game.on('onPlayerJoined', (player) => console.log('입장:', player.clientId))
game.on('onPlayerLeft', (player) => console.log('퇴장:', player.clientId))

// 상태 업데이트
game.on('onStateUpdate', (gameState) => {
    updateGameWorld(gameState.state)
})

// 델타 업데이트
game.on('onDelta', (delta) => {
    for (const change of delta.changes) {
        applyChange(change)
    }
})

// 채팅
game.on('onChat', (msg) => console.log(msg.clientId + ': ' + msg.message))

// 커스텀 이벤트
game.on('onEvent', (event) => {
    if (event.type === 'player_died') {
        showDeathScreen(event.data)
    }
})

액션 전송

typescript
// 기본 액션
game.sendAction({
    type: 'move',
    data: { x: 100, y: 200, direction: 'right' }
})

// 신뢰성 있는 액션 (중요한 이벤트)
game.sendAction({
    type: 'use_skill',
    data: { skillId: 'fireball', targetId: 'enemy_123' }
}, true)  // reliable = true

// 채팅 전송
game.sendChat('Hello!')

타입 정의

typescript
interface GameState {
    roomId: string
    state: Record<string, unknown>
    version: number
    serverTime: number
    tickRate: number
    players: GamePlayer[]
}

interface GamePlayer {
    clientId: string
    userId?: string
    joinedAt: number
    metadata?: Record<string, string>
}

interface GameRoomInfo {
    id: string
    appId: string
    playerCount: number
    maxPlayers: number
    tickRate: number
    isRunning: boolean
    metadata?: Record<string, string>
}

Unity/Unreal 연동

게임 엔진에서는 WebSocket 클라이언트를 직접 구현합니다:

Unity (C#)

csharp
using System.Net.WebSockets;

public class GameClient : MonoBehaviour
{
    private ClientWebSocket ws;

    async void Start()
    {
        ws = new ClientWebSocket();
        await ws.ConnectAsync(
            new Uri("wss://game.connectbase.world/v1/game/{appID}/ws?public_key=YOUR_PUBLIC_KEY&client_id=PLAYER_ID"),
            CancellationToken.None
        );

        // 룸 참가 — 모든 클라이언트→서버 메시지는
        // { type, data, msg_id } 봉투를 따르고 필드는 snake_case 입니다
        await SendMessage(new {
            type = "join_room",
            data = new { room_id = "room-123" },
            msg_id = "join-1"
        });
    }
}

⚠️ roomId (camelCase) 가 아니라 data.room_id (snake_case + data 봉투) 입니다. WebSocket URL 의 쿼리 파라미터도 room_id 입니다 — ?room_id=room-123 로 쿼리에 넣으면 연결과 동시에 자동 입장됩니다.

Unreal (C++)

cpp
#include "WebSocketsModule.h"

void AGameClient::ConnectToServer()
{
    WebSocket = FWebSocketsModule::Get().CreateWebSocket(
        TEXT("wss://game.connectbase.world/v1/game/{appID}/ws?public_key=YOUR_PUBLIC_KEY&client_id=PLAYER_ID")
    );

    WebSocket->OnMessage().AddLambda([this](const FString& Message) {
        HandleServerMessage(Message);
    });

    WebSocket->Connect();
}