commit 77e0f60987638c58b363f05006e26496c13113f3 Author: Ilya Date: Sun Jan 17 22:47:02 2021 +0300 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..add57be --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +bin/ +obj/ +/packages/ +riderModule.iml +/_ReSharper.Caches/ \ No newline at end of file diff --git a/MafiaCommon/MafiaCommon.csproj b/MafiaCommon/MafiaCommon.csproj new file mode 100644 index 0000000..5f6a68f --- /dev/null +++ b/MafiaCommon/MafiaCommon.csproj @@ -0,0 +1,11 @@ + + + + netcoreapp3.1 + + + + + + + diff --git a/MafiaCommon/Packets/ChatType.cs b/MafiaCommon/Packets/ChatType.cs new file mode 100644 index 0000000..119228d --- /dev/null +++ b/MafiaCommon/Packets/ChatType.cs @@ -0,0 +1,7 @@ +namespace MafiaCommon.Packets +{ + public enum ChatType + { + Queue=1 + } +} \ No newline at end of file diff --git a/MafiaCommon/Packets/ConnectPacket.cs b/MafiaCommon/Packets/ConnectPacket.cs new file mode 100644 index 0000000..87eac7c --- /dev/null +++ b/MafiaCommon/Packets/ConnectPacket.cs @@ -0,0 +1,14 @@ +using System; + +namespace MafiaCommon.Packets +{ + public class ConnectPacket : Packet + { + public readonly String Name; + + public ConnectPacket(String name) : base(PacketType.Connect) + { + Name = name; + } + } +} \ No newline at end of file diff --git a/MafiaCommon/Packets/DisconnectPacket.cs b/MafiaCommon/Packets/DisconnectPacket.cs new file mode 100644 index 0000000..505cf45 --- /dev/null +++ b/MafiaCommon/Packets/DisconnectPacket.cs @@ -0,0 +1,12 @@ +namespace MafiaCommon.Packets +{ + public class DisconnectPacket : Packet + { + public readonly string Reason; + + public DisconnectPacket(string reason) : base(PacketType.Disconnect) + { + Reason = reason; + } + } +} \ No newline at end of file diff --git a/MafiaCommon/Packets/MessageReceivePacket.cs b/MafiaCommon/Packets/MessageReceivePacket.cs new file mode 100644 index 0000000..cd47418 --- /dev/null +++ b/MafiaCommon/Packets/MessageReceivePacket.cs @@ -0,0 +1,18 @@ +namespace MafiaCommon.Packets +{ + public class MessageReceivePacket : Packet + { + public readonly ChatType ChatType; + public readonly bool IsSystem; + public readonly string Author; + public readonly string Text; + + public MessageReceivePacket(ChatType chatType, bool isSystem, string author, string text) : base(PacketType.MessageReceivePacket) + { + ChatType = chatType; + IsSystem = isSystem; + Author = author; + Text = text; + } + } +} \ No newline at end of file diff --git a/MafiaCommon/Packets/MessageSendPacket.cs b/MafiaCommon/Packets/MessageSendPacket.cs new file mode 100644 index 0000000..13bc26a --- /dev/null +++ b/MafiaCommon/Packets/MessageSendPacket.cs @@ -0,0 +1,14 @@ +namespace MafiaCommon.Packets +{ + public class MessageSendPacket : Packet + { + public readonly ChatType ChatType; + public readonly string Text; + + public MessageSendPacket(ChatType chatType, string text) : base(PacketType.MessageSendPacket) + { + ChatType = chatType; + Text = text; + } + } +} \ No newline at end of file diff --git a/MafiaCommon/Packets/Packet.cs b/MafiaCommon/Packets/Packet.cs new file mode 100644 index 0000000..4571b0e --- /dev/null +++ b/MafiaCommon/Packets/Packet.cs @@ -0,0 +1,12 @@ +namespace MafiaCommon.Packets +{ + public class Packet + { + public readonly PacketType PacketType; + + public Packet(PacketType type) + { + PacketType = type; + } + } +} \ No newline at end of file diff --git a/MafiaCommon/Packets/PacketConverter.cs b/MafiaCommon/Packets/PacketConverter.cs new file mode 100644 index 0000000..f11a208 --- /dev/null +++ b/MafiaCommon/Packets/PacketConverter.cs @@ -0,0 +1,51 @@ +using System; +using System.Text; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace MafiaCommon.Packets +{ + public class PacketConverter + { + public static byte[] toBytes(Packet packet) + { + return Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(packet)); + } + + public static Packet toPacket(String json) + { + PacketType packetType = ((JObject)JsonConvert.DeserializeObject(json)).GetValue("PacketType").ToObject(); + Packet packet = null; + + switch (packetType) + { + case PacketType.ServerShutdown: + packet = JsonConvert.DeserializeObject(json); + break; + case PacketType.Connect: + packet = JsonConvert.DeserializeObject(json); + break; + case PacketType.Welcome: + packet = JsonConvert.DeserializeObject(json); + break; + case PacketType.Disconnect: + packet = JsonConvert.DeserializeObject(json); + break; + case PacketType.PlayerConnected: + packet = JsonConvert.DeserializeObject(json); + break; + case PacketType.PlayerDisconnected: + packet = JsonConvert.DeserializeObject(json); + break; + case PacketType.MessageReceivePacket: + packet = JsonConvert.DeserializeObject(json); + break; + case PacketType.MessageSendPacket: + packet = JsonConvert.DeserializeObject(json); + break; + } + + return packet; + } + } +} \ No newline at end of file diff --git a/MafiaCommon/Packets/PacketType.cs b/MafiaCommon/Packets/PacketType.cs new file mode 100644 index 0000000..f549539 --- /dev/null +++ b/MafiaCommon/Packets/PacketType.cs @@ -0,0 +1,14 @@ +namespace MafiaCommon.Packets +{ + public enum PacketType + { + Connect=1, + Welcome=2, + Disconnect=3, + PlayerConnected=4, + PlayerDisconnected=5, + MessageReceivePacket=6, + MessageSendPacket=7, + ServerShutdown=99 + } +} \ No newline at end of file diff --git a/MafiaCommon/Packets/PlayerConnectedPacket.cs b/MafiaCommon/Packets/PlayerConnectedPacket.cs new file mode 100644 index 0000000..c22ebc9 --- /dev/null +++ b/MafiaCommon/Packets/PlayerConnectedPacket.cs @@ -0,0 +1,16 @@ +namespace MafiaCommon.Packets +{ + public class PlayerConnectedPacket : Packet + { + public readonly string Name; + public readonly int Players; + public readonly int MaxPlayers; + + public PlayerConnectedPacket(string name, int players, int maxPlayers) : base(PacketType.PlayerConnected) + { + Name = name; + Players = players; + MaxPlayers = maxPlayers; + } + } +} \ No newline at end of file diff --git a/MafiaCommon/Packets/PlayerDisconnectedPacket.cs b/MafiaCommon/Packets/PlayerDisconnectedPacket.cs new file mode 100644 index 0000000..e63cd0f --- /dev/null +++ b/MafiaCommon/Packets/PlayerDisconnectedPacket.cs @@ -0,0 +1,18 @@ +namespace MafiaCommon.Packets +{ + public class PlayerDisconnectedPacket : Packet + { + public readonly bool IsByError; + public readonly int Id; + public readonly int Players; + public readonly int MaxPlayers; + + public PlayerDisconnectedPacket(bool isByError, int id, int players, int maxPlayers) : base(PacketType.PlayerDisconnected) + { + IsByError = isByError; + Id = id; + Players = players; + MaxPlayers = maxPlayers; + } + } +} \ No newline at end of file diff --git a/MafiaCommon/Packets/ServerShutdownPacket.cs b/MafiaCommon/Packets/ServerShutdownPacket.cs new file mode 100644 index 0000000..c1bf388 --- /dev/null +++ b/MafiaCommon/Packets/ServerShutdownPacket.cs @@ -0,0 +1,14 @@ +using System; + +namespace MafiaCommon.Packets +{ + public class ServerShutdownPacket : Packet + { + public readonly String Reason; + + public ServerShutdownPacket(String reason) : base(PacketType.ServerShutdown) + { + Reason = reason; + } + } +} \ No newline at end of file diff --git a/MafiaCommon/Packets/WelcomePacket.cs b/MafiaCommon/Packets/WelcomePacket.cs new file mode 100644 index 0000000..ee69f39 --- /dev/null +++ b/MafiaCommon/Packets/WelcomePacket.cs @@ -0,0 +1,18 @@ +using System; + +namespace MafiaCommon.Packets +{ + public class WelcomePacket : Packet + { + public readonly String ServerName; + public readonly int Players; + public readonly int MaxPlayers; + + public WelcomePacket(String serverName, int players, int maxPlayers) : base(PacketType.Welcome) + { + ServerName = serverName; + Players = players; + MaxPlayers = maxPlayers; + } + } +} \ No newline at end of file diff --git a/MafiaGame.sln b/MafiaGame.sln new file mode 100644 index 0000000..977397e --- /dev/null +++ b/MafiaGame.sln @@ -0,0 +1,28 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MafiaGame", "MafiaGame\MafiaGame.csproj", "{5A612B5D-831A-420F-AAE2-C0CA0CB8ADB4}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MafiaServer", "MafiaServer\MafiaServer.csproj", "{89353158-42E7-44A3-81E9-F0BD9A00259A}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MafiaCommon", "MafiaCommon\MafiaCommon.csproj", "{F2F93699-D38E-4416-84C3-7455BAEEB5E0}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {5A612B5D-831A-420F-AAE2-C0CA0CB8ADB4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5A612B5D-831A-420F-AAE2-C0CA0CB8ADB4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5A612B5D-831A-420F-AAE2-C0CA0CB8ADB4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5A612B5D-831A-420F-AAE2-C0CA0CB8ADB4}.Release|Any CPU.Build.0 = Release|Any CPU + {89353158-42E7-44A3-81E9-F0BD9A00259A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {89353158-42E7-44A3-81E9-F0BD9A00259A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {89353158-42E7-44A3-81E9-F0BD9A00259A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {89353158-42E7-44A3-81E9-F0BD9A00259A}.Release|Any CPU.Build.0 = Release|Any CPU + {F2F93699-D38E-4416-84C3-7455BAEEB5E0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F2F93699-D38E-4416-84C3-7455BAEEB5E0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F2F93699-D38E-4416-84C3-7455BAEEB5E0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F2F93699-D38E-4416-84C3-7455BAEEB5E0}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal diff --git a/MafiaGame/App.xaml b/MafiaGame/App.xaml new file mode 100644 index 0000000..4aab632 --- /dev/null +++ b/MafiaGame/App.xaml @@ -0,0 +1,11 @@ + + + + + diff --git a/MafiaGame/App.xaml.cs b/MafiaGame/App.xaml.cs new file mode 100644 index 0000000..bbecb9f --- /dev/null +++ b/MafiaGame/App.xaml.cs @@ -0,0 +1,69 @@ +using System; +using System.Collections.Generic; +using System.Configuration; +using System.Data; +using System.Linq; +using System.Threading.Tasks; +using System.Windows; +using DiscordRPC; +using DiscordRPC.Logging; +using DiscordRPC.Message; + +namespace MafiaGame +{ + /// + /// Interaction logic for App.xaml + /// + public partial class App : Application + { + public App() + { + App.Instance = this; + } + + public static App Instance; + + private DiscordRpcClient _rpcClient; + + public ServerConnection Connection; + + public DiscordRpcClient GetRpcClient() + { + return _rpcClient; + } + + private void App_OnStartup(object sender, StartupEventArgs e) + { + _rpcClient = new DiscordRpcClient("800016130097152000", autoEvents: true); + _rpcClient.RegisterUriScheme(); + _rpcClient.Logger = new ConsoleLogger() { Level = LogLevel.Warning }; + _rpcClient.OnJoinRequested += RpcClientOnOnJoinRequested; + _rpcClient.OnJoin += RpcClientOnOnJoin; + _rpcClient.SetSubscription(EventType.Join | EventType.JoinRequest); + _rpcClient.Initialize(); + _rpcClient.SetPresence(new RichPresence() + { + State = "Запуск игры..." + }); + + Settings.Initialize(); + Settings.Save(); + } + + private void RpcClientOnOnJoin(object sender, JoinMessage args) + { + string secret = args.Secret; + Connection = new ServerConnection(secret.Replace("/join", "")); + } + + private void RpcClientOnOnJoinRequested(object sender, JoinRequestMessage args) + { + _rpcClient.Respond(args, true); + } + + private void App_OnExit(object sender, ExitEventArgs e) + { + _rpcClient.Dispose(); + } + } +} \ No newline at end of file diff --git a/MafiaGame/AssemblyInfo.cs b/MafiaGame/AssemblyInfo.cs new file mode 100644 index 0000000..4a05c7d --- /dev/null +++ b/MafiaGame/AssemblyInfo.cs @@ -0,0 +1,10 @@ +using System.Windows; + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] \ No newline at end of file diff --git a/MafiaGame/MafiaGame.csproj b/MafiaGame/MafiaGame.csproj new file mode 100644 index 0000000..a683ffa --- /dev/null +++ b/MafiaGame/MafiaGame.csproj @@ -0,0 +1,17 @@ + + + + WinExe + netcoreapp3.1 + true + + + + + + + + + + + \ No newline at end of file diff --git a/MafiaGame/MainConfig.cs b/MafiaGame/MainConfig.cs new file mode 100644 index 0000000..b60ddd6 --- /dev/null +++ b/MafiaGame/MainConfig.cs @@ -0,0 +1,7 @@ +namespace MafiaGame +{ + public class MainConfig + { + public string Nick = "the Player"; + } +} \ No newline at end of file diff --git a/MafiaGame/MainWindow.xaml b/MafiaGame/MainWindow.xaml new file mode 100644 index 0000000..b16bd9a --- /dev/null +++ b/MafiaGame/MainWindow.xaml @@ -0,0 +1,156 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/MafiaGame/MainWindow.xaml.cs b/MafiaGame/MainWindow.xaml.cs new file mode 100644 index 0000000..51800e5 --- /dev/null +++ b/MafiaGame/MainWindow.xaml.cs @@ -0,0 +1,147 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; +using DiscordRPC; +using MafiaCommon.Packets; + +namespace MafiaGame +{ + /// + /// Interaction logic for MainWindow.xaml + /// + public partial class MainWindow : Window + { + private static MainWindow _mainWindow; + + public static MainWindow Instance => _mainWindow; + + public MainWindow() + { + InitializeComponent(); + + _mainWindow = this; + + App.Instance.GetRpcClient().SetPresence(new RichPresence() + { + State = "В главном меню" + }); + } + + private void Exit_OnClick(object sender, RoutedEventArgs e) + { + App.Current.Shutdown(0); + } + + private void Play_OnClick(object sender, RoutedEventArgs e) + { + IpInputGUIBack.IsEnabled = true; + IpInputGUIConnect.IsEnabled = true; + IpBox.IsEnabled = true; + MainMenu.Visibility = Visibility.Hidden; + IpInput.Visibility = Visibility.Visible; + App.Instance.GetRpcClient().SetPresence(new RichPresence() + { + State = "Выбирает сервер" + }); + } + + private void ConnectToServer_OnClick(object sender, RoutedEventArgs e) + { + String ip = IpBox.Text; + App.Instance.GetRpcClient().SetPresence(new RichPresence() + { + State = "Присоединяется к серверу" + }); + IpInputGUIBack.IsEnabled = false; + IpInputGUIConnect.IsEnabled = false; + IpBox.IsEnabled = false; + Thread thread = new Thread(() => + { + App.Instance.Connection = new ServerConnection(ip); + }); + thread.Start(); + } + + private void Back_OnClick(object sender, RoutedEventArgs e) + { + IpInput.Visibility = Visibility.Hidden; + DisconnectScreen.Visibility = Visibility.Hidden; + MainMenu.Visibility = Visibility.Visible; + App.Instance.GetRpcClient().SetPresence(new RichPresence() + { + State = "В главном меню" + }); + } + + private void SettingsBack_OnClick(object sender, RoutedEventArgs e) + { + Settings.Save(); + SettingsGUI.Visibility = Visibility.Hidden; + MainMenu.Visibility = Visibility.Visible; + App.Instance.GetRpcClient().SetPresence(new RichPresence() + { + State = "В главном меню" + }); + } + + private void Settings_OnClick(object sender, RoutedEventArgs e) + { + MainMenu.Visibility = Visibility.Hidden; + SettingsGUI.Visibility = Visibility.Visible; + NickBox.Text = Settings.Config().Nick; + } + + private void NickBox_OnTextInput(object sender, TextChangedEventArgs e) + { + Settings.Config().Nick = NickBox.Text; + } + + public void ShowGameQueueScreen() + { + MainMenu.Visibility = Visibility.Hidden; + IpInput.Visibility = Visibility.Hidden; + SettingsGUI.Visibility = Visibility.Hidden; + DisconnectScreen.Visibility = Visibility.Hidden; + GameQueue.Visibility = Visibility.Visible; + } + + public void ShowDisconnectScreen(string reason) + { + ReasonText.Text = reason; + MainMenu.Visibility = Visibility.Hidden; + IpInput.Visibility = Visibility.Hidden; + SettingsGUI.Visibility = Visibility.Hidden; + GameQueue.Visibility = Visibility.Hidden; + DisconnectScreen.Visibility = Visibility.Visible; + } + + private void GameQueue_OnKeyUp(object sender, KeyEventArgs e) + { + if (e.Key == Key.Enter) + { + GameQueueChatSend_OnClick(null, null); + } + } + + private void GameQueueChatSend_OnClick(object sender, RoutedEventArgs e) + { + if (QueueChatInput.Text.Trim() != "") + { + App.Instance.Connection.SendMessage(ChatType.Queue, QueueChatInput.Text); + QueueChatInput.Clear(); + } + } + } +} \ No newline at end of file diff --git a/MafiaGame/ServerConnection.cs b/MafiaGame/ServerConnection.cs new file mode 100644 index 0000000..ddf4f6c --- /dev/null +++ b/MafiaGame/ServerConnection.cs @@ -0,0 +1,154 @@ +using System; +using System.Net.Sockets; +using System.Text; +using System.Threading; +using System.Windows.Controls; +using DiscordRPC; +using MafiaCommon.Packets; + +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))); + } + + private void serverListener() + { + while (!_breakFlag) + { + StringBuilder builder = new StringBuilder(); + int bytes = 0; + byte[] data = new byte[256]; + do + { + bytes = _socket.Receive(data); + builder.Append(Encoding.UTF8.GetString(data, 0, bytes)); + } + while (_socket.Available>0); + + Console.WriteLine(builder.ToString()); + + Packet packet = PacketConverter.toPacket(builder.ToString()); + 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 + }); + })); + 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; + })); + App.Instance.GetRpcClient().UpdatePartySize(((PlayerConnectedPacket) packet).Players); + break; + case PacketType.PlayerDisconnected: + App.Current.Dispatcher.Invoke((Action)(() => + { + MainWindow.Instance.QueueOnline.Text = ((PlayerDisconnectedPacket) packet).Players + "/" + + ((PlayerDisconnectedPacket) packet).MaxPlayers; + })); + App.Instance.GetRpcClient().UpdatePartySize(((PlayerDisconnectedPacket) packet).Players); + 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; + } + })); + break; + } + } + } + } +} \ No newline at end of file diff --git a/MafiaGame/Settings.cs b/MafiaGame/Settings.cs new file mode 100644 index 0000000..6b8c9dc --- /dev/null +++ b/MafiaGame/Settings.cs @@ -0,0 +1,35 @@ +using System; +using System.IO; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace MafiaGame +{ + public class Settings + { + private static MainConfig _config; + + public static MainConfig Config() + { + return _config; + } + + public static void Initialize() + { + try + { + _config = JsonConvert.DeserializeObject(File.ReadAllText("config.json")); + } + catch (FileNotFoundException e) + { + _config = new MainConfig(); + File.Create("config.json").Close(); + } + } + + public static void Save() + { + File.WriteAllText("config.json",JsonConvert.SerializeObject(_config,Formatting.Indented)); + } + } +} \ No newline at end of file diff --git a/MafiaServer/Events/OnDisconnectByErrorEvent.cs b/MafiaServer/Events/OnDisconnectByErrorEvent.cs new file mode 100644 index 0000000..4090454 --- /dev/null +++ b/MafiaServer/Events/OnDisconnectByErrorEvent.cs @@ -0,0 +1,4 @@ +namespace MafiaServer.Events +{ + public delegate void OnDisconnectByErrorEvent(PlayerSocketWorker player); +} \ No newline at end of file diff --git a/MafiaServer/Events/OnPlayerSendMessageEvent.cs b/MafiaServer/Events/OnPlayerSendMessageEvent.cs new file mode 100644 index 0000000..2797730 --- /dev/null +++ b/MafiaServer/Events/OnPlayerSendMessageEvent.cs @@ -0,0 +1,6 @@ +using MafiaCommon.Packets; + +namespace MafiaServer.Events +{ + public delegate void OnPlayerSendMessageEvent(PlayerSocketWorker sender, ChatType chatType, string text); +} \ No newline at end of file diff --git a/MafiaServer/Game.cs b/MafiaServer/Game.cs new file mode 100644 index 0000000..ccca371 --- /dev/null +++ b/MafiaServer/Game.cs @@ -0,0 +1,72 @@ +using System; +using System.Collections.Generic; +using MafiaCommon.Packets; + +namespace MafiaServer +{ + public class Game + { + private List _players = new List(); + private bool isStarted = false; + + public Game() + { + + } + + public void ConnectPlayer(PlayerSocketWorker player) + { + if (isStarted) + { + player.sendPacket(new DisconnectPacket("Game already started!")); + player.disconnect(); + } + else + { + foreach (PlayerSocketWorker othPlayer in _players) + { + othPlayer.sendPacket(new PlayerConnectedPacket(player.PlayerName,_players.Count+1,Settings.Config().MaxPlayers)); + } + _players.Add(player); + player.Id = _players.LastIndexOf(player); + player.OnDisconnectByErrorEvent += OnDisconnectByError; + player.OnPlayerSendMessageEvent += PlayerOnOnPlayerSendMessageEvent; + player.sendPacket(new WelcomePacket(Settings.Config().ServerName,_players.Count,Settings.Config().MaxPlayers)); + } + } + + public void Start() + { + if (_players.Count < 2) + { + Console.WriteLine("Not Enough Players"); + return; + } + } + + private void OnDisconnectByError(PlayerSocketWorker sender) + { + _players.Remove(sender); + foreach (PlayerSocketWorker player in _players) + { + player.sendPacket(new PlayerDisconnectedPacket(true,sender.Id,_players.Count,Settings.Config().MaxPlayers)); + } + } + + private void PlayerOnOnPlayerSendMessageEvent(PlayerSocketWorker sender, ChatType chatType, string text) + { + switch (chatType) + { + case ChatType.Queue: + if (!isStarted) + { + foreach (PlayerSocketWorker player in _players) + { + player.sendPacket(new MessageReceivePacket(ChatType.Queue,false,sender.PlayerName,text)); + } + } + break; + } + } + } +} \ No newline at end of file diff --git a/MafiaServer/MafiaServer.csproj b/MafiaServer/MafiaServer.csproj new file mode 100644 index 0000000..b756407 --- /dev/null +++ b/MafiaServer/MafiaServer.csproj @@ -0,0 +1,16 @@ + + + + Exe + netcoreapp3.1 + + + + + + + + + + + diff --git a/MafiaServer/MainConfig.cs b/MafiaServer/MainConfig.cs new file mode 100644 index 0000000..d995a1f --- /dev/null +++ b/MafiaServer/MainConfig.cs @@ -0,0 +1,11 @@ +using System; + +namespace MafiaServer +{ + public class MainConfig + { + public int Port = 25743; + public String ServerName = "Test server"; + public int MaxPlayers = 20; + } +} \ No newline at end of file diff --git a/MafiaServer/PlayerSocketWorker.cs b/MafiaServer/PlayerSocketWorker.cs new file mode 100644 index 0000000..feb83ae --- /dev/null +++ b/MafiaServer/PlayerSocketWorker.cs @@ -0,0 +1,83 @@ +using System; +using System.Net.Sockets; +using System.Text; +using MafiaCommon.Packets; +using MafiaServer.Events; + +namespace MafiaServer +{ + public class PlayerSocketWorker + { + private Socket _socket; + public readonly string PlayerName; + public event OnDisconnectByErrorEvent OnDisconnectByErrorEvent; + public event OnPlayerSendMessageEvent OnPlayerSendMessageEvent; + public int Id; + public PlayerSocketWorker(Socket socket) + { + _socket = socket; + StringBuilder builder = new StringBuilder(); + int bytes = 0; + byte[] data = new byte[256]; + do + { + bytes = _socket.Receive(data); + builder.Append(Encoding.UTF8.GetString(data, 0, bytes)); + } + while (_socket.Available>0); + + var packet = PacketConverter.toPacket(builder.ToString()); + if (packet.GetType() == typeof(ConnectPacket)) + { + PlayerName = ((ConnectPacket) packet).Name; + MafiaServer.Game.ConnectPlayer(this); + } + else + { + _socket.Close(); + } + } + + public void sendPacket(Packet packet) + { + _socket.Send(PacketConverter.toBytes(packet)); + } + + public void disconnect() + { + _socket.Close(); + } + + public void run() + { + while (_socket.Connected) + { + try + { + StringBuilder builder = new StringBuilder(); + int bytes = 0; + byte[] data = new byte[256]; + do + { + bytes = _socket.Receive(data); + builder.Append(Encoding.UTF8.GetString(data, 0, bytes)); + } while (_socket.Available > 0); + + Console.WriteLine(builder.ToString()); + + Packet packet = PacketConverter.toPacket(builder.ToString()); + switch (packet.PacketType) + { + case PacketType.MessageSendPacket: + OnPlayerSendMessageEvent.Invoke(this,((MessageSendPacket)packet).ChatType,((MessageSendPacket)packet).Text); + break; + } + } + catch (SocketException e) + { + OnDisconnectByErrorEvent.Invoke(this); + } + } + } + } +} \ No newline at end of file diff --git a/MafiaServer/Program.cs b/MafiaServer/Program.cs new file mode 100644 index 0000000..e945738 --- /dev/null +++ b/MafiaServer/Program.cs @@ -0,0 +1,35 @@ +using System; +using System.Net.Sockets; +using System.Threading; + +namespace MafiaServer +{ + class MafiaServer + { + private static Server server; + private static Boolean breakFlag = false; + public static Game Game; + + static void Main(string[] args) + { + Settings.Initialize(); + Settings.Save(); + Game = new Game(); + server = new Server(); + while (!breakFlag) + { + String input = Console.ReadLine(); + switch (input.Split(" ")[0].ToLower()) + { + case "stop": + server.stop("Manual stop"); + breakFlag = true; + break; + case "start": + Game.Start(); + break; + } + } + } + } +} \ No newline at end of file diff --git a/MafiaServer/Server.cs b/MafiaServer/Server.cs new file mode 100644 index 0000000..d9d8461 --- /dev/null +++ b/MafiaServer/Server.cs @@ -0,0 +1,60 @@ +using System; +using System.Collections.Generic; +using System.Net; +using System.Net.Sockets; +using System.Threading; +using MafiaCommon.Packets; +using Newtonsoft.Json; + +namespace MafiaServer +{ + public class Server + { + private Socket _socket; + private Thread _acceptor; + private List _clientSockets = new List(); + private List _clientThreads = new List(); + + public Server() + { + _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); + _socket.Bind(new IPEndPoint(IPAddress.Any, Settings.Config().Port)); + _socket.Listen(10); + + _acceptor = new Thread(new ThreadStart(acceptor)); + _acceptor.IsBackground = true; + _acceptor.Start(); + + Console.WriteLine("Server started!"); + } + + public void stop(String reason) + { + _acceptor.Interrupt(); + foreach (Thread thread in _clientThreads) + { + thread.Interrupt(); + } + foreach (Socket socket in _clientSockets) + { + if (socket.Connected) + { + socket.Send(PacketConverter.toBytes(new ServerShutdownPacket(reason))); + } + } + } + + private void acceptor() + { + while (true) + { + Socket playerSocket = _socket.Accept(); + PlayerSocketWorker playerSocketWorker = new PlayerSocketWorker(playerSocket); + Thread thread = new Thread(playerSocketWorker.run); + _clientSockets.Add(playerSocket); + _clientThreads.Add(thread); + thread.Start(); + } + } + } +} \ No newline at end of file diff --git a/MafiaServer/Settings.cs b/MafiaServer/Settings.cs new file mode 100644 index 0000000..f7074e5 --- /dev/null +++ b/MafiaServer/Settings.cs @@ -0,0 +1,35 @@ +using System; +using System.IO; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace MafiaServer +{ + public class Settings + { + private static MainConfig _config; + + public static MainConfig Config() + { + return _config; + } + + public static void Initialize() + { + try + { + _config = JsonConvert.DeserializeObject(File.ReadAllText("config.json")); + } + catch (FileNotFoundException e) + { + _config = new MainConfig(); + File.Create("config.json").Close(); + } + } + + public static void Save() + { + File.WriteAllText("config.json",JsonConvert.SerializeObject(_config,Formatting.Indented)); + } + } +} \ No newline at end of file