Decompiled source of PeakSave v1.0.1

plugins/PEAKSaveManager.dll

Decompiled 2 weeks ago
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.Logging;
using HarmonyLib;
using Newtonsoft.Json;
using Photon.Pun;
using UnityEngine;
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.1.9")]
	public class SaveManagerMod : BaseUnityPlugin
	{
		public static SaveManagerMod Instance;

		private string sDir;

		private bool ui;

		private Rect rect = new Rect(50f, 50f, 400f, 500f);

		private string input = "";

		private Vector2 scrollPos;

		private void Awake()
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			Instance = this;
			sDir = Path.Combine(Paths.GameRootPath, "PeakSaves");
			if (!Directory.Exists(sDir))
			{
				Directory.CreateDirectory(sDir);
			}
			new Harmony("com.maxbridgland.peaksavemanager").PatchAll();
		}

		public static void UpdatePlayerData(Player p)
		{
		}

		private void Update()
		{
			if (Input.GetKeyDown((KeyCode)291))
			{
				ui = !ui;
				Cursor.visible = ui;
				Cursor.lockState = (CursorLockMode)((!ui) ? 1 : 0);
			}
		}

		private void OnGUI()
		{
			//IL_0009: 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_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Expected O, but got Unknown
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			if (!ui)
			{
				return;
			}
			GUI.backgroundColor = Color.white;
			GUI.contentColor = Color.white;
			rect = GUILayout.Window(999, rect, (WindowFunction)delegate
			{
				//IL_0069: Unknown result type (might be due to invalid IL or missing references)
				//IL_0081: Unknown result type (might be due to invalid IL or missing references)
				//IL_0086: Unknown result type (might be due to invalid IL or missing references)
				//IL_0126: Unknown result type (might be due to invalid IL or missing references)
				//IL_015a: Unknown result type (might be due to invalid IL or missing references)
				GUILayout.Label("Session Name (Date will be added):", Array.Empty<GUILayoutOption>());
				input = GUILayout.TextField(input, Array.Empty<GUILayoutOption>());
				if (GUILayout.Button("Save State", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(30f) }) && !string.IsNullOrEmpty(input))
				{
					SaveCurrentState(input);
				}
				GUILayout.Space(10f);
				scrollPos = GUILayout.BeginScrollView(scrollPos, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(250f) });
				if (Directory.Exists(sDir))
				{
					foreach (FileInfo item in from f in new DirectoryInfo(sDir).GetFiles("*.json")
						orderby f.CreationTime descending
						select f)
					{
						string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(item.Name);
						GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
						if (GUILayout.Button("Load: " + fileNameWithoutExtension, Array.Empty<GUILayoutOption>()))
						{
							((MonoBehaviour)this).StartCoroutine(LoadCoroutine(item.FullName));
						}
						GUI.backgroundColor = Color.red;
						if (GUILayout.Button("X", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(30f) }))
						{
							File.Delete(item.FullName);
						}
						GUI.backgroundColor = Color.white;
						GUILayout.EndHorizontal();
					}
				}
				GUILayout.EndScrollView();
				if (GUILayout.Button("Close (F10)", Array.Empty<GUILayoutOption>()))
				{
					ui = false;
				}
				GUI.DragWindow();
			}, "PEAK Save Manager", Array.Empty<GUILayoutOption>());
		}

		private IEnumerator LoadCoroutine(string path)
		{
			FlatSave__2 bundle = JsonConvert.DeserializeObject<FlatSave__2>(File.ReadAllText(path));
			if (bundle == null)
			{
				yield break;
			}
			Vector3 val = default(Vector3);
			Item val2 = default(Item);
			Item val3 = default(Item);
			for (int i = 0; i < bundle.names.Length; i++)
			{
				string pName = bundle.names[i];
				Player p = ((IEnumerable<Player>)Object.FindObjectsByType<Player>((FindObjectsSortMode)0)).FirstOrDefault((Func<Player, bool>)((Player x) => ((MonoBehaviourPun)x).photonView.Owner.NickName == pName));
				if (!((Object)(object)p != (Object)null) || !((Object)(object)p.character != (Object)null))
				{
					continue;
				}
				int idx = Array.IndexOf(bundle.names, pName);
				((Vector3)(ref val))..ctor(bundle.posX[idx], bundle.posY[idx], bundle.posZ[idx]);
				((MonoBehaviourPun)p.character).photonView.RPC("WarpPlayerRPC", (RpcTarget)0, new object[2] { val, false });
				for (int j = 0; j < p.itemSlots.Length; j++)
				{
					p.itemSlots[j].SetItem((Item)null, (ItemInstanceData)null);
				}
				ushort[] array = bundle.mainInv[idx];
				for (int k = 0; k < array.Length && k < p.itemSlots.Length; k++)
				{
					if (array[k] != ushort.MaxValue && ItemDatabase.TryGetItem(array[k], ref val2))
					{
						p.itemSlots[k].SetItem(val2, new ItemInstanceData(Guid.NewGuid()));
					}
				}
				if (bundle.hasBP[idx])
				{
					p.backpackSlot.hasBackpack = true;
					((ItemSlot)p.backpackSlot).data = new ItemInstanceData(Guid.NewGuid());
					BackpackData backpackData = null;
					float timeout = 5f;
					float timer = 0f;
					while (timer < timeout)
					{
						if (((ItemSlot)p.backpackSlot).data != null && ((ItemSlot)p.backpackSlot).data.data.TryGetValue((DataEntryKey)7, out var value))
						{
							backpackData = (BackpackData)(object)((value is BackpackData) ? value : null);
							if (backpackData != null)
							{
								break;
							}
						}
						timer += 0.2f;
						yield return (object)new WaitForSeconds(0.2f);
					}
					if (backpackData != null)
					{
						ushort[] array2 = bundle.bpInv[idx];
						for (int l = 0; l < array2.Length && l < backpackData.itemSlots.Length; l++)
						{
							if (array2[l] != ushort.MaxValue && ItemDatabase.TryGetItem(array2[l], ref val3))
							{
								backpackData.AddItem(val3, new ItemInstanceData(Guid.NewGuid()), (byte)l);
							}
						}
						BackpackVisuals componentInChildren = ((Component)p).GetComponentInChildren<BackpackVisuals>();
						if ((Object)(object)componentInChildren != (Object)null)
						{
							componentInChildren.RefreshVisuals();
						}
					}
				}
				else
				{
					p.backpackSlot.hasBackpack = false;
					((ItemSlot)p.backpackSlot).data = null;
				}
				byte[] array3 = IBinarySerializable.ToManagedArray<InventorySyncData>(new InventorySyncData(p.itemSlots, p.backpackSlot, p.tempFullSlot));
				((MonoBehaviourPun)p).photonView.RPC("SyncInventoryRPC", (RpcTarget)0, new object[2] { array3, true });
			}
		}

		private void SaveCurrentState(string fileName)
		{
			string text = DateTime.Now.ToString("yyyy-MM-dd_HH-mm");
			string path = Path.Combine(sDir, fileName + "_" + text + ".json");
			Player[] array = Object.FindObjectsByType<Player>((FindObjectsSortMode)0);
			FlatSave__2 flatSave__ = new FlatSave__2();
			flatSave__.names = array.Select((Player p) => ((MonoBehaviourPun)p).photonView.Owner.NickName).ToArray();
			flatSave__.posX = array.Select((Player p) => p.character.refs.hip.Rig.position.x).ToArray();
			flatSave__.posY = array.Select((Player p) => p.character.refs.hip.Rig.position.y).ToArray();
			flatSave__.posZ = array.Select((Player p) => p.character.refs.hip.Rig.position.z).ToArray();
			flatSave__.mainInv = new ushort[array.Length][];
			flatSave__.bpInv = new ushort[array.Length][];
			flatSave__.hasBP = new bool[array.Length];
			for (int i = 0; i < array.Length; i++)
			{
				flatSave__.mainInv[i] = array[i].itemSlots.Select((ItemSlot slot) => (!((Object)(object)slot.prefab != (Object)null)) ? ushort.MaxValue : slot.prefab.itemID).ToArray();
				if (array[i].backpackSlot.hasBackpack && ((ItemSlot)array[i].backpackSlot).data != null)
				{
					flatSave__.hasBP[i] = true;
					if (!((ItemSlot)array[i].backpackSlot).data.data.TryGetValue((DataEntryKey)7, out var value))
					{
						continue;
					}
					BackpackData val = (BackpackData)(object)((value is BackpackData) ? value : null);
					if (val != null)
					{
						flatSave__.bpInv[i] = val.itemSlots.Select((ItemSlot slot) => (!((Object)(object)slot.prefab != (Object)null)) ? ushort.MaxValue : slot.prefab.itemID).ToArray();
					}
				}
				else
				{
					flatSave__.hasBP[i] = false;
					flatSave__.bpInv[i] = new ushort[0];
				}
			}
			File.WriteAllText(path, JsonConvert.SerializeObject((object)flatSave__, (Formatting)1));
		}
	}
}
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
	{
		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)
		{
			if ((Object)(object)__instance != (Object)null)
			{
				SaveManagerMod.UpdatePlayerData(__instance);
			}
		}

		[HarmonyPatch(typeof(Player), "AddItem")]
		[HarmonyPostfix]
		public static void AddItem_Postfix(Player __instance, bool __result)
		{
			if (__result && (Object)(object)__instance != (Object)null)
			{
				SaveManagerMod.UpdatePlayerData(__instance);
			}
		}

		[HarmonyPatch(typeof(Player), "EmptySlot")]
		[HarmonyPostfix]
		public static void EmptySlot_Postfix(Player __instance)
		{
			if ((Object)(object)__instance != (Object)null)
			{
				SaveManagerMod.UpdatePlayerData(__instance);
			}
		}

		[HarmonyPatch(typeof(Player), "Awake")]
		[HarmonyPostfix]
		public static void Awake_Postfix(Player __instance)
		{
			if ((Object)(object)__instance != (Object)null)
			{
				SaveManagerMod.UpdatePlayerData(__instance);
			}
		}
	}
}
namespace PEAKSaveManager
{
	public class FlatSave__2
	{
		public string[] names;

		public float[] posX;

		public float[] posY;

		public float[] posZ;

		public ushort[][] mainInv;

		public ushort[][] bpInv;

		public bool[] hasBP;
	}
}