2022-11-03 12:29:35 +01:00
|
|
|
|
using Microsoft.AspNetCore.SignalR;
|
|
|
|
|
|
|
|
|
|
namespace PongGame.Hubs;
|
|
|
|
|
|
|
|
|
|
public class PongRoom {
|
|
|
|
|
public string ID { get; }
|
|
|
|
|
private readonly ILogger Logger;
|
2022-11-04 00:13:00 +01:00
|
|
|
|
private const string JOIN_LOG_TEMPLATE = "[{ID}] {Player} joined pong room as player {Number}!";
|
|
|
|
|
private const string LEAVE_LOG_TEMPLATE = "[{ID}] Player {Number} {Player} left pong room!";
|
|
|
|
|
private const string DIRECTION_LOG_TEMPLATE = "[{ID}] Player {Number} {player} moves paddle in direction: {direction}!";
|
2022-11-03 12:29:35 +01:00
|
|
|
|
|
|
|
|
|
public PongRoom(string id, ILogger logger) {
|
|
|
|
|
ID = id;
|
|
|
|
|
Logger = logger;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public PongPlayer? Player1 { get; private set; }
|
|
|
|
|
public PongPlayer? Player2 { get; private set; }
|
2022-11-04 00:13:00 +01:00
|
|
|
|
private PongGameState State = PongGameState.Initial;
|
2022-11-03 12:29:35 +01:00
|
|
|
|
|
|
|
|
|
public void Join(PongPlayer player) {
|
|
|
|
|
// TODO: synchronize this
|
|
|
|
|
if (Player1 is null) {
|
|
|
|
|
Player1 = player;
|
2022-11-04 00:13:00 +01:00
|
|
|
|
Logger.LogInformation(JOIN_LOG_TEMPLATE, ID, player, 1);
|
2022-11-03 12:29:35 +01:00
|
|
|
|
} else if (Player2 is null) {
|
|
|
|
|
Player2 = player;
|
2022-11-04 00:13:00 +01:00
|
|
|
|
Logger.LogInformation(JOIN_LOG_TEMPLATE, ID, player, 1);
|
2022-11-03 12:29:35 +01:00
|
|
|
|
} 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;
|
2022-11-04 00:13:00 +01:00
|
|
|
|
Logger.LogInformation(LEAVE_LOG_TEMPLATE, ID, 1, player);
|
2022-11-03 12:29:35 +01:00
|
|
|
|
} else if (Player2 == player) {
|
|
|
|
|
Player2 = null;
|
2022-11-04 00:13:00 +01:00
|
|
|
|
Logger.LogInformation(LEAVE_LOG_TEMPLATE, ID, 2, player);
|
2022-11-03 12:29:35 +01:00
|
|
|
|
}
|
|
|
|
|
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) {
|
2022-11-04 00:13:00 +01:00
|
|
|
|
Logger.LogInformation("[{ID}] Pong game started: {player1} vs. {player2}", ID, player1, player2);
|
|
|
|
|
State.Status = GameStatus.InProgress;
|
|
|
|
|
player1.Client.GameStateChanged(State.Status);
|
|
|
|
|
player2.Client.GameStateChanged(State.Status);
|
2022-11-03 12:29:35 +01:00
|
|
|
|
}
|
|
|
|
|
|
2022-11-04 00:13:00 +01:00
|
|
|
|
private void PauseGame() => State.Status = GameStatus.WaitingForPlayers;
|
|
|
|
|
private void CloseRoom() => State.Status = GameStatus.Finished;
|
2022-11-03 12:29:35 +01:00
|
|
|
|
|
|
|
|
|
public override string ToString() => $"[{ID}]";
|
2022-11-04 00:13:00 +01:00
|
|
|
|
|
|
|
|
|
public void MovePaddle(PongPlayer player, PongPaddleDirection direction) {
|
|
|
|
|
if (Player1 == player) {
|
|
|
|
|
State.P1Direction = direction;
|
|
|
|
|
Logger.LogInformation(DIRECTION_LOG_TEMPLATE, ID, 1, player, direction);
|
|
|
|
|
return;
|
|
|
|
|
} else if (Player2 == player) {
|
|
|
|
|
State.P2Direction = direction;
|
|
|
|
|
Logger.LogInformation(DIRECTION_LOG_TEMPLATE, ID, 2, player, direction);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
throw new InvalidOperationException("Player is not in this room, but moved! Assumably players room wasn't deleted.");
|
|
|
|
|
}
|
2022-11-03 12:29:35 +01:00
|
|
|
|
}
|