Files
MauMau-Server/Websockets/Room.cs
DTieman cf13f07f98 Automatic room closing (#6)
* Ace now lets you play again if there are two players

* 1 line if :o

* Better Ace

* Feature/automautic room closing (#5)

* Room now closes when nobody is in the room

* cleanup
2023-03-24 18:30:45 +01:00

130 lines
3.5 KiB
C#

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<string, WebSocket> _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<ActionDTO>(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<string, WebSocket> GetAllConnections()
{
return _connections;
}
public void RemoveConnection(string socketId)
{
_connections.Remove(socketId);
}
private static async Task<WebSocketReceiveResult?> ReceiveAsync(WebSocket webSocket, byte[] buffer)
{
var arraySegment = new ArraySegment<byte>(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<byte>(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;
}
}