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 int coins = 0; private static int gems = 0; public static List buildingStates = new List(); public static UnityEvent OnStateChanged = new UnityEvent(); public static int Coins => coins; public static int Gems => gems; 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(); } // stackoverflow.com/a/3294698/162671 static uint SwapEndianness(ulong x) { return (uint) (((x & 0x000000ff) << 24) + ((x & 0x0000ff00) << 8) + ((x & 0x00ff0000) >> 8) + ((x & 0xff000000) >> 24)); } 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(); } 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(); } public static void GetBuildingStates(string rawData){ try{ buildingStates = JsonConvert.DeserializeObject>(rawData); Debug.Log("Updating buildings data, isNull: " + (buildingStates==null).ToString()); if(buildingStates==null){ buildingStates = new List(); } }catch(Exception e){ Debug.LogError(e.Message); Debug.LogError("Error updating buildings from server, Response:" + rawData); } OnStateChanged.Invoke(); } 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; } } buildingStates.Add(new BuildingState(buildingData.buildingName, 0,Vector3.zero)); Debug.Log("Added new building "+ buildingData.buildingName); await UpdateBuildingsToServer(); OnStateChanged.Invoke(); } 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 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); } } } }