using System; using System.Collections.Generic; using System.Net.Sockets; using System.Text; using System.Threading; using System.Windows.Controls; using DiscordRPC; using MafiaCommon.Packets; using MafiaCommon; namespace MafiaGame { public class ServerConnection { private String _host = "localhost"; private int _port = 25743; private Socket _socket; private Thread _thread; private bool _breakFlag = false; private bool connected; public ServerConnection(String ip) { if (ip.Contains(':')) { _host = ip.Split(":")[0]; _port = Convert.ToInt32(ip.Split(":")[1]); } else if (_host.Length != 0) { _host = ip; } _thread = new Thread(serverListener); _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); try { _socket.Connect(_host, _port); } catch (Exception e) { App.Current.Dispatcher.Invoke((Action) (() => { MainWindow.Instance.ShowDisconnectScreen(e.Message); })); return; } _socket.Send(PacketConverter.toBytes(new ConnectPacket(Settings.Config().Nick))); _thread.IsBackground = true; _thread.Start(); connected = true; } public void SendMessage(ChatType chatType, string text) { _socket.Send(PacketConverter.toBytes(new MessageSendPacket(chatType, text))); } public void Disconnect() { connected = false; _socket.Send(PacketConverter.toBytes(new DisconnectPlayerPacket())); _thread.Interrupt(); _socket.Close(); } public void Vote(int id) { _socket.Send(PacketConverter.toBytes(new VotePacket(id))); } private void serverListener() { while (!_breakFlag) { StringBuilder builder = new StringBuilder(); int bytes = 0; byte[] data = new byte[256]; try { do { bytes = _socket.Receive(data); builder.Append(Encoding.UTF8.GetString(data, 0, bytes)); } while (_socket.Available > 0); } catch (Exception e) { _socket.Close(); if (connected) { App.Current.Dispatcher.Invoke((Action) (() => { MainWindow.Instance.HideAll(); MainWindow.Instance.ShowDisconnectScreen(e.Message); })); connected = false; } _breakFlag = true; } if (!_breakFlag) { Console.WriteLine(builder.ToString()); List packets = PacketConverter.toPacket(builder.ToString()); foreach (Packet packet in packets) { WorkPacket(packet); } } } } private void WorkPacket(Packet packet) { switch (packet.PacketType) { case PacketType.Welcome: App.Current.Dispatcher.Invoke((Action) (() => { MainWindow.Instance.QueueOnline.Text = ((WelcomePacket) packet).Players + "/" + ((WelcomePacket) packet).MaxPlayers; MainWindow.Instance.ShowGameQueueScreen(); Party party = new Party(); party.ID = _host + ":" + _port; party.Size = ((WelcomePacket) packet).Players; party.Max = ((WelcomePacket) packet).MaxPlayers; Secrets secrets = new Secrets(); secrets.JoinSecret = _host + ":" + _port + "/join"; secrets.SpectateSecret = _host + ":" + _port + "/spectate"; App.Instance.GetRpcClient().SetPresence(new RichPresence() { State = ((WelcomePacket) packet).ServerName, Party = party, Secrets = secrets, Timestamps = Timestamps.Now, Details = "Ожидание старта" }); })); break; case PacketType.Disconnect: App.Current.Dispatcher.Invoke((Action) (() => { MainWindow.Instance.ShowDisconnectScreen(((DisconnectPacket) packet).Reason); })); _breakFlag = true; break; case PacketType.PlayerConnected: App.Current.Dispatcher.Invoke((Action) (() => { MainWindow.Instance.QueueOnline.Text = ((PlayerConnectedPacket) packet).Players + "/" + ((PlayerConnectedPacket) packet).MaxPlayers; })); try { App.Instance.GetRpcClient().UpdatePartySize(((PlayerConnectedPacket) packet).Players); } catch (Exception e) { Console.WriteLine(e.Message); } break; case PacketType.PlayerDisconnected: App.Current.Dispatcher.Invoke((Action) (() => { MainWindow.Instance.QueueOnline.Text = ((PlayerDisconnectedPacket) packet).Players + "/" + ((PlayerDisconnectedPacket) packet).MaxPlayers; })); try { App.Instance.GetRpcClient().UpdatePartySize(((PlayerDisconnectedPacket) packet).Players); } catch (Exception e) { Console.WriteLine(e.Message); } break; case PacketType.ServerShutdown: App.Current.Dispatcher.Invoke((Action) (() => { MainWindow.Instance.ShowDisconnectScreen("Сервер выключен: " + ((ServerShutdownPacket) packet).Reason); })); _breakFlag = true; break; case PacketType.MessageReceivePacket: App.Current.Dispatcher.Invoke((Action) (() => { ListBoxItem message = new ListBoxItem(); if (((MessageReceivePacket) packet).IsSystem) { message.Content = ((MessageReceivePacket) packet).Text; } else { message.Content = ((MessageReceivePacket) packet).Author + ": " + ((MessageReceivePacket) packet).Text; } switch (((MessageReceivePacket) packet).ChatType) { case ChatType.Queue: MainWindow.Instance.QueueChat.Items.Add(message); MainWindow.Instance.QueueChat.ScrollIntoView(message); break; case ChatType.Active: MainWindow.Instance.GameVotingActiveChat.Items.Add(message); MainWindow.Instance.GameVotingActiveChat.ScrollIntoView(message); break; case ChatType.Day: MainWindow.Instance.GameDayChat.Items.Add(message); MainWindow.Instance.GameDayChat.ScrollIntoView(message); break; } })); break; case PacketType.GameStartPacket: List players = ((GameStartPacket) packet).Players; switch (((GameStartPacket) packet).Role) { case Role.Citizen: App.Current.Dispatcher.Invoke((Action) (() => { MainWindow.Instance.ShowVotingPassive("Ты Мирный Житель"); })); break; 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; } App.Instance.GetRpcClient().UpdateDetails("Ночь"); break; case PacketType.EndGame: App.Current.Dispatcher.Invoke((Action) (() => { MainWindow.Instance.ShowGameEnd(((EndGamePacket)packet).IsWon,((EndGamePacket)packet).PlayerRoles); })); App.Instance.GetRpcClient().UpdateDetails("Ожидание старта"); break; case PacketType.GameStateChanged: App.Current.Dispatcher.Invoke((Action) (() => { MainWindow.Instance.HideAll(); })); players = ((GameStageChangedPacket) packet).Players; switch (((GameStageChangedPacket) packet).GameState) { case GameState.Day: App.Current.Dispatcher.Invoke((Action) (() => { MainWindow.Instance.ShowDay(false, ((GameStageChangedPacket) packet).Role,players); })); App.Instance.GetRpcClient().UpdateDetails("День"); break; case GameState.VotingDay: App.Current.Dispatcher.Invoke((Action) (() => { MainWindow.Instance.ShowDay(true, ((GameStageChangedPacket) packet).Role,players); })); App.Instance.GetRpcClient().UpdateDetails("Голосование!"); break; case GameState.VotingNight: switch (((GameStageChangedPacket)packet).Role) { case Role.Citizen: case Role.Died: App.Current.Dispatcher.Invoke((Action) (() => { String rol; if (((GameStageChangedPacket)packet).Role == Role.Citizen) rol = "Мирный житель"; else rol = "Мёртв"; MainWindow.Instance.ShowVotingPassive("Ты " +rol+ "!"); })); break; case Role.Mafia: case Role.Don: App.Current.Dispatcher.Invoke((Action) (() => { String rol; if (((GameStageChangedPacket)packet).Role == Role.Mafia) rol = "Мафия"; else rol = "Дон"; MainWindow.Instance.GameVotingActiveSelect.Items.Clear(); MainWindow.Instance.ShowVotingActive("Ты "+rol+", выбери кого убить!"); foreach (Player player in players) { ListBoxItem item = new ListBoxItem(); item.Content = player.Id.ToString() + ") " + player.Name; MainWindow.Instance.GameVotingActiveSelect.Items.Add(item); } })); break; } break; } break; } } } }