using Microsoft.AspNetCore.SignalR; namespace PongGame.Hubs; public class PongRoom { public string ID { get; } private readonly ILogger Logger; public PongRoom(string id, ILogger logger) { ID = id; Logger = logger; } public PongPlayer? Player1 { get; private set; } public PongPlayer? Player2 { get; private set; } public GameState State { get; private set; } = GameState.WaitingForPlayers; public void Join(PongPlayer player) { // TODO: synchronize this if (Player1 is null) { Player1 = player; Logger.LogInformation($"[{ID}] {player} joined pong room as player 1!"); } else if (Player2 is null) { Player2 = player; Logger.LogInformation($"[{ID}] {player} joined pong room as player 2!"); } else throw new HubException($"Lobby [{ID}] is already full!"); _ = Task.Run(PlayersChanged); player.ConnectedRoom = this; } public void Leave(PongPlayer player) { if (Player1 == player) { Player1 = null; Logger.LogInformation($"[{ID}] Player 1 {player} left pong room!"); } else if (Player2 == player) { Player2 = null; Logger.LogInformation($"[{ID}] Player 2 {player} left pong room!"); } player.ConnectedRoom = null; _ = Task.Run(PlayersChanged); } private Task PlayersChanged() { if (Player1 is PongPlayer player1 && Player2 is PongPlayer player2) { ResumeGame(player1, player2); } else if (Player1 is null && Player2 is null) { CloseRoom(); } else PauseGame(); return Task.CompletedTask; } private void ResumeGame(PongPlayer player1, PongPlayer player2) { Logger.LogInformation($"[{ID}] Pong game started: {player1} vs. {player2}"); State = GameState.InProgress; player1.Client.GameStateChanged(State); player2.Client.GameStateChanged(State); } private void PauseGame() => State = GameState.WaitingForPlayers; private void CloseRoom() => State = GameState.Finished; public override string ToString() => $"[{ID}]"; }