Ghost characters are saved in backend after each move

This commit is contained in:
Martin Berg Alstad 2023-07-19 17:09:47 +02:00
parent 23ee40c96d
commit 7e8dc44ce9
3 changed files with 49 additions and 40 deletions

View File

@ -30,22 +30,27 @@ public class ActionServiceTests
_whiteMessage = new ActionMessage
{
Action = GameAction.PlayerInfo,
Data = JsonSerializer.Serialize(new { Player = _whitePlayer, Spawns = CreateQueue() })
Data = SerializeData(_whitePlayer)
};
_blackMessage = new ActionMessage
{
Action = GameAction.PlayerInfo,
Data = JsonSerializer.Serialize(new { Player = _blackPlayer, Spawns = CreateQueue() })
Data = SerializeData(_blackPlayer)
};
_redMessage = new ActionMessage
{
Action = GameAction.PlayerInfo,
Data = JsonSerializer.Serialize(new { Player = _redPlayer, Spawns = CreateQueue() })
Data = SerializeData(_redPlayer)
};
_gameService = Substitute.For<GameService>(Substitute.For<ILogger<GameService>>());
_service = new ActionService(Substitute.For<ILogger<ActionService>>(), _gameService);
}
private static JsonElement SerializeData(Player player) =>
JsonDocument.Parse(JsonSerializer.Serialize(
new PlayerInfoData { Player = player, Spawns = CreateQueue() })
).RootElement;
private static Queue<DirectionalPosition> CreateQueue() =>
new(new[]
{
@ -77,26 +82,29 @@ public class ActionServiceTests
public void PlayerInfo_DataIsNull()
{
var message = new ActionMessage { Action = GameAction.PlayerInfo, Data = "null" };
Assert.Throws<JsonException>(() => _service.SetPlayerInfo(message));
var serialized = JsonDocument.Parse(JsonSerializer.Serialize(message.Data));
Assert.Throws<JsonException>(() => _service.SetPlayerInfo(serialized.RootElement));
message.Data = null;
Assert.Throws<NullReferenceException>(() => _service.SetPlayerInfo(message));
Assert.Throws<NullReferenceException>(() => _service.SetPlayerInfo(message.Data));
}
[Test]
public void PlayerInfo_DataIsNotPlayer()
{
var serialized =
JsonDocument.Parse(JsonSerializer.Serialize(new Box { Colour = "white", Pellets = new List<Pellet>() }));
var message = new ActionMessage
{
Action = GameAction.PlayerInfo,
Data = JsonSerializer.Serialize(new Box { Colour = "white", Pellets = new List<Pellet>() })
Data = serialized.RootElement
};
Assert.Throws<JsonException>(() => _service.SetPlayerInfo(message));
Assert.Throws<JsonException>(() => _service.SetPlayerInfo(message.Data));
}
[Test]
public void PlayerInfo_DataIsPlayer()
{
var players = _service.SetPlayerInfo(_whiteMessage);
var players = _service.SetPlayerInfo(_whiteMessage.Data);
var pos = _spawns.Dequeue();
_whitePlayer.PacMan.Position = pos;
@ -140,8 +148,8 @@ public class ActionServiceTests
[Test]
public void Ready_NotAllReady()
{
_service.SetPlayerInfo(_whiteMessage);
_service.SetPlayerInfo(_blackMessage);
_service.SetPlayerInfo(_whiteMessage.Data);
_service.SetPlayerInfo(_blackMessage.Data);
var result = _service.Ready();
if (result is ReadyData r1)
@ -149,7 +157,7 @@ public class ActionServiceTests
else
Assert.Fail("Result should be ReadyData");
_service.SetPlayerInfo(_redMessage);
_service.SetPlayerInfo(_redMessage.Data);
result = _service.Ready();
if (result is ReadyData r2)
@ -161,7 +169,7 @@ public class ActionServiceTests
[Test]
public void Ready_OneReady()
{
_service.SetPlayerInfo(_whiteMessage);
_service.SetPlayerInfo(_whiteMessage.Data);
var result = _service.Ready();
// If selected the state is changed to InGame
_whitePlayer.State = State.InGame;

View File

@ -1,5 +1,4 @@
using System.Text.Json;
using Microsoft.CSharp.RuntimeBinder;
using pacMan.GameStuff;
using pacMan.GameStuff.Items;
@ -11,7 +10,8 @@ public interface IActionService
Game Group { set; }
void DoAction(ActionMessage message);
List<int> RollDice();
List<IPlayer> SetPlayerInfo(ActionMessage message);
List<IPlayer> SetPlayerInfo(JsonElement? jsonElement);
object? HandleMoveCharacter(JsonElement? jsonElement); // TODO test
object Ready();
string FindNextPlayer();
void Disconnect();
@ -37,9 +37,10 @@ public class ActionService : IActionService
message.Data = message.Action switch
{
GameAction.RollDice => RollDice(),
GameAction.PlayerInfo => SetPlayerInfo(message),
GameAction.PlayerInfo => SetPlayerInfo(message.Data),
GameAction.Ready => Ready(),
GameAction.NextPlayer => FindNextPlayer(),
GameAction.MoveCharacter => HandleMoveCharacter(message.Data),
_ => message.Data
};
}
@ -53,35 +54,24 @@ public class ActionService : IActionService
return rolls;
}
public List<IPlayer> SetPlayerInfo(ActionMessage message)
public List<IPlayer> SetPlayerInfo(JsonElement? jsonElement)
{
try
{
// Receieving JsonElement from frontend
PlayerInfoData data = JsonSerializer.Deserialize<PlayerInfoData>(message.Data);
Player = data.Player;
var data = jsonElement?.Deserialize<PlayerInfoData>() ?? throw new NullReferenceException("Data is null");
Player = data.Player;
Game? group;
IPlayer? player;
if ((group = _gameService.FindGameByUsername(Player.UserName)) != null &&
(player = group.Players.Find(p => p.UserName == Player.UserName))?.State == State.Disconnected)
{
player.State = group.IsGameStarted ? State.InGame : State.WaitingForPlayers;
Player = player;
Group = group;
// TODO send missing data: Dices, CurrentPlayer, Ghosts
}
else
{
Group = _gameService.AddPlayer(Player, data.Spawns);
}
Game? group;
IPlayer? player;
if ((group = _gameService.FindGameByUsername(Player.UserName)) != null &&
(player = group.Players.Find(p => p.UserName == Player.UserName))?.State == State.Disconnected)
{
player.State = group.IsGameStarted ? State.InGame : State.WaitingForPlayers;
Player = player;
Group = group;
// TODO send missing data: Dices, CurrentPlayer, Ghosts
}
catch (RuntimeBinderException e)
else
{
Console.WriteLine(e);
if (message.Data is null) throw new NullReferenceException();
throw;
Group = _gameService.AddPlayer(Player, data.Spawns);
}
return Group.Players;
@ -113,6 +103,15 @@ public class ActionService : IActionService
{
if (Player != null) Player.State = State.Disconnected;
}
public object? HandleMoveCharacter(JsonElement? jsonElement)
{
if (Group != null && jsonElement.HasValue)
Group.Ghosts = jsonElement.Value.GetProperty("Ghosts").Deserialize<List<Character>>() ??
throw new JsonException("Ghosts is null");
return jsonElement;
}
}
public struct PlayerInfoData

View File

@ -16,6 +16,8 @@ public class Game // TODO handle disconnects and reconnects
[JsonIgnore] public List<IPlayer> Players { get; } = new();
[JsonIgnore] public List<Character> Ghosts { get; set; } = new();
[JsonIgnore] private Queue<DirectionalPosition> Spawns { get; }
[JsonIgnore] public DiceCup DiceCup { get; } = new();