using 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
};
}
}
}