Game seems to work
All checks were successful
Build Mau & Deploy Mau / build (push) Successful in 1m31s
Build Mau & Deploy Mau / deploy (push) Has been skipped

This commit is contained in:
DTieman
2024-05-05 17:08:02 +02:00
parent 694bc6147a
commit 90c9b0031c
20 changed files with 213 additions and 212 deletions

View File

@@ -2,12 +2,12 @@
public class ActionDTO
{
public string Action { get; set; }
public string Type { get; set; }
public string Data { get; set; }
public ActionDTO(string action, string data)
public ActionDTO(string type, string data)
{
Action = action;
Type = type;
Data = data;
}

View File

@@ -4,6 +4,7 @@ public class Deck
{
private List<Card> _unusedDeck = new();
private List<Card> _usedDeck = new();
public Card CurrentCard;
/**
* <summary>
@@ -14,6 +15,8 @@ public class Deck
{
CreateSet();
ShuffleDeck();
CurrentCard = DrawCard();
_usedDeck.Add(CurrentCard);
}
/**

View File

@@ -2,6 +2,7 @@
using MauMau_Server.Mau.Managers;
using MauMau_Server.Websockets;
using MauMau_Server.Room;
using MauMau_Server.Room.Messages;
using Newtonsoft.Json;
namespace MauMau_Server.Mau;
@@ -9,51 +10,55 @@ namespace MauMau_Server.Mau;
public class Game : RoomType
{
private readonly Deck _deck = new();
public Card CurrentCard;
private readonly TurnManager _turnManager = new();
public Game(Room.Room room, IEnumerable<ConnectionInstance> connections) : base(room)
{
CurrentCard = _deck.DrawCard();
_deck.AddCardToUsedDeck(CurrentCard);
// Convert all the connections to players
List<Player> players = new();
foreach (var player in connections.Select(connection => new Player(connection)))
{
// Give the new player a hand of cards
var initialHand = _deck.DrawCards(8);
player.GiveCards(initialHand);
players.Add(player);
}
// Add all the players to the turn manager
_turnManager.Initialize(players);
// Broadcast new game state
SendGameState();
}
/**
* <inheritdoc cref="RoomType.OnMessage"/>
*/
public override void OnMessage(ConnectionInstance sender, string message)
public override void OnMessage(ConnectionInstance sender, RoomMessage<string> message)
{
// If the message type is not a game message, ignore the message
if (message.Type is not ("CHOOSE" or "DRAW" or "PLAY"))
{
return;
}
// Get the player that sent the message
var player = _turnManager.Players.FirstOrDefault(x => x.IsMe(sender.Id));
// If the player is not the player that is currently playing, ignore the message
if (_turnManager.CurrentPlayer != player) return;
// Deserialize the message
var gameMessage = JsonConvert.DeserializeObject<GameMessage>(message);
// Based on the message intent, handle the message
switch (gameMessage.Intent)
switch (message.Type)
{
case GameIntent.CHOOSE:
Choose(player, gameMessage.Data);
case "CHOOSE":
Choose(player, message.Data);
break;
case "PLAY":
Play(player, message.Data);
break;
case GameIntent.DRAW:
default:
Draw(player, gameMessage.Data);
break;
case GameIntent.PLAY:
Play(player, gameMessage.Data);
Draw(player);
break;
}
}
@@ -63,10 +68,18 @@ public class Game : RoomType
*/
public override void OnConnect(ConnectionInstance connection)
{
// Broadcast that a player joined
var joinMessage = new JoinMessage(connection.Id, connection.Name + " has joined the room.");
_room.BroadCast(new RoomMessage<JoinMessage>("JOIN", joinMessage));
// Create a new player, give them a new hand and add them to the game
var player = new Player(connection);
var initialHand = _deck.DrawCards(8);
player.GiveCards(initialHand);
_turnManager.Players.Add(player);
// Broadcast new game state
SendGameState();
}
/**
@@ -74,16 +87,29 @@ public class Game : RoomType
*/
public override void OnDisconnect(ConnectionInstance connection)
{
// Broadcast that the player left
var leaveMessage = new LeaveMessage(connection.Id, connection.Name + " has left the room.");
_room.BroadCast(new RoomMessage<LeaveMessage>("LEAVE", leaveMessage));
// Get the player that left
var player = _turnManager.Players.FirstOrDefault(x => x.IsMe(connection.Id));
if (player is null) return;
// Add the player's hand to the used deck
var playerHand = player.Hand;
_deck.AddCardsToUsedDeck(playerHand);
// Change the turn if the player that left was the current player
if (player == _turnManager.CurrentPlayer)
{
_turnManager.ChangeTurn();
}
// Remove the player from the game
_turnManager.Players.Remove(player);
// Broadcast new game state
SendGameState();
}
/**
@@ -102,10 +128,10 @@ public class Game : RoomType
}
// Does the current card require the next player to draw cards?
var isCardGivingCard = CurrentCard.CardType == CardType.JOKER || CurrentCard.CardValue == CardValue.TWO;
var isCardGivingCard = _deck.CurrentCard.CardType == CardType.JOKER || _deck.CurrentCard.CardValue == CardValue.TWO;
// Can the player that received a card giving card counter the card?
var skippedPlayerCanPlay = player.CanPlayCard(CurrentCard);
var skippedPlayerCanPlay = player.CanPlayCard(_deck.CurrentCard);
// If the card is a card giving card and the player cannot counter it, skip the next player
var shouldSkipPlayer = isCardGivingCard && !skippedPlayerCanPlay;
@@ -113,12 +139,15 @@ public class Game : RoomType
? _turnManager.GetNextPlayer(2)
: _turnManager.GetNextPlayer();
// TODO: Not make it a jack, as it would not work when a Joker is played
// TODO: Not make it a jack, as it would not work when a Joker was played
// Set the new current card
CurrentCard = new Card(cardType, CardValue.JACK);
_deck.CurrentCard = new Card(cardType, CardValue.JACK);
// Change the turns
_turnManager.ChangeTurn(nextPlayer);
// Broadcast new game state
SendGameState();
}
/**
@@ -132,21 +161,22 @@ public class Game : RoomType
* <param name="player">The player that drew a card</param>
* <param name="data">A string that can be serialized to a drawcard instance</param>
*/
private void Draw(Player player, string data)
private void Draw(Player player)
{
// TODO: data will contain the amount of cards to draw in the future, for now, just draw 1 card
// Draw a card from the deck
var drawnCard = _deck.DrawCard();
// Give the card to the player
player.GiveCard(drawnCard);
// If the player can play the card, do not change the player
if (drawnCard.CanBePlayedOn(CurrentCard)) return;
// Change the turn to the next player
_turnManager.ChangeTurn();
// Change the player if the drawn card cannot be played
if (!drawnCard.CanBePlayedOn(_deck.CurrentCard))
{
_turnManager.ChangeTurn();
}
// Broadcast new game state
SendGameState();
}
/**
@@ -181,7 +211,7 @@ public class Game : RoomType
// Check if the played card is compatible with the current card
// If not, ignore the play
if (!playerCard.CanBePlayedOn(CurrentCard))
if (!playerCard.CanBePlayedOn(_deck.CurrentCard))
{
return;
}
@@ -193,7 +223,7 @@ public class Game : RoomType
_deck.AddCardToUsedDeck(playerCard);
// Set the new current card
CurrentCard = playerCard;
_deck.CurrentCard = playerCard;
if (player.Hand.Count == 0)
{
@@ -201,9 +231,19 @@ public class Game : RoomType
return;
}
// Change the turn based on the played card
HandleNextPlayer(playerCard);
// Broadcast new game state
SendGameState();
}
/**
* <summary>
* Based on the played card, change the turn to the next player.
* </summary>
* <param name="card">The card that was played</param>
*/
private void HandleNextPlayer(Card card)
{
switch (card.CardValue)
@@ -250,13 +290,31 @@ public class Game : RoomType
}
}
private void EndGame(Player winner)
/**
* <summary>
* Create a game state for each player and send it to them.
* By making a unique game state for each player we can hide information (like other player's hands).
* </summary>
*/
private void SendGameState()
{
_room._roomType = new Lobby(_room, winner.Connection);
foreach (var player in _turnManager.Players)
{
var gameState = new GameState(player, _deck.CurrentCard, _turnManager.CurrentPlayer, _turnManager.Players);
player.Connection.SendMessageAsync(JsonConvert.SerializeObject(new RoomMessage<GameState>("GAME", gameState)));
}
}
public Player? GetPlayer(string playerId)
/**
* <summary>
* Broadcast the winner of the game and change the room's type to a lobby.
* </summary>
* <param name="winner">The player that won the game</param>
*/
private void EndGame(Player winner)
{
return _turnManager.Players.FirstOrDefault(p => p.IsMe(playerId));
var winMessage = new EndMessage(winner.Connection.Id, winner.Connection.Name);
_room.BroadCast(new RoomMessage<EndMessage>("END", winMessage));
_room.RoomType = new Lobby(_room);
}
}

