public static void UpdateUserDataMeta()
        {
            if (userDataMeta == null)
            {
                userDataMeta = new UserDataMeta();
            }

            if (userDataMeta.deviceModel == null)
            {
                userDataMeta.deviceModel = "Unity Editor";
            }

            if (userDataMeta.timezoneOffset == 0)
            {
                userDataMeta.timezoneOffset = (int)(DateTime.UtcNow - DateTime.Now).TotalMinutes;
            }

            if (userDataMeta.appVersion == null)
            {
                userDataMeta.appVersion = Application.version;
            }

            userDataMeta.clientTime = DateTime.Now.Millisecond;
        }
        public static void ProcessMergeConflict(WalletData receivedWallet, InventoryData receivedInventory, string receivedGameState, List <UserDataVersion> receivedUserDataVersions, UserDataMeta receivedMetaData)
        {
            JSONObject localData  = new JSONObject();
            JSONObject remoteData = new JSONObject();

            WalletData    localWallet           = SpilUnityEditorImplementation.pData.Wallet;
            InventoryData localInventory        = SpilUnityEditorImplementation.pData.Inventory;
            string        localPrivateGameState = GameStateManager.PrivateGameStateData;
            string        localPublicGameState  = GameStateManager.PublicGameStateData;
            UserDataMeta  localDataMeta         = userDataMeta;

            //Local
            JSONObject localPlayerData = new JSONObject();

            JSONObject walletJSON = new JSONObject(JsonHelper.getJSONFromObject(localWallet));

            localPlayerData.AddField("wallet", walletJSON);

            JSONObject inventoryJSON = new JSONObject(JsonHelper.getJSONFromObject(localInventory));

            localPlayerData.AddField("inventory", inventoryJSON);

            localData.AddField("playerData", localPlayerData);

            JSONObject privateGameStateJSON = new JSONObject();

            privateGameStateJSON.AddField("access", "private");
            privateGameStateJSON.AddField("data", localPrivateGameState);

            JSONObject publicGameStateJSON = null;

            if (localPublicGameState != null)
            {
                publicGameStateJSON = new JSONObject();
                publicGameStateJSON.AddField("access", "public");
                publicGameStateJSON.AddField("data", localPublicGameState);
            }

            JSONObject localGameStateArray = new JSONObject(JSONObject.Type.ARRAY);

            localGameStateArray.Add(privateGameStateJSON);
            if (publicGameStateJSON != null)
            {
                localGameStateArray.Add(publicGameStateJSON);
            }

            JSONObject localGameState = new JSONObject();

            localGameState.AddField("gameStates", localGameStateArray);

            localData.AddField("gameState", localGameState);

            localData.AddField("metaData", new JSONObject(JsonHelper.getJSONFromObject(localDataMeta)));

            //Remote
            JSONObject remotePlayerData = new JSONObject();

            for (int i = 0; i < receivedWallet.currencies.Count; i++)
            {
                for (int j = 0; j < SpilUnityEditorImplementation.gData.currencies.Count; j++)
                {
                    if (receivedWallet.currencies[i].id == SpilUnityEditorImplementation.gData.currencies[j].id)
                    {
                        receivedWallet.currencies[i].name               = SpilUnityEditorImplementation.gData.currencies[j].name;
                        receivedWallet.currencies[i].type               = SpilUnityEditorImplementation.gData.currencies[j].type;
                        receivedWallet.currencies[i].displayName        = SpilUnityEditorImplementation.gData.currencies[j].displayName;
                        receivedWallet.currencies[i].displayDescription = SpilUnityEditorImplementation.gData.currencies[j].displayDescription;
                        receivedWallet.currencies[i].imageUrl           = SpilUnityEditorImplementation.gData.currencies[j].imageUrl;
                        receivedWallet.currencies[i].initialValue       = SpilUnityEditorImplementation.gData.currencies[j].initialValue;
                    }
                }
            }

            remotePlayerData.AddField("wallet", new JSONObject(JsonHelper.getJSONFromObject(receivedWallet)));

            for (int i = 0; i < receivedInventory.items.Count; i++)
            {
                for (int j = 0; j < SpilUnityEditorImplementation.gData.items.Count; j++)
                {
                    if (receivedInventory.items[i].id == SpilUnityEditorImplementation.gData.items[j].id)
                    {
                        receivedInventory.items[i].name               = SpilUnityEditorImplementation.gData.items[j].name;
                        receivedInventory.items[i].type               = SpilUnityEditorImplementation.gData.items[j].type;
                        receivedInventory.items[i].displayName        = SpilUnityEditorImplementation.gData.items[j].displayName;
                        receivedInventory.items[i].displayDescription = SpilUnityEditorImplementation.gData.items[j].displayDescription;
                        receivedInventory.items[i].imageUrl           = SpilUnityEditorImplementation.gData.items[j].imageUrl;
                        receivedInventory.items[i].initialValue       = SpilUnityEditorImplementation.gData.items[j].initialValue;
                        receivedInventory.items[i].isGacha            = SpilUnityEditorImplementation.gData.items[j].isGacha;
                        receivedInventory.items[i].content            = SpilUnityEditorImplementation.gData.items[j].content;
                    }
                }
            }

            remotePlayerData.AddField("inventory", new JSONObject(JsonHelper.getJSONFromObject(receivedInventory)));

            remoteData.AddField("playerData", remotePlayerData);

            remoteData.AddField("gameState", new JSONObject(receivedGameState));

            remoteData.AddField("metaData", new JSONObject(JsonHelper.getJSONFromObject(receivedMetaData)));

            remoteUserDataVersions = receivedUserDataVersions;

            JSONObject mergeData = new JSONObject();

            mergeData.AddField("localData", localData);
            mergeData.AddField("remoteData", remoteData);

            SpilUnityImplementationBase.fireUserDataMergeConflict(mergeData.Print());
        }
        public static void ProcessRequestUserData(WalletData receivedWallet, InventoryData receivedInventory, bool externalChange, string gameStateData, List <UserDataVersion> receivedUserDataVersions, UserDataMeta receivedUserDataMeta)
        {
            SpilUnityEditorImplementation.pData.CalculatePlayerDataResponse(receivedWallet, receivedInventory, true);
            GameStateManager.ProcessMyGameStateResponse(new JSONObject(gameStateData));

            if (receivedUserDataVersions != null)
            {
                userDataVersions = receivedUserDataVersions;
            }

            UpdateUserDataMeta();
            if (receivedUserDataMeta != null)
            {
                userDataMeta.serverTime = receivedUserDataMeta.serverTime;
            }

            SpilUnityImplementationBase.fireUserDataAvailable();
        }
        public static void ProcessUserDataResponse(ResponseEvent responseEvent)
        {
            WalletData             receivedWallet    = null;
            InventoryData          receivedInventory = null;
            string                 gameStateData     = null;
            List <UserDataVersion> userDataVersions  = null;
            UserDataMeta           userDataMeta      = null;
            bool externalChange = false;

            if (responseEvent.data.HasField("playerData"))
            {
                JSONObject playerDataJSON = responseEvent.data.GetField("playerData");
                if (playerDataJSON.HasField("wallet"))
                {
                    JSONObject walletJSON = playerDataJSON.GetField("wallet");

                    receivedWallet = new WalletData();

                    if (walletJSON.HasField("currencies"))
                    {
                        receivedWallet.currencies = new List <PlayerCurrencyData>();

                        JSONObject currenciesJSON = walletJSON.GetField("currencies");

                        for (int i = 0; i < currenciesJSON.Count; i++)
                        {
                            PlayerCurrencyData currency = new PlayerCurrencyData();

                            currency.id             = (int)currenciesJSON.list[i].GetField("id").n;
                            currency.currentBalance = (int)currenciesJSON.list[i].GetField("currentBalance").n;
                            currency.delta          = (int)currenciesJSON.list[i].GetField("delta").n;

                            receivedWallet.currencies.Add(currency);
                        }
                    }

                    receivedWallet.offset = (long)walletJSON.GetField("offset").n;
                    receivedWallet.logic  = walletJSON.GetField("logic").str;
                }

                if (playerDataJSON.HasField("inventory"))
                {
                    JSONObject inventoryJSON = playerDataJSON.GetField("inventory");

                    receivedInventory = new InventoryData();

                    if (inventoryJSON.HasField("items"))
                    {
                        receivedInventory.items = new List <PlayerItemData>();

                        JSONObject itemsJSON = inventoryJSON.GetField("items");

                        for (int i = 0; i < itemsJSON.Count; i++)
                        {
                            PlayerItemData item = new PlayerItemData();

                            item.id     = (int)itemsJSON.list[i].GetField("id").n;
                            item.amount = (int)itemsJSON.list[i].GetField("amount").n;
                            item.delta  = (int)itemsJSON.list[i].GetField("delta").n;

                            receivedInventory.items.Add(item);
                        }
                    }

                    receivedInventory.offset = (long)inventoryJSON.GetField("offset").n;
                    receivedInventory.logic  = inventoryJSON.GetField("logic").str;
                }
            }

            if (responseEvent.data.HasField("gameState"))
            {
                gameStateData = responseEvent.data.GetField("gameState").Print();
            }

            if (responseEvent.data.HasField("externalChange"))
            {
                externalChange = responseEvent.data.GetField("externalChange").b;
            }

            if (responseEvent.data.HasField("deviceVersions"))
            {
                JSONObject deviceVersionsJSON = responseEvent.data.GetField("deviceVersions");
                userDataVersions = new List <UserDataVersion>();

                if (deviceVersionsJSON.Count > 0)
                {
                    for (int i = 0; i < deviceVersionsJSON.Count; i++)
                    {
                        UserDataVersion userDataVersion = new UserDataVersion();
                        userDataVersion.deviceId = deviceVersionsJSON.keys[i];
                        userDataVersion.version  = (int)deviceVersionsJSON.list[i].i;

                        userDataVersions.Add(userDataVersion);
                    }
                }
            }

            if (responseEvent.data.HasField("metaData"))
            {
                JSONObject metaDataJSON = responseEvent.data.GetField("metaData");

                userDataMeta = new UserDataMeta();

                if (metaDataJSON.HasField("serverTime"))
                {
                    userDataMeta.serverTime = metaDataJSON.GetField("serverTime").i;
                }

                if (metaDataJSON.HasField("clientTime"))
                {
                    userDataMeta.clientTime = metaDataJSON.GetField("clientTime").i;
                }

                if (metaDataJSON.HasField("timezoneOffset"))
                {
                    userDataMeta.timezoneOffset = (int)metaDataJSON.GetField("timezoneOffset").i;
                }

                if (metaDataJSON.HasField("deviceModel"))
                {
                    userDataMeta.deviceModel = metaDataJSON.GetField("deviceModel").str;
                }

                if (metaDataJSON.HasField("appVersion"))
                {
                    userDataMeta.appVersion = metaDataJSON.GetField("appVersion").str;
                }
            }

            if (responseEvent.action.ToLower().Trim().Equals("request"))
            {
                UserDataManager.ProcessRequestUserData(receivedWallet, receivedInventory, externalChange, gameStateData, userDataVersions, userDataMeta);
            }
            else if (responseEvent.action.ToLower().Trim().Equals("mergeconflict"))
            {
                UserDataManager.ProcessMergeConflict(receivedWallet, receivedInventory, gameStateData, userDataVersions, userDataMeta);
            }
            else if (responseEvent.action.ToLower().Trim().Equals("merge"))
            {
                UserDataManager.ProcessMergeUserData(userDataVersions);
            }
            else if (responseEvent.action.ToLower().Trim().Equals("lockerror"))
            {
                UserDataManager.ProcessLockError();
            }
            else if (responseEvent.action.ToLower().Trim().Equals("syncerror"))
            {
                UserDataManager.ProcessSyncError();
            }
        }