Decompiled source of The All You Need Save Manager v1.0.4
BepInEx\plugins\TAYNSM\TAYNSM.dll
Decompiled 2 weeks ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Photon.Pun; using Photon.Realtime; using TMPro; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.SceneManagement; using UnityEngine.UI; using Zorro.Core; using Zorro.Core.Serizalization; using Zorro.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyVersion("0.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace PEAKSaveManager { [BepInPlugin("com.lucasandersen.peakallyouneedsavemanager", "The All You Need Save Manager", "1.0.0")] public sealed class SaveManagerPlugin : BaseUnityPlugin { [CompilerGenerated] private sealed class <>c__DisplayClass188_0 { public PlayerSnapshot snapshot; internal bool <WaitForPlayersRoutine>b__0(Player player) { PhotonView photonView = GetPhotonView((Component)(object)player); if ((Object)(object)photonView == (Object)null) { return false; } Player owner = photonView.Owner; if (snapshot.actorNumber > 0 && owner != null && owner.ActorNumber == snapshot.actorNumber) { return true; } if (owner != null) { return string.Equals(owner.NickName, snapshot.playerName, StringComparison.OrdinalIgnoreCase); } return false; } } [CompilerGenerated] private sealed class <ApplyPlayerSnapshotRoutine>d__189 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public Player player; public SaveManagerPlugin <>4__this; public PlayerSnapshot snapshot; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <ApplyPlayerSnapshotRoutine>d__189(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_019e: Expected O, but got Unknown //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) int num = <>1__state; SaveManagerPlugin saveManagerPlugin = <>4__this; switch (num) { default: return false; case 0: { <>1__state = -1; Character character = player.character; if ((Object)(object)character == (Object)null) { return false; } saveManagerPlugin.ApplyInventory(player, character, snapshot.inventory); saveManagerPlugin.ApplyCharacterSnapshot(character, snapshot.character); Vector3 val = snapshot.position.ToUnity(); PhotonView photonView = GetPhotonView((Component)(object)character); Player val2 = (((Object)(object)photonView != (Object)null) ? photonView.Owner : null); if ((Object)(object)photonView != (Object)null && val2 != null) { photonView.RPC("WarpPlayerRPC", val2, new object[2] { val, false }); } else { ((Component)character).transform.position = val; } if ((Object)(object)photonView != (Object)null && photonView.IsMine) { ((Component)character).transform.eulerAngles = snapshot.rotation.ToUnity(); character.data.lookValues = snapshot.character.lookValues.ToUnity(); RecalculateLookDirectionsMethod?.Invoke(character, null); } else if ((Object)(object)photonView == (Object)null) { ((Component)character).transform.eulerAngles = snapshot.rotation.ToUnity(); } ApplyCharacterVelocity(character, snapshot.velocity, snapshot.angularVelocity); ApplyEquippedSelection(player, character, snapshot.inventory); <>2__current = (object)new WaitForSeconds(0.05f); <>1__state = 1; return true; } case 1: <>1__state = -1; return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <EnumeratePlayersFromHandler>d__155 : IEnumerable<Player>, IEnumerable, IEnumerator<Player>, IDisposable, IEnumerator { private int <>1__state; private Player <>2__current; private int <>l__initialThreadId; private IEnumerator <>7__wrap1; Player IEnumerator<Player>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <EnumeratePlayersFromHandler>d__155(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || num == 1) { try { } finally { <>m__Finally1(); } } <>7__wrap1 = null; <>1__state = -2; } private bool MoveNext() { try { int num = <>1__state; if (num != 0) { if (num != 1) { return false; } <>1__state = -3; } else { <>1__state = -1; Type type = AccessTools.TypeByName("PlayerHandler"); if (type == null) { return false; } MethodInfo methodInfo = AccessTools.Method(type, "GetAllPlayers", (Type[])null, (Type[])null); if (methodInfo == null) { return false; } object obj; try { obj = methodInfo.Invoke(null, null); } catch { return false; } if (!(obj is IEnumerable enumerable)) { goto IL_00d9; } <>7__wrap1 = enumerable.GetEnumerator(); <>1__state = -3; } while (<>7__wrap1.MoveNext()) { object current = <>7__wrap1.Current; Player val = (Player)((current is Player) ? current : null); if (val != null) { <>2__current = val; <>1__state = 1; return true; } } <>m__Finally1(); <>7__wrap1 = null; goto IL_00d9; IL_00d9: return false; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; if (<>7__wrap1 is IDisposable disposable) { disposable.Dispose(); } } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator<Player> IEnumerable<Player>.GetEnumerator() { if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; return this; } return new <EnumeratePlayersFromHandler>d__155(0); } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable<Player>)this).GetEnumerator(); } } [CompilerGenerated] private sealed class <LoadSaveRoutine>d__185 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public SaveManagerPlugin <>4__this; public string fullPath; private SaveEnvelope <envelope>5__2; private string <targetScene>5__3; private int <appliedCount>5__4; private List<PlayerSnapshot>.Enumerator <>7__wrap4; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <LoadSaveRoutine>d__185(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if ((uint)(num - -4) <= 1u || (uint)(num - 1) <= 4u) { try { if (num == -4 || num == 5) { try { } finally { <>m__Finally2(); } } } finally { <>m__Finally1(); } } <envelope>5__2 = null; <targetScene>5__3 = null; <>7__wrap4 = default(List<PlayerSnapshot>.Enumerator); <>1__state = -2; } private bool MoveNext() { //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0249: Unknown result type (might be due to invalid IL or missing references) //IL_02c5: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_02f2: Unknown result type (might be due to invalid IL or missing references) //IL_02f7: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_030f: Unknown result type (might be due to invalid IL or missing references) //IL_04ae: Unknown result type (might be due to invalid IL or missing references) //IL_045f: Unknown result type (might be due to invalid IL or missing references) //IL_0314: Unknown result type (might be due to invalid IL or missing references) //IL_0316: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_031a: Unknown result type (might be due to invalid IL or missing references) //IL_031c: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_0320: Unknown result type (might be due to invalid IL or missing references) //IL_032d: Unknown result type (might be due to invalid IL or missing references) //IL_0337: Expected O, but got Unknown bool result; try { int num = <>1__state; SaveManagerPlugin saveManagerPlugin = <>4__this; switch (num) { default: result = false; goto end_IL_0000; case 0: <>1__state = -1; if (saveManagerPlugin.isLoading) { result = false; } else { saveManagerPlugin.isLoading = true; saveManagerPlugin.SetStatus("Loading save...", Color.cyan, 10f); <>1__state = -3; if (!TryReadSaveEnvelope(fullPath, out <envelope>5__2, out var reason)) { saveManagerPlugin.SetStatus("Incompatible save: " + reason, Color.yellow, 6f); result = false; break; } if (<envelope>5__2.players.Count == 0) { saveManagerPlugin.SetStatus("Save file has no player snapshots.", Color.yellow, 6f); result = false; break; } if (PhotonNetwork.InRoom && !PhotonNetwork.IsMasterClient) { saveManagerPlugin.SetStatus("Only host can load shared saves.", Color.yellow, 4f); result = false; break; } <targetScene>5__3 = ResolveTargetScene(<envelope>5__2.metadata); bool flag = SaveNeedsNonAirportScene(<envelope>5__2.metadata); if (string.IsNullOrWhiteSpace(<targetScene>5__3) && flag) { if (IsInAirportScene()) { saveManagerPlugin.SetStatus("Saved level is unavailable or mismatched for this version.", Color.yellow, 7f); result = false; break; } saveManagerPlugin.SetStatus("Saved level mismatch. Loading into current level.", Color.yellow, 5f); } int num2; if (!string.IsNullOrEmpty(<targetScene>5__3)) { Scene activeScene = SceneManager.GetActiveScene(); num2 = ((!string.Equals(((Scene)(ref activeScene)).name, <targetScene>5__3, StringComparison.OrdinalIgnoreCase)) ? 1 : 0); } else { num2 = 0; } if (<envelope>5__2.metadata.levelSeed != 0) { SetPendingSeedForLoad(<envelope>5__2.metadata.levelSeed); ((BaseUnityPlugin)saveManagerPlugin).Logger.LogInfo((object)$"Queued seed {PendingSeedForLoad.Value} for next level generation"); } else { ClearPendingSeedForLoad(); } if (num2 == 0) { Ascents.currentAscent = <envelope>5__2.metadata.ascent; goto IL_0274; } <>2__current = ((MonoBehaviour)saveManagerPlugin).StartCoroutine(saveManagerPlugin.LoadSceneRoutine(<targetScene>5__3, <envelope>5__2.metadata.ascent)); <>1__state = 1; result = true; } goto end_IL_0000; case 1: <>1__state = -3; if (!saveManagerPlugin.lastSceneLoadSucceeded) { saveManagerPlugin.SetStatus("Failed to load scene '" + <targetScene>5__3 + "'.", Color.red, 6f); result = false; break; } goto IL_0274; case 2: { <>1__state = -3; if (saveManagerPlugin.CountMatchedPlayers(<envelope>5__2.players) <= 0) { saveManagerPlugin.SetStatus("No matching players were found for this save.", Color.yellow, 6f); result = false; break; } if (!MapHandler.Exists) { goto IL_034d; } Segment val2 = ClampSegment(<envelope>5__2.metadata.currentSegment); MapHandler val3 = Object.FindFirstObjectByType<MapHandler>(); Segment val4 = (Segment)(((Object)(object)val3 != (Object)null) ? ((int)val3.GetCurrentSegment()) : 0); if ((int)val2 == 0 || val2 == val4) { goto IL_034d; } MapHandler.JumpToSegment(val2); <>2__current = (object)new WaitForSeconds(0.75f); <>1__state = 3; result = true; goto end_IL_0000; } case 3: <>1__state = -3; goto IL_034d; case 4: <>1__state = -3; <appliedCount>5__4 = 0; <>7__wrap4 = <envelope>5__2.players.GetEnumerator(); <>1__state = -4; goto IL_042e; case 5: { <>1__state = -4; <appliedCount>5__4++; goto IL_042e; } IL_042e: while (true) { if (<>7__wrap4.MoveNext()) { PlayerSnapshot current = <>7__wrap4.Current; Player val = saveManagerPlugin.FindPlayer(current); if ((Object)(object)val == (Object)null) { ((BaseUnityPlugin)saveManagerPlugin).Logger.LogWarning((object)$"Could not find player for snapshot '{current.playerName}' (Actor: {current.actorNumber})"); continue; } <>2__current = ((MonoBehaviour)saveManagerPlugin).StartCoroutine(saveManagerPlugin.ApplyPlayerSnapshotRoutine(val, current)); <>1__state = 5; result = true; } else { <>m__Finally2(); <>7__wrap4 = default(List<PlayerSnapshot>.Enumerator); if (<appliedCount>5__4 <= 0) { saveManagerPlugin.SetStatus("Load finished but no players were restored.", Color.yellow, 6f); result = false; break; } saveManagerPlugin.RestoreRunMetadata(<envelope>5__2.metadata); saveManagerPlugin.SetStatus($"Loaded save successfully ({<appliedCount>5__4}/{<envelope>5__2.players.Count} players).", Color.green, 4f); <envelope>5__2 = null; <targetScene>5__3 = null; <>m__Finally1(); result = false; } goto end_IL_0000; } break; IL_034d: <>2__current = ((MonoBehaviour)saveManagerPlugin).StartCoroutine(saveManagerPlugin.RestoreWorldInteractablesRoutine(<envelope>5__2)); <>1__state = 4; result = true; goto end_IL_0000; IL_0274: <>2__current = ((MonoBehaviour)saveManagerPlugin).StartCoroutine(WaitForPlayersRoutine(<envelope>5__2.players, 20f)); <>1__state = 2; result = true; goto end_IL_0000; } <>m__Finally1(); end_IL_0000:; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } return result; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; SaveManagerPlugin saveManagerPlugin = <>4__this; ClearPendingSeedForLoad(); saveManagerPlugin.isLoading = false; saveManagerPlugin.RefreshSaveFileList(); } private void <>m__Finally2() { <>1__state = -3; ((IDisposable)<>7__wrap4).Dispose(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <LoadSceneRoutine>d__186 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public SaveManagerPlugin <>4__this; public int ascent; public string sceneName; private bool <usedLoadingScreen>5__2; private float <timeout>5__3; private AsyncOperation <operation>5__4; private float <fallbackTimeout>5__5; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <LoadSceneRoutine>d__186(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <operation>5__4 = null; <>1__state = -2; } private bool MoveNext() { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Expected O, but got Unknown //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Unknown result type (might be due to invalid IL or missing references) int num = <>1__state; SaveManagerPlugin saveManagerPlugin = <>4__this; switch (num) { default: return false; case 0: <>1__state = -1; saveManagerPlugin.lastSceneLoadSucceeded = false; Ascents.currentAscent = ascent; try { GameHandler.AddStatus<SceneSwitchingStatus>((GameStatus)new SceneSwitchingStatus()); } catch (Exception ex) { ((BaseUnityPlugin)saveManagerPlugin).Logger.LogWarning((object)("Could not set scene switching status: " + ex.Message)); } <usedLoadingScreen>5__2 = false; try { LoadingScreenHandler instance = RetrievableResourceSingleton<LoadingScreenHandler>.Instance; if ((Object)(object)instance != (Object)null) { instance.Load((LoadingScreenType)1, (Action)null, new IEnumerator[1] { instance.LoadSceneProcess(sceneName, true, true, 0.5f) }); <usedLoadingScreen>5__2 = true; } } catch (Exception ex2) { ((BaseUnityPlugin)saveManagerPlugin).Logger.LogWarning((object)("LoadingScreenHandler load failed, using fallback load: " + ex2.Message)); } if (!<usedLoadingScreen>5__2) { <operation>5__4 = SceneManager.LoadSceneAsync(sceneName); if (<operation>5__4 == null) { ((BaseUnityPlugin)saveManagerPlugin).Logger.LogError((object)("Could not start fallback scene load for '" + sceneName + "'.")); return false; } <fallbackTimeout>5__5 = 45f; goto IL_0144; } goto IL_0165; case 1: <>1__state = -1; goto IL_0144; case 2: { <>1__state = -1; break; } IL_0165: <timeout>5__3 = 45f; break; IL_0144: if (!<operation>5__4.isDone && <fallbackTimeout>5__5 > 0f) { <fallbackTimeout>5__5 -= Time.unscaledDeltaTime; <>2__current = null; <>1__state = 1; return true; } <operation>5__4 = null; goto IL_0165; } if (<timeout>5__3 > 0f) { Scene activeScene = SceneManager.GetActiveScene(); bool num2 = string.Equals(((Scene)(ref activeScene)).name, sceneName, StringComparison.OrdinalIgnoreCase); bool flag = !<usedLoadingScreen>5__2 || !LoadingScreenHandler.loading; if (num2 && flag) { saveManagerPlugin.lastSceneLoadSucceeded = true; return false; } <timeout>5__3 -= Time.unscaledDeltaTime; <>2__current = null; <>1__state = 2; return true; } ((BaseUnityPlugin)saveManagerPlugin).Logger.LogWarning((object)("Timed out waiting for scene '" + sceneName + "' to finish loading.")); return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <RestoreWorldInteractablesRoutine>d__208 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public SaveEnvelope envelope; public SaveManagerPlugin <>4__this; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <RestoreWorldInteractablesRoutine>d__208(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Expected O, but got Unknown //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Expected O, but got Unknown int num = <>1__state; SaveManagerPlugin saveManagerPlugin = <>4__this; switch (num) { default: return false; case 0: <>1__state = -1; if (envelope == null) { return false; } saveManagerPlugin.RestoreCampfires(envelope.campfires); saveManagerPlugin.RestoreContainerStates(envelope.containerStates, envelope.luggageStates); saveManagerPlugin.RestoreWorldObjects(envelope.worldObjects, envelope.formatVersion); <>2__current = (object)new WaitForSeconds(0.2f); <>1__state = 1; return true; case 1: <>1__state = -1; saveManagerPlugin.RestoreCampfires(envelope.campfires); saveManagerPlugin.RestoreContainerStates(envelope.containerStates, envelope.luggageStates); saveManagerPlugin.RestoreWorldObjects(envelope.worldObjects, envelope.formatVersion); <>2__current = (object)new WaitForSeconds(1.1f); <>1__state = 2; return true; case 2: <>1__state = -1; saveManagerPlugin.RestoreContainerStates(envelope.containerStates, envelope.luggageStates); saveManagerPlugin.RestoreWorldObjects(envelope.worldObjects, envelope.formatVersion); saveManagerPlugin.RestoreGroundItems(envelope.groundItems); saveManagerPlugin.RestoreWorldObjects(envelope.worldObjects, envelope.formatVersion); return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <WaitForPlayersRoutine>d__188 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public float timeoutSeconds; public List<PlayerSnapshot> players; private float <timeout>5__2; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <WaitForPlayersRoutine>d__188(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <timeout>5__2 = Mathf.Max(1f, timeoutSeconds); break; case 1: <>1__state = -1; break; } if (<timeout>5__2 > 0f) { Player[] array = Object.FindObjectsByType<Player>((FindObjectsSortMode)0); if (array.Length != 0) { int num = 0; for (int i = 0; i < players.Count; i++) { if (array.Any(new <>c__DisplayClass188_0 { snapshot = players[i] }.<WaitForPlayersRoutine>b__0)) { num++; } } if (num > 0) { return false; } } <timeout>5__2 -= Time.deltaTime; <>2__current = (object)new WaitForSeconds(0.1f); <>1__state = 1; return true; } return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } public const string PluginGuid = "com.lucasandersen.peakallyouneedsavemanager"; public const string PluginName = "The All You Need Save Manager"; public const string PluginVersion = "1.0.0"; private const string SaveFilePattern = "*.json"; private const int UiWindowId = 129193; private const string PauseMenuButtonObjectName = "PeakSaveManagerButton"; private const float PendingSeedLifetimeSeconds = 90f; private static readonly MethodInfo RecalculateLookDirectionsMethod = AccessTools.Method(typeof(Character), "RecalculateLookDirections", (Type[])null, (Type[])null); private static readonly MethodInfo CampfireUpdateLitMethod = AccessTools.Method(typeof(Campfire), "UpdateLit", (Type[])null, (Type[])null); private static readonly MethodInfo CampfireHideLogsMethod = AccessTools.Method(typeof(Campfire), "HideLogs", (Type[])null, (Type[])null); private static readonly FieldInfo LuggageStateField = AccessTools.Field(typeof(Luggage), "state"); private static readonly MethodInfo LuggageOpenRpcMethod = AccessTools.Method(typeof(Luggage), "OpenLuggageRPC", (Type[])null, (Type[])null); private static readonly MethodInfo MenuWindowOpenMethod = AccessTools.Method(typeof(MenuWindow), "Open", (Type[])null, (Type[])null); private static readonly MethodInfo MenuWindowCloseMethod = AccessTools.Method(typeof(MenuWindow), "Close", (Type[])null, (Type[])null); private static readonly MethodInfo RespawnChestSetSpentMethod = AccessTools.PropertySetter(typeof(RespawnChest), "IsSpent"); private static readonly MethodInfo RespawnChestSetRevivedPlayersMethod = AccessTools.PropertySetter(typeof(RespawnChest), "HasRevivedPlayers"); private static readonly MethodInfo RespawnChestGetRevivedPlayersMethod = AccessTools.PropertyGetter(typeof(RespawnChest), "HasRevivedPlayers"); private static readonly FieldInfo RespawnChestRevivedPlayersField = AccessTools.Field(typeof(RespawnChest), "hasRevivedPlayers"); private static readonly MethodInfo RunManagerRpcSyncTimeMethod = AccessTools.Method(typeof(RunManager), "RPC_SyncTime", new Type[2] { typeof(float), typeof(bool) }, (Type[])null); private static readonly FieldInfo RunManagerTimerActiveField = AccessTools.Field(typeof(RunManager), "timerActive"); private static readonly PropertyInfo RopeShooterAmmoProperty = AccessTools.Property(typeof(RopeShooter), "Ammo"); private static readonly MethodInfo RopeShooterSyncRpcMethod = AccessTools.Method(typeof(RopeShooter), "Sync_Rpc", new Type[1] { typeof(bool) }, (Type[])null); private static readonly FieldInfo ItemTotalUsesField = AccessTools.Field(typeof(Item), "totalUses"); private static readonly FieldInfo ItemDataField = AccessTools.Field(typeof(Item), "data"); private static readonly FieldInfo MagicBeanVineCurrentLengthField = AccessTools.Field(typeof(MagicBeanVine), "currentLength"); private static readonly FieldInfo MagicBeanVineInitialLengthField = AccessTools.Field(typeof(MagicBeanVine), "initialLength"); private static readonly FieldInfo MagicBeanVineMaxLengthField = AccessTools.Field(typeof(MagicBeanVine), "maxLength"); private static readonly FieldInfo CloudFungusAlreadyBrokeField = AccessTools.Field(typeof(CloudFungus), "alreadyBroke"); private static readonly FieldInfo CloudFungusTimeAliveField = AccessTools.Field(typeof(CloudFungus), "timeAlive"); private static readonly FieldInfo OptionableIntHasDataField = AccessTools.Field(typeof(OptionableIntItemData), "HasData"); private static readonly FieldInfo OptionableIntValueField = AccessTools.Field(typeof(OptionableIntItemData), "Value"); private static readonly FieldInfo OptionableBoolHasDataField = AccessTools.Field(typeof(OptionableBoolItemData), "HasData"); private static readonly FieldInfo OptionableBoolValueField = AccessTools.Field(typeof(OptionableBoolItemData), "Value"); private static readonly FieldInfo CharacterDataCheckpointFlagsField = AccessTools.Field(typeof(CharacterData), "checkpointFlags"); private static readonly FieldInfo CheckpointFlagStatusesField = AccessTools.Field(typeof(CheckpointFlag), "currentStatuses"); private static readonly FieldInfo CheckpointFlagPlanterField = AccessTools.Field(typeof(CheckpointFlag), "planterCharacter"); private static readonly FieldInfo CharacterItemsCurrentSelectedSlotField = AccessTools.Field(typeof(CharacterItems), "currentSelectedSlot"); private static readonly MethodInfo CharacterItemsEquipSlotMethod = AccessTools.Method(typeof(CharacterItems), "EquipSlot", new Type[1] { typeof(Optionable<byte>) }, (Type[])null); private static readonly ConstructorInfo OptionableByteConstructor = AccessTools.Constructor(typeof(Optionable<byte>), new Type[2] { typeof(byte), typeof(byte) }, false); private static readonly FieldInfo OptionableByteHasValueField = AccessTools.Field(typeof(Optionable<byte>), "hasValue"); private static readonly FieldInfo OptionableByteValueField = AccessTools.Field(typeof(Optionable<byte>), "value"); private static readonly MethodInfo MirageLuggageSetStateMethod = AccessTools.Method(typeof(MirageLuggage), "setMirageState", new Type[1] { typeof(float) }, (Type[])null); private static readonly FieldInfo MirageLuggageRenderersField = AccessTools.Field(typeof(MirageLuggage), "renderers"); private static readonly MethodInfo DayNightTimeStringGetterMethod = AccessTools.PropertyGetter(typeof(DayNightManager), "timeString"); private static readonly MethodInfo DayNightTimeStringSetterMethod = AccessTools.PropertySetter(typeof(DayNightManager), "timeString"); private static readonly FieldInfo DayNightTimeStringField = AccessTools.Field(typeof(DayNightManager), "timeString"); private static readonly HashSet<STATUSTYPE> SkippedSavedStatuses = new HashSet<STATUSTYPE> { (STATUSTYPE)7 }; private static SaveManagerPlugin Instance; private static int? PendingSeedForLoad; private static float PendingSeedSetRealtime; private Harmony harmony; private ConfigEntry<bool> autoSaveEnabled; private ConfigEntry<float> autoSaveIntervalSeconds; private string saveDirectory; private string preferredSaveDirectory; private string fallbackSaveDirectory; private bool showUi; private bool isLoading; private float lastAutoSaveTime; private bool lastSceneLoadSucceeded = true; private Rect windowRect = new Rect(34f, 34f, 820f, 620f); private Vector2 fileScroll = Vector2.zero; private string newSaveName = ""; private readonly List<SaveListEntry> saveEntries = new List<SaveListEntry>(); private string statusMessage = ""; private Color statusColor = Color.white; private float statusMessageUntil; private bool hasConfirmationPending; private string confirmationTitle = ""; private string confirmationMessage = ""; private Action confirmationAction; private bool stylesBuilt; private GUIStyle windowStyle; private GUIStyle sectionStyle; private GUIStyle titleStyle; private GUIStyle subtitleStyle; private GUIStyle normalLabelStyle; private GUIStyle errorLabelStyle; private GUIStyle softButtonStyle; private GUIStyle dangerButtonStyle; private GUIStyle textFieldStyle; private GUIStyle cardStyle; private GUIStyle cardWarningStyle; private Texture2D overlayTexture; private Texture2D windowTexture; private Texture2D sectionTexture; private Texture2D cardTexture; private Texture2D warningCardTexture; private Texture2D buttonTexture; private Texture2D buttonHoverTexture; private Texture2D dangerButtonTexture; private Texture2D textFieldTexture; private SaveManagerPausePage pauseMenuPage; private UIPageHandler pauseMenuPageHandler; private UIPage pauseMenuMainPage; private Button pauseMenuButtonTemplate; private bool quitPendingSaveDecision; private PauseMenuMainPage quitPendingPage; private bool allowVanillaQuitClick; private void Awake() { //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Expected O, but got Unknown //IL_00b1: Unknown result type (might be due to invalid IL or missing references) Instance = this; autoSaveEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("AutoSave", "Enable AutoSave", true, "Automatically create rolling autosaves"); autoSaveIntervalSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("AutoSave", "Interval Seconds", 300f, "Seconds between autosaves"); preferredSaveDirectory = Path.Combine(Paths.GameRootPath, "PeakSaves"); fallbackSaveDirectory = Path.Combine(Application.persistentDataPath, "PeakSaves"); saveDirectory = preferredSaveDirectory; EnsureSaveDirectoryReady(showStatus: false); harmony = new Harmony("com.lucasandersen.peakallyouneedsavemanager"); harmony.PatchAll(); RefreshSaveFileList(); SetStatus("Save manager ready.", Color.cyan, 2f); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Loaded The All You Need Save Manager 1.0.0 by Lucas Andersen"); } private void OnDestroy() { try { Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } } catch (Exception arg) { ((BaseUnityPlugin)this).Logger.LogWarning((object)$"Failed to unpatch Harmony cleanly: {arg}"); } DestroyUiResources(); } private void Update() { if (showUi) { Cursor.visible = true; Cursor.lockState = (CursorLockMode)0; } if (!showUi && !isLoading && autoSaveEnabled.Value && Time.time - lastAutoSaveTime > Mathf.Max(15f, autoSaveIntervalSeconds.Value)) { if (CanAutoSaveNow()) { TrySaveGame("Autosave"); } lastAutoSaveTime = Time.time; } } private bool CanAutoSaveNow() { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) if (!CanSaveNow(showReason: false)) { return false; } Scene activeScene = SceneManager.GetActiveScene(); string name = ((Scene)(ref activeScene)).name; if (string.IsNullOrWhiteSpace(name) || !name.StartsWith("Level_", StringComparison.OrdinalIgnoreCase)) { return false; } if (LoadingScreenHandler.loading) { return false; } return true; } private void OnGUI() { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Expected O, but got Unknown //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) if (showUi) { EnsureStyles(); DrawOverlay(); GUI.depth = -1000; windowRect = GUI.Window(129193, windowRect, new WindowFunction(DrawMainWindow), "PEAK ALL YOU NEED SAVE MANAGER", windowStyle); } } private void DrawMainWindow(int _) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_02fc: Unknown result type (might be due to invalid IL or missing references) //IL_0314: Unknown result type (might be due to invalid IL or missing references) //IL_0319: Unknown result type (might be due to invalid IL or missing references) //IL_0405: Unknown result type (might be due to invalid IL or missing references) float num = statusMessageUntil - Time.unscaledTime; bool flag = IsInAirportScene(); GUILayout.BeginVertical(Array.Empty<GUILayoutOption>()); if (!string.IsNullOrEmpty(statusMessage) && num > 0f) { Color color = GUI.color; GUI.color = statusColor; GUILayout.Label(statusMessage, sectionStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(30f) }); GUI.color = color; } if (isLoading) { GUILayout.Label("Loading save and synchronizing players...", sectionStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(28f) }); } if (hasConfirmationPending) { DrawConfirmationPrompt(); GUILayout.EndVertical(); GUI.DragWindow(new Rect(0f, 0f, ((Rect)(ref windowRect)).width, 24f)); return; } GUILayout.BeginVertical(sectionStyle, Array.Empty<GUILayoutOption>()); GUILayout.Label("Create Save", subtitleStyle, Array.Empty<GUILayoutOption>()); GUILayout.Space(4f); if (flag) { GUILayout.Label("You cannot save in the Airport.", errorLabelStyle, Array.Empty<GUILayoutOption>()); GUILayout.Space(4f); } GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUILayout.Label("Name", normalLabelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(55f) }); newSaveName = GUILayout.TextField(newSaveName, textFieldStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) }); GUILayout.EndHorizontal(); GUILayout.Space(6f); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUI.enabled = !isLoading && !flag; if (GUILayout.Button("Quick Save", softButtonStyle, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Height(28f), GUILayout.Width(120f) })) { TrySaveGame("Quick Save"); } GUI.enabled = !isLoading && !flag && !string.IsNullOrWhiteSpace(newSaveName); if (GUILayout.Button("Save", softButtonStyle, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Height(28f), GUILayout.Width(80f) })) { string saveName = newSaveName.Trim(); newSaveName = string.Empty; TrySaveGame(saveName); } GUI.enabled = true; GUILayout.EndHorizontal(); GUILayout.EndVertical(); GUILayout.Space(8f); GUILayout.BeginVertical(sectionStyle, Array.Empty<GUILayoutOption>()); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUILayout.Label("Saved Runs", subtitleStyle, Array.Empty<GUILayoutOption>()); GUILayout.FlexibleSpace(); GUI.enabled = !isLoading; if (GUILayout.Button("Refresh", softButtonStyle, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(90f), GUILayout.Height(24f) })) { RefreshSaveFileList(); } GUI.enabled = true; GUILayout.EndHorizontal(); GUILayout.Space(6f); fileScroll = GUILayout.BeginScrollView(fileScroll, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(390f) }); if (saveEntries.Count == 0) { GUILayout.Label("No save files found.", normalLabelStyle, Array.Empty<GUILayoutOption>()); } else { foreach (SaveListEntry saveEntry in saveEntries) { DrawSaveCard(saveEntry); GUILayout.Space(5f); } } GUILayout.EndScrollView(); GUILayout.EndVertical(); GUILayout.Space(8f); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUILayout.FlexibleSpace(); if (GUILayout.Button("Close", softButtonStyle, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(120f), GUILayout.Height(30f) })) { showUi = false; } GUILayout.EndHorizontal(); GUILayout.EndVertical(); GUI.DragWindow(new Rect(0f, 0f, ((Rect)(ref windowRect)).width, 24f)); } private void DrawSaveCard(SaveListEntry entry) { GUIStyle obj = (entry.isCompatible ? cardStyle : cardWarningStyle); bool flag = CanSaveNow(showReason: false); GUILayout.BeginVertical(obj, Array.Empty<GUILayoutOption>()); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUILayout.Label(entry.fileName, titleStyle, Array.Empty<GUILayoutOption>()); GUILayout.FlexibleSpace(); GUILayout.Label(FormatBytes(entry.fileSize), normalLabelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(78f) }); GUILayout.EndHorizontal(); if (entry.metadata != null) { string text = ((entry.metadata.savedAtUtc == default(DateTime)) ? entry.fileTime.ToString("yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture) : entry.metadata.savedAtUtc.ToLocalTime().ToString("yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture)); int num = entry.metadata.playerCount; if (num <= 0) { num = 0; } string text2 = Safe(entry.metadata.levelName); if (entry.metadata.levelNumber.HasValue) { text2 += $" (#{entry.metadata.levelNumber.Value})"; } GUILayout.Label("Saved: " + text, normalLabelStyle, Array.Empty<GUILayoutOption>()); GUILayout.Label("Level: " + text2 + " Segment: " + Safe(ToDisplaySegmentName(entry.metadata.currentSegmentName, entry.metadata.biomeId)), normalLabelStyle, Array.Empty<GUILayoutOption>()); GUILayout.Label($"Seed: {entry.metadata.levelSeed} Ascent: {entry.metadata.ascent} Players: {num}", normalLabelStyle, Array.Empty<GUILayoutOption>()); GUILayout.Label(FormatRunSummary(entry.metadata), normalLabelStyle, Array.Empty<GUILayoutOption>()); } else { GUILayout.Label($"File Time: {entry.fileTime:yyyy-MM-dd HH:mm:ss}", normalLabelStyle, Array.Empty<GUILayoutOption>()); } if (!entry.isCompatible) { GUILayout.Label("Incompatible: " + entry.incompatibilityReason, errorLabelStyle, Array.Empty<GUILayoutOption>()); } GUILayout.Space(4f); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUI.enabled = !isLoading && entry.isCompatible; if (GUILayout.Button("Load", softButtonStyle, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Height(24f), GUILayout.Width(90f) })) { StartLoadFromUi(entry.fullPath); } GUI.enabled = !isLoading && flag; if (GUILayout.Button("Overwrite", softButtonStyle, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Height(24f), GUILayout.Width(100f) })) { string saveNameHint = ((entry.metadata != null && !string.IsNullOrWhiteSpace(entry.metadata.saveName)) ? entry.metadata.saveName : Path.GetFileNameWithoutExtension(entry.fileName)); string targetPath2 = entry.fullPath; string fileName = entry.fileName; RequestConfirmation("Overwrite Save?", "Overwrite '" + fileName + "' with your current run state?", delegate { TryOverwriteSave(targetPath2, saveNameHint); }); } GUI.enabled = !isLoading; if (GUILayout.Button("Delete", dangerButtonStyle, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Height(24f), GUILayout.Width(90f) })) { string targetPath = entry.fullPath; string fileName2 = entry.fileName; RequestConfirmation("Delete Save?", "Delete '" + fileName2 + "' permanently? This cannot be undone.", delegate { TryDeleteSave(targetPath); }); } GUI.enabled = true; GUILayout.EndHorizontal(); GUILayout.EndVertical(); } private void StartLoadFromUi(string fullPath) { if (!string.IsNullOrWhiteSpace(fullPath)) { showUi = false; ClearPendingConfirmation(); pauseMenuPage?.PrepareForLoad(); ClosePauseMenuForLoad(); ((MonoBehaviour)this).StartCoroutine(LoadSaveRoutine(fullPath)); } } private void ClosePauseMenuForLoad() { try { if ((Object)(object)EventSystem.current != (Object)null) { EventSystem.current.SetSelectedGameObject((GameObject)null); } PauseMainMenu val = Object.FindFirstObjectByType<PauseMainMenu>(); if ((Object)(object)val != (Object)null) { CloseMenuWindow((MenuWindow)(object)val); ((Component)val).gameObject.SetActive(false); } if ((Object)(object)pauseMenuPage != (Object)null) { ((Component)pauseMenuPage).gameObject.SetActive(false); } if ((Object)(object)pauseMenuPageHandler != (Object)null) { ((Component)pauseMenuPageHandler).gameObject.SetActive(false); } Cursor.visible = false; Cursor.lockState = (CursorLockMode)1; } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Failed to close pause menu before load: " + ex.Message)); } } private void ToggleUi() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) if (PhotonNetwork.InRoom && !PhotonNetwork.IsMasterClient) { SetStatus("Only the host can open Save Manager.", Color.yellow, 2.5f); return; } showUi = !showUi; if (showUi) { RefreshSaveFileList(); Cursor.visible = true; Cursor.lockState = (CursorLockMode)0; } else { ClearPendingConfirmation(); } } private void RequestConfirmation(string title, string message, Action confirmedAction) { if (confirmedAction != null) { hasConfirmationPending = true; confirmationTitle = (string.IsNullOrWhiteSpace(title) ? "Are you sure?" : title); confirmationMessage = (string.IsNullOrWhiteSpace(message) ? "Please confirm this action." : message); confirmationAction = confirmedAction; } } private void ClearPendingConfirmation() { hasConfirmationPending = false; confirmationTitle = string.Empty; confirmationMessage = string.Empty; confirmationAction = null; } private void ExecutePendingConfirmation() { //IL_0037: Unknown result type (might be due to invalid IL or missing references) Action action = confirmationAction; ClearPendingConfirmation(); if (action == null) { return; } try { action(); } catch (Exception arg) { ((BaseUnityPlugin)this).Logger.LogError((object)$"Confirmation action failed: {arg}"); SetStatus("Action failed. Check BepInEx log.", Color.red, 4f); } } private void DrawConfirmationPrompt() { GUILayout.Space(8f); GUILayout.BeginVertical(sectionStyle, Array.Empty<GUILayoutOption>()); GUILayout.Label(confirmationTitle, subtitleStyle, Array.Empty<GUILayoutOption>()); GUILayout.Space(4f); GUILayout.Label(confirmationMessage, normalLabelStyle, Array.Empty<GUILayoutOption>()); GUILayout.Space(10f); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUILayout.FlexibleSpace(); GUI.enabled = !isLoading; if (GUILayout.Button("Cancel", softButtonStyle, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Height(30f), GUILayout.Width(120f) })) { ClearPendingConfirmation(); } GUI.enabled = !isLoading; if (GUILayout.Button("Confirm", dangerButtonStyle, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Height(30f), GUILayout.Width(120f) })) { ExecutePendingConfirmation(); } GUI.enabled = true; GUILayout.EndHorizontal(); GUILayout.EndVertical(); } internal static void TryAttachPauseMenuButton(PauseMenuMainPage pauseMenuPage) { Instance?.AttachPauseMenuButton(pauseMenuPage); } private void AttachPauseMenuButton(PauseMenuMainPage pauseMenuPage) { //IL_0222: Unknown result type (might be due to invalid IL or missing references) //IL_022c: Expected O, but got Unknown //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)pauseMenuPage == (Object)null) { return; } try { object? obj = AccessTools.Field(typeof(PauseMenuMainPage), "m_settingsButton")?.GetValue(pauseMenuPage); Button val = (Button)((obj is Button) ? obj : null); if ((Object)(object)val == (Object)null || (Object)(object)((Component)val).transform == (Object)null || (Object)(object)((Component)val).transform.parent == (Object)null) { return; } Transform parent = ((Component)val).transform.parent; Transform val2 = parent.Find("PeakSaveManagerButton"); Button component; if ((Object)(object)val2 == (Object)null) { GameObject val3 = Object.Instantiate<GameObject>(((Component)val).gameObject, parent, false); ((Object)val3).name = "PeakSaveManagerButton"; Transform transform = ((Component)val).transform; RectTransform val4 = (RectTransform)(object)((transform is RectTransform) ? transform : null); Transform transform2 = val3.transform; RectTransform val5 = (RectTransform)(object)((transform2 is RectTransform) ? transform2 : null); if ((Object)(object)val4 != (Object)null && (Object)(object)val5 != (Object)null) { val5.anchorMin = val4.anchorMin; val5.anchorMax = val4.anchorMax; val5.pivot = val4.pivot; val5.sizeDelta = val4.sizeDelta; ((Transform)val5).localScale = ((Transform)val4).localScale; Vector2 anchoredPosition = val4.anchoredPosition; Rect rect = val4.rect; val5.anchoredPosition = anchoredPosition + new Vector2(0f, 0f - Mathf.Max(50f, ((Rect)(ref rect)).height + 8f)); } val3.transform.SetSiblingIndex(((Component)val).transform.GetSiblingIndex() + 1); MonoBehaviour[] componentsInChildren = val3.GetComponentsInChildren<MonoBehaviour>(true); foreach (MonoBehaviour val6 in componentsInChildren) { if ((Object)(object)val6 != (Object)null && ((object)val6).GetType().Name == "LocalizedText") { Object.Destroy((Object)(object)val6); } } SetPauseMenuButtonText(val3, "SAVE MANAGER"); component = val3.GetComponent<Button>(); } else { component = ((Component)val2).GetComponent<Button>(); } if (!((Object)(object)component == (Object)null)) { ((UnityEventBase)component.onClick).RemoveAllListeners(); ((UnityEvent)component.onClick).AddListener((UnityAction)delegate { OpenPauseMenuSavePage(pauseMenuPage); }); ((Selectable)component).interactable = !PhotonNetwork.InRoom || PhotonNetwork.IsMasterClient; } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Failed to attach pause menu save button: " + ex.Message)); } } private void OpenPauseMenuSavePage(PauseMenuMainPage pauseMainPage) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Expected O, but got Unknown if ((Object)(object)pauseMainPage == (Object)null) { return; } if (PhotonNetwork.InRoom && !PhotonNetwork.IsMasterClient) { SetStatus("Only the host can open Save Manager.", Color.yellow, 2.5f); return; } UIPageHandler pageHandler = ((UIPage)pauseMainPage).GetPageHandler<UIPageHandler>(); if ((Object)(object)pageHandler == (Object)null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"Pause menu page handler not found."); return; } object? obj = AccessTools.Field(typeof(PauseMenuMainPage), "m_settingsButton")?.GetValue(pauseMainPage); Button settingsButtonTemplate = (Button)((obj is Button) ? obj : null); SaveManagerPausePage saveManagerPausePage = EnsurePauseMenuSavePage(pageHandler, (UIPage)(object)pauseMainPage, settingsButtonTemplate); if ((Object)(object)saveManagerPausePage == (Object)null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"Save manager pause page could not be created."); return; } saveManagerPausePage.RefreshFromSource(); pageHandler.TransistionToPage((UIPage)(object)saveManagerPausePage, (PageTransistion)new SetActivePageTransistion()); Cursor.visible = true; Cursor.lockState = (CursorLockMode)0; } private SaveManagerPausePage EnsurePauseMenuSavePage(UIPageHandler pageHandler, UIPage mainPage, Button settingsButtonTemplate) { //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)pageHandler == (Object)null || (Object)(object)mainPage == (Object)null) { return null; } if ((Object)(object)pauseMenuPage != (Object)null && (Object)(object)pauseMenuPageHandler == (Object)(object)pageHandler) { pauseMenuPage.Initialize(this, pageHandler, mainPage, settingsButtonTemplate); return pauseMenuPage; } SaveManagerPausePage saveManagerPausePage = pageHandler.GetPage<SaveManagerPausePage>() as SaveManagerPausePage; if ((Object)(object)saveManagerPausePage != (Object)null) { pauseMenuPage = saveManagerPausePage; pauseMenuPageHandler = pageHandler; pauseMenuMainPage = mainPage; pauseMenuButtonTemplate = settingsButtonTemplate; pauseMenuPage.Initialize(this, pageHandler, mainPage, settingsButtonTemplate); return pauseMenuPage; } GameObject val = new GameObject("PauseMenuSaveManagerPage", new Type[3] { typeof(RectTransform), typeof(Image), typeof(SaveManagerPausePage) }); RectTransform component = val.GetComponent<RectTransform>(); ((Transform)component).SetParent(((Component)pageHandler).transform, false); component.anchorMin = Vector2.zero; component.anchorMax = Vector2.one; component.offsetMin = Vector2.zero; component.offsetMax = Vector2.zero; ((Graphic)val.GetComponent<Image>()).color = new Color(0.02f, 0.05f, 0.1f, 0.75f); SaveManagerPausePage component2 = val.GetComponent<SaveManagerPausePage>(); AccessTools.Field(typeof(UIPage), "pageHandler")?.SetValue(component2, pageHandler); component2.Initialize(this, pageHandler, mainPage, settingsButtonTemplate); val.SetActive(false); object obj = AccessTools.Field(typeof(UIPageHandler), "_pages")?.GetValue(pageHandler); if (obj != null) { obj.GetType().GetMethod("Remove", new Type[1] { typeof(Type) })?.Invoke(obj, new object[1] { typeof(SaveManagerPausePage) }); MethodInfo method = obj.GetType().GetMethod("Add", new Type[2] { typeof(Type), typeof(UIPage) }); if (method != null) { method.Invoke(obj, new object[2] { typeof(SaveManagerPausePage), component2 }); } else { obj.GetType().GetMethod("Add")?.Invoke(obj, new object[2] { typeof(SaveManagerPausePage), component2 }); } } pauseMenuPage = component2; pauseMenuPageHandler = pageHandler; pauseMenuMainPage = mainPage; pauseMenuButtonTemplate = settingsButtonTemplate; return component2; } internal static bool TryInterceptPauseQuit(PauseMenuMainPage page) { if ((Object)(object)Instance != (Object)null) { return Instance.InterceptPauseQuit(page); } return false; } private bool InterceptPauseQuit(PauseMenuMainPage page) { //IL_0180: Unknown result type (might be due to invalid IL or missing references) //IL_018a: Expected O, but got Unknown //IL_01a4: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Expected O, but got Unknown if (allowVanillaQuitClick || (Object)(object)page == (Object)null) { return false; } if (!CanSaveNow(showReason: false)) { return false; } FieldInfo fieldInfo = AccessTools.Field(typeof(PauseMenuMainPage), "confirmWindow"); FieldInfo fieldInfo2 = AccessTools.Field(typeof(PauseMenuMainPage), "m_confirmOkButton"); FieldInfo fieldInfo3 = AccessTools.Field(typeof(PauseMenuMainPage), "m_confirmCancelButton"); FieldInfo fieldInfo4 = AccessTools.Field(typeof(PauseMenuMainPage), "confirmText"); MenuWindow confirmWindow = default(MenuWindow); ref MenuWindow reference = ref confirmWindow; object? obj = fieldInfo?.GetValue(page); reference = (MenuWindow)((obj is MenuWindow) ? obj : null); object? obj2 = fieldInfo2?.GetValue(page); Button val = (Button)((obj2 is Button) ? obj2 : null); object? obj3 = fieldInfo3?.GetValue(page); Button val2 = (Button)((obj3 is Button) ? obj3 : null); object? obj4 = fieldInfo4?.GetValue(page); LocalizedText val3 = (LocalizedText)((obj4 is LocalizedText) ? obj4 : null); if ((Object)(object)confirmWindow == (Object)null || (Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null) { return false; } quitPendingSaveDecision = true; quitPendingPage = page; OpenMenuWindow(confirmWindow); if (val3 != null) { val3.SetText("Would you like to save your game before quitting?"); } SetPauseMenuButtonText(((Component)val).gameObject, "YES"); SetPauseMenuButtonText(((Component)val2).gameObject, "NO"); ((UnityEventBase)val.onClick).RemoveAllListeners(); ((UnityEvent)val.onClick).AddListener((UnityAction)delegate { CloseMenuWindow(confirmWindow); OpenPauseMenuSavePage(page); }); ((UnityEventBase)val2.onClick).RemoveAllListeners(); ((UnityEvent)val2.onClick).AddListener((UnityAction)delegate { CloseMenuWindow(confirmWindow); quitPendingSaveDecision = false; quitPendingPage = null; ContinueWithVanillaQuit(page); }); return true; } private void ContinueWithVanillaQuit(PauseMenuMainPage page) { if ((Object)(object)page == (Object)null) { return; } try { allowVanillaQuitClick = true; MethodInfo methodInfo = AccessTools.Method(typeof(PauseMenuMainPage), "Quit", (Type[])null, (Type[])null); if (methodInfo != null) { methodInfo.Invoke(page, null); } else { AccessTools.Method(typeof(PauseMenuMainPage), "OnQuitClicked", (Type[])null, (Type[])null)?.Invoke(page, null); } } finally { allowVanillaQuitClick = false; } } private static void SetPauseMenuButtonText(GameObject buttonObject, string text) { if ((Object)(object)buttonObject == (Object)null) { return; } TMP_Text componentInChildren = buttonObject.GetComponentInChildren<TMP_Text>(true); if ((Object)(object)componentInChildren != (Object)null) { componentInChildren.text = text; componentInChildren.enableAutoSizing = true; componentInChildren.fontSizeMin = 13f; componentInChildren.fontSizeMax = 21f; componentInChildren.fontStyle = (FontStyles)16; componentInChildren.overflowMode = (TextOverflowModes)1; return; } Text componentInChildren2 = buttonObject.GetComponentInChildren<Text>(true); if ((Object)(object)componentInChildren2 != (Object)null) { componentInChildren2.text = text; componentInChildren2.fontStyle = (FontStyle)0; componentInChildren2.resizeTextForBestFit = true; componentInChildren2.resizeTextMinSize = 13; componentInChildren2.resizeTextMaxSize = 21; } } private static void OpenMenuWindow(MenuWindow window) { if ((Object)(object)window == (Object)null) { return; } try { MenuWindowOpenMethod?.Invoke(window, null); } catch { ((Component)window).gameObject.SetActive(true); } } private static void CloseMenuWindow(MenuWindow window) { if ((Object)(object)window == (Object)null) { return; } try { MenuWindowCloseMethod?.Invoke(window, null); } catch { ((Component)window).gameObject.SetActive(false); } } private static int GetLuggageState(Luggage luggage) { if ((Object)(object)luggage == (Object)null || LuggageStateField == null) { return 0; } try { object value = LuggageStateField.GetValue(luggage); return (value != null) ? Convert.ToInt32(value, CultureInfo.InvariantCulture) : 0; } catch { return 0; } } private static void SetLuggageStateRaw(Luggage luggage, int rawState) { if ((Object)(object)luggage == (Object)null || LuggageStateField == null) { return; } int num = Mathf.Max(0, rawState); try { Type fieldType = LuggageStateField.FieldType; if (fieldType != null && fieldType.IsEnum) { Array values = Enum.GetValues(fieldType); if (values != null && values.Length > 0) { int num2 = (from object value in values select Convert.ToInt32(value, CultureInfo.InvariantCulture)).DefaultIfEmpty(0).Max(); num = Mathf.Clamp(num, 0, num2); } } object value2 = ((fieldType != null && fieldType.IsEnum) ? Enum.ToObject(fieldType, num) : ((object)num)); LuggageStateField.SetValue(luggage, value2); } catch { } } private static PhotonView GetPhotonView(Component component) { if ((Object)(object)component == (Object)null) { return null; } PhotonView component2 = component.GetComponent<PhotonView>(); if ((Object)(object)component2 != (Object)null) { return component2; } return component.GetComponentInParent<PhotonView>(); } private static void SetRespawnChestState(RespawnChest respawnChest, bool isSpent, bool hasRevivedPlayers) { if ((Object)(object)respawnChest == (Object)null) { return; } try { RespawnChestSetSpentMethod?.Invoke(respawnChest, new object[1] { isSpent }); SetRespawnChestHasRevivedPlayers(respawnChest, hasRevivedPlayers); } catch { } } private static bool GetRespawnChestHasRevivedPlayers(RespawnChest respawnChest) { if ((Object)(object)respawnChest == (Object)null) { return false; } try { if (RespawnChestGetRevivedPlayersMethod?.Invoke(respawnChest, null) is bool result) { return result; } object obj = RespawnChestRevivedPlayersField?.GetValue(respawnChest); if (obj is bool) { return (bool)obj; } } catch { } return false; } private static void SetRespawnChestHasRevivedPlayers(RespawnChest respawnChest, bool hasRevivedPlayers) { if ((Object)(object)respawnChest == (Object)null) { return; } try { if (RespawnChestSetRevivedPlayersMethod != null) { RespawnChestSetRevivedPlayersMethod.Invoke(respawnChest, new object[1] { hasRevivedPlayers }); } else { RespawnChestRevivedPlayersField?.SetValue(respawnChest, hasRevivedPlayers); } } catch { } } private static string GetDayNightTimeString(DayNightManager dayNight) { if ((Object)(object)dayNight == (Object)null) { return string.Empty; } try { if ((DayNightTimeStringGetterMethod?.Invoke(dayNight, null) ?? DayNightTimeStringField?.GetValue(dayNight)) is string result) { return result; } } catch { } return string.Empty; } private static void SetDayNightTimeString(DayNightManager dayNight, string timeString) { if ((Object)(object)dayNight == (Object)null || string.IsNullOrWhiteSpace(timeString)) { return; } try { if (DayNightTimeStringSetterMethod != null) { DayNightTimeStringSetterMethod.Invoke(dayNight, new object[1] { timeString }); } else { DayNightTimeStringField?.SetValue(dayNight, timeString); } } catch { } } private bool CanSaveNow(bool showReason) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) if (IsInAirportScene()) { if (showReason) { SetStatus("You cannot save in the Airport.", Color.yellow, 3f); } return false; } if (PhotonNetwork.InRoom && !PhotonNetwork.IsMasterClient) { if (showReason) { SetStatus("Only host can save shared runs.", Color.yellow, 3f); } return false; } return true; } private bool TrySaveGame(string saveName) { //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) if (!CanSaveNow(showReason: true)) { return false; } try { if (!EnsureSaveDirectoryReady(showStatus: true)) { return false; } string text = NormalizeSaveDisplayName(saveName); SaveEnvelope saveEnvelope = CaptureSnapshot(text); if (saveEnvelope.players == null || saveEnvelope.players.Count == 0) { SetStatus("Could not find an active player to save. Try again in-run.", Color.yellow, 4f); ((BaseUnityPlugin)this).Logger.LogWarning((object)"Save aborted: snapshot captured 0 players."); return false; } string text2 = ResolveSavePathForName(text); string contents = JsonConvert.SerializeObject((object)saveEnvelope, (Formatting)1); File.WriteAllText(text2, contents); if (text.Equals("Autosave", StringComparison.OrdinalIgnoreCase)) { CleanupLegacyAutosaves(text2); } RefreshSaveFileList(); SetStatus("Saved: " + text, Color.green, 3f); ((BaseUnityPlugin)this).Logger.LogInfo((object)("Saved run to " + text2)); return true; } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)$"Save failed: {ex}"); SetStatus(BuildSaveFailureStatus(ex), Color.red, 6f); return false; } } private bool TryOverwriteSave(string fullPath, string saveNameHint) { //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) if (!CanSaveNow(showReason: true)) { return false; } if (string.IsNullOrWhiteSpace(fullPath)) { SetStatus("Invalid save path.", Color.red, 4f); return false; } try { if (!EnsureSaveDirectoryReady(showStatus: true)) { return false; } string text = NormalizeSaveDisplayName(string.IsNullOrWhiteSpace(saveNameHint) ? Path.GetFileNameWithoutExtension(fullPath) : saveNameHint.Trim()); SaveEnvelope saveEnvelope = CaptureSnapshot(text); if (saveEnvelope.players == null || saveEnvelope.players.Count == 0) { SetStatus("Could not find an active player to overwrite from. Try again in-run.", Color.yellow, 4f); ((BaseUnityPlugin)this).Logger.LogWarning((object)("Overwrite aborted for '" + fullPath + "': snapshot captured 0 players.")); return false; } string contents = JsonConvert.SerializeObject((object)saveEnvelope, (Formatting)1); File.WriteAllText(fullPath, contents); RefreshSaveFileList(); SetStatus("Overwrote save: " + text, Color.green, 3f); ((BaseUnityPlugin)this).Logger.LogInfo((object)("Overwrote run at " + fullPath)); return true; } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)$"Overwrite failed for '{fullPath}': {ex}"); SetStatus(BuildSaveFailureStatus(ex), Color.red, 6f); return false; } } internal void UiRefreshSaveList() { RefreshSaveFileList(); } internal List<SaveListEntry> UiGetSaveEntries() { return new List<SaveListEntry>(saveEntries); } internal void UiQuickSave() { bool saveSucceeded = TrySaveGame("Quick Save"); MaybeCompletePendingQuitAfterSave(saveSucceeded); } internal void UiNamedSave(string saveName) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrWhiteSpace(saveName)) { SetStatus("Enter a save name first.", Color.yellow, 3f); return; } bool saveSucceeded = TrySaveGame(saveName.Trim()); MaybeCompletePendingQuitAfterSave(saveSucceeded); } internal void UiLoadSave(string fullPath) { StartLoadFromUi(fullPath); } internal void UiOverwriteSave(string fullPath, string saveNameHint) { bool saveSucceeded = TryOverwriteSave(fullPath, saveNameHint); MaybeCompletePendingQuitAfterSave(saveSucceeded); } internal void UiDeleteSave(string fullPath) { TryDeleteSave(fullPath); } internal bool UiCanSaveNow(bool showReason = false) { return CanSaveNow(showReason); } internal bool UiIsLoading() { return isLoading; } internal string UiCurrentStatus() { if (string.IsNullOrWhiteSpace(statusMessage)) { return string.Empty; } if (statusMessageUntil <= Time.unscaledTime) { return string.Empty; } return statusMessage; } internal bool UiHasPendingQuitSaveDecision() { return quitPendingSaveDecision; } internal void UiQuickSaveAndQuit() { if (CanSaveNow(showReason: true) && TrySaveGame("Quick Save")) { CompletePendingQuit(); } } internal void UiNamedSaveAndQuit(string saveName) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) if (CanSaveNow(showReason: true)) { if (string.IsNullOrWhiteSpace(saveName)) { SetStatus("Enter a save name before Save & Quit.", Color.yellow, 3f); } else if (TrySaveGame(saveName.Trim())) { CompletePendingQuit(); } } } internal void UiQuitWithoutSaving() { CompletePendingQuit(); } internal void UiCancelPendingQuit() { quitPendingSaveDecision = false; quitPendingPage = null; } private void MaybeCompletePendingQuitAfterSave(bool saveSucceeded) { if (saveSucceeded && quitPendingSaveDecision) { CompletePendingQuit(); } } private void CompletePendingQuit() { PauseMenuMainPage page = quitPendingPage; quitPendingSaveDecision = false; quitPendingPage = null; ContinueWithVanillaQuit(page); } private SaveEnvelope CaptureSnapshot(string saveName) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Expected I4, but got Unknown Scene activeScene = SceneManager.GetActiveScene(); string name = ((Scene)(ref activeScene)).name; LevelGeneration val = Object.FindFirstObjectByType<LevelGeneration>(); int levelSeed = (((Object)(object)val != (Object)null) ? val.seed : 0); int currentSegment = 0; Segment val2 = (Segment)0; string currentSegmentName = ((object)(Segment)(ref val2)).ToString(); if (MapHandler.Exists) { MapHandler val3 = Object.FindFirstObjectByType<MapHandler>(); if ((Object)(object)val3 != (Object)null) { Segment currentSegment2 = val3.GetCurrentSegment(); currentSegment = (int)currentSegment2; currentSegmentName = ((object)(Segment)(ref currentSegment2)).ToString(); } } int? dailyLevelIndex = null; string biomeId = string.Empty; try { NextLevelService service = GameHandler.GetService<NextLevelService>(); if (service != null && service.HasReceivedLevelIndex) { dailyLevelIndex = service.NextLevelIndexOrFallback; biomeId = SingletonAsset<MapBaker>.Instance.GetBiomeID(dailyLevelIndex.Value + NextLevelService.debugLevelIndexOffset); } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not capture NextLevelService metadata: " + ex.Message)); } string text = ResolveLevelName(name, dailyLevelIndex); int? levelNumber = ParseLevelNumber(text); CaptureRunMetadata(out var runDay, out var runTimeSeconds, out var runTimerActive, out var timeOfDay, out var inGameTime); SaveEnvelope saveEnvelope = new SaveEnvelope { pluginGuid = "com.lucasandersen.peakallyouneedsavemanager", pluginVersion = "1.0.0", metadata = new SaveMetadata { saveName = saveName, savedAtUtc = DateTime.UtcNow, sceneName = name, levelName = text, levelNumber = levelNumber, dailyLevelIndex = dailyLevelIndex, biomeId = biomeId, levelSeed = levelSeed, currentSegment = currentSegment, currentSegmentName = currentSegmentName, ascent = Ascents.currentAscent, runDay = runDay, runTimeSeconds = runTimeSeconds, runTimerActive = runTimerActive, timeOfDay = timeOfDay, inGameTime = inGameTime } }; CapturePlayers(saveEnvelope.players); saveEnvelope.metadata.playerCount = saveEnvelope.players.Count; CaptureCampfires(saveEnvelope.campfires); CaptureLuggageStates(saveEnvelope.luggageStates); CaptureContainerStates(saveEnvelope.containerStates); CaptureGroundItems(saveEnvelope.groundItems); CaptureWorldObjects(saveEnvelope.worldObjects); return saveEnvelope; } private static void CaptureRunMetadata(out int? runDay, out float? runTimeSeconds, out bool? runTimerActive, out float? timeOfDay, out string inGameTime) { runDay = null; runTimeSeconds = null; runTimerActive = null; timeOfDay = null; inGameTime = string.Empty; try { DayNightManager val = DayNightManager.instance ?? Object.FindFirstObjectByType<DayNightManager>(); if ((Object)(object)val != (Object)null) { runDay = Mathf.Max(0, val.dayCount); timeOfDay = val.timeOfDay; string dayNightTimeString = GetDayNightTimeString(val); if (!string.IsNullOrWhiteSpace(dayNightTimeString)) { inGameTime = dayNightTimeString; } else { inGameTime = val.FloatToTimeString(val.timeOfDay); } } } catch (Exception ex) { SaveManagerPlugin instance = Instance; if (instance != null) { ((BaseUnityPlugin)instance).Logger.LogWarning((object)("Could not capture day/night metadata: " + ex.Message)); } } try { RunManager val2 = RunManager.Instance ?? Object.FindFirstObjectByType<RunManager>(); if ((Object)(object)val2 != (Object)null) { runTimeSeconds = Mathf.Max(0f, val2.timeSinceRunStarted); runTimerActive = TryGetRunTimerActive(val2); } } catch (Exception ex2) { SaveManagerPlugin instance2 = Instance; if (instance2 != null) { ((BaseUnityPlugin)instance2).Logger.LogWarning((object)("Could not capture run timer metadata: " + ex2.Message)); } } } private static bool? TryGetRunTimerActive(RunManager runManager) { if ((Object)(object)runManager == (Object)null || RunManagerTimerActiveField == null) { return null; } try { object value = RunManagerTimerActiveField.GetValue(runManager); if (value is bool) { return (bool)value; } } catch { } return null; } private void CapturePlayers(List<PlayerSnapshot> output) { Player[] array = Object.FindObjectsByType<Player>((FindObjectsSortMode)0); foreach (Player player in array) { try { output.Add(CapturePlayer(player)); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Failed to snapshot player: " + ex.Message)); } } if (output.Count > 0) { return; } Character[] array2 = Object.FindObjectsByType<Character>((FindObjectsSortMode)0); foreach (Character val in array2) { if ((Object)(object)val == (Object)null) { continue; } Player val2 = ((Component)val).GetComponent<Player>() ?? ((Component)val).GetComponentInParent<Player>(); if (!((Object)(object)val2 == (Object)null)) { try { output.Add(CapturePlayer(val2)); } catch (Exception ex2) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Failed to snapshot fallback player: " + ex2.Message)); } if (output.Count > 0) { break; } } } if (output.Count > 0) { return; } foreach (Player item in EnumeratePlayersFromHandler()) { if (!((Object)(object)item == (Object)null)) { try { output.Add(CapturePlayer(item)); } catch (Exception ex3) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Failed to snapshot handler fallback player: " + ex3.Message)); } if (output.Count > 0) { break; } } } } [IteratorStateMachine(typeof(<EnumeratePlayersFromHandler>d__155))] private static IEnumerable<Player> EnumeratePlayersFromHandler() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <EnumeratePlayersFromHandler>d__155(-2); } private PlayerSnapshot CapturePlayer(Player player) { //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) string text = "Unknown"; int actorNumber = 0; PhotonView photonView = GetPhotonView((Component)(object)player); if ((Object)(object)photonView == (Object)null && (Object)(object)player != (Object)null && (Object)(object)player.character != (Object)null) { photonView = GetPhotonView((Component)(object)player.character); } if ((Object)(object)photonView != (Object)null) { Player owner = photonView.Owner; if (owner != null) { text = owner.NickName; actorNumber = owner.ActorNumber; } else { actorNumber = photonView.OwnerActorNr; } } Character character = player.character; Vector3 source = (((Object)(object)character != (Object)null) ? GetCharacterPosition(character) : ((Component)player).transform.position); Vector3 source2 = (((Object)(object)character != (Object)null) ? ((Component)character).transform.eulerAngles : ((Component)player).transform.eulerAngles); CaptureCharacterVelocity(character, out var velocity, out var angularVelocity); InventorySnapshot inventory; try { inventory = CaptureInventory(player, character); } catch (Exception ex) { SaveManagerPlugin instance = Instance; if (instance != null) { ((BaseUnityPlugin)instance).Logger.LogWarning((object)("Inventory capture fallback for player '" + text + "': " + ex.Message)); } inventory = new InventorySnapshot(); } return new PlayerSnapshot { playerName = text, actorNumber = actorNumber, position = new Vector3Snapshot(source), rotation = new Vector3Snapshot(source2), velocity = new Vector3Snapshot(velocity), angularVelocity = new Vector3Snapshot(angularVelocity), character = CaptureCharacter(character), inventory = inventory }; } private static CharacterSnapshot CaptureCharacter(Character character) { //IL_00d3: Unknown result type (might be due to invalid IL or missing references) CharacterSnapshot characterSnapshot = new CharacterSnapshot(); if ((Object)(object)character == (Object)null) { return characterSnapshot; } characterSnapshot.dead = character.data.dead; characterSnapshot.passedOut = character.data.passedOut; characterSnapshot.fullyPassedOut = character.data.fullyPassedOut; characterSnapshot.isGrounded = character.data.isGrounded; characterSnapshot.isClimbing = character.data.isClimbing; characterSnapshot.isRopeClimbing = character.data.isRopeClimbing; characterSnapshot.isVineClimbing = character.data.isVineClimbing; characterSnapshot.isSprinting = character.data.isSprinting; characterSnapshot.currentStamina = character.data.currentStamina; characterSnapshot.extraStamina = character.data.extraStamina; characterSnapshot.sinceGrounded = character.data.sinceGrounded; characterSnapshot.lookValues = new Vector2Snapshot(character.data.lookValues); characterSnapshot.checkpointFlagPaths = CaptureCharacterCheckpointPaths(character); characterSnapshot.statuses = CaptureCharacterStatuses(character); return characterSnapshot; } private static List<string> CaptureCharacterCheckpointPaths(Character character) { List<string> list = new List<string>(); if ((Object)(object)character == (Object)null || (Object)(object)character.data == (Object)null || CharacterDataCheckpointFlagsField == null) { return list; } try { if (CharacterDataCheckpointFlagsField.GetValue(character.data) is IEnumerable enumerable) { foreach (object item in enumerable) { CheckpointFlag val = (CheckpointFlag)((item is CheckpointFlag) ? item : null); if (val != null && (Object)(object)val != (Object)null) { string text = BuildTransformPath(((Component)val).transform); if (!string.IsNullOrWhiteSpace(text)) { list.Add(text); } } } } } catch { } return list; } private static void CaptureCharacterVelocity(Character character, out Vector3 velocity, out Vector3 angularVelocity) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) velocity = Vector3.zero; angularVelocity = Vector3.zero; if (!((Object)(object)character == (Object)null)) { Rigidbody val = ((character.refs != null && (Object)(object)character.refs.hip != (Object)null) ? character.refs.hip.Rig : null); if ((Object)(object)val != (Object)null) { velocity = val.linearVelocity; angularVelocity = val.angularVelocity; } else if ((Object)(object)character.data != (Object)null) { velocity = character.data.avarageVelocity; angularVelocity = character.data.avarageLastFrameVelocity; } } } private static List<CharacterStatusSnapshot> CaptureCharacterStatuses(Character character) { //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) List<CharacterStatusSnapshot> list = new List<CharacterStatusSnapshot>(); if ((Object)(object)character == (Object)null || character.refs == null || (Object)(object)character.refs.afflictions == (Object)null) { return list; } CharacterAfflictions afflictions = character.refs.afflictions; Array values = Enum.GetValues(typeof(STATUSTYPE)); for (int i = 0; i < values.Length; i++) { STATUSTYPE val = (STATUSTYPE)values.GetValue(i); if (!SkippedSavedStatuses.Contains(val)) { float currentStatus = afflictions.GetCurrentStatus(val); if (!(currentStatus <= 0f)) { list.Add(new CharacterStatusSnapshot { statusType = ((object)(STATUSTYPE)(ref val)).ToString(), amount = currentStatus }); } } } return list; } private static InventorySnapshot CaptureInventory(Player player, Character character) { InventorySnapshot inventorySnapshot = new InventorySnapshot(); if ((Object)(object)player == (Object)null) { return inventorySnapshot; } if (player.itemSlots != null) { for (int i = 0; i < player.itemSlots.Length; i++) { inventorySnapshot.mainSlots.Add(CaptureItemSlot(player.itemSlots[i])); } } inventorySnapshot.tempSlot = CaptureItemSlot(player.tempFullSlot); inventorySnapshot.hasBackpack = player.backpackSlot != null && player.backpackSlot.hasBackpack; if (inventorySnapshot.hasBackpack && TryGetBackpackData(player, out var backpackData) && backpackData != null && backpackData.itemSlots != null) { for (int j = 0; j < backpackData.itemSlots.Length; j++) { inventorySnapshot.backpackSlots.Add(CaptureItemSlot(backpackData.itemSlots[j])); } } CaptureEquippedSelection(player, character, inventorySnapshot); return inventorySnapshot; } private static void CaptureEquippedSelection(Player player, Character character, InventorySnapshot snapshot) { if (snapshot == null) { return; } Item val = (((Object)(object)character != (Object)null && (Object)(object)character.data != (Object)null) ? character.data.currentItem : null); if ((Object)(object)val != (Object)null) { snapshot.heldItemId = val.itemID; } if (TryGetCharacterSelectedSlot(character, out var selectedSlot)) { snapshot.selectedSlotId = selectedSlot; if ((Object)(object)player != (Object)null && player.itemSlots != null && selectedSlot >= 0 && selectedSlot < player.itemSlots.Length) { snapshot.equippedMainSlotIndex = selectedSlot; } } if (!snapshot.equippedMainSlotIndex.HasValue && snapshot.heldItemId != ushort.MaxValue && (Object)(object)player != (Object)null && player.itemSlots != null) { for (int i = 0; i < player.itemSlots.Length; i++) { ItemSlot val2 = player.itemSlots[i]; if (val2 != null && (Object)(object)val2.prefab != (Object)null && val2.prefab.itemID == snapshot.heldItemId) { snapshot.equippedMainSlotIndex = i; break; } } } if (snapshot.heldItemId != ushort.MaxValue && (Object)(object)player != (Object)null && player.tempFullSlot != null && (Object)(object)player.tempFullSlot.prefab != (Object)null && player.tempFullSlot.prefab.itemID == snapshot.heldItemId) { snapshot.equippedTempSlot = true; } if (snapshot.heldItemId == ushort.MaxValue || !((Object)(object)player != (Object)null) || !TryGetBackpackData(player, out var backpackData) || backpackData == null || backpackData.itemSlots == null) { return; } for (int j = 0; j < backpackData.itemSlots.Length; j++) { ItemSlot val3 = backpackData.itemSlots[j]; if (val3 != null && (Object)(object)val3.prefab != (Object)null && val3.prefab.itemID == snapshot.heldItemId) { snapshot.equippedBackpackSlotIndex = j; break; } } } private static ItemSlotSnapshot CaptureItemSlot(ItemSlot slot) { if (slot == null || (Object)(object)slot.prefab == (Object)null) { return ItemSlotSnapshot.Empty(); } ItemSlotSnapshot itemSlotSnapshot = new ItemSlotSnapshot { itemId = slot.prefab.itemID }; CaptureItemUsageData(slot.data, itemSlotSnapshot); return itemSlotSnapshot; } private static void CaptureItemUsageData(ItemInstanceData data, ItemSlotSnapshot snapshot) { if (data != null && snapshot != null) { if (TryReadItemUsageInt(data, (DataEntryKey)2, out var value)) { snapshot.itemUses = value; } if (TryReadItemUsageInt(data, (DataEntryKey)12, out var value2)) { snapshot.petterItemUses = value2; } if (TryReadItemUsageFloat(data, (DataEntryKey)11, out var value3)) { snapshot.useRemainingPercentage = value3; } if (TryReadItemUsageBool(data, (DataEntryKey)8, out var value4)) { snapshot.used = value4; } if (TryReadItemUsageFloat(data, (DataEntryKey)10, out var value5)) { snapshot.fuel = value5; } if (TryReadItemUsageInt(data, (DataEntryKey)1, out var value6)) { snapshot.cookedAmount = value6; } if (TryReadItemUsageBool(data, (DataEntryKey)3, out var value7)) { snapshot.flareActive = value7; } if (TryReadItemUsageFloat(data, (DataEntryKey)13, out var value8)) { snapshot.screamTime = value8; } if (TryReadItemUsageBool(data, (DataEntryKey)5, out var value9)) { snapshot.spawnedBees = value9; } CaptureGenericItemData(data, snapshot.dataEntries); } } private static void CaptureItemUsageData(ItemInstanceData data, GroundItemSnapshot snapshot) { if (data != null && snapshot != null) { if (TryReadItemUsageInt(data, (DataEntryKey)2, out var value)) { snapshot.itemUses = value; } if (TryReadItemUsageInt(data, (DataEntryKey)12, out var value2)) { snapshot.petterItemUses = value2; } if (TryReadItemUsageFloat(data, (DataEntryKey)11, out var value3)) { snapshot.useRemainingPercentage = value3; } if (TryReadItemUsageBool(data, (DataEntryKey)8, out var value4)) { snapshot.used = value4; } if (TryReadItemUsageFloat(data, (DataEntryKey)10, out var value5)) { snapshot.fuel = value5; } if (TryReadItemUsageInt(data, (DataEntryKey)1, out var value6)) { snapshot.cookedAmount = value6; } if (TryReadItemUsageBool(data, (DataEntryKey)3, out var value7)) { snapshot.flareActive = value7; } if (TryReadItemUsageFloat(data, (DataEntryKey)13, out var value8)) { snapshot.screamTime = value8; } if (TryReadItemUsageBool(data, (DataEntryKey)5, out var value9)) { snapshot.spawnedBees = value9; } CaptureGenericItemData(data, snapshot.dataEntries); } } private static bool TryReadItemUsageInt(ItemInstanceData data, DataEntryKey key, out int value) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) value = 0; if (!TryGetRawDataEntry(data, key, out var value2) || value2 == null) { return false; } OptionableIntItemData val = (OptionableIntItemData)(object)((value2 is OptionableIntItemData) ? value2 : null); if (val != null && TryReadOptionableInt(val, out var value3)) { value = value3; return true; } IntItemData val2 = (IntItemData)(object)((value2 is IntItemData) ? value2 : null); if (val2 != null) { value = val2.Value; return true; } FloatItemData val3 = (FloatItemData)(object)((value2 is FloatItemData) ? value2 : null); if (val3 != null) { value = Mathf.RoundToInt(val3.Value); return true; } BoolItemData val4 = (BoolItemData)(object)((value2 is BoolItemData) ? value2 : null); if (val4 != null) { value = (val4.Value ? 1 : 0); return true; } return false; } private static bool TryReadItemUsageFloat(ItemInstanceData data, DataEntryKey key, out float value) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) value = 0f; if (!TryGetRawDataEntry(data, key, out var value2) || value2 == null) { return false; } OptionableIntItemData val = (OptionableIntItemData)(object)((value2 is OptionableIntItemData) ? value2 : null); if (val != null && TryReadOptionableInt(val, out var value3)) { value = value3; return true; } FloatItemData val2 = (FloatItemData)(object)((value2 is FloatItemData) ? value2 : null); if (val2 != null) { value = val2.Value; return true; } IntItemData val3 = (IntItemData)(object)((value2 is IntItemData) ? value2 : null); if (val3 != null) { value = val3.Value; return true; } return false; } private static bool TryReadItemUsageBool(ItemInstanceData data, DataEntryKey key, out bool value) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) value = false; if (!TryGetRawDataEntry(data, key, out var value2) || value2 == null) { return false; } OptionableBoolItemData val = (OptionableBoolItemData)(object)((value2 is OptionableBoolItemData) ? value2 : null); if (val != null && TryReadOptionableBool(val, out var value3)) { value = value3; return true; } BoolItemData val2 = (BoolItemData)(object)((value2 is BoolItemData) ? value2 : null); if (val2 != null) { value = val2.Value; return true; } IntItemData val3 = (IntItemData)(object)((value2 is IntItemData) ? value2 : null); if (val3 != null) { value = val3.Value > 0; return true; } return false; } private static bool TryReadOptionableInt(OptionableIntItemData data, out int value) { value = 0; if (data == null) { return false; } bool flag = true; if (OptionableIntHasDataField != null) { try { object value2 = OptionableIntHasDataField.GetValue(data); if (value2 is bool) { bool flag2 = (bool)value2; flag = flag2; } } catch { } } if (!flag) { return false; } if (OptionableIntValueField != null) { try { object value3 = OptionableIntValueField.GetValue(data); if (value3 is int) { int num = (int)value3; value = num; return true; } } catch { } } return false; } private static bool TryReadOptionableBool(OptionableBoolItemData data, out bool value) { value = false; if (data == null) { return false; } bool flag = true; if (OptionableBoolHasDataField != null) { try { object value2 = OptionableBoolHasDataField.GetValue(data); if (value2 is bool) { bool flag2 = (bool)value2; flag = flag2; } } catch { } } if (!flag) { return false; } if (OptionableBoolValueField != null) { try { object value3 = OptionableBoolValueField.GetValue(data); if (value3 is bool) { bool flag3 = (bool)value3; value = flag3; return true; } } catch { } } return false; } private static bool TryGetRawDataEntry(ItemInstanceData data, DataEntryKey key, out DataEntryValue value) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) value = null; if (data == null || data.data == null) { return false; } try { if (data.data.TryGetValue(key, out var value2) && value2 != null) { value = value2; return true; } } catch { } return false; } private static void CaptureGenericItemData(ItemInstanceData data, List<ItemDataEntrySnapshot> output) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) if (data == null || output == null || data.data == null) { return; } output.Clear(); foreach (KeyValuePair<DataEntryKey, DataEntryValue> datum in data.data) { if (TryCreateItemDataEntrySnapshot(datum.Key, datum.Value, out var snapshot)) { output.Add(snapshot); } } } private static bool TryCreateItemDataEntrySnapshot(DataEntryKey key, DataEntryValue value, out ItemDataEntrySnapshot snapshot) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Expected I4, but got Unknown //IL_0166: Unknown result type (might be due to invalid IL or missing references) snapshot = null; if (value == null) { return false; } snapshot = new ItemDataEntrySnapshot { keyValue = (int)key, keyName = ((object)(DataEntryKey)(ref key)).ToString(), valueType = ((object)value).GetType().AssemblyQualifiedName, hasValue = true }; IntItemData val = (IntItemData)(object)((value is IntItemData) ? value : null); if (val == null) { FloatItemData val2 = (FloatItemData)(object)((value is FloatItemData) ? value : null); if (val2 == null) { BoolItemData val3 = (BoolItemData)(object)((value is BoolItemData) ? value : null); if (val3 == null) { OptionableIntItemData val4 = (OptionableIntItemData)(object)((value is OptionableIntItemData) ? value : null); if (val4 == null) { OptionableBoolItemData val5 = (OptionableBoolItemData)(object)((value is OptionableBoolItemData) ? value : null); if (val5 == null) { ColorItemData val6 = (ColorItemData)(object)((value is ColorItemData) ? value : null); if (val6 == null) { BackpackData val7 = (BackpackData)(object)((value is BackpackData) ? value : null); if (val7 != null) { if (val7.itemSlots != null) { for (int i = 0; i < val7.itemSlots.Length; i++) { snapshot.backpackSlots.Add(CaptureItemSlot(val7.itemSlots[i])); } } return true; } try { snapshot.serializedJson = JsonConvert.SerializeObject((object)value, (Formatting)0); return true; } catch { snapshot.serializedJson = ((object)value).ToString(); snapshot.stringValue = ((object)value).ToString(); return true; } } snapshot.hasColorValue = true; snapshot.colorValue = new Vector4Snapshot(new Vector4(val6.Value.r, val6.Value.g, val6.Value.b, val6.Value.a)); retu