File size: 1,954 Bytes
a7476ec
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7eec780
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
a7476ec
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
import WebSocket from 'ws'

export class RoomManager {
    // Map<RoomId, Map<Username, WebSocket>>
    private rooms: Map<string, Map<string, WebSocket>>

    constructor() {
        this.rooms = new Map()
    }

    /**
     * Adds a user to a specific room.
     * Creates the room if it doesn't exist.
     */
    joinRoom(roomId: string, username: string, socket: WebSocket): void {
        if (!this.rooms.has(roomId)) {
            this.rooms.set(roomId, new Map())
        }
        this.rooms.get(roomId)?.set(username, socket)
    }

    renameUser(
        roomId: string,
        username: string,
        newUsername: string,
        socket: WebSocket
    ): boolean {
        const room = this.rooms.get(roomId)
        if (!room) return false

        if (!room.has(username)) return false
        if (room.has(newUsername)) return false

        // Remove old username
        room.delete(username)

        // Add new username with same socket
        room.set(newUsername, socket)
        return true
    }

    /**
     * Removes a user from a room.
     * Cleans up the room if it becomes empty.
     */
    leaveRoom(roomId: string, username: string): boolean {
        const room = this.rooms.get(roomId)
        if (room) {
            const deleted = room.delete(username)
            if (room.size === 0) {
                this.rooms.delete(roomId)
            }
            return deleted
        }
        return false
    }

    /**
     * Checks if a room exists.
     */
    hasRoom(roomId: string): boolean {
        return this.rooms.has(roomId)
    }

    /**
     * Sends a message to all users in a specific room.
     */
    broadcast(roomId: string, message: string): void {
        const room = this.rooms.get(roomId)
        if (!room) return

        for (const client of room.values()) {
            if (client.readyState === WebSocket.OPEN) {
                client.send(message)
            }
        }
    }
}