UPF/Assets/Game/Scripts/DBmanager.cs

287 lines
9.7 KiB
C#

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;
private static int metal = 0;
private static int oxygen = 0;
public static List<BuildingState> buildingStates = new List<BuildingState>();
public static UnityEvent OnStateChanged = new UnityEvent();
public static int Coins => coins;
public static int Gems => gems;
public static int Metal => metal;
public static int Oxygen => oxygen;
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 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 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();
}
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();
}
public static bool GetBuildingStates(string rawData){
bool success = false;
try{
buildingStates = JsonConvert.DeserializeObject<List<BuildingState>>(rawData);
Debug.Log("Updating buildings data, isNull: " + (buildingStates==null).ToString());
if(buildingStates==null){
buildingStates = new List<BuildingState>();
}
success=true;
}catch(Exception e){
Debug.LogError(e.Message);
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;
}
}
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 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);
}
}
}
}