using System; using System.Collections.Generic; using System.Drawing; using System.Linq; using System.Net; using System.Net.NetworkInformation; using System.Net.Sockets; using System.Text; using System.Text.Json; using System.Threading; using System.Windows.Forms; namespace GUIApp { public class ServerClass { public string IP; int PORT; string PASSWORD; bool[] SETTINGS; string SERVERNAME; string enemySyncList; public string NetworkInterfaceName; bool serverOpen = false; int CLEARMINUTES = 5; public int SerializationRate { get; set; } public int TargetFPS { get; set; } public int SleepMultiplier { get; set; } public int isLocalTest { get; set; } public int ischaracterSpawn { get; set; } Form1 mainWindow; Socket listen; Thread listenThread; Thread EnemyClearThread; List clientThreads = new List(); public List> serverData = new List>(); public List> extraData = new List>(); public Dictionary serverEnemyData = new Dictionary(); List> enemyDataQueue = new List>(); List AccessingEnemyData = new List() { false, false, false, false }; List> Updated = new List>(); bool ClearingData = false; DateTime lastClear; public List serverQuestData = new List(); List> questDataQueue = new List>(); public Dictionary> animationData = new Dictionary>(); public ServerClass(Form1 mW) { if(mW != null) this.mainWindow = mW; this.animationData = readXML.readAnimationFile(); for (int i = 0; i < 4; i++) { Dictionary player = new Dictionary(); player.Add("Con", false); serverData.Add(player); Dictionary dataQueue = new Dictionary(); enemyDataQueue.Add(dataQueue); List qDataQueue = new List(); questDataQueue.Add(qDataQueue); Dictionary extra = new Dictionary(); extraData.Add(extra); List updated = new List() { false, false, false, false }; Updated.Add(updated); } this.SerializationRate = 60; this.TargetFPS = 60; this.SleepMultiplier = 1; this.isLocalTest = 0; this.ischaracterSpawn = 1; lastClear = DateTime.Now; } public bool serverStart(string serverName, string IP, int PORT, string PASSWORD, bool[] SETTINGS, string ESList) { this.SERVERNAME = serverName; this.PORT = PORT; this.PASSWORD = PASSWORD; this.SETTINGS = SETTINGS; this.enemySyncList = ESList; Dictionary ipAddresses = new Dictionary(); if (IP == "localhost") { var host = Dns.GetHostEntry(Dns.GetHostName()); foreach (NetworkInterface item in NetworkInterface.GetAllNetworkInterfaces()) { if (item.OperationalStatus == OperationalStatus.Up) { foreach (UnicastIPAddressInformation ip in item.GetIPProperties().UnicastAddresses) { if (ip.Address.AddressFamily == AddressFamily.InterNetwork && host.AddressList.Contains(ip.Address)) { ipAddresses.Add(item.Name.ToString(), ip.Address.ToString()); } } } } }else { ipAddresses.Add("custom IP", IP); } foreach(var key in ipAddresses.Keys) { try { listen = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); this.IP = ipAddresses[key].ToString(); IPEndPoint connect = new IPEndPoint(IPAddress.Parse(this.IP), PORT); listen.Bind(connect); this.NetworkInterfaceName = key; if(mainWindow != null) { mainWindow.changeServerStatus("Server opened on " + this.NetworkInterfaceName + "."); } else { Console.WriteLine("Server opened on " + this.NetworkInterfaceName + "."); } serverOpen = true; return true; }catch { continue; } } return false; } public void stopServer() { serverOpen = false; listen.Close(); if(listenThread != null) listenThread.Abort(); foreach(Thread clientThread in clientThreads) { clientThread.Abort(); } } public void startListen() { listenThread = new Thread(serverListen); listenThread.IsBackground = true; listenThread.Start(); } public void serverListen() { while(true) { Socket connection; listen.Listen(4); connection = listen.Accept(); var thread2 = new Thread(() => handleClient(connection)); thread2.Start(); clientThreads.Add(thread2); } } public void handleClient(Socket connection) { int SIZE = 2048; byte[] info = new byte[SIZE]; string data = ""; int array_size = 0; bool clientConnected = true; int playerNumber = 0; string temporaryMessage = ""; while (serverOpen && clientConnected) { try { array_size = connection.Receive(info, 0, info.Length, 0); Array.Resize(ref info, array_size); data = Encoding.UTF8.GetString(info); if(data.Length < 18) { connection.Send(Encoding.UTF8.GetBytes("FW-01")); continue; } int data_size; string command; if(!Int32.TryParse(data.Substring(0,5), out data_size)) { connection.Send(Encoding.UTF8.GetBytes("FW-01")); continue; }else { if (data.Length < data_size) { connection.Send(Encoding.UTF8.GetBytes("FW-01")); continue; } command = data.Substring(5, 11); List possibleCommands = new List { "!ping", "!host", "!connect", "!update", "!disconnect" }; bool correct = false; for (int i = 0; i < possibleCommands.Count; i++) { if (command.Contains(possibleCommands[i])) { correct = true; } } if(!correct) { connection.Send(Encoding.UTF8.GetBytes("FW-01")); continue; } } Dictionary playerExtraData = new Dictionary(); //playerExtraData.Add("Animation", animationName); //playerExtraData.Add("Hash", animationHash); playerExtraData.Add("Message", data); string message; try { message = data.Substring(17, data_size); } catch (Exception e) { connection.Send(Encoding.UTF8.GetBytes("FW-01")); continue; } temporaryMessage = message; if (command.Contains("!ping")) { connection.Send(Encoding.UTF8.GetBytes(SERVERNAME + ";" + mainWindow.serverInterfaceForm.serverDescription)); connection.Close(); clientConnected = false; }else if(command.Contains("!host")) { playerNumber = 0; connection.Send(Encoding.UTF8.GetBytes("Connection successful")); } else if (command.Contains("!connect")) { int counter = 0; foreach (Dictionary item in serverData) { if (!(bool)item["Con"]) { playerNumber = counter; break; } counter++; } Dictionary sendData = new Dictionary(); if (playerNumber == -1) { sendData["Response"] = 2; connection.Send(Encoding.UTF8.GetBytes(JsonSerializer.Serialize(sendData))); connection.Close(); clientConnected = false; break; } string[] splittedMessage = message.Split(';'); if(splittedMessage[1] == this.PASSWORD || this.PASSWORD == "") { serverData[playerNumber]["Name"] = splittedMessage[0]; //serverData[playerNumber]["Con"] = true; }else { sendData["Response"] = 3; connection.Send(Encoding.UTF8.GetBytes(JsonSerializer.Serialize(sendData))); connection.Close(); clientConnected = false; break; } int enemySync = SETTINGS[0] ? 1 : 0; int glyphSync = SETTINGS[1] ? 1 : 0; sendData["Response"] = 1; sendData["playerNumber"] = playerNumber; sendData["isEnemySync"] = SETTINGS[0]; sendData["isGlyphSync"] = SETTINGS[1]; sendData["isQuestSync"] = SETTINGS[2]; sendData["enemySyncList"] = enemySyncList; sendData["serverName"] = SERVERNAME; foreach(KeyValuePair kvp in serverEnemyData) { enemyDataQueue[playerNumber].Add(kvp.Key, kvp.Value); } foreach(string item in serverQuestData) { questDataQueue[playerNumber].Add(item); } connection.Send(Encoding.UTF8.GetBytes(JsonSerializer.Serialize(sendData))); } else if (command.Contains("!update")) { Dictionary playerData = new Dictionary(); playerData.Add("Con", true); playerData.Add("Name", serverData[playerNumber]["Name"]); if(message.Contains("Initial connection")) { serverData[playerNumber] = playerData; connection.Send(Encoding.UTF8.GetBytes(JsonSerializer.Serialize("Added to server"))); continue; } Dictionary svDict = JsonSerializer.Deserialize>(message); // Player data Dictionary playerDataDict = svDict["PD"].Deserialize>(); string animationName = ""; string animationHash = ""; foreach(KeyValuePair pair in playerDataDict) { if(pair.Key == "A") { int[] animData = readAnimation(pair.Value.GetInt32()); playerData.Add("Schd", animData[0]); playerData.Add("Anim", animData[1]); if (animationData.ContainsKey(pair.Value.GetInt32().ToString())) { animationName = animationData[pair.Value.GetInt32().ToString()]["Name"]; animationHash = pair.Value.GetInt32().ToString(); playerExtraData.Add("animationName", animationName); playerExtraData.Add("animationHash", animationHash); } } else { if (pair.Value.ValueKind == JsonValueKind.Object) { if(pair.Key != "E") { playerData.Add(pair.Key, playerDataReadMap(playerDataDict[pair.Key].Deserialize>())); }else { playerData.Add(pair.Key, playerDataReadEq(playerDataDict[pair.Key].Deserialize>(), playerNumber)); } } else { if (pair.Value.ValueKind == JsonValueKind.Number) { float value = (float)Math.Round(pair.Value.GetDouble(), 4); if (value % 1 == 0) { playerData.Add(pair.Key, Convert.ToInt32(value)); } else { playerData.Add(pair.Key, value); } } else { playerData.Add(pair.Key, pair.Value.GetString()); } } } } serverData[playerNumber] = playerData; // Enemy data if (playerNumber == 0) { double currentTime = DateTime.Now.Subtract(lastClear).TotalMinutes; if (DateTime.Now.Subtract(lastClear).TotalMinutes > CLEARMINUTES) { ClearingData = true; while (AccessingEnemyData[0] || AccessingEnemyData[1] || AccessingEnemyData[2] || AccessingEnemyData[3]) { } serverEnemyData.Clear(); ClearingData = false; lastClear = DateTime.Now; } } if (!ClearingData) { AccessingEnemyData[playerNumber] = true; Dictionary enemyData = svDict["ED"].Deserialize>()["H"].Deserialize>(); foreach (KeyValuePair kvp in enemyData) { if (serverEnemyData.ContainsKey(kvp.Key)) { if (serverEnemyData[kvp.Key] > kvp.Value.GetInt32()) { serverEnemyData[kvp.Key] = kvp.Value.GetInt32(); for (int i = 0; i < 4; i++) { if ((bool)serverData[i]["Con"]) { if (enemyDataQueue[i].ContainsKey(kvp.Key)) { enemyDataQueue[i][kvp.Key] = kvp.Value.GetInt32(); } else { enemyDataQueue[i].Add(kvp.Key, kvp.Value.GetInt32()); } } } } } else { serverEnemyData[kvp.Key] = kvp.Value.GetInt32(); for (int i = 0; i < 4; i++) { if ((bool)serverData[i]["Con"]) { enemyDataQueue[i].Add(kvp.Key, kvp.Value.GetInt32()); } } } } AccessingEnemyData[playerNumber] = false; } // Quest data JsonElement quests = svDict["QD"].Deserialize>()["C"]; for(int i = 0; i < quests.GetArrayLength(); i++) { if(!serverQuestData.Contains(quests[i].GetString())) { serverQuestData.Add(quests[i].GetString()); for(int j = 0; j < 4; j++) { if((bool)serverData[j]["Con"]) { questDataQueue[j].Add(quests[i].GetString()); } } } } List playerQuestQueue = new List(); for(int i = 0; i < 100; i++) { if(questDataQueue[playerNumber].Count > 0) { playerQuestQueue.Add(questDataQueue[playerNumber][0]); questDataQueue[playerNumber].RemoveAt(0); } } for(int i = 0; i < 4; i++) { Updated[i][playerNumber] = true; } Dictionary sendData = new Dictionary(); //serverDataAnim = new List>(serverData); //serverDataAnim[playerNumber]["Animation"] = animationName; //serverDataAnim[playerNumber]["Hash"] = animationHash; Dictionary NetworkData = new Dictionary(); List UpdatedData = new List(); for (int i = 0; i < 4; i++) { UpdatedData.Add(Updated[playerNumber][i] ? 1 : 0); Updated[playerNumber][i] = false; } NetworkData["SR"] = this.SerializationRate; NetworkData["TFPS"] = this.TargetFPS; NetworkData["SM"] = this.SleepMultiplier; NetworkData["LT"] = this.isLocalTest; NetworkData["CS"] = this.ischaracterSpawn; extraData[playerNumber] = playerExtraData; sendData.Add("PD", serverData); sendData.Add("ED", enemyDataQueue[playerNumber]); sendData.Add("QD", playerQuestQueue); sendData.Add("ND", NetworkData); sendData.Add("UD", UpdatedData); connection.Send(Encoding.UTF8.GetBytes(JsonSerializer.Serialize(sendData))); enemyDataQueue[playerNumber].Clear(); } else if(command.Contains("!disconnect")) { connection.Close(); clientConnected = false; serverData[playerNumber]["Con"] = false; } } catch (Exception e) { if(mainWindow != null) { mainWindow.serverInterfaceForm.AppendLog(e.ToString(), Color.Black); } else { Console.WriteLine(e.ToString()); } connection.Close(); clientConnected = false; serverData[playerNumber]["Name"] = ""; serverData[playerNumber]["Con"] = false; enemyDataQueue[playerNumber].Clear(); questDataQueue[playerNumber].Clear(); } } Thread.CurrentThread.Join(); } private List playerDataReadMap(Dictionary data) { //object[] result = new object[3]; List result = new List(); foreach(KeyValuePair kvp in data) { if (kvp.Value.ValueKind == JsonValueKind.Number) { float value = (float)Math.Round(kvp.Value.GetDouble(), 4); if (value % 1 == 0) { result.Add(Convert.ToInt32(value)); } else { result.Add(value); } } else if (kvp.Value.ValueKind == JsonValueKind.String) { result.Add(kvp.Value.GetString()); } } return result; } private Dictionary playerDataReadEq(Dictionary data, int playerNumber) { //object[] result = new object[3]; Dictionary result = new Dictionary(); int i = 0; foreach (KeyValuePair kvp in data) { //if (kvp.Value.ValueKind == JsonValueKind.Number) //{ // float value = (float)Math.Round(kvp.Value.GetDouble(), 4); // if (value % 1 == 0) // { // result.Add(Convert.ToInt32(value)); // } // else // { // result.Add(value); // } //} //else if (kvp.Value.ValueKind == JsonValueKind.String) //{ // result.Add(kvp.Value.GetString()); //} if(kvp.Value.ToString() != ".") { result[kvp.Key] = kvp.Value.ToString(); }else { Dictionary serverEqData = (Dictionary)serverData[playerNumber]["E"]; result[kvp.Key] = serverEqData[kvp.Key]; } //i++; } return result; } private int[] readAnimation(int animationHash) { string animationHashMsg = animationHash.ToString(); int[] result = { 0, 0 }; if (animationData.ContainsKey(animationHashMsg)) { result[0] = Convert.ToInt32(animationData[animationHashMsg]["Schedule"]); result[1] = Convert.ToInt32(animationData[animationHashMsg]["Animation"]); } return result; } } }