RMafia/MafiaGame/ServerConnection.cs
2021-02-10 22:11:55 +03:00

275 lines
12 KiB
C#

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<Packet> 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<Player> 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,((GameStageChangedPacket)packet).Role);
}));
App.Instance.GetRpcClient().UpdateDetails("День");
break;
}
break;
}
}
}
}