# GEMINI.md — VIBE Coding 서버 규칙

## 프로젝트 구조

이 프로젝트는 **웹 브라우저에서 실행되는 실시간 멀티플레이어 게임**이다.
학생은 **프론트엔드 코드만** 작성한다 (HTML, CSS, JavaScript).
서버는 이미 `code-fiesta.xyz`에서 운영 중이다.

## 중요 규칙

### 1. 프론트엔드만 작성
- 만들 수 있는 파일: `index.html`, `.js` 파일, `.css` 파일, 이미지 파일
- **만들지 말 것**: `server.js`, `app.js` 등 서버 파일
- **사용하지 말 것**: `npm install`, `require()`, Node.js 모듈
- 모든 코드는 웹 브라우저에서 직접 실행되어야 한다

### 2. 파일 구조
```
my-game/
├── index.html      (메인 페이지 - 필수)
├── style.css       (스타일 - 선택)
├── game.js         (게임 로직 - 선택)
└── img/            (이미지 - 선택)
    ├── player.png
    └── enemy.png
```

### 3. 게임 서버 - WebSocket API

멀티플레이어 서버 주소: `wss://code-fiesta.xyz/ws`

#### 서버에 연결:
```javascript
const ws = new WebSocket('wss://code-fiesta.xyz/ws');

ws.onopen = () => {
    console.log('서버에 연결됨');
};

ws.onmessage = (event) => {
    const msg = JSON.parse(event.data);
    // msg.type에 따라 메시지 처리
};
```

#### 방 만들기:
```javascript
ws.send(JSON.stringify({
    type: 'CREATE_ROOM',
    nickname: '내이름'
}));
// 응답: { type: 'ROOM_CREATED', roomCode: 'ABC123', playerId: '...', players: [...] }
```

#### 방 참가하기:
```javascript
ws.send(JSON.stringify({
    type: 'JOIN_ROOM',
    roomCode: 'ABC123',
    nickname: '내이름'
}));
// 응답: { type: 'ROOM_JOINED', roomCode: '...', playerId: '...', players: [...] }
```

#### 방의 모든 플레이어에게 데이터 보내기 (RELAY):
```javascript
// 나를 제외한 모든 플레이어에게 전송
ws.send(JSON.stringify({
    type: 'RELAY',
    data: {
        action: 'MOVE',
        x: 100,
        y: 200
    }
}));

// 나를 포함한 모든 플레이어에게 전송
ws.send(JSON.stringify({
    type: 'RELAY',
    data: { action: 'MOVE', x: 100, y: 200 },
    includeSelf: true
}));
```

#### 특정 플레이어에게만 데이터 보내기:
```javascript
ws.send(JSON.stringify({
    type: 'RELAY_TO',
    targetId: '대상_플레이어_id',
    data: { action: 'ATTACK', damage: 10 }
}));
```

#### 공유 데이터 저장/조회 (방 상태):
```javascript
// 저장
ws.send(JSON.stringify({
    type: 'SET_STATE',
    key: 'scores',
    value: { player1: 10, player2: 5 }
}));

// 조회
ws.send(JSON.stringify({
    type: 'GET_STATE',
    key: 'scores'
}));
// 응답: { type: 'STATE', key: 'scores', value: { player1: 10, player2: 5 } }
```

#### 방 나가기:
```javascript
ws.send(JSON.stringify({ type: 'LEAVE_ROOM' }));
```

### 4. 클라이언트가 수신하는 메시지 종류

```javascript
ws.onmessage = (event) => {
    const msg = JSON.parse(event.data);

    switch (msg.type) {
        case 'ROOM_CREATED':
            // 방 생성 완료 — msg.roomCode, msg.playerId, msg.players
            break;

        case 'ROOM_JOINED':
            // 방 참가 완료 — msg.roomCode, msg.playerId, msg.players
            break;

        case 'PLAYER_JOINED':
            // 다른 플레이어 입장 — msg.playerId, msg.nickname, msg.players
            break;

        case 'PLAYER_LEFT':
            // 플레이어 퇴장 — msg.playerId, msg.nickname, msg.players
            break;

        case 'RELAY':
            // 다른 플레이어가 보낸 데이터 — msg.from.id, msg.from.nickname, msg.data
            break;

        case 'STATE_UPDATED':
            // 공유 데이터 변경됨 — msg.key, msg.value, msg.updatedBy.id, msg.updatedBy.nickname
            break;

        case 'STATE':
            // 요청한 공유 데이터 응답 — msg.key, msg.value
            break;

        case 'ERROR':
            // 에러 — msg.message
            break;

        case 'LEFT_ROOM':
            // 방 나가기 완료 확인
            break;
    }
};
```

