diff --git a/src/server.ts b/src/server.ts index bb51278..60ded16 100644 --- a/src/server.ts +++ b/src/server.ts @@ -70,9 +70,75 @@ if (isMain) { ws.send(JSON.stringify({ type: "player_list", players: list })); break; - case "join_room": - // TODO: implement room creation / joining logic + case "create_room": { + // Player creates a room and becomes host + if (player.roomId) { + ws.send( + JSON.stringify({ type: "error", message: "already_in_room" }), + ); + break; + } + const roomId = createRoomId(); + const room: Room = { id: roomId, players: [playerId] }; + rooms.set(roomId, room); + player.roomId = roomId; + ws.send(JSON.stringify({ type: "room_created", roomId, playerId })); break; + } + + case "join_room": { + // Player joins another player's room + const targetId = msg.targetId as string | undefined; + if (!targetId || !players.has(targetId)) { + ws.send( + JSON.stringify({ type: "error", message: "invalid_target" }), + ); + break; + } + if (player.roomId) { + ws.send( + JSON.stringify({ type: "error", message: "already_in_room" }), + ); + break; + } + const target = players.get(targetId)!; + if (!target.roomId || !rooms.has(target.roomId)) { + ws.send( + JSON.stringify({ + type: "error", + message: "target_not_in_room", + }), + ); + break; + } + const room = rooms.get(target.roomId)!; + if (room.players.length >= 2) { + ws.send(JSON.stringify({ type: "error", message: "room_full" })); + break; + } + // Add player to room + room.players.push(playerId); + player.roomId = target.roomId; + + // Notify both players + ws.send( + JSON.stringify({ + type: "room_joined", + roomId: target.roomId, + peerId: targetId, + peerNickname: target.nickname, + }), + ); + target.ws.send( + JSON.stringify({ + type: "peer_joined", + roomId: target.roomId, + peerId: playerId, + peerNickname: player.nickname, + }), + ); + break; + } default: ws.send(JSON.stringify({ type: "error", message: "unknown_type" })); @@ -83,8 +149,31 @@ if (isMain) { }); ws.on("close", () => { + // Clean up room if player was in one + if (player.roomId) { + const room = rooms.get(player.roomId); + if (room) { + room.players = room.players.filter((p) => p !== playerId); + // Notify remaining players + for (const pId of room.players) { + const p = players.get(pId); + if (p) { + p.ws.send( + JSON.stringify({ + type: "peer_left", + roomId: player.roomId, + peerId: playerId, + }), + ); + } + } + // Delete empty rooms + if (room.players.length === 0) { + rooms.delete(player.roomId); + } + } + } players.delete(playerId); - // TODO: clean up rooms if player was in one }); ws.send(JSON.stringify({ type: "welcome", id: playerId }));