using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Net; using System.Threading.Tasks; using Impostor.Api.Events.Managers; using Impostor.Api.Games; using Impostor.Api.Innersloth; using Impostor.Api.Net; using Impostor.Api.Net.Messages; using Impostor.Api.Net.Messages.S2C; using Impostor.Server.Events; using Impostor.Server.Net.Manager; using Microsoft.Extensions.Logging; namespace Impostor.Server.Net.State { internal partial class Game { private readonly ILogger _logger; private readonly IServiceProvider _serviceProvider; private readonly GameManager _gameManager; private readonly ClientManager _clientManager; private readonly ConcurrentDictionary _players; private readonly HashSet _bannedIps; private readonly IEventManager _eventManager; public Game( ILogger logger, IServiceProvider serviceProvider, GameManager gameManager, IPEndPoint publicIp, GameCode code, GameOptionsData options, ClientManager clientManager, IEventManager eventManager) { _logger = logger; _serviceProvider = serviceProvider; _gameManager = gameManager; _players = new ConcurrentDictionary(); _bannedIps = new HashSet(); PublicIp = publicIp; Code = code; HostId = -1; GameState = GameStates.NotStarted; GameNet = new GameNet(); Options = options; _clientManager = clientManager; _eventManager = eventManager; Items = new ConcurrentDictionary(); } public IPEndPoint PublicIp { get; } public GameCode Code { get; } public bool IsPublic { get; private set; } public int HostId { get; private set; } public GameStates GameState { get; private set; } internal GameNet GameNet { get; } public GameOptionsData Options { get; } public IDictionary Items { get; } public int PlayerCount => _players.Count; public ClientPlayer Host => _players[HostId]; public IEnumerable Players => _players.Select(p => p.Value); public bool TryGetPlayer(int id, out ClientPlayer player) { if (_players.TryGetValue(id, out var result)) { player = result; return true; } player = default; return false; } public IClientPlayer GetClientPlayer(int clientId) { return _players.TryGetValue(clientId, out var clientPlayer) ? clientPlayer : null; } internal ValueTask StartedAsync() { if (GameState == GameStates.Starting) { GameState = GameStates.Started; return _eventManager.CallAsync(new GameStartedEvent(this)); } return default; } public ValueTask EndAsync() { return _gameManager.RemoveAsync(Code); } private ValueTask BroadcastJoinMessage(IMessageWriter message, bool clear, ClientPlayer player) { Message01JoinGameS2C.SerializeJoin(message, clear, Code, player.Client.Id, HostId); return SendToAllExceptAsync(message, player.Client.Id); } private IEnumerable GetConnections(Func filter) { return Players .Where(filter) .Select(p => p.Client.Connection); } } }