### 5. 서버 제한 사항
- 방당 최대 **30명**
- 업로드 시 최대 **20개** 파일
- 파일당 최대 **5MB**
- 방 코드: 영문+숫자 6자리
- 닉네임: 최대 20자

### 6. 게임 업로드 방법
1. 브라우저에서 `https://code-fiesta.xyz` 접속
2. 팀 이름 입력 (영어, 공백 없이)
3. 게임 파일 전체 선택
4. "Upload" 클릭
5. 게임 주소: `https://code-fiesta.xyz/students/팀이름/`

### 7. 완성 예제: 최소 멀티플레이어 게임

```html
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>멀티플레이어 게임</title>
    <style>
        body { font-family: sans-serif; text-align: center; padding: 20px; }
        canvas { border: 2px solid #333; display: block; margin: 20px auto; }
        input, button { font-size: 1.2rem; padding: 10px; margin: 5px; }
    </style>
</head>
<body>
    <div id="lobby">
        <h1>내 게임</h1>
        <input type="text" id="nickname" placeholder="닉네임">
        <br>
        <button onclick="createRoom()">방 만들기</button>
        <br>
        <input type="text" id="roomCode" placeholder="방 코드">
        <button onclick="joinRoom()">참가하기</button>
        <p id="status"></p>
    </div>

    <div id="game" style="display:none;">
        <h2>방: <span id="roomDisplay"></span></h2>
        <p>플레이어: <span id="playerList"></span></p>
        <canvas id="canvas" width="600" height="400"></canvas>
    </div>

    <script>
        const ws = new WebSocket('wss://code-fiesta.xyz/ws');
        let myId = null;
        let players = {};

        ws.onopen = () => {
            document.getElementById('status').textContent = '서버에 연결됨';
        };

        ws.onmessage = (event) => {
            const msg = JSON.parse(event.data);

            if (msg.type === 'ROOM_CREATED' || msg.type === 'ROOM_JOINED') {
                myId = msg.playerId;
                document.getElementById('lobby').style.display = 'none';
                document.getElementById('game').style.display = 'block';
                document.getElementById('roomDisplay').textContent = msg.roomCode;
                updatePlayerList(msg.players);
            }

            if (msg.type === 'PLAYER_JOINED' || msg.type === 'PLAYER_LEFT') {
                updatePlayerList(msg.players);
            }

            if (msg.type === 'RELAY') {
                // 여기서 게임 데이터 처리
                // msg.from.id, msg.from.nickname, msg.data
            }

            if (msg.type === 'ERROR') {
                document.getElementById('status').textContent = '에러: ' + msg.message;
            }
        };

        function createRoom() {
            const nickname = document.getElementById('nickname').value || '플레이어';
            ws.send(JSON.stringify({ type: 'CREATE_ROOM', nickname }));
        }

        function joinRoom() {
            const nickname = document.getElementById('nickname').value || '플레이어';
            const roomCode = document.getElementById('roomCode').value;
            ws.send(JSON.stringify({ type: 'JOIN_ROOM', roomCode, nickname }));
        }

        function updatePlayerList(playerArray) {
            document.getElementById('playerList').textContent =
                playerArray.map(p => p.nickname).join(', ');
        }

        // === 여기에 게임 로직 작성 ===

    </script>
</body>
</html>
```

## Gemini CLI 사용 팁

Gemini에게 게임 제작을 요청할 때 다음 내용을 포함할 것:
- "프론트엔드 코드만 사용해서 멀티플레이어 브라우저 게임을 만들어줘 (HTML, CSS, JavaScript)"
- "멀티플레이어는 wss://code-fiesta.xyz/ws 웹소켓 연결을 사용해"
- "GEMINI.md에 설명된 API를 따라서 만들어줘"
- "서버 코드는 만들지 마"
- "index.html 하나 또는 몇 개의 정적 파일로 구성해줘"