diff --git a/MafiaCommon/ArrayUtils.cs b/MafiaCommon/ArrayUtils.cs index 672e9bc..ed8a32f 100644 --- a/MafiaCommon/ArrayUtils.cs +++ b/MafiaCommon/ArrayUtils.cs @@ -23,5 +23,17 @@ namespace MafiaCommon tmp.RemoveAt(numIdx); return tmp.ToArray(); } + + public static void AddEmpty(this Dictionary original, T id, int add) + { + if (original.ContainsKey(id)) + { + original[id] += add; + } + else + { + original.Add(id,add); + } + } } } \ No newline at end of file diff --git a/MafiaCommon/Packets/GameStartPacket.cs b/MafiaCommon/Packets/GameStartPacket.cs index 975f24f..bbffa04 100644 --- a/MafiaCommon/Packets/GameStartPacket.cs +++ b/MafiaCommon/Packets/GameStartPacket.cs @@ -1,12 +1,16 @@ -namespace MafiaCommon.Packets +using System.Collections.Generic; + +namespace MafiaCommon.Packets { public class GameStartPacket : Packet { public readonly Role Role; + public readonly List Players; - public GameStartPacket(Role role) : base(PacketType.GameStartPacket) + public GameStartPacket(Role role, List players) : base(PacketType.GameStartPacket) { Role = role; + Players = players; } } } \ No newline at end of file diff --git a/MafiaCommon/Packets/PacketConverter.cs b/MafiaCommon/Packets/PacketConverter.cs index 8729c3a..6432a6d 100644 --- a/MafiaCommon/Packets/PacketConverter.cs +++ b/MafiaCommon/Packets/PacketConverter.cs @@ -49,6 +49,12 @@ namespace MafiaCommon.Packets case PacketType.EndGame: packet = JsonConvert.DeserializeObject(json); break; + case PacketType.DisconnectPlayer: + packet = JsonConvert.DeserializeObject(json); + break; + case PacketType.Vote: + packet = JsonConvert.DeserializeObject(json); + break; } return packet; diff --git a/MafiaCommon/Packets/PacketType.cs b/MafiaCommon/Packets/PacketType.cs index e68a0be..5e68d8f 100644 --- a/MafiaCommon/Packets/PacketType.cs +++ b/MafiaCommon/Packets/PacketType.cs @@ -12,6 +12,7 @@ GameStartPacket=8, EndGame=9, DisconnectPlayer=10, + Vote=11, ServerShutdown=99 } } \ No newline at end of file diff --git a/MafiaCommon/Packets/VotePacket.cs b/MafiaCommon/Packets/VotePacket.cs new file mode 100644 index 0000000..3a3e09e --- /dev/null +++ b/MafiaCommon/Packets/VotePacket.cs @@ -0,0 +1,12 @@ +namespace MafiaCommon.Packets +{ + public class VotePacket : Packet + { + public readonly int Id; + + public VotePacket(int id) : base(PacketType.Vote) + { + Id = id; + } + } +} \ No newline at end of file diff --git a/MafiaCommon/Player.cs b/MafiaCommon/Player.cs new file mode 100644 index 0000000..48c39ff --- /dev/null +++ b/MafiaCommon/Player.cs @@ -0,0 +1,14 @@ +namespace MafiaCommon +{ + public class Player + { + public readonly int Id; + public readonly string Name; + + public Player(int id, string name) + { + Id = id; + Name = name; + } + } +} \ No newline at end of file diff --git a/MafiaGame/MainWindow.xaml b/MafiaGame/MainWindow.xaml index ca96dc4..4e3f9e3 100644 --- a/MafiaGame/MainWindow.xaml +++ b/MafiaGame/MainWindow.xaml @@ -221,7 +221,7 @@ - + diff --git a/MafiaGame/MainWindow.xaml.cs b/MafiaGame/MainWindow.xaml.cs index 0efe5cd..429319e 100644 --- a/MafiaGame/MainWindow.xaml.cs +++ b/MafiaGame/MainWindow.xaml.cs @@ -39,6 +39,18 @@ namespace MafiaGame }); } + public void HideAll() + { + MainMenu.Visibility = Visibility.Hidden; + SettingsGUI.Visibility = Visibility.Hidden; + IpInput.Visibility = Visibility.Hidden; + GameQueue.Visibility = Visibility.Hidden; + DisconnectScreen.Visibility = Visibility.Hidden; + GameVotingPassive.Visibility = Visibility.Hidden; + GameVotingActive.Visibility = Visibility.Hidden; + GameEndScreen.Visibility = Visibility.Hidden; + } + private void Exit_OnClick(object sender, RoutedEventArgs e) { App.Current.Shutdown(0); @@ -230,5 +242,11 @@ namespace MafiaGame State = "В главном меню" }); } + + private void GameVotingActiveSelect_OnMouseDoubleClick(object sender, MouseButtonEventArgs e) + { + ListBoxItem selected = (ListBoxItem)GameVotingActiveSelect.SelectedItem; + App.Instance.Connection.Vote(Convert.ToInt32(((string)selected.Content).Split(")")[0])); + } } } \ No newline at end of file diff --git a/MafiaGame/ServerConnection.cs b/MafiaGame/ServerConnection.cs index 91e6a54..8cf6357 100644 --- a/MafiaGame/ServerConnection.cs +++ b/MafiaGame/ServerConnection.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Net.Sockets; using System.Text; using System.Threading; @@ -62,6 +63,11 @@ namespace MafiaGame _socket.Close(); } + public void Vote(int id) + { + _socket.Send(PacketConverter.toBytes(new VotePacket(id))); + } + private void serverListener() { while (!_breakFlag) @@ -69,11 +75,24 @@ namespace MafiaGame StringBuilder builder = new StringBuilder(); int bytes = 0; byte[] data = new byte[256]; - do + try { - bytes = _socket.Receive(data); - builder.Append(Encoding.UTF8.GetString(data, 0, bytes)); - } while (_socket.Available > 0); + do + { + bytes = _socket.Receive(data); + builder.Append(Encoding.UTF8.GetString(data, 0, bytes)); + } while (_socket.Available > 0); + } + catch (Exception e) + { + _socket.Close(); + App.Current.Dispatcher.Invoke((Action) (() => + { + MainWindow.Instance.HideAll(); + MainWindow.Instance.ShowDisconnectScreen(e.Message); + })); + _breakFlag = true; + } Console.WriteLine(builder.ToString()); @@ -178,6 +197,7 @@ namespace MafiaGame })); break; case PacketType.GameStartPacket: + List players = ((GameStartPacket) packet).Players; switch (((GameStartPacket) packet).Role) { case Role.Citizen: @@ -189,13 +209,27 @@ namespace MafiaGame case Role.Don: App.Current.Dispatcher.Invoke((Action) (() => { + MainWindow.Instance.GameVotingActiveSelect.Items.Clear(); MainWindow.Instance.ShowVotingActive("Ты Дон, выбери кого убить!"); + foreach (Player player in players) + { + ListBoxItem item = new ListBoxItem(); + item.Content = player.Id.ToString() + ") " + player.Name; + MainWindow.Instance.GameVotingActiveSelect.Items.Add(item); + } })); break; case Role.Mafia: App.Current.Dispatcher.Invoke((Action) (() => { + MainWindow.Instance.GameVotingActiveSelect.Items.Clear(); MainWindow.Instance.ShowVotingActive("Ты Мафия, выбери кого убить!"); + foreach (Player player in players) + { + ListBoxItem item = new ListBoxItem(); + item.Content = player.Id.ToString() + ") " + player.Name; + MainWindow.Instance.GameVotingActiveSelect.Items.Add(item); + } })); break; } diff --git a/MafiaServer/Events/OnPlayerVoteEvent.cs b/MafiaServer/Events/OnPlayerVoteEvent.cs new file mode 100644 index 0000000..354d090 --- /dev/null +++ b/MafiaServer/Events/OnPlayerVoteEvent.cs @@ -0,0 +1,6 @@ +using MafiaCommon; + +namespace MafiaServer.Events +{ + public delegate void OnPlayerVoteEvent(PlayerSocketWorker sender, int id); +} \ No newline at end of file diff --git a/MafiaServer/Game.cs b/MafiaServer/Game.cs index 9c46b09..167e94b 100644 --- a/MafiaServer/Game.cs +++ b/MafiaServer/Game.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; using MafiaCommon.Packets; using MafiaCommon; @@ -12,9 +11,11 @@ namespace MafiaServer 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(); + public Game() { @@ -22,23 +23,78 @@ namespace MafiaServer public void ConnectPlayer(PlayerSocketWorker player) { - if (isStarted) + if (_players.Count >= Settings.Config().MaxPlayers) { - player.sendPacket(new DisconnectPacket("Game already started!")); + player.sendPacket(new DisconnectPacket("Game Full!")); player.disconnect(); } else { - foreach (PlayerSocketWorker othPlayer in _players) + if (isStarted) { - othPlayer.sendPacket(new PlayerConnectedPacket(player.PlayerName,_players.Count+1,Settings.Config().MaxPlayers)); + 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)); + } + } + } + + 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; } - _players.Add(player); - player.Id = _players.LastIndexOf(player); - player.OnDisconnectByErrorEvent += OnDisconnectByError; - player.OnPlayerSendMessageEvent += PlayerOnOnPlayerSendMessageEvent; - player.OnDisconnectEvent += PlayerOnOnDisconnectEvent; - player.sendPacket(new WelcomePacket(Settings.Config().ServerName,_players.Count,Settings.Config().MaxPlayers)); } } @@ -79,7 +135,7 @@ namespace MafiaServer { return; } - if (_players.Count < 2) + if (_players.Count < 3) { Console.WriteLine("Not Enough Players"); return; @@ -90,17 +146,18 @@ namespace MafiaServer 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 = 1; - if (empty.Length > 5) - { - mafiasNeed = empty.Length / 3; - } + int mafiasNeed = empty.Length / 3; + + Console.WriteLine("Debug: needs counted"); while (mafiasNeed!=0) { @@ -111,29 +168,43 @@ namespace MafiaServer case 0: //Мирный break; case 1: //Мафия - empty[i].Role = Role.Mafia; - mafiasNeed--; - _mafia.Add(empty[i]); - empty = empty.RemoveFromArray(i); + 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 = new List(); - don.sendPacket(new GameStartPacket(Role.Don)); + foreach (PlayerSocketWorker player in _players) + { + players.Add(new Player(player.Id, player.PlayerName)); + } + + don.sendPacket(new GameStartPacket(Role.Don,players)); + _votesRemain.Add(don); foreach (PlayerSocketWorker player in empty) { - player.sendPacket(new GameStartPacket(Role.Citizen)); + player.sendPacket(new GameStartPacket(Role.Citizen,players)); } foreach (PlayerSocketWorker player in _mafia) { - player.sendPacket(new GameStartPacket(Role.Mafia)); + player.sendPacket(new GameStartPacket(Role.Mafia,players)); + _votesRemain.Add(player); } foreach (PlayerSocketWorker player in _players) @@ -141,6 +212,8 @@ namespace MafiaServer _playerRolesAtStart.Add(new PlayerRole(player.PlayerName,player.Role)); } + Console.WriteLine("Debug: packets sended"); + isStarted = true; _gameState = GameState.VotingNight; } diff --git a/MafiaServer/PlayerSocketWorker.cs b/MafiaServer/PlayerSocketWorker.cs index 2b59c4d..c270c6b 100644 --- a/MafiaServer/PlayerSocketWorker.cs +++ b/MafiaServer/PlayerSocketWorker.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Net.Sockets; using System.Text; using MafiaCommon.Packets; @@ -14,8 +15,10 @@ namespace MafiaServer public event OnDisconnectByErrorEvent OnDisconnectByErrorEvent; public event OnPlayerSendMessageEvent OnPlayerSendMessageEvent; public event OnDisconnectEvent OnDisconnectEvent; + public event OnPlayerVoteEvent OnPlayerVoteEvent; public int Id; public Role Role = Role.Citizen; + public PlayerSocketWorker(Socket socket) { _socket = socket; @@ -26,8 +29,7 @@ namespace MafiaServer { bytes = _socket.Receive(data); builder.Append(Encoding.UTF8.GetString(data, 0, bytes)); - } - while (_socket.Available>0); + } while (_socket.Available > 0); var packet = PacketConverter.toPacket(builder.ToString()); if (packet.GetType() == typeof(ConnectPacket)) @@ -43,7 +45,14 @@ namespace MafiaServer public void sendPacket(Packet packet) { - _socket.Send(PacketConverter.toBytes(packet)); + try + { + _socket.Send(PacketConverter.toBytes(packet)); + } + catch (Exception e) + { + + } } public void disconnect() @@ -72,12 +81,16 @@ namespace MafiaServer switch (packet.PacketType) { case PacketType.MessageSendPacket: - OnPlayerSendMessageEvent.Invoke(this,((MessageSendPacket)packet).ChatType,((MessageSendPacket)packet).Text); + OnPlayerSendMessageEvent.Invoke(this, ((MessageSendPacket) packet).ChatType, + ((MessageSendPacket) packet).Text); break; case PacketType.DisconnectPlayer: _socket.Close(); OnDisconnectEvent.Invoke(this); break; + case PacketType.Vote: + OnPlayerVoteEvent.Invoke(this, ((VotePacket) packet).Id); + break; } } catch (SocketException e) @@ -87,4 +100,16 @@ namespace MafiaServer } } } + + public static class PlayerSocketWorkerUtils { + public static PlayerSocketWorker FindPlayerById(this List original, int id) + { + foreach (PlayerSocketWorker player in original) + { + if (player.Id == id) return player; + } + + return null; + } + } } \ No newline at end of file