using System; using System.Collections.Generic; using System.Threading.Tasks; using Newtonsoft.Json; using UnityEngine; using UnityEngine.Events; using UnityEngine.Networking; using System.Net; using System.Net.Sockets; public class DBmanager : MonoBehaviour { public static string phpRoot = "http://38.242.232.13/upf/"; public static string username = null; private static float level = 0; private static int xp = 0; private static int coins = 0; private static int gems = 0; private static int metal = 0; private static int oxygen = 0; private static List expPassCollected = new List(); public static List buildingStates = new List(); public static UnityEvent OnStateChanged = new UnityEvent(); public static int Xp => xp; public static int Coins => coins; public static int Gems => gems; public static int Metal => metal; public static int Oxygen => oxygen; public static float Level => level; public static int LevelInt => Mathf.CeilToInt(level); public static List ExpPassCollected => expPassCollected; public static bool LoggedIn { get { return username != null; } } public static void LogOut() { username = null; } public static DateTime GetNetworkTime() { //default Windows time server const string ntpServer = "time.windows.com"; // NTP message size - 16 bytes of the digest (RFC 2030) var ntpData = new byte[48]; //Setting the Leap Indicator, Version Number and Mode values ntpData[0] = 0x1B; //LI = 0 (no warning), VN = 3 (IPv4 only), Mode = 3 (Client Mode) var addresses = Dns.GetHostEntry(ntpServer).AddressList; //The UDP port number assigned to NTP is 123 var ipEndPoint = new IPEndPoint(addresses[0], 123); //NTP uses UDP using (var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp)) { socket.Connect(ipEndPoint); //Stops code hang if NTP is blocked socket.ReceiveTimeout = 3000; socket.Send(ntpData); socket.Receive(ntpData); socket.Close(); } //Offset to get to the "Transmit Timestamp" field (time at which the reply //departed the server for the client, in 64-bit timestamp format." const byte serverReplyTime = 40; //Get the seconds part ulong intPart = BitConverter.ToUInt32(ntpData, serverReplyTime); //Get the seconds fraction ulong fractPart = BitConverter.ToUInt32(ntpData, serverReplyTime + 4); //Convert From big-endian to little-endian intPart = SwapEndianness(intPart); fractPart = SwapEndianness(fractPart); var milliseconds = (intPart * 1000) + ((fractPart * 1000) / 0x100000000L); //**UTC** time var networkDateTime = (new DateTime(1900, 1, 1, 0, 0, 0, DateTimeKind.Utc)).AddMilliseconds((long)milliseconds); return networkDateTime.ToLocalTime(); } static uint SwapEndianness(ulong x) { return (uint)(((x & 0x000000ff) << 24) + ((x & 0x0000ff00) << 8) + ((x & 0x00ff0000) >> 8) + ((x & 0xff000000) >> 24)); } public async static Task SetXp(int newValue, bool justOffline = false) { WWWForm form = new WWWForm(); form.AddField("name", username); form.AddField("xp", newValue); if (justOffline) { xp = newValue; } else { using (UnityWebRequest www = UnityWebRequest.Post(phpRoot + "set_xp.php", form)) { var operation = www.SendWebRequest(); while (!operation.isDone) { await Task.Yield(); } if (www.downloadHandler.text == "0") { xp = newValue; // Debug } else { Debug.Log("Response : " + www.downloadHandler.text); Debug.LogWarning("Failed to set xp to " + newValue); } } } // for(int i =0; i < xp / 100; i++){ // i // } level = (Mathf.Sqrt((float)Mathf.Clamp(xp,100,float.PositiveInfinity) / 100f)); if(level == LevelInt){ level-=0.1f; } Debug.Log("Level : " + (float)xp / 100f + " : " + level + " : " + LevelInt); GameManagerInstance.gameManager.RefreshData(); OnStateChanged.Invoke(); } public async static Task SetCoins(int newValue, bool justOffline = false) { WWWForm form = new WWWForm(); form.AddField("name", username); form.AddField("coins", newValue); if (justOffline) { coins = newValue; return; } using (UnityWebRequest www = UnityWebRequest.Post(phpRoot + "set_coins.php", form)) { var operation = www.SendWebRequest(); while (!operation.isDone) { await Task.Yield(); } if (www.downloadHandler.text == "0") { coins = newValue; } else { Debug.Log("Response : " + www.downloadHandler.text); Debug.LogWarning("Failed to set coins to " + newValue); } } GameManagerInstance.gameManager.RefreshData(); OnStateChanged.Invoke(); } public async static void SetGems(int newValue, bool justOffline = false) { WWWForm form = new WWWForm(); form.AddField("name", username); form.AddField("gems", newValue); if (justOffline) { gems = newValue; return; } using (UnityWebRequest www = UnityWebRequest.Post(phpRoot + "set_gems.php", form)) { var operation = www.SendWebRequest(); while (!operation.isDone) { await Task.Yield(); } if (www.downloadHandler.text == "0") { gems = newValue; } else { Debug.Log("Response : " + www.downloadHandler.text); Debug.LogWarning("Failed to set gems to " + newValue); } } GameManagerInstance.gameManager.RefreshData(); OnStateChanged.Invoke(); } public async static void SetMetal(int newValue, bool justOffline = false) { WWWForm form = new WWWForm(); form.AddField("name", username); form.AddField("metal", newValue); if (justOffline) { metal = newValue; return; } using (UnityWebRequest www = UnityWebRequest.Post(phpRoot + "set_metal.php", form)) { var operation = www.SendWebRequest(); while (!operation.isDone) { await Task.Yield(); } if (www.downloadHandler.text == "0") { metal = newValue; } else { Debug.Log("Response : " + www.downloadHandler.text); Debug.LogWarning("Failed to set metal to " + newValue); } } GameManagerInstance.gameManager.RefreshData(); OnStateChanged.Invoke(); } public async static void SetOxygen(int newValue, bool justOffline = false) { WWWForm form = new WWWForm(); form.AddField("name", username); form.AddField("oxygen", newValue); if (justOffline) { oxygen = newValue; return; } using (UnityWebRequest www = UnityWebRequest.Post(phpRoot + "set_oxygen.php", form)) { var operation = www.SendWebRequest(); while (!operation.isDone) { await Task.Yield(); } if (www.downloadHandler.text == "0") { oxygen = newValue; } else { Debug.Log("Response : " + www.downloadHandler.text); Debug.LogWarning("Failed to set oxygen to " + newValue); } } GameManagerInstance.gameManager.RefreshData(); OnStateChanged.Invoke(); } public static void SetExpPassCollected(string rawData, bool justOffline = false) { string[] data = rawData.Split(','); expPassCollected = new List(); foreach(string item in data){ try{ int itemVal = int.Parse(item); expPassCollected.Add(itemVal); }catch { } } GameManagerInstance.gameManager.RefreshData(); OnStateChanged.Invoke(); } public async static void AddCollectedExpPass(int newPassLevel) { expPassCollected.Add(newPassLevel); string output = ""; for(int i =0;i < expPassCollected.Count;i++){ output += expPassCollected[i].ToString(); if(i < expPassCollected.Count -1){ output += ","; } } WWWForm form = new WWWForm(); form.AddField("name", username); form.AddField("expPass", output); using (UnityWebRequest www = UnityWebRequest.Post(phpRoot + "set_expPassCollected.php", form)) { var operation = www.SendWebRequest(); while (!operation.isDone) { await Task.Yield(); } if (www.downloadHandler.text == "0") { Debug.Log("Success updating ExpPassCollected"); } else { Debug.Log("Response : " + www.downloadHandler.text); Debug.LogWarning("Failed to set exp_pass_collected to " + output); } } GameManagerInstance.gameManager.RefreshData(); OnStateChanged.Invoke(); } public static bool GetBuildingStates(string rawData) { bool success = false; //try{ buildingStates = JsonConvert.DeserializeObject>(rawData); Debug.Log("Updating buildings data, isNull: " + (buildingStates == null).ToString()); if (buildingStates == null) { buildingStates = new List(); } success = true; // }catch(Exception e){ // Debug.LogError(e.Message+'\n' + e.StackTrace); // // Debug.LogError("Error updating buildings from server, Response:" + rawData); // success=false; // } OnStateChanged.Invoke(); return success; } public async static Task AddBuilding(BuildingData buildingData) { foreach (BuildingState buildingState in buildingStates) { if (buildingState.id == buildingData.buildingName) { Debug.LogError("Building already exists. Cannot add " + buildingState.id); return; } } Debug.Log("adding new building " + buildingData.buildingName); buildingStates.Add(new BuildingState(buildingData.buildingName, 0, Vector3.zero, GetNetworkTime())); Debug.Log("Added new building " + buildingData.buildingName); await UpdateBuildingsToServer(); OnStateChanged.Invoke(); SetXp(xp + buildingData.levels[0].xpGain); } public async static Task UpgradeBuilding(string id, int newLevel) { for (int i = 0; i < buildingStates.Count; i++) { if (buildingStates[i].id == id) { buildingStates[i].level = newLevel; Debug.Log("Upgrading " + id + " to " + newLevel); break; } } await UpdateBuildingsToServer(); OnStateChanged.Invoke(); } public async static Task CollectBuilding(string id) { for (int i = 0; i < buildingStates.Count; i++) { if (buildingStates[i].id == id) { buildingStates[i].lastCollectedTimestamp = GetNetworkTime(); Debug.Log("Setting " + id + " last collected to " + buildingStates[i].lastCollectedTimestamp); break; } } await UpdateBuildingsToServer(); OnStateChanged.Invoke(); } public async static Task RelocateBuilding(string id, Vector3 newPosition) { for (int i = 0; i < buildingStates.Count; i++) { if (buildingStates[i].id == id) { buildingStates[i].position = newPosition; Debug.Log("Relocating " + id + " to " + newPosition); // break; } } Debug.Log("Going to update to server" + JsonConvert.SerializeObject(buildingStates)); await UpdateBuildingsToServer(); OnStateChanged.Invoke(); } public async static Task UpdateBuildingsToServer() { string buildingsJson = JsonConvert.SerializeObject(buildingStates); Debug.Log(buildingsJson); WWWForm form = new WWWForm(); form.AddField("name", username); form.AddField("buildings", buildingsJson); using (UnityWebRequest www = UnityWebRequest.Post(phpRoot + "set_buildings.php", form)) { var operation = www.SendWebRequest(); while (!operation.isDone) { await Task.Yield(); } if (www.downloadHandler.text == "0") { } else { Debug.Log("Response : " + www.downloadHandler.text); Debug.LogWarning("Failed to set buildings to " + buildingsJson); } } } }