IEnumerator FileFetchAllVersions() { JCloudDocumentOperation operation = JCloudDocument.FileFetchAllVersions("testfile.txt"); while (!operation.finished) { yield return(null); } if (operation.success && operation.result != null) { JCloudDocumentVersions versions = (JCloudDocumentVersions)operation.result; documentResultString = "cloud document test file versions :"; int offset = 1; foreach (JCloudDocumentVersionMetadata metadata in versions.versionsMetadata) { documentResultString += " " + offset + ". " + metadata.modificationDate + (metadata.isCurrent ? " (current)" : ""); offset++; } documentResultString += " (hash : " + versions.versionsHash + ")" + (operation.error != null ? (" ; error : " + operation.error) : ""); } else { documentResultString = "cloud document test file versions : failure" + (operation.error != null ? (" ; error : " + operation.error) : ""); } }
IEnumerator FileReadConflictVersionBytes() { JCloudDocumentOperation operation; operation = JCloudDocument.FileFetchAllVersions("testfile.txt"); while (!operation.finished) { yield return(null); } if (operation.success && operation.result != null) { JCloudDocumentVersions versions = (JCloudDocumentVersions)operation.result; JCloudDocumentVersionMetadata?conflictVersionMetadata = null; foreach (JCloudDocumentVersionMetadata metadata in versions.versionsMetadata) { if (metadata.isCurrent == false) { conflictVersionMetadata = metadata; break; } } if (conflictVersionMetadata != null) { operation = JCloudDocument.FileReadVersionBytes("testfile.txt", conflictVersionMetadata.Value.uniqueIdentifier); while (!operation.finished) { documentResultString = "cloud document read conflict version bytes progress : " + operation.progress; yield return(null); } System.Text.UTF8Encoding encoder = new System.Text.UTF8Encoding(); if (operation.success) { documentResultString = "cloud document did read conflict version bytes ; read this : " + ((operation.result == null) ? "(null)" : encoder.GetString(operation.result as byte[])) + (operation.error != null ? (" ; error : " + operation.error) : ""); } else { documentResultString = "cloud document read conflict version bytes : failure" + (operation.error != null ? (" ; error : " + operation.error) : ""); } } else { documentResultString = "cloud document read conflict version bytes : failure" + (operation.error != null ? (" ; error : " + operation.error) : "") + " (found no conflict version)"; } } else { documentResultString = "cloud document read conflict version bytes : failure" + (operation.error != null ? (" ; error : " + operation.error) : ""); } }
IEnumerator FilePickCurrentVersion() { JCloudDocumentOperation operation; operation = JCloudDocument.FileFetchAllVersions("testfile.txt"); while (!operation.finished) { yield return(null); } if (operation.success && operation.result != null) { JCloudDocumentVersions versions = (JCloudDocumentVersions)operation.result; JCloudDocumentVersionMetadata?currentVersionMetadata = null; foreach (JCloudDocumentVersionMetadata metadata in versions.versionsMetadata) { if (metadata.isCurrent == true) { currentVersionMetadata = metadata; break; } } if (currentVersionMetadata != null) { operation = JCloudDocument.FilePickVersion("testfile.txt", currentVersionMetadata.Value.uniqueIdentifier, versions.versionsHash); while (!operation.finished) { yield return(null); } if (operation.success) { documentResultString = "cloud document did pick current version : " + (((bool)operation.result == true) ? "success" : "failure") + (operation.error != null ? (" ; error : " + operation.error) : ""); } else { documentResultString = "cloud document did pick current version : failure" + (operation.error != null ? (" ; error : " + operation.error) : ""); } } else { documentResultString = "cloud document did pick current version : failure" + (operation.error != null ? (" ; error : " + operation.error) : "") + " (found no current version)"; } } else { documentResultString = "cloud document did pick current version : failure" + (operation.error != null ? (" ; error : " + operation.error) : ""); } }
private IEnumerator DownloadFromCloudByCheckingConflicts(System.Action <UserCloudDownloadDelegateEventArgs> onResul = null) { #if UNITY_IPHONE || UNITY_EDITOR JCloudDocumentOperation operation; // Let's check file for conflict first operation = JCloudDocument.FileHasConflictVersions(FILE_NAME_CLOUD); while (operation.finished == false) { yield return(null); // Wait for 1 frame } // Look for error -- if any, handle & stop coroutine here -- ignore cloud unvailable as it simply means conflicts are not handled if (operation.error.HasValue && operation.error.Value != JCloudDocumentError.CloudUnavailable) { HandleDocumentError(operation.error.Value, onResul); yield break; } // Did looking for conflict trigger a result? if (((bool?)operation.result).HasValue && (bool)operation.result == true) { // We have conflicts -- sort them out operation = JCloudDocument.FileFetchAllVersions(FILE_NAME_CLOUD); while (operation.finished == false) { yield return(null); } // Look for error -- if any, handle & stop coroutine here if (operation.error.HasValue) { HandleDocumentError(operation.error.Value, onResul); yield break; } // Get conflict versions JCloudDocumentVersions versions = (JCloudDocumentVersions)operation.result; // We will now attempt to pick the "best" version (e.g. most progress) -- you could offer UI UserCloud temporalUser; int lastLevelTemporalUser = -1; byte[] bestVersionIdentifier = null; foreach (JCloudDocumentVersionMetadata metadata in versions.versionsMetadata) { // Read version bytes operation = JCloudDocument.FileReadVersionBytes(FILE_NAME_CLOUD, metadata.uniqueIdentifier); while (operation.finished == false) { yield return(null); } // Look for error -- if any, handle & stop coroutine here if (operation.error.HasValue) { HandleDocumentError(operation.error.Value, onResul); yield break; } // Pick best version temporalUser = UserCloud.Deserialize((byte[])operation.result); if (temporalUser == null) { continue; } if (temporalUser.LastFinishedLvl > lastLevelTemporalUser) { lastLevelTemporalUser = temporalUser.LastFinishedLvl; bestVersionIdentifier = metadata.uniqueIdentifier; } } // At that point we should have the best version if (bestVersionIdentifier != null) { // Pick it as current version operation = JCloudDocument.FilePickVersion(FILE_NAME_CLOUD, bestVersionIdentifier, versions.versionsHash); while (operation.finished == false) { yield return(null); } // Look for error -- if any, handle & stop coroutine here if (operation.error.HasValue) { HandleDocumentError(operation.error.Value, onResul); yield break; } } } // At that point conflicts have been cleared -- wait for file reading operation = JCloudDocument.FileReadAllBytes(FILE_NAME_CLOUD); while (operation.finished == false) { yield return(null); // Wait for 1 frame } // Look for error -- if any, handle & stop coroutine here if (operation.error.HasValue) { HandleDocumentError(operation.error.Value, onResul); yield break; } byte[] bytes = operation.result as byte[]; if (bytes != null) { //Save iCloud info in Memory. Then, merge information with local user data Debug.Log("- LoadUserFromCloud OK"); CurrentCloudUser = UserCloud.Deserialize(bytes); this.MergeUsers(onResul); } #endif #if UNITY_ANDROID && !disableGoogleCloud byte[] googleCloudDataBytes = null; if (CanUseGoogleCloud()) { while (!PlayGameServices.isSignedIn() && googleCloudTryingToLogin) { yield return(null); // Wait for n frames until googleCloudTryingToLogin was setted to FALSE } if (!PlayGameServices.isSignedIn() && !googleCloudTryingToLogin) { HandleDocumentError(JCloudDocumentError.CloudUnavailable, onResul); yield break; } Debug.Log("[UserManagerCloud] DownloadFromCloudByCheckingConflicts(): Downloading user data from cloud..."); PlayGameServices.loadCloudDataForKey(0, false); // Wait a maximum of 6 seconds to retrieve google cloud data float timeLeftToWait = 6f; float lastTime = Time.realtimeSinceStartup; while (googleCloudData == null && timeLeftToWait > 0f) { timeLeftToWait -= Time.realtimeSinceStartup - lastTime; lastTime = Time.realtimeSinceStartup; yield return(null); // Wait for n frames until googleCloudData was setted in loadCloudDataForKeyFailedEvent or loadCloudDataForKeySucceededEvent } if (googleCloudData == "ERROR" || googleCloudData == null) { Debug.Log("ANDROID CLOUD SERVICES RETURNED ERROR DOWNLOADING"); HandleDocumentError(JCloudDocumentError.DocumentNotFound, onResul); yield break; } Debug.Log("[UserManagerCloud] There is google cloud data : " + googleCloudData.Length); try { googleCloudDataBytes = System.Convert.FromBase64String(googleCloudData); Debug.Log("[UserManagerCloud] Cloud data size: " + googleCloudDataBytes.Length); } catch (Exception) { Debug.LogWarning("[UserManagerCloud] Failed to decode android cloud data: " + googleCloudData); } } CurrentCloudUser = UserCloud.Deserialize(googleCloudDataBytes); MergeUsers(onResul); //Free memory googleCloudData = null; #endif yield break; }
// Fetch conflict versions metadata + current live version metadata at path protected static IEnumerator FileFetchAllVersionsOperation(string path, JCloudDocumentOperation operation) { // Failsafe if ((path == null) || (path == "")) { operation.error = JCloudDocumentError.InvalidArguments; operation.finished = true; yield break; } #if !UNITY_EDITOR && ((UNITY_IPHONE && JCLOUDPLUGIN_IOS) || (UNITY_STANDALONE_OSX && JCLOUDPLUGIN_OSX)) // Make sure our platfom is compatible if (JCloudManager.PlatformIsCloudCompatible() && (AcceptJailbrokenDevices || JCloudExtern.IsJailbroken() == false)) { // Prepare a new cloud document int documentUID = JCloudDocument.NewCloudDocument(path, false); // Any current operation on that document? Just wait yield until they end int lockId = JCloudManager.GetDocumentLock(documentUID); while (!JCloudManager.CheckDocumentLock(documentUID, lockId)) yield return null; // Check for existence JCloudExtern.JCloudDocumentVersionsInternal versionsInternal = new JCloudExtern.JCloudDocumentVersionsInternal(); if (JCloudExtern.CloudItemFetchAllVersions(documentUID, ref versionsInternal)) { JCloudManager.DocumentStatus? status; while (!JCloudManager.GetDocumentStatus(documentUID, out status)) yield return null; if (status.Value.success) { // Spawn data in public struct JCloudDocumentVersions versions = new JCloudDocumentVersions(); versions.versionsHash = Marshal.PtrToStringAnsi(versionsInternal.versionsHash); versions.versionsMetadata = new JCloudDocumentVersionMetadata[versionsInternal.versionsCount]; System.IntPtr[] uniqueIdentifiersPointers = new System.IntPtr[versionsInternal.versionsCount]; int[] uniqueIdentifiersLengthes = new int[versionsInternal.versionsCount]; long[] modificationDates = new long[versionsInternal.versionsCount]; byte[] isCurrent = new byte[versionsInternal.versionsCount]; Marshal.Copy(versionsInternal.versionsUniqueIdentifiers, uniqueIdentifiersPointers, 0, versionsInternal.versionsCount); Marshal.Copy(versionsInternal.versionsUniqueIdentifiersLengthes, uniqueIdentifiersLengthes, 0, versionsInternal.versionsCount); Marshal.Copy(versionsInternal.versionsModificationDates, modificationDates, 0, versionsInternal.versionsCount); Marshal.Copy(versionsInternal.versionsIsCurrent, isCurrent, 0, versionsInternal.versionsCount); for (int i = 0; i < versionsInternal.versionsCount; i++) { JCloudDocumentVersionMetadata metadata = new JCloudDocumentVersionMetadata(); metadata.uniqueIdentifier = new byte[uniqueIdentifiersLengthes[i]]; Marshal.Copy(uniqueIdentifiersPointers[i], metadata.uniqueIdentifier, 0, uniqueIdentifiersLengthes[i]); metadata.modificationDate = new System.DateTime(1970, 1, 1, 0, 0, 0).AddSeconds(modificationDates[i]).ToLocalTime(); metadata.isCurrent = (isCurrent[i] != 0); versions.versionsMetadata[i] = metadata; } // Free memory JCloudExtern.FreeMemory(versionsInternal.versionsHash); for (int i = 0; i < versionsInternal.versionsCount; i++) { JCloudExtern.FreeMemory(uniqueIdentifiersPointers[i]); } JCloudExtern.FreeMemory(versionsInternal.versionsUniqueIdentifiers); JCloudExtern.FreeMemory(versionsInternal.versionsUniqueIdentifiersLengthes); JCloudExtern.FreeMemory(versionsInternal.versionsModificationDates); JCloudExtern.FreeMemory(versionsInternal.versionsIsCurrent); operation.success = true; operation.result = versions; } operation.error = status.Value.error; } else operation.error = JCloudDocumentError.PluginError; // We have a result, no need to let user yield any longer operation.finished = true; // Dismiss document handling DismissCloudDocument(documentUID); } else { #endif #if !UNITY_WEBPLAYER && !UNITY_METRO operation.error = JCloudDocumentError.CloudUnavailable; operation.finished = true; #else operation.error = JCloudDocumentError.InvalidPlatform; operation.finished = true; #endif #if !UNITY_EDITOR && ((UNITY_IPHONE && JCLOUDPLUGIN_IOS) || (UNITY_STANDALONE_OSX && JCLOUDPLUGIN_OSX)) } #endif }