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 readonly String _host = "localhost"; private readonly int _port = 25743; private readonly Socket _socket; private readonly Thread _thread; private bool _breakFlag; 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) { Application.Current.Dispatcher.Invoke(() => { 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(); byte[] data = new byte[256]; try { do { var bytes = _socket.Receive(data); builder.Append(Encoding.UTF8.GetString(data, 0, bytes)); } while (_socket.Available > 0); } catch (Exception e) { _socket.Close(); if (_connected) { Application.Current.Dispatcher.Invoke(() => { 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: Application.Current.Dispatcher.Invoke(() => { MainWindow.Instance.QueueOnline.Text = ((WelcomePacket) packet).Players + "/" + ((WelcomePacket) packet).MaxPlayers; MainWindow.Instance.ShowGameQueueScreen(); Party party = new Party { ID = _host + ":" + _port, Size = ((WelcomePacket) packet).Players, Max = ((WelcomePacket) packet).MaxPlayers }; Secrets secrets = new Secrets { JoinSecret = _host + ":" + _port + "/join", 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: Application.Current.Dispatcher.Invoke(() => { MainWindow.Instance.ShowDisconnectScreen(((DisconnectPacket) packet).Reason); }); _breakFlag = true; break; case PacketType.PlayerConnected: Application.Current.Dispatcher.Invoke(() => { 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: Application.Current.Dispatcher.Invoke(() => { 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: Application.Current.Dispatcher.Invoke(() => { MainWindow.Instance.ShowDisconnectScreen("Сервер выключен: " + ((ServerShutdownPacket) packet).Reason); }); _breakFlag = true; break; case PacketType.MessageReceivePacket: Application.Current.Dispatcher.Invoke(() => { 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: Application.Current.Dispatcher.Invoke(() => { MainWindow.Instance.HideAll(); MainWindow.Instance.ShowVotingPassive("Ты Мирный Житель"); }); break; case Role.Don: Application.Current.Dispatcher.Invoke(() => { MainWindow.Instance.HideAll(); MainWindow.Instance.GameVotingActiveSelect.Items.Clear(); MainWindow.Instance.ShowVotingActive("Ты Дон, выбери кого убить!"); foreach (Player player in players) { ListBoxItem item = new ListBoxItem { Content = player.Id.ToString() + ") " + player.Name }; MainWindow.Instance.GameVotingActiveSelect.Items.Add(item); } }); break; case Role.Mafia: Application.Current.Dispatcher.Invoke(() => { MainWindow.Instance.HideAll(); MainWindow.Instance.GameVotingActiveSelect.Items.Clear(); MainWindow.Instance.ShowVotingActive("Ты Мафия, выбери кого убить!"); foreach (Player player in players) { ListBoxItem item = new ListBoxItem { Content = player.Id.ToString() + ") " + player.Name }; MainWindow.Instance.GameVotingActiveSelect.Items.Add(item); } }); break; } App.Instance.GetRpcClient().UpdateDetails("Ночь"); break; case PacketType.EndGame: Application.Current.Dispatcher.Invoke(() => { MainWindow.Instance.ShowGameEnd(((EndGamePacket)packet).IsWon,((EndGamePacket)packet).PlayerRoles); }); App.Instance.GetRpcClient().UpdateDetails("Ожидание старта"); break; case PacketType.GameStateChanged: Application.Current.Dispatcher.Invoke(() => { MainWindow.Instance.HideAll(); }); players = ((GameStageChangedPacket) packet).Players; switch (((GameStageChangedPacket) packet).GameState) { case GameState.Day: Application.Current.Dispatcher.Invoke(() => { MainWindow.Instance.ShowDay(false, ((GameStageChangedPacket) packet).Role,players); }); App.Instance.GetRpcClient().UpdateDetails("День"); break; case GameState.VotingDay: Application.Current.Dispatcher.Invoke(() => { 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: Application.Current.Dispatcher.Invoke(() => { var rol = ((GameStageChangedPacket)packet).Role == Role.Citizen ? "Мирный житель" : "Мёртв"; MainWindow.Instance.ShowVotingPassive("Ты " +rol+ "!"); }); break; case Role.Mafia: case Role.Don: Application.Current.Dispatcher.Invoke(() => { var rol = ((GameStageChangedPacket)packet).Role == Role.Mafia ? "Мафия" : "Дон"; MainWindow.Instance.GameVotingActiveSelect.Items.Clear(); MainWindow.Instance.ShowVotingActive("Ты "+rol+", выбери кого убить!"); foreach (Player player in players) { ListBoxItem item = new ListBoxItem { Content = player.Id.ToString() + ") " + player.Name }; MainWindow.Instance.GameVotingActiveSelect.Items.Add(item); } }); break; } break; } break; } } } }