View File

@@ -1,6 +0,0 @@
namespace MauMau_Server.Mau.GameMessages;
public class ChooseCard
{
}

View File

@@ -1,14 +0,0 @@
namespace MauMau_Server.Mau.GameMessages;
public class GameMessage
{
public GameIntent Intent { get; set; }
public string Data { get; set; }
}
public enum GameIntent
{
CHOOSE,
DRAW,
PLAY,
}

View File

@@ -3,29 +3,28 @@
public class GameState
{
public PlayerDTO Me { get; set; }
public string CurrentState { get; set; }
public string MyState { get; set; }
public List<string> Hand { get; set; } = new();
public string CurrentCard { get; set; }
public PlayerDTO CurrentPlayer { get; set; }
public List<PlayerDTO> Players { get; set; } = new();
public GameState(Game game, string playerId)
public GameState(Player me, Card currentCard, Player currentPlayer, List<Player> others)
{
var p = game.GetPlayer(playerId);
Me = new PlayerDTO(game.GetPlayer(playerId));
CurrentState = p.State.ToString();
foreach (var card in p.Hand)
Me = new PlayerDTO(me);
MyState = me.State.ToString();
foreach (var card in me.Hand)
{
Hand.Add(card.ToString());
}
foreach (var player in game.Players)
foreach (var player in others)
{
Players.Add(new PlayerDTO(player));
}
CurrentCard = game.CurrentCard.ToString();
CurrentPlayer = new PlayerDTO(game.CurrentPlayer);
CurrentCard = currentCard.ToString();
CurrentPlayer = new PlayerDTO(currentPlayer);
}
}
@@ -38,7 +37,7 @@ public class PlayerDTO
public PlayerDTO(Player player)
{
Name = player.Connection.Name;
Id = player.Connection.Id;
Id = player.Connection.Id.ToString();
CardsLeft = player.Hand.Count;
}
}

View File

@@ -28,7 +28,7 @@ public class Player
return Hand.FirstOrDefault(handCard => handCard.IsSameCard(card));
}
public bool IsMe(string playerId) => Connection.Id == playerId;
public bool IsMe(Guid playerId) => Connection.Id == playerId;
public bool CanPlayCard(Card currentCard)
{