using System.Net.WebSockets; using System.Text; using System.Text.Json; using MauMau_Server.Mau; namespace MauMau_Server.Websockets; public class Room { private readonly IRoomManager _roomManager; private readonly string _roomId; private readonly Dictionary _connections = new(); private string _host; private readonly Game _game = new(); public Room(IRoomManager roomManager, string roomId) { _roomManager = roomManager; _roomId = roomId; } public async Task InstantiateConnection(WebSocket socket) { var socketId = AddConnection(socket); await HandleConnection(socket, socketId); } private async Task HandleConnection(WebSocket socket, string socketId) { BroadcastGameState(); var buffer = EmptyBuffer(); var result = await ReceiveAsync(socket, buffer); while (!result.CloseStatus.HasValue) { var slicedBuffer = buffer[0..result.Count]; var action = JsonSerializer.Deserialize(slicedBuffer); _game.HandleAction(socketId, action); BroadcastGameState(); buffer = EmptyBuffer(); result = await ReceiveAsync(socket, buffer); } await socket.CloseAsync(result.CloseStatus.Value, result.CloseStatusDescription, CancellationToken.None); HandleDisconnect(socketId); } private string AddConnection(WebSocket socket) { var socketId = Guid.NewGuid().ToString(); if (_connections.Count == 0) { _host = socketId; } _connections.Add(socketId, socket); _game.AddPlayerToGame(socketId, socket); return socketId; } public WebSocket GetConnection(string socketId) { return _connections[socketId]; } public Dictionary GetAllConnections() { return _connections; } public void RemoveConnection(string socketId) { _connections.Remove(socketId); } private static async Task ReceiveAsync(WebSocket webSocket, byte[] buffer) { var arraySegment = new ArraySegment(buffer); var result = await webSocket.ReceiveAsync(arraySegment, CancellationToken.None); return result; } private void BroadcastGameState() { foreach (var (id, socket) in GetAllConnections()) { var gameState = new GameState(_game, id); var message = JsonSerializer.Serialize(gameState); SendAsync(socket, message); } } private void BroadcastAsync(string message) { foreach (var (id, socket) in GetAllConnections()) { SendAsync(socket, message); } } private static void SendAsync(WebSocket socket, string message) { var bytes = Encoding.Default.GetBytes(message); var arraySegment = new ArraySegment(bytes); socket.SendAsync(arraySegment, WebSocketMessageType.Text, true, CancellationToken.None); } private void HandleDisconnect(string socketId) { RemoveConnection(socketId); _game.RemovePlayer(socketId); if (IsEmpty()) { _roomManager.RemoveRoom(_roomId); } else if (socketId == _host) { _host = _connections.First().Key; } } private static byte[] EmptyBuffer() { return new byte[4096]; } public bool IsEmpty() { return _connections.Count == 0; } }