using System; using System.Collections.Generic; using System.Threading; using MafiaCommon.Packets; using MafiaCommon; namespace MafiaServer { public class Game { private List _players = new List(); private List _playerRolesAtStart = new List(); private bool isStarted = false; private GameState _gameState = GameState.NotStarted; private List _votesRemain = new List(); List _mafia = new List(); private Dictionary _mafiaVotes = new Dictionary(); private Dictionary _dayVote = new Dictionary(); private Timer _voteStartTimer; public Game() { } public void ConnectPlayer(PlayerSocketWorker player) { if (_players.Count >= Settings.Config().MaxPlayers) { player.sendPacket(new DisconnectPacket("Game Full!")); player.disconnect(); } else { if (isStarted) { player.sendPacket(new DisconnectPacket("Game already started!")); player.disconnect(); } else { foreach (PlayerSocketWorker othPlayer in _players) { othPlayer.sendPacket(new PlayerConnectedPacket(player.PlayerName, _players.Count + 1, Settings.Config().MaxPlayers)); } _players.Add(player); player.Id = _players.LastIndexOf(player); player.OnDisconnectByErrorEvent += OnDisconnectByError; player.OnPlayerSendMessageEvent += PlayerOnOnPlayerSendMessageEvent; player.OnDisconnectEvent += PlayerOnOnDisconnectEvent; player.OnPlayerVoteEvent += PlayerOnOnPlayerVoteEvent; player.sendPacket(new WelcomePacket(Settings.Config().ServerName, _players.Count, Settings.Config().MaxPlayers)); } } } public List GetPlayersRoles() { List players = new List(); foreach (PlayerSocketWorker player in _players) { if (player.Role != Role.Died) { players.Add(new Player(player.Id, player.PlayerName)); } } return players; } private bool WorkDeath(PlayerSocketWorker player) { switch (player.Role) { case Role.Don: _mafia.Remove(player); if (_mafia.Count == 0) { foreach (PlayerSocketWorker p in _players) { p.sendPacket(new EndGamePacket(true,_playerRolesAtStart)); } isStarted = false; _gameState = GameState.NotStarted; return false; } else { _mafia[0].Role = Role.Don; if (_gameState == GameState.VotingNight) { _mafia[0].sendPacket(new MessageReceivePacket(ChatType.Active,true,"System","Дон покинул игру, ты новый дон!")); } _mafia.RemoveAt(0); } break; } int mafias = _mafia.Count + 1; int aliveLefts = 0; foreach (PlayerSocketWorker pl in _players) { if (pl.Role != Role.Died && pl.Role != Role.Don && pl.Role != Role.Mafia) aliveLefts++; } if (mafias >= aliveLefts) { foreach (PlayerSocketWorker p in _players) { p.sendPacket(new EndGamePacket(p.Role == Role.Mafia || p.Role == Role.Don, _playerRolesAtStart)); } isStarted = false; _gameState = GameState.NotStarted; return false; } player.Role = Role.Died; return true; } private void PlayerOnOnPlayerVoteEvent(PlayerSocketWorker sender, int id) { if (_votesRemain.Contains(sender)) { PlayerSocketWorker voteFor = _players.FindPlayerById(id); switch (_gameState) { case GameState.VotingNight: switch (sender.Role) { case Role.Don: _mafiaVotes.AddEmpty(id,2); _votesRemain.Remove(sender); foreach (PlayerSocketWorker player in _players) { if (player.Role == Role.Mafia || player.Role == Role.Don) { player.sendPacket(new MessageReceivePacket(ChatType.Active,true,"System",sender.PlayerName+" проголосовал за "+voteFor.PlayerName)); } } break; case Role.Mafia: _mafiaVotes.AddEmpty(id,1); _votesRemain.Remove(sender); foreach (PlayerSocketWorker player in _players) { if (player.Role == Role.Mafia || player.Role == Role.Don) { player.sendPacket(new MessageReceivePacket(ChatType.Active,true,"System",sender.PlayerName+" проголосовал за "+voteFor.PlayerName)); } } break; } break; case GameState.VotingDay: _dayVote.AddEmpty(id,1); _votesRemain.Remove(sender); break; } } if (_votesRemain.Count == 0) { switch (_gameState) { case GameState.VotingNight: int selId = 0; int selVotes = 0; foreach (KeyValuePair votes in _mafiaVotes) { if (votes.Value > selVotes) { selId = votes.Key; selVotes = votes.Value; } } PlayerSocketWorker killed = _players.FindPlayerById(selId); if (WorkDeath(killed)) { _gameState = GameState.Day; foreach (PlayerSocketWorker player in _players) { player.sendPacket(new GameStageChangedPacket(GameState.Day, player.Role, GetPlayersRoles())); player.sendPacket(new MessageReceivePacket(ChatType.Day, true, "System", killed.PlayerName + " был убит!")); } _voteStartTimer = new Timer(StartDayVote, null, 60000, 60000); } break; case GameState.VotingDay: selId = 0; selVotes = 0; foreach (KeyValuePair votes in _dayVote) { if (votes.Value > selVotes) { selId = votes.Key; selVotes = votes.Value; } } killed = _players.FindPlayerById(selId); if (WorkDeath(killed)) { _gameState = GameState.VotingNight; FillNightVotes(); foreach (PlayerSocketWorker player in _players) { player.sendPacket(new GameStageChangedPacket(GameState.VotingNight, player.Role, GetPlayersRoles())); player.sendPacket(new MessageReceivePacket(ChatType.Day, true, "System", killed.PlayerName + " был повешен!")); } } break; } } } private void StartDayVote(object obj) { _voteStartTimer.Dispose(); _gameState = GameState.VotingDay; _votesRemain.Clear(); foreach (PlayerSocketWorker player in _players) { if (player.Role != Role.Died) { _votesRemain.Add(player); } } foreach (PlayerSocketWorker player in _players) { player.sendPacket(new GameStageChangedPacket(GameState.VotingDay,player.Role,GetPlayersRoles())); player.sendPacket(new MessageReceivePacket(ChatType.Day,true,"System","Начинаем голосование!")); } } private void FillNightVotes() { foreach (PlayerSocketWorker player in _players) { switch (player.Role) { case Role.Don: case Role.Mafia: _votesRemain.Add(player); break; } } } private void PlayerOnOnDisconnectEvent(PlayerSocketWorker sender) { _players.Remove(sender); foreach (PlayerSocketWorker player in _players) { player.sendPacket(new PlayerDisconnectedPacket(true, sender.Id, _players.Count, Settings.Config().MaxPlayers)); } if (_gameState != GameState.NotStarted) { WorkDeath(sender); } } public void Start() { if (isStarted) { return; } if (_players.Count < 3) { Console.WriteLine("Not Enough Players"); return; } foreach (PlayerSocketWorker player in _players) { player.Role = Role.Citizen; } _playerRolesAtStart.Clear(); _votesRemain.Clear(); _mafiaVotes.Clear(); _dayVote.Clear(); Random random = new Random(); PlayerSocketWorker[] empty = _players.ToArray(); random.Shuffle(empty); int mafiasNeed = empty.Length / 3; Console.WriteLine("Debug: needs counted"); while (mafiasNeed!=0) { for (var i = 0; i < empty.Length; i++) { switch (random.Next(2)) { case 0: //Мирный break; case 1: //Мафия if (mafiasNeed > 0) { empty[i].Role = Role.Mafia; mafiasNeed--; _mafia.Add(empty[i]); empty = empty.RemoveFromArray(i); } break; } } } Console.WriteLine("Debug: randomazed"); PlayerSocketWorker don = _mafia[0]; don.Role = Role.Don; _mafia.RemoveAt(0); List players = GetPlayersRoles(); don.sendPacket(new GameStartPacket(Role.Don,players)); _votesRemain.Add(don); foreach (PlayerSocketWorker player in empty) { player.sendPacket(new GameStartPacket(Role.Citizen,players)); } foreach (PlayerSocketWorker player in _mafia) { player.sendPacket(new GameStartPacket(Role.Mafia,players)); _votesRemain.Add(player); } foreach (PlayerSocketWorker player in _players) { _playerRolesAtStart.Add(new PlayerRole(player.PlayerName,player.Role)); } Console.WriteLine("Debug: packets sended"); isStarted = true; _gameState = GameState.VotingNight; } private void OnDisconnectByError(PlayerSocketWorker sender) { _players.Remove(sender); foreach (PlayerSocketWorker player in _players) { player.sendPacket(new PlayerDisconnectedPacket(true,sender.Id,_players.Count,Settings.Config().MaxPlayers)); } WorkDeath(sender); } private void PlayerOnOnPlayerSendMessageEvent(PlayerSocketWorker sender, ChatType chatType, string text) { switch (chatType) { case ChatType.Queue: if (!isStarted) { foreach (PlayerSocketWorker player in _players) { player.sendPacket(new MessageReceivePacket(ChatType.Queue,false,sender.PlayerName,text)); } } break; case ChatType.Active: if (isStarted) { switch (sender.Role) { case Role.Mafia: case Role.Don: foreach (PlayerSocketWorker player in _players) { if (player.Role == Role.Mafia || player.Role == Role.Don) { player.sendPacket(new MessageReceivePacket(ChatType.Active, false, sender.PlayerName, text)); } } break; } } break; case ChatType.Day: if (isStarted) { if (sender.Role == Role.Died) { sender.sendPacket(new MessageReceivePacket(ChatType.Day,true,"system","Мёртвое говорить не может")); } else { foreach (PlayerSocketWorker player in _players) { player.sendPacket( new MessageReceivePacket(ChatType.Day, false, sender.PlayerName, text)); } } } break; } } } }