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