using System; using System.Collections.Generic; using System.Net.Sockets; using System.Text; using System.Threading; using System.Windows; 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; 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(); } public void SendMessage(ChatType chatType, string text) { _socket.Send(PacketConverter.toBytes(new MessageSendPacket(chatType, text))); } public void Disconnect() { _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(); App.Current.Dispatcher.Invoke((Action) (() => { MainWindow.Instance.HideAll(); MainWindow.Instance.ShowDisconnectScreen(e.Message); })); _breakFlag = true; } 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: switch (((GameStageChangedPacket)packet).GameState) { case GameState.Day: App.Current.Dispatcher.Invoke((Action) (() => { MainWindow.Instance.ShowDay(false); })); App.Instance.GetRpcClient().UpdateDetails("День"); break; } break; } } } }