RMafia/MafiaGame/ServerConnection.cs
2021-02-23 18:42:40 +03:00

334 lines
16 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 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<Packet> 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<Player> 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;
}
}
}
}