internal static void InternalOpenWithManualConflictResolution(string name, bool prefetchDataOnConflict, iOSConflictCallback conflictCallback, Action <iOSGKSavedGame, string> completedCallback) { Util.NullArgumentTest(name); Util.NullArgumentTest(conflictCallback); Util.NullArgumentTest(completedCallback); InternalOpenSavedGame(name, matchingGames => { if (matchingGames.Length == 0) { Debug.LogError("Something really wrong happened: no saved game was opened. Please check."); } else if (matchingGames.Length == 1) { completedCallback(matchingGames[0], null); } else { // There're more than one game: conflict detected! // Sort the saved games from old to new, the oldest one is considered the base var sortedGames = new List <iOSGKSavedGame>(matchingGames); sortedGames.Sort((x, y) => x.ModificationDate.CompareTo(y.ModificationDate)); // Run the conflict resolve loop ConflictResolvingLoop(sortedGames.ToArray(), prefetchDataOnConflict, conflictCallback, completedCallback); } }); }
// This method will automatically be called repeatedly until no conflict remains. private static void ConflictResolvingLoop(iOSGKSavedGame[] conflictingGames, bool prefetchData, iOSConflictCallback conflictCallback, Action <iOSGKSavedGame, string> completedCallback) { if (conflictingGames.Length == 1) { // No more conflict! var openedSavedGame = conflictingGames[0]; completedCallback(openedSavedGame, null); return; } // The 1st element in the array is always the base game. // Either it is the game with oldest timestamp to start with, // or the resolved game of the previous conflict resolution request. var baseGame = conflictingGames[0]; var remoteGame = conflictingGames[1]; var resolver = new NativeConflictResolver( baseGame, remoteGame, completedCallback, updatedConflictingGames => ConflictResolvingLoop(updatedConflictingGames, prefetchData, conflictCallback, completedCallback) ); // Invoke the conflict callback immediately if we don't need to prefetch data if (!prefetchData) { conflictCallback(resolver, baseGame, null, remoteGame, null); return; } // If we have to prefetch the data, we delegate invoking the conflict resolution // callback to the joiner instance (once both callbacks resolve, the joiner will // invoke the lambda that we declare here, using the fetched data). Prefetcher joiner = new Prefetcher((baseData, remoteData) => conflictCallback(resolver, baseGame, baseData, remoteGame, remoteData), completedCallback); // Kick off the read calls. InternalLoadSavedGameData(baseGame, joiner.OnBaseDataRead); InternalLoadSavedGameData(remoteGame, joiner.OnRemoteDataRead); }