From 0c2cb8272d5fb8620a18c6e1e0e04d9b9160eefc Mon Sep 17 00:00:00 2001 From: DTieman Date: Mon, 22 Apr 2024 21:51:35 +0200 Subject: [PATCH] Better lobby system --- Mau/Game.cs | 36 ++++++++++++-------- Room/Chat/Chat.cs | 6 ++-- Room/Room.cs | 83 ++++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 99 insertions(+), 26 deletions(-) diff --git a/Mau/Game.cs b/Mau/Game.cs index b7516a1..3f15e0f 100644 --- a/Mau/Game.cs +++ b/Mau/Game.cs @@ -10,9 +10,11 @@ public class Game public List Players = new(); public Player CurrentPlayer; public int TurnDirection = 1; + private readonly Room _room; - public Game() + public Game(Room room) { + _room = room; CurrentCard = Deck.DrawCard(); Deck.AddCardToUsedDeck(CurrentCard); } @@ -57,10 +59,10 @@ public class Game { break; } - CurrentCard = new Card(cardType, CardValue.JACK); CurrentPlayer.State = PlayerState.WAIT; - CurrentPlayer = CurrentCard.CardType == CardType.JOKER ? GetNextPlayer() : GetNextPlayer(2); + CurrentPlayer = CurrentCard.CardType == CardType.JOKER ? GetNextPlayer(2) : GetNextPlayer(); CurrentPlayer.State = PlayerState.TURN; + CurrentCard = new Card(cardType, CardValue.JACK); break; case "DRAW": if (player.State != PlayerState.TURN) @@ -79,6 +81,11 @@ public class Game Deck.AddCardToUsedDeck(card); hand.Remove(GetSameCardFromHand(hand, card)); CurrentCard = card; + if (hand.Count == 0) + { + _room.EndGame(player); + return; + } HandleNextPlayer(card); } @@ -106,24 +113,20 @@ public class Game { nextPlayer.Hand.Add(drawnCard); } - CurrentPlayer.State = PlayerState.WAIT; - CurrentPlayer = GetNextPlayer(2); - CurrentPlayer.State = PlayerState.TURN; + HandleNextPlayer(CurrentPlayer, GetNextPlayer(2)); break; } case CardValue.SEVEN: case CardValue.KING: break; case CardValue.EIGHT: - CurrentPlayer.State = PlayerState.WAIT; - CurrentPlayer = GetNextPlayer(2); - CurrentPlayer.State = PlayerState.TURN; + HandleNextPlayer(CurrentPlayer, GetNextPlayer(2)); break; case CardValue.ACE: if (Players.Count > 2) { TurnDirection *= -1; - CurrentPlayer = GetNextPlayer(); + HandleNextPlayer(CurrentPlayer, GetNextPlayer()); } break; case CardValue.JACK: @@ -137,17 +140,22 @@ public class Game case CardValue.TEN: case CardValue.QUEEN: default: - CurrentPlayer = GetNextPlayer(); + HandleNextPlayer(CurrentPlayer, GetNextPlayer()); break; } } + private void HandleNextPlayer(Player current, Player next) + { + current.State = PlayerState.WAIT; + next.State = PlayerState.TURN; + CurrentPlayer = next; + } + private void DrawCard(Player player) { player.Hand.Add(Deck.DrawCard()); - CurrentPlayer = GetNextPlayer(); - player.State = PlayerState.WAIT; - CurrentPlayer.State = PlayerState.TURN; + HandleNextPlayer(player, GetNextPlayer()); } private Player GetNextPlayer(int numberOfPlayers = 1) diff --git a/Room/Chat/Chat.cs b/Room/Chat/Chat.cs index e6d7b56..338321f 100644 --- a/Room/Chat/Chat.cs +++ b/Room/Chat/Chat.cs @@ -15,7 +15,7 @@ public class Chat public void SendChatMessage(ConnectionInstance connection, string message) { - var chatMessage = new ChatMessage(DateTime.UtcNow, connection.Name, message); + var chatMessage = new ChatMessage(connection.Name, message); var formattedMessage = new MessageDTO("CHAT", JsonSerializer.Serialize(chatMessage)); WebsocketManager.BroadcastAsync(_room.GetWebsockets(), JsonSerializer.Serialize(formattedMessage)); } @@ -23,13 +23,11 @@ public class Chat public class ChatMessage { - public DateTime Time { get; set; } public string Sender { get; set; } public string Message { get; set; } - public ChatMessage(DateTime dateTime, string sender, string message) + public ChatMessage(string sender, string message) { - Time = dateTime; Sender = sender; Message = message; } diff --git a/Room/Room.cs b/Room/Room.cs index 753e620..c6bda50 100644 --- a/Room/Room.cs +++ b/Room/Room.cs @@ -10,9 +10,10 @@ public class Room private readonly IRoomManager _roomManager; private readonly string _roomId; private readonly List _connections = new(); - private ConnectionInstance _host; + private ConnectionInstance? _host; private readonly Chat _chat; - private readonly Game _game = new(); + private Game? _game; + private RoomState _state = RoomState.LOBBY; public Room(IRoomManager roomManager, string roomId) { @@ -24,14 +25,13 @@ public class Room public async Task InstantiateConnection(WebSocket socket, string name) { var connection = AddConnection(socket, name); - if (IsEmpty()) _host = connection; - _game.AddPlayerToGame(connection); + _game?.AddPlayerToGame(connection); await HandleConnection(connection); } private async Task HandleConnection(ConnectionInstance connection) { - BroadcastGameState(); + BroadcastState(); var webSocketResponse = await WebsocketManager.ReceiveAsync(connection.Socket); while (!webSocketResponse.Result!.CloseStatus.HasValue) { @@ -40,6 +40,7 @@ public class Room { case "GAME": { + if (_state != RoomState.GAME) break; var gameInput = JsonSerializer.Deserialize(message.Payload); _game.HandleAction(connection.ConnectionId, gameInput); break; @@ -54,9 +55,17 @@ public class Room _chat.SendChatMessage(connection, cleanedMessage); break; } + case "LOBBY": + { + if (connection.ConnectionId == _host?.ConnectionId) + { + ChangeLobbyState(RoomState.GAME); + } + break; + } } - BroadcastGameState(); + BroadcastState(); webSocketResponse = await WebsocketManager.ReceiveAsync(connection.Socket); } WebsocketManager.CloseAsync(connection.Socket, webSocketResponse.Result); @@ -67,6 +76,7 @@ public class Room { var connectionId = Guid.NewGuid().ToString(); var connection = new ConnectionInstance(name, connectionId, socket); + if (IsEmpty()) _host = connection; _connections.Add(connection); return connection; } @@ -78,6 +88,10 @@ public class Room private void BroadcastGameState() { + if (_game == null) + { + return; + } foreach (var connection in _connections) { var gameState = new GameState(_game, connection.ConnectionId); @@ -86,10 +100,50 @@ public class Room } } + private void BroadcastState() + { + switch (_state) + { + case RoomState.LOBBY: + var message = new MessageDTO("LOBBY", JsonSerializer.Serialize("a")); + WebsocketManager.BroadcastAsync(GetWebsockets(), JsonSerializer.Serialize(message)); + break; + case RoomState.GAME: + BroadcastGameState(); + break; + default: + // + break; + } + } + + private void ChangeLobbyState(RoomState targetState) + { + switch (targetState) + { + case RoomState.LOBBY: + _state = RoomState.LOBBY; + _game = null; + break; + case RoomState.GAME: + { + _state = RoomState.GAME; + _game = new Game(this); + foreach (var connectionInstance in _connections) + { + _game.AddPlayerToGame(connectionInstance); + } + break; + } + default: + throw new ArgumentOutOfRangeException(nameof(targetState), targetState, null); + } + } + private void HandleDisconnect(string socketId) { RemoveConnection(socketId); - _game.RemovePlayer(socketId); + _game?.RemovePlayer(socketId); if (IsEmpty()) { _roomManager.RemoveRoom(_roomId); @@ -112,6 +166,19 @@ public class Room private static string StripHTML(string input) { - return Regex.Replace(input, "<.*?>", String.Empty); + return Regex.Replace(input, "<.*?>", string.Empty); } + + public void EndGame(Player player) + { + var message = new MessageDTO("END", JsonSerializer.Serialize(new PlayerDTO(player))); + WebsocketManager.BroadcastAsync(GetWebsockets(), JsonSerializer.Serialize(message)); + ChangeLobbyState(RoomState.LOBBY); + } +} + +public enum RoomState +{ + LOBBY, + GAME } \ No newline at end of file