114 lines
3.5 KiB
C#
Raw Normal View History

using System.Text.Json.Serialization;
2023-07-11 14:23:41 +02:00
using pacMan.Exceptions;
using pacMan.GameStuff;
using pacMan.GameStuff.Items;
namespace pacMan.Services;
public class Game // TODO handle disconnects and reconnects
{
private readonly Random _random = new();
private int _currentPlayerIndex;
private List<Player> _players = new();
public Game(Queue<DirectionalPosition> spawns) => Spawns = spawns;
[JsonInclude] public Guid Id { get; } = Guid.NewGuid();
[JsonIgnore]
public List<Player> Players
{
get => _players;
set =>
_players = _players.Select((player, index) =>
{
player.State = value[index].State;
player.PacMan = value[index].PacMan;
player.Box = value[index].Box;
return player;
}).ToList();
}
[JsonIgnore] public List<Character> Ghosts { get; set; } = new();
[JsonIgnore] private Queue<DirectionalPosition> Spawns { get; }
[JsonIgnore] public DiceCup DiceCup { get; } = new();
[JsonInclude] public int Count => Players.Count;
[JsonInclude]
public bool IsGameStarted => Count > 0 && Players.All(player => player.State is State.InGame or State.Disconnected);
2023-07-20 18:06:30 +02:00
public Player NextPlayer()
{
try
{
_currentPlayerIndex = (_currentPlayerIndex + 1) % Count;
}
catch (DivideByZeroException)
{
throw new InvalidOperationException("There are no players in the game group.");
}
return Players[_currentPlayerIndex];
}
public void Shuffle() => Players.Sort((_, _) => _random.Next(-1, 2));
public event Func<ArraySegment<byte>, Task>? Connections;
2023-07-20 18:06:30 +02:00
public bool AddPlayer(Player player)
{
if (Players.Count >= Rules.MaxPlayers || IsGameStarted) return false;
2023-07-18 18:19:54 +02:00
/* TODO remove above and uncomment below
if (Players.Count >= Rules.MaxPlayers)
throw new GameNotPlayableException("Game is full");
if (IsGameStarted)
throw new GameNotPlayableException("Game has already started");
*/
2023-07-01 18:54:59 +02:00
player.State = State.WaitingForPlayers;
if (Players.Exists(p => p.Username == player.Username)) return true; // TODO change to false
Players.Add(player);
if (player.PacMan.SpawnPosition is null) SetSpawn(player);
return true;
}
2023-07-20 18:06:30 +02:00
public Player? RemovePlayer(string username)
{
var index = Players.FindIndex(p => p.Username == username);
if (index == -1) return null;
var removedPlayer = Players[index];
Players.RemoveAt(index);
return removedPlayer;
}
2023-07-20 18:06:30 +02:00
private void SetSpawn(Player player)
{
if (player.PacMan.SpawnPosition is not null) return;
var spawn = Spawns.Dequeue();
player.PacMan.SpawnPosition = spawn;
player.PacMan.Position = spawn;
}
public void SendToAll(ArraySegment<byte> segment) => Connections?.Invoke(segment);
2023-07-01 18:54:59 +02:00
public IEnumerable<Player> SetReady(string username)
2023-07-01 18:54:59 +02:00
{
var player = Players.FirstOrDefault(p => p.Username == username);
if (player is null)
2023-07-11 14:23:41 +02:00
throw new PlayerNotFoundException("The player was not found in the game group.");
2023-07-01 18:54:59 +02:00
player.State = State.Ready;
return Players;
2023-07-01 18:54:59 +02:00
}
public bool SetAllInGame()
{
if (Players.Any(player => player.State != State.Ready)) return false;
foreach (var player in Players) player.State = State.InGame;
return true;
}
}