The BepInEx console will not appear when launching like it does for other games on Thunderstore. This is normal (and helps prevent crashes during startup). You can turn it back on in your BepInEx.cfg file.
Decompiled source of PEAK Save Manager v1.0.1
BepInEx/plugins/PEAKSaveManager.dll
Decompiled a week agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Newtonsoft.Json; using PEAKSaveManager.Patches; using Photon.Pun; using Photon.Realtime; using UnityEngine; using UnityEngine.SceneManagement; using Zorro.Core.Serizalization; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("PEAKSaveManager")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("PEAKSaveManager")] [assembly: AssemblyCopyright("Copyright © 2025")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("06cb7bdd-b341-45d6-bfcf-dabd9498a75c")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyVersion("1.0.0.0")] namespace PEAKSaveManager { [BepInPlugin("com.maxbridgland.peaksavemanager", "PEAK Save Manager", "1.0.1")] public class SaveManagerMod : BaseUnityPlugin { [CompilerGenerated] private sealed class <ApplyLoadedDataCoroutine>d__44 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public GameSaveData saveData; public SaveManagerMod <>4__this; public string fileName; private int <successCount>5__2; private int <totalPlayers>5__3; private List<PlayerSaveData>.Enumerator <>7__wrap3; private PlayerSaveData <playerData>5__5; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <ApplyLoadedDataCoroutine>d__44(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || (uint)(num - 2) <= 1u) { try { } finally { <>m__Finally1(); } } <>7__wrap3 = default(List<PlayerSaveData>.Enumerator); <playerData>5__5 = null; <>1__state = -2; } private bool MoveNext() { //IL_026a: Unknown result type (might be due to invalid IL or missing references) //IL_0274: Expected O, but got Unknown //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Expected O, but got Unknown //IL_0111: Unknown result type (might be due to invalid IL or missing references) try { int num = <>1__state; SaveManagerMod saveManagerMod = <>4__this; switch (num) { default: return false; case 0: <>1__state = -1; Logger.LogInfo((object)$"Loading save data with {saveData.players.Count} players"); saveManagerMod.ShowStatusMessage("Loading: " + fileName + "...", 5f); if ((Object)(object)Object.FindFirstObjectByType<MapHandler>() != (Object)null) { MethodInfo methodInfo = AccessTools.Method(typeof(MapHandler), "JumpToSegmentLogic", new Type[3] { typeof(Segment), typeof(HashSet<int>), typeof(bool) }, (Type[])null); HashSet<int> hashSet = (from player in PlayerHandler.GetAllPlayers() select ((MonoBehaviourPun)player).photonView.Owner.ActorNumber).ToHashSet(); methodInfo.Invoke(null, new object[3] { saveManagerMod.StringToSegment(saveData.mapSegment), hashSet, true }); } <>2__current = (object)new WaitForSeconds(1f); <>1__state = 1; return true; case 1: <>1__state = -1; <successCount>5__2 = 0; <totalPlayers>5__3 = saveData.players.Count; <>7__wrap3 = saveData.players.GetEnumerator(); <>1__state = -3; goto IL_02c2; case 2: <>1__state = -3; saveManagerMod.playersBeingLoaded.Remove(<playerData>5__5.actorNumber); <successCount>5__2++; <>2__current = (object)new WaitForSeconds(0.5f); <>1__state = 3; return true; case 3: { <>1__state = -3; goto IL_02bb; } IL_02c2: if (<>7__wrap3.MoveNext()) { <playerData>5__5 = <>7__wrap3.Current; Player val = saveManagerMod.FindPlayerByActorNumber(<playerData>5__5.actorNumber); if ((Object)(object)val != (Object)null) { Logger.LogInfo((object)$"Loading data for player: {<playerData>5__5.playerName} (Actor: {<playerData>5__5.actorNumber})"); saveManagerMod.playersBeingLoaded.Add(<playerData>5__5.actorNumber); <>2__current = ((MonoBehaviour)saveManagerMod).StartCoroutine(saveManagerMod.ApplyPlayerDataCoroutine(val, <playerData>5__5)); <>1__state = 2; return true; } Logger.LogWarning((object)$"Could not find player with actor number: {<playerData>5__5.actorNumber} ({<playerData>5__5.playerName})"); goto IL_02bb; } <>m__Finally1(); <>7__wrap3 = default(List<PlayerSaveData>.Enumerator); saveManagerMod.isLoading = false; if (<successCount>5__2 > 0) { saveManagerMod.ShowStatusMessage($"Loaded {<successCount>5__2}/{<totalPlayers>5__3} players successfully", 3f); Logger.LogInfo((object)$"Successfully loaded {<successCount>5__2}/{<totalPlayers>5__3} players"); } else { saveManagerMod.ShowStatusMessage("Failed to load any players", 3f); Logger.LogWarning((object)"Failed to load any players"); } return false; IL_02bb: <playerData>5__5 = null; goto IL_02c2; } } 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; ((IDisposable)<>7__wrap3).Dispose(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <ApplyPlayerDataCoroutine>d__46 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public PlayerSaveData data; public Player player; public SaveManagerMod <>4__this; private Character <character>5__2; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <ApplyPlayerDataCoroutine>d__46(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <character>5__2 = null; <>1__state = -2; } private bool MoveNext() { //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_0295: Unknown result type (might be due to invalid IL or missing references) //IL_029f: Expected O, but got Unknown //IL_01fb: Unknown result type (might be due to invalid IL or missing references) //IL_0205: Expected O, but got Unknown int num = <>1__state; SaveManagerMod saveManagerMod = <>4__this; switch (num) { default: return false; case 0: <>1__state = -1; Logger.LogInfo((object)$"Starting to apply data for {data.playerName} (Actor: {data.actorNumber})"); <character>5__2 = player.character; if ((Object)(object)<character>5__2 == (Object)null) { Logger.LogError((object)("No character component found for player " + data.playerName)); return false; } Logger.LogInfo((object)$"Character state before load - Dead: {<character>5__2.data.dead}, PassedOut: {<character>5__2.data.passedOut}, FullyPassedOut: {<character>5__2.data.fullyPassedOut}"); Logger.LogInfo((object)$"Target position: {data.position.ToVector3()}, Current position: {((Component)<character>5__2).transform.position}"); if (<character>5__2.data.dead || <character>5__2.data.fullyPassedOut) { Logger.LogInfo((object)("Player " + data.playerName + " is dead or passed out, checking if we should revive...")); if (data.characterState != null && !data.characterState.dead && !data.characterState.fullyPassedOut) { Logger.LogInfo((object)("Reviving player " + data.playerName + " to match saved state")); ((MonoBehaviourPun)<character>5__2).photonView.RPC("RPCA_Revive", (RpcTarget)0, new object[1] { false }); <>2__current = (object)new WaitForSeconds(1f); <>1__state = 1; return true; } Logger.LogInfo((object)("Skipping position load for " + data.playerName + " - player should remain dead/passed out")); saveManagerMod.ApplyInventoryData(player, data.inventory); return false; } goto IL_0254; case 1: <>1__state = -1; goto IL_0254; case 2: <>1__state = -1; <>2__current = ((MonoBehaviour)saveManagerMod).StartCoroutine(saveManagerMod.ApplyPlayerPositionCoroutine(<character>5__2, data)); <>1__state = 3; return true; case 3: { <>1__state = -1; Logger.LogInfo((object)("Finished applying all data for player: " + data.playerName)); return false; } IL_0254: saveManagerMod.ApplyInventoryData(player, data.inventory); if (data.characterState != null) { saveManagerMod.ApplyCharacterState(<character>5__2, data.characterState); } <>2__current = (object)new WaitForSeconds(0.5f); <>1__state = 2; return true; } } 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 <ApplyPlayerPositionCoroutine>d__49 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public PlayerSaveData data; public Character character; public SaveManagerMod <>4__this; private Vector3 <targetRotation>5__2; private Vector3 <safePosition>5__3; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <ApplyPlayerPositionCoroutine>d__49(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: 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_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Expected O, but got Unknown //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_02a3: Unknown result type (might be due to invalid IL or missing references) //IL_02b8: Unknown result type (might be due to invalid IL or missing references) //IL_01f3: Unknown result type (might be due to invalid IL or missing references) //IL_030c: Unknown result type (might be due to invalid IL or missing references) //IL_0322: Unknown result type (might be due to invalid IL or missing references) //IL_0228: Unknown result type (might be due to invalid IL or missing references) //IL_0258: Unknown result type (might be due to invalid IL or missing references) //IL_024c: Unknown result type (might be due to invalid IL or missing references) //IL_025d: Unknown result type (might be due to invalid IL or missing references) //IL_038c: Unknown result type (might be due to invalid IL or missing references) //IL_039d: Unknown result type (might be due to invalid IL or missing references) //IL_03ae: Unknown result type (might be due to invalid IL or missing references) int num = <>1__state; SaveManagerMod saveManagerMod = <>4__this; switch (num) { default: return false; case 0: { <>1__state = -1; Logger.LogInfo((object)("Starting position loading for " + data.playerName)); Vector3 val = data.position.ToVector3(); <targetRotation>5__2 = data.rotation.ToVector3(); Logger.LogInfo((object)$"Target position: {val}, Target rotation: {<targetRotation>5__2}"); Logger.LogInfo((object)$"Current position: {((Component)character).transform.position}, Current rotation: {((Component)character).transform.eulerAngles}"); val.y += 2f; <safePosition>5__3 = saveManagerMod.FindSafeSpawnPosition(val); Logger.LogInfo((object)$"Safe position calculated: {<safePosition>5__3}"); Player owner = ((MonoBehaviourPun)character).photonView.Owner; Logger.LogInfo((object)$"Sending WarpPlayerRPC to {owner.NickName} (Actor: {owner.ActorNumber})"); ((MonoBehaviourPun)character).photonView.RPC("WarpPlayerRPC", owner, new object[2] { <safePosition>5__3, false }); <>2__current = (object)new WaitForSeconds(2f); <>1__state = 1; return true; } case 1: { <>1__state = -1; float num2 = Vector3.Distance(((Component)character).transform.position, <safePosition>5__3); Logger.LogInfo((object)$"Position verification - Distance from target: {num2:F2}"); if (num2 < 10f) { Logger.LogInfo((object)$"Position loaded successfully for {data.playerName}. Final position: {((Component)character).transform.position}"); if (((MonoBehaviourPun)character).photonView.IsMine) { ((Component)character).transform.eulerAngles = <targetRotation>5__2; character.data.lookValues = data.characterState?.lookValues.ToVector2() ?? Vector2.zero; CharacterAccessibilityPatches.CallRecalculateLookDirections(character); } } else { Logger.LogWarning((object)$"Position may not have loaded correctly for {data.playerName}. Distance from target: {num2:F2}"); Logger.LogWarning((object)$"Expected: {<safePosition>5__3}, Actual: {((Component)character).transform.position}"); if (((MonoBehaviourPun)character).photonView.IsMine) { Logger.LogInfo((object)("Attempting direct position setting for " + data.playerName)); ((Component)character).transform.position = <safePosition>5__3; ((Component)character).transform.eulerAngles = <targetRotation>5__2; if ((Object)(object)character.refs.ragdoll != (Object)null) { foreach (Bodypart part in character.refs.ragdoll.partList) { if ((Object)(object)((part != null) ? part.Rig : null) != (Object)null) { part.Rig.position = <safePosition>5__3; part.Rig.linearVelocity = Vector3.zero; part.Rig.angularVelocity = Vector3.zero; } } } } } 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 PLUGIN_GUID = "com.maxbridgland.peaksavemanager"; public const string PLUGIN_NAME = "PEAK Save Manager"; public const string PLUGIN_VERSION = "1.0.1"; private static SaveManagerMod Instance; private static ManualLogSource Logger; private Harmony harmony; private ConfigEntry<KeyCode> toggleUIKey; private ConfigEntry<bool> autoSave; private ConfigEntry<float> autoSaveInterval; private Dictionary<int, PlayerSaveData> playerDataCache = new Dictionary<int, PlayerSaveData>(); private string saveDirectory; private float lastAutoSave; private bool showUI; private Rect windowRect = new Rect(50f, 50f, 400f, 500f); private Vector2 scrollPosition = Vector2.zero; private string newSaveName = ""; private List<SaveFileInfo> saveFiles = new List<SaveFileInfo>(); private int selectedSaveIndex = -1; private string statusMessage = ""; private float statusMessageTime; private bool isLoading; private HashSet<int> playersBeingLoaded = new HashSet<int>(); private void Awake() { //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Expected O, but got Unknown Instance = this; Logger = ((BaseUnityPlugin)this).Logger; toggleUIKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Controls", "Toggle UI Key", (KeyCode)291, "Key to toggle save/load UI"); autoSave = ((BaseUnityPlugin)this).Config.Bind<bool>("AutoSave", "Enable AutoSave", true, "Enable automatic saving"); autoSaveInterval = ((BaseUnityPlugin)this).Config.Bind<float>("AutoSave", "AutoSave Interval", 300f, "AutoSave interval in seconds"); saveDirectory = Path.Combine(Paths.GameRootPath, "PeakSaves"); if (!Directory.Exists(saveDirectory)) { Directory.CreateDirectory(saveDirectory); } harmony = new Harmony("com.maxbridgland.peaksavemanager"); harmony.PatchAll(); RefreshSaveFileList(); Logger.LogInfo((object)"PEAK Save Manager 1.0.1 loaded!"); } private void Update() { //IL_000e: Unknown result type (might be due to invalid IL or missing references) if (!PhotonNetwork.IsMasterClient) { return; } if (Input.GetKeyDown(toggleUIKey.Value)) { showUI = !showUI; if (showUI) { RefreshSaveFileList(); EnableUIMode(); } else { DisableUIMode(); } } if (showUI) { BlockGameInput(); } if (!showUI && !isLoading && autoSave.Value && Time.time - lastAutoSave > autoSaveInterval.Value) { SaveGameState("autosave"); lastAutoSave = Time.time; } if (statusMessageTime > 0f) { statusMessageTime -= Time.deltaTime; if (statusMessageTime <= 0f) { statusMessage = ""; } } } private void EnableUIMode() { Cursor.lockState = (CursorLockMode)0; Cursor.visible = true; Logger.LogInfo((object)"UI Mode enabled - cursor unlocked"); } private void DisableUIMode() { Logger.LogInfo((object)"UI Mode disabled - returning control to game"); } private void BlockGameInput() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) if ((int)Cursor.lockState != 0) { Cursor.lockState = (CursorLockMode)0; } if (!Cursor.visible) { Cursor.visible = true; } } private void LateUpdate() { if (showUI) { Cursor.lockState = (CursorLockMode)0; Cursor.visible = true; } } private void OnGUI() { //IL_002b: 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_0046: Expected O, but got Unknown //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Invalid comparison between Unknown and I4 //IL_005d: 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) //IL_006f: Invalid comparison between Unknown and I4 if (showUI && PhotonNetwork.IsMasterClient) { GUI.skin = GUI.skin; GUI.FocusWindow(12345); windowRect = GUI.Window(12345, windowRect, new WindowFunction(DrawSaveLoadWindow), "PEAK Save/Load Manager"); if ((int)Event.current.type == 4 || (int)Event.current.type == 0 || (int)Event.current.type == 1) { Event.current.Use(); } } } private void DrawSaveLoadWindow(int windowID) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_01eb: Unknown result type (might be due to invalid IL or missing references) //IL_0203: Unknown result type (might be due to invalid IL or missing references) //IL_0208: Unknown result type (might be due to invalid IL or missing references) //IL_0293: Unknown result type (might be due to invalid IL or missing references) //IL_02ef: Unknown result type (might be due to invalid IL or missing references) //IL_0346: Unknown result type (might be due to invalid IL or missing references) //IL_0376: Unknown result type (might be due to invalid IL or missing references) //IL_041b: Unknown result type (might be due to invalid IL or missing references) //IL_0469: Unknown result type (might be due to invalid IL or missing references) GUI.BringWindowToFront(windowID); GUILayout.BeginVertical(Array.Empty<GUILayoutOption>()); if (!string.IsNullOrEmpty(statusMessage)) { GUI.color = Color.green; GUILayout.Label(statusMessage, GUI.skin.box, Array.Empty<GUILayoutOption>()); GUI.color = Color.white; } if (isLoading) { GUI.color = Color.yellow; GUILayout.Label("Loading game state... Please wait.", GUI.skin.box, Array.Empty<GUILayoutOption>()); GUI.color = Color.white; } GUILayout.Label("Save Game", GUI.skin.box, Array.Empty<GUILayoutOption>()); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUILayout.Label("Save Name:", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(80f) }); newSaveName = GUILayout.TextField(newSaveName, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) }); GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUI.enabled = !isLoading; if (GUILayout.Button("Quick Save", Array.Empty<GUILayoutOption>())) { SaveGameState($"quicksave_{DateTime.Now:yyyy-MM-dd_HH-mm-ss}"); } GUI.enabled = !string.IsNullOrEmpty(newSaveName.Trim()) && !isLoading; if (GUILayout.Button("Save with Name", Array.Empty<GUILayoutOption>())) { SaveGameState(newSaveName.Trim()); newSaveName = ""; } GUI.enabled = !isLoading; GUILayout.EndHorizontal(); GUILayout.Space(10f); GUILayout.Label("Load Game", GUI.skin.box, Array.Empty<GUILayoutOption>()); if (GUILayout.Button("Refresh Save List", Array.Empty<GUILayoutOption>())) { RefreshSaveFileList(); } GUILayout.Label($"Save Files ({saveFiles.Count}):", Array.Empty<GUILayoutOption>()); scrollPosition = GUILayout.BeginScrollView(scrollPosition, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(250f) }); for (int i = 0; i < saveFiles.Count; i++) { SaveFileInfo saveFileInfo = saveFiles[i]; GUILayout.BeginHorizontal(GUI.skin.box, Array.Empty<GUILayoutOption>()); bool flag = selectedSaveIndex == i; bool flag2 = GUILayout.Toggle(flag, "", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(20f) }); if (flag2 != flag) { selectedSaveIndex = (flag2 ? i : (-1)); } GUILayout.BeginVertical(Array.Empty<GUILayoutOption>()); GUILayout.Label(saveFileInfo.displayName, GUI.skin.label, Array.Empty<GUILayoutOption>()); GUI.color = Color.gray; GUILayout.Label($"Saved: {saveFileInfo.saveTime:yyyy-MM-dd HH:mm:ss}", GUI.skin.label, Array.Empty<GUILayoutOption>()); GUILayout.Label($"Players: {saveFileInfo.playerCount}", GUI.skin.label, Array.Empty<GUILayoutOption>()); GUI.color = Color.white; GUILayout.EndVertical(); GUILayout.FlexibleSpace(); GUILayout.BeginVertical((GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(80f) }); if (GUILayout.Button("Load", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(20f) })) { LoadGameState(saveFileInfo.fileName); } GUI.color = Color.red; if (GUILayout.Button("Delete", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(20f) })) { DeleteSaveFile(saveFileInfo); } GUI.color = Color.white; GUILayout.EndVertical(); GUILayout.EndHorizontal(); GUILayout.Space(2f); } GUILayout.EndScrollView(); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUI.enabled = selectedSaveIndex >= 0 && !isLoading; if (GUILayout.Button("Load Selected", Array.Empty<GUILayoutOption>()) && selectedSaveIndex >= 0 && selectedSaveIndex < saveFiles.Count) { LoadGameState(saveFiles[selectedSaveIndex].fileName); } GUI.color = Color.red; if (GUILayout.Button("Delete Selected", Array.Empty<GUILayoutOption>()) && selectedSaveIndex >= 0 && selectedSaveIndex < saveFiles.Count) { DeleteSaveFile(saveFiles[selectedSaveIndex]); } GUI.color = Color.white; GUI.enabled = !isLoading; GUILayout.EndHorizontal(); GUILayout.Space(10f); if (GUILayout.Button("Close", Array.Empty<GUILayoutOption>())) { showUI = false; } GUILayout.EndVertical(); GUI.DragWindow(); } private void RefreshSaveFileList() { saveFiles.Clear(); selectedSaveIndex = -1; try { foreach (string item in from f in Directory.GetFiles(saveDirectory, "*.json") orderby File.GetLastWriteTime(f) descending select f) { try { string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(item); FileInfo fileInfo = new FileInfo(item); GameSaveData gameSaveData = JsonConvert.DeserializeObject<GameSaveData>(File.ReadAllText(item)); saveFiles.Add(new SaveFileInfo { fileName = fileNameWithoutExtension, displayName = fileNameWithoutExtension.Replace("_", " "), filePath = item, saveTime = gameSaveData.saveTime, playerCount = gameSaveData.players.Count, fileSize = fileInfo.Length }); } catch (Exception ex) { Logger.LogWarning((object)("Could not read save file " + item + ": " + ex.Message)); } } } catch (Exception arg) { Logger.LogError((object)$"Error refreshing save file list: {arg}"); ShowStatusMessage("Error loading save files!", 3f); } } private void DeleteSaveFile(SaveFileInfo saveFile) { try { File.Delete(saveFile.filePath); RefreshSaveFileList(); ShowStatusMessage("Deleted: " + saveFile.displayName); Logger.LogInfo((object)("Deleted save file: " + saveFile.fileName)); } catch (Exception arg) { Logger.LogError((object)$"Error deleting save file: {arg}"); ShowStatusMessage("Error deleting file!", 3f); } } private void ShowStatusMessage(string message, float duration = 2f) { statusMessage = message; statusMessageTime = duration; } private static Vector3 GetCharacterActualPosition(Character character) { //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_01a5: Unknown result type (might be due to invalid IL or missing references) //IL_01aa: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: 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_0107: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) Vector3 val = Vector3.zero; string arg = "unknown"; try { if (character.Center != Vector3.zero) { val = character.Center; arg = "Center (torso)"; } else if ((Object)(object)character.refs.ragdoll != (Object)null && (Object)(object)character.refs.hip != (Object)null && (Object)(object)character.refs.hip.Rig != (Object)null) { val = character.refs.hip.Rig.position; arg = "Hip rigidbody"; } else if ((Object)(object)character.refs.ragdoll != (Object)null && character.refs.ragdoll.partList != null) { Vector3 val2 = Vector3.zero; int num = 0; foreach (Bodypart part in character.refs.ragdoll.partList) { if ((Object)(object)((part != null) ? part.Rig : null) != (Object)null) { val2 += part.Rig.position; num++; } } if (num > 0) { val = val2 / (float)num; arg = $"Average of {num} body parts"; } } if (val == Vector3.zero) { val = ((Component)character).transform.position; arg = "Transform position (fallback)"; } Logger.LogInfo((object)$"Got character position from {arg}: {val}"); return val; } catch (Exception arg2) { Logger.LogError((object)$"Error getting character position: {arg2}"); return ((Component)character).transform.position; } } private static Vector3 GetCharacterActualRotation(Character character) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: 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) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) try { if (character.data.lookDirection != Vector3.zero) { Quaternion val = Quaternion.LookRotation(character.data.lookDirection_Flat); return ((Quaternion)(ref val)).eulerAngles; } return ((Component)character).transform.eulerAngles; } catch (Exception arg) { Logger.LogError((object)$"Error getting character rotation: {arg}"); return ((Component)character).transform.eulerAngles; } } public static void UpdatePlayerData(Player player) { //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: 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_0116: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_01db: Unknown result type (might be due to invalid IL or missing references) //IL_021a: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)Instance == (Object)null || !PhotonNetwork.IsMasterClient) { return; } try { Character character = player.character; if ((Object)(object)character == (Object)null) { Logger.LogWarning((object)("No character found for player " + ((MonoBehaviourPun)player).photonView.Owner.NickName)); return; } Vector3 characterActualPosition = GetCharacterActualPosition(character); Vector3 characterActualRotation = GetCharacterActualRotation(character); Logger.LogInfo((object)$"Updating player data for {((MonoBehaviourPun)player).photonView.Owner.NickName} at position {characterActualPosition}"); PlayerSaveData value = new PlayerSaveData { playerName = ((MonoBehaviourPun)player).photonView.Owner.NickName, actorNumber = ((MonoBehaviourPun)player).photonView.Owner.ActorNumber, position = new Vector3Data(characterActualPosition), rotation = new Vector3Data(characterActualRotation), mapId = GetCurrentMapId(), inventory = ConvertInventoryToSaveData(player), characterState = new CharacterStateData { isGrounded = character.data.isGrounded, sinceGrounded = character.data.sinceGrounded, groundPos = new Vector3Data(character.data.groundPos), groundNormal = new Vector3Data(character.data.groundNormal), currentStamina = character.data.currentStamina, extraStamina = character.data.extraStamina, passedOut = character.data.passedOut, fullyPassedOut = character.data.fullyPassedOut, dead = character.data.dead, isClimbing = character.data.isClimbing, isRopeClimbing = character.data.isRopeClimbing, isVineClimbing = character.data.isVineClimbing, isSprinting = character.data.isSprinting, lookValues = new Vector2Data(character.data.lookValues) } }; Instance.playerDataCache[((MonoBehaviourPun)player).photonView.Owner.ActorNumber] = value; Logger.LogInfo((object)$"Successfully cached position {characterActualPosition} for player {((MonoBehaviourPun)player).photonView.Owner.NickName}"); } catch (Exception arg) { Logger.LogError((object)$"Error updating player data: {arg}"); } } private static InventoryData ConvertInventoryToSaveData(Player player) { InventoryData inventoryData = new InventoryData(); for (int i = 0; i < player.itemSlots.Length; i++) { ItemSlot val = player.itemSlots[i]; inventoryData.itemSlots.Add(new ItemSlotData { slotId = (byte)i, itemId = (val.prefab?.itemID ?? ushort.MaxValue), instanceDataGuid = val.data?.guid.ToString(), instanceData = ConvertInstanceData(val.data) }); } inventoryData.tempSlot = new ItemSlotData { slotId = 250, itemId = (player.tempFullSlot.prefab?.itemID ?? ushort.MaxValue), instanceDataGuid = player.tempFullSlot.data?.guid.ToString(), instanceData = ConvertInstanceData(player.tempFullSlot.data) }; inventoryData.backpack = new BackpackData { hasBackpack = player.backpackSlot.hasBackpack, instanceDataGuid = ((ItemSlot)player.backpackSlot).data?.guid.ToString(), instanceData = ConvertInstanceData(((ItemSlot)player.backpackSlot).data) }; return inventoryData; } private static Dictionary<string, object> ConvertInstanceData(ItemInstanceData data) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) if (data?.data == null) { return null; } Dictionary<string, object> dictionary = new Dictionary<string, object>(); foreach (KeyValuePair<DataEntryKey, DataEntryValue> datum in data.data) { DataEntryKey key = datum.Key; dictionary[((object)(DataEntryKey)(ref key)).ToString()] = SerializeDataEntryValue(datum.Value); } return dictionary; } private static object SerializeDataEntryValue(DataEntryValue value) { if (value == null) { return null; } return new Dictionary<string, object> { ["type"] = ((object)value).GetType().Name, ["data"] = ((object)value).ToString() }; } private static string GetCurrentMapId() { //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) Scene activeScene = SceneManager.GetActiveScene(); return ((Scene)(ref activeScene)).name; } private string SegmentToString(Segment segment) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected I4, but got Unknown return (int)segment switch { 2 => "alpine", 5 => "peak", 0 => "beach", 1 => "tropics", 4 => "kiln", 3 => "caldera", _ => "beach", }; } private Segment StringToSegment(string str) { return (Segment)(str switch { "alpine" => 2, "peak" => 5, "beach" => 0, "tropics" => 1, "kiln" => 4, "caldera" => 3, _ => 0, }); } private void SaveGameState(string fileName) { //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: 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) try { Logger.LogInfo((object)("Starting save process for: " + fileName)); Player[] array = Object.FindObjectsByType<Player>((FindObjectsSortMode)0); Logger.LogInfo((object)$"Found {array.Length} players to save"); Player[] array2 = array; for (int i = 0; i < array2.Length; i++) { UpdatePlayerData(array2[i]); } Segment currentSegment = Object.FindFirstObjectByType<MapHandler>().GetCurrentSegment(); GameSaveData gameSaveData = new GameSaveData { saveTime = DateTime.Now, players = new List<PlayerSaveData>(playerDataCache.Values), mapSegment = SegmentToString(currentSegment) }; string contents = JsonConvert.SerializeObject((object)gameSaveData, (Formatting)1); string text = Path.Combine(saveDirectory, fileName + ".json"); File.WriteAllText(text, contents); Logger.LogInfo((object)$"Game saved to: {text} with {gameSaveData.players.Count} players"); ShowStatusMessage("Saved: " + fileName); RefreshSaveFileList(); } catch (Exception arg) { Logger.LogError((object)$"Error saving game: {arg}"); ShowStatusMessage("Save failed!", 3f); } } private void LoadGameState(string fileName) { if (isLoading) { ShowStatusMessage("Already loading a save!", 3f); return; } try { string text = Path.Combine(saveDirectory, fileName + ".json"); if (!File.Exists(text)) { Logger.LogWarning((object)("Save file not found: " + text)); ShowStatusMessage("Save file not found!", 3f); return; } GameSaveData gameSaveData = JsonConvert.DeserializeObject<GameSaveData>(File.ReadAllText(text)); isLoading = true; Logger.LogInfo((object)$"Starting load process for: {fileName} with {gameSaveData.players.Count} players"); ((MonoBehaviour)this).StartCoroutine(ApplyLoadedDataCoroutine(gameSaveData, fileName)); } catch (Exception arg) { Logger.LogError((object)$"Error loading game: {arg}"); ShowStatusMessage("Load failed!", 3f); isLoading = false; } } [IteratorStateMachine(typeof(<ApplyLoadedDataCoroutine>d__44))] private IEnumerator ApplyLoadedDataCoroutine(GameSaveData saveData, string fileName) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <ApplyLoadedDataCoroutine>d__44(0) { <>4__this = this, saveData = saveData, fileName = fileName }; } private Player FindPlayerByActorNumber(int actorNumber) { Player[] array = Object.FindObjectsByType<Player>((FindObjectsSortMode)0); foreach (Player val in array) { PhotonView photonView = ((MonoBehaviourPun)val).photonView; if (photonView != null) { Player owner = photonView.Owner; if (((owner != null) ? new int?(owner.ActorNumber) : null) == actorNumber) { Logger.LogInfo((object)$"Found player {((MonoBehaviourPun)val).photonView.Owner.NickName} with actor number {actorNumber}"); return val; } } } Character[] array2 = Object.FindObjectsByType<Character>((FindObjectsSortMode)0); foreach (Character val2 in array2) { PhotonView photonView2 = ((MonoBehaviourPun)val2).photonView; if (photonView2 == null) { continue; } Player owner2 = photonView2.Owner; if (((owner2 != null) ? new int?(owner2.ActorNumber) : null) == actorNumber) { Player component = ((Component)val2).GetComponent<Player>(); if ((Object)(object)component != (Object)null) { Logger.LogInfo((object)$"Found player {((MonoBehaviourPun)val2).photonView.Owner.NickName} via character lookup with actor number {actorNumber}"); return component; } } } Logger.LogWarning((object)$"Could not find player with actor number {actorNumber}"); return null; } [IteratorStateMachine(typeof(<ApplyPlayerDataCoroutine>d__46))] private IEnumerator ApplyPlayerDataCoroutine(Player player, PlayerSaveData data) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <ApplyPlayerDataCoroutine>d__46(0) { <>4__this = this, player = player, data = data }; } private void ApplyCharacterState(Character character, CharacterStateData stateData) { //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) try { Logger.LogInfo((object)("Applying character state for " + character.characterName)); character.data.currentStamina = stateData.currentStamina; character.data.extraStamina = stateData.extraStamina; character.data.isGrounded = stateData.isGrounded; character.data.sinceGrounded = stateData.sinceGrounded; character.data.groundPos = stateData.groundPos.ToVector3(); character.data.groundNormal = stateData.groundNormal.ToVector3(); character.data.isClimbing = stateData.isClimbing; character.data.isRopeClimbing = stateData.isRopeClimbing; character.data.isVineClimbing = stateData.isVineClimbing; character.data.isSprinting = stateData.isSprinting; character.data.lookValues = stateData.lookValues.ToVector2(); CharacterAccessibilityPatches.CallRecalculateLookDirections(character); Logger.LogInfo((object)("Character state applied successfully for " + character.characterName)); } catch (Exception arg) { Logger.LogError((object)$"Error applying character state: {arg}"); } } private void ApplyInventoryData(Player player, InventoryData inventoryData) { //IL_0164: Unknown result type (might be due to invalid IL or missing references) try { Logger.LogInfo((object)$"Loading inventory for player {((MonoBehaviourPun)player).photonView.Owner.NickName} with {inventoryData.itemSlots.Count} item slots"); for (int i = 0; i < player.itemSlots.Length; i++) { player.itemSlots[i].EmptyOut(); } player.tempFullSlot.EmptyOut(); ((ItemSlot)player.backpackSlot).EmptyOut(); for (int j = 0; j < inventoryData.itemSlots.Count && j < player.itemSlots.Length; j++) { ItemSlotData itemSlotData = inventoryData.itemSlots[j]; if (itemSlotData.itemId != ushort.MaxValue) { LoadItemToSlot(player.itemSlots[j], itemSlotData); } } if (inventoryData.tempSlot.itemId != ushort.MaxValue) { LoadItemToSlot(player.tempFullSlot, inventoryData.tempSlot); } if (inventoryData.backpack.hasBackpack) { player.backpackSlot.hasBackpack = true; if (!string.IsNullOrEmpty(inventoryData.backpack.instanceDataGuid)) { Guid guid = Guid.Parse(inventoryData.backpack.instanceDataGuid); ItemInstanceData orCreateInstanceData = GetOrCreateInstanceData(guid, inventoryData.backpack.instanceData); ((ItemSlot)player.backpackSlot).data = orCreateInstanceData; } } InventorySyncData val = default(InventorySyncData); ((InventorySyncData)(ref val))..ctor(player.itemSlots, player.backpackSlot, player.tempFullSlot); ((MonoBehaviourPun)player).photonView.RPC("SyncInventoryRPC", (RpcTarget)1, new object[2] { IBinarySerializable.ToManagedArray<InventorySyncData>(val), true }); Logger.LogInfo((object)("Inventory loaded successfully for " + ((MonoBehaviourPun)player).photonView.Owner.NickName)); } catch (Exception arg) { Logger.LogError((object)$"Error loading inventory: {arg}"); } } [IteratorStateMachine(typeof(<ApplyPlayerPositionCoroutine>d__49))] private IEnumerator ApplyPlayerPositionCoroutine(Character character, PlayerSaveData data) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <ApplyPlayerPositionCoroutine>d__49(0) { <>4__this = this, character = character, data = data }; } private Vector3 FindSafeSpawnPosition(Vector3 originalPosition) { //IL_0000: 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_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: 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_003e: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: 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_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0055: 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_0064: 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) //IL_0074: 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_008a: 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_00ee: Unknown result type (might be due to invalid IL or missing references) try { Vector3 val = new Vector3(originalPosition.x, originalPosition.y + 100f, originalPosition.z); RaycastHit val2 = HelperFunctions.LineCheck(val, val + Vector3.down * 200f, (LayerType)1, 0f, (QueryTriggerInteraction)1); if ((Object)(object)((RaycastHit)(ref val2)).transform != (Object)null) { Vector3 val3 = ((RaycastHit)(ref val2)).point + Vector3.up * 2f; Logger.LogInfo((object)$"Found safe spawn position: {val3} (original: {originalPosition})"); return val3; } Logger.LogWarning((object)$"No ground found for position {originalPosition}, using original + offset"); return originalPosition + Vector3.up * 5f; } catch (Exception arg) { Logger.LogError((object)$"Error finding safe spawn position: {arg}"); return originalPosition + Vector3.up * 5f; } } private void LoadItemToSlot(ItemSlot slot, ItemSlotData slotData) { //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Expected O, but got Unknown try { Item val = default(Item); if (!ItemDatabase.TryGetItem(slotData.itemId, ref val)) { Logger.LogWarning((object)$"Could not find item with ID: {slotData.itemId}"); return; } ItemInstanceData val2 = null; if (!string.IsNullOrEmpty(slotData.instanceDataGuid)) { Guid guid = Guid.Parse(slotData.instanceDataGuid); val2 = GetOrCreateInstanceData(guid, slotData.instanceData); } else { val2 = new ItemInstanceData(Guid.NewGuid()); ItemInstanceDataHandler.AddInstanceData(val2); } slot.SetItem(val, val2); Logger.LogInfo((object)$"Loaded item {((Object)val).name} to slot {slotData.slotId}"); } catch (Exception arg) { Logger.LogError((object)$"Error loading item to slot: {arg}"); } } private ItemInstanceData GetOrCreateInstanceData(Guid guid, Dictionary<string, object> savedData) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Expected O, but got Unknown //IL_0044: Unknown result type (might be due to invalid IL or missing references) ItemInstanceData result = default(ItemInstanceData); if (ItemInstanceDataHandler.TryGetInstanceData(guid, ref result)) { return result; } result = new ItemInstanceData(guid); if (savedData != null) { foreach (KeyValuePair<string, object> savedDatum in savedData) { try { if (Enum.TryParse<DataEntryKey>(savedDatum.Key, out DataEntryKey result2)) { Logger.LogInfo((object)$"Restoring data entry: {result2}"); } } catch (Exception ex) { Logger.LogWarning((object)("Could not restore data entry " + savedDatum.Key + ": " + ex.Message)); } } } ItemInstanceDataHandler.AddInstanceData(result); return result; } private void OnDestroy() { Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } } } [Serializable] public class PlayerSaveData { public string playerName; public int actorNumber; public Vector3Data position; public Vector3Data rotation; public string mapId; public InventoryData inventory; public CharacterStateData characterState; } [Serializable] public class CharacterStateData { public bool isGrounded; public float sinceGrounded; public Vector3Data groundPos; public Vector3Data groundNormal; public float currentStamina; public float extraStamina; public bool passedOut; public bool fullyPassedOut; public bool dead; public bool isClimbing; public bool isRopeClimbing; public bool isVineClimbing; public bool isSprinting; public Vector2Data lookValues; } [Serializable] public class Vector3Data { public float x; public float y; public float z; public Vector3Data() { } public Vector3Data(Vector3 vector) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) x = vector.x; y = vector.y; z = vector.z; } public Vector3 ToVector3() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) return new Vector3(x, y, z); } } [Serializable] public class Vector2Data { public float x; public float y; public Vector2Data() { } public Vector2Data(Vector2 vector) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) x = vector.x; y = vector.y; } public Vector2 ToVector2() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) return new Vector2(x, y); } } [Serializable] public class InventoryData { public List<ItemSlotData> itemSlots = new List<ItemSlotData>(); public ItemSlotData tempSlot; public BackpackData backpack; } [Serializable] public class ItemSlotData { public byte slotId; public ushort itemId; public string instanceDataGuid; public Dictionary<string, object> instanceData; } [Serializable] public class BackpackData { public bool hasBackpack; public string instanceDataGuid; public Dictionary<string, object> instanceData; } [Serializable] public class GameSaveData { public string saveVersion = "1.0"; public string saveName; public DateTime saveTime; public List<PlayerSaveData> players = new List<PlayerSaveData>(); public string mapSegment; } [Serializable] public class SaveFileInfo { public string fileName; public string displayName; public string filePath; public DateTime saveTime; public int playerCount; public long fileSize; } } namespace PEAKSaveManager.Patches { [HarmonyPatch] public class CharacterAccessibilityPatches { private static MethodInfo recalculateMethod; static CharacterAccessibilityPatches() { recalculateMethod = typeof(Character).GetMethod("RecalculateLookDirections", BindingFlags.Instance | BindingFlags.NonPublic); } public static void CallRecalculateLookDirections(Character character) { try { recalculateMethod?.Invoke(character, null); } catch (Exception arg) { Logger.CreateLogSource("CharacterPatches").LogError((object)$"Error calling RecalculateLookDirections: {arg}"); } } } [HarmonyPatch] internal class CharacterPatches { private static ManualLogSource Logger => Logger.CreateLogSource("PlayerPatches"); [HarmonyPatch(typeof(Character), "WarpPlayerRPC")] [HarmonyPrefix] public static bool WarpPlayerRPC_Prefix(Character __instance, Vector3 position) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) try { Logger.LogInfo((object)$"WarpPlayerRPC called for character {((Object)__instance).name} at {((Component)__instance).transform.position} to {position}"); return true; } catch (Exception arg) { Logger.LogError((object)$"Error in Character WarpPlayerRPC patch: {arg}"); return true; } } } [HarmonyPatch] public class PlayerPatches { [CompilerGenerated] private sealed class <DelayedUpdatePlayerData>d__7 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public Player player; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <DelayedUpdatePlayerData>d__7(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSeconds(1f); <>1__state = 1; return true; case 1: <>1__state = -1; SaveManagerMod.UpdatePlayerData(player); 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(); } } private static ManualLogSource Logger => Logger.CreateLogSource("PlayerPatches"); [HarmonyPatch(typeof(Character), "FixedUpdate")] [HarmonyPostfix] public static void FixedUpdate_Postfix(Character __instance) { if (__instance.IsLocal && Time.fixedTime % 1f < Time.fixedDeltaTime) { Player player = __instance.player; if ((Object)(object)player != (Object)null) { SaveManagerMod.UpdatePlayerData(player); } } } [HarmonyPatch(typeof(Player), "SyncInventoryRPC")] [HarmonyPostfix] public static void SyncInventoryRPC_Postfix(Player __instance) { SaveManagerMod.UpdatePlayerData(__instance); } [HarmonyPatch(typeof(Player), "AddItem")] [HarmonyPostfix] public static void AddItem_Postfix(Player __instance, bool __result) { if (__result) { SaveManagerMod.UpdatePlayerData(__instance); } } [HarmonyPatch(typeof(Player), "EmptySlot")] [HarmonyPostfix] public static void EmptySlot_Postfix(Player __instance) { SaveManagerMod.UpdatePlayerData(__instance); } [HarmonyPatch(typeof(Player), "Awake")] [HarmonyPostfix] public static void Awake_Postfix(Player __instance) { ((MonoBehaviour)__instance).StartCoroutine(DelayedUpdatePlayerData(__instance)); } [IteratorStateMachine(typeof(<DelayedUpdatePlayerData>d__7))] private static IEnumerator DelayedUpdatePlayerData(Player player) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <DelayedUpdatePlayerData>d__7(0) { player = player }; } } }