Please disclose if your mod was created primarily using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of TruckLoot v1.0.4
TruckLoot.dll
Decompiled a year 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 System.Xml.Serialization; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Logging; using HarmonyLib; using ItemPersistenceMod.Patches; using Photon.Pun; using REPOLib.Modules; using UnityEngine; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("KeepLootInShip")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("KeepLootInShip")] [assembly: AssemblyCopyright("Copyright © 2025")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("1083bfd6-e88e-49d3-b763-146f4fc02662")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyVersion("1.0.0.0")] namespace ItemPersistenceMod { [BepInPlugin("TruckLoot", "TruckLoot", "1.0.4")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class ItemPersistenceModBase : BaseUnityPlugin { private const string modGUID = "TruckLoot"; private const string modName = "TruckLoot"; private const string modVersion = "1.0.4"; private const string repoLibGUID = "REPOLib"; private readonly Harmony harmony = new Harmony("TruckLoot"); internal static ItemPersistenceModBase instance; internal ManualLogSource mls; public static List<SerializedValuable> savedValuables; public static bool hasSavedValuables; public static Transform truckInteriorReference; private static string saveFolderPath; private static string currentSaveId; public static bool forceLoadOnNextLevel; public static bool repoLibAvailable; private float stateCheckInterval = 5f; private float stateCheckTimer = 0f; static ItemPersistenceModBase() { savedValuables = new List<SerializedValuable>(); hasSavedValuables = false; truckInteriorReference = null; currentSaveId = "default"; forceLoadOnNextLevel = false; repoLibAvailable = false; savedValuables = new List<SerializedValuable>(); hasSavedValuables = false; currentSaveId = "default"; } private void Awake() { if ((Object)(object)instance == (Object)null) { instance = this; } Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject); mls = Logger.CreateLogSource("TruckLoot"); mls.LogInfo((object)"TruckLoot v1.0.4 by Maflingus has Loaded!"); foreach (KeyValuePair<string, PluginInfo> pluginInfo in Chainloader.PluginInfos) { BepInPlugin metadata = pluginInfo.Value.Metadata; if (metadata.GUID.Equals("REPOLib")) { repoLibAvailable = true; mls.LogInfo((object)"Found REPOLib, enabling modded valuables support!"); break; } } if (!repoLibAvailable) { mls.LogInfo((object)"REPOLib not detected - only vanilla items will be supported"); } saveFolderPath = Path.Combine(Paths.ConfigPath, "ItemPersistenceMod"); if (!Directory.Exists(saveFolderPath)) { Directory.CreateDirectory(saveFolderPath); } mls.LogInfo((object)("Save folder path: " + saveFolderPath)); LoadValuablesFromFile(); harmony.PatchAll(typeof(ItemPersistenceModBase)); harmony.PatchAll(typeof(GameDirectorPatch)); harmony.PatchAll(typeof(LevelGeneratorPatch)); harmony.PatchAll(typeof(RunManagerPatch)); harmony.PatchAll(typeof(SaveFileDeletionPatch)); CheckGameState(); ((MonoBehaviour)this).StartCoroutine(DelayedSceneScanner()); } private void Update() { stateCheckTimer -= Time.deltaTime; if (stateCheckTimer <= 0f) { stateCheckTimer = stateCheckInterval; CheckGameState(); } } private void OnEnable() { SceneManager.sceneLoaded += OnSceneLoaded; } private void OnDisable() { SceneManager.sceneLoaded -= OnSceneLoaded; } private void OnSceneLoaded(Scene scene, LoadSceneMode mode) { if ((Object)(object)instance == (Object)null) { instance = this; } if (!hasSavedValuables || savedValuables.Count == 0) { LoadValuablesFromFile(); } } private void CheckGameState() { try { if (!((Object)(object)Object.FindObjectOfType<MainMenuOpen>() != (Object)null)) { return; } if (!hasSavedValuables || savedValuables.Count == 0) { UpdateCurrentSaveId(); LoadValuablesFromFile(); if (hasSavedValuables) { forceLoadOnNextLevel = true; } } else { forceLoadOnNextLevel = true; } } catch (Exception ex) { mls.LogError((object)("Error in CheckGameState: " + ex.Message)); } } public static void UpdateCurrentSaveId() { try { string text = currentSaveId; if ((Object)(object)StatsManager.instance != (Object)null) { FieldInfo fieldInfo = AccessTools.Field(typeof(StatsManager), "saveFileCurrent"); string text2 = (string)fieldInfo.GetValue(StatsManager.instance); if (!string.IsNullOrEmpty(text2)) { if (text2.EndsWith(".sav")) { text2 = text2.Substring(0, text2.Length - 4); } currentSaveId = text2; return; } } if (string.IsNullOrEmpty(currentSaveId)) { currentSaveId = "default"; } } catch (Exception) { if (string.IsNullOrEmpty(currentSaveId)) { currentSaveId = "default"; } } } public static string GetSaveFilePath(string saveId) { if (string.IsNullOrEmpty(saveId)) { saveId = "default"; } if (saveId.EndsWith(".sav")) { saveId = saveId.Substring(0, saveId.Length - 4); } return Path.Combine(saveFolderPath, saveId + ".xml"); } public static void DeleteSaveFile(string saveId) { string saveFilePath = GetSaveFilePath(saveId); if (File.Exists(saveFilePath)) { try { File.Delete(saveFilePath); instance.mls.LogInfo((object)("Deleted persistence file for save: " + saveId)); } catch (Exception ex) { instance.mls.LogError((object)("Error deleting persistence file: " + ex.Message)); } } } public static void SaveValuablesToFile() { //IL_01fe: Unknown result type (might be due to invalid IL or missing references) //IL_021c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)instance == (Object)null) { } if (!hasSavedValuables || savedValuables == null || savedValuables.Count == 0) { return; } try { string currentSaveFilePath = GetCurrentSaveFilePath(); string directoryName = Path.GetDirectoryName(currentSaveFilePath); if (!Directory.Exists(directoryName)) { Directory.CreateDirectory(directoryName); Debug.Log((object)("[ItemPersistenceMod] Created directory: " + directoryName)); } SaveData saveData = new SaveData(); foreach (SerializedValuable savedValuable in savedValuables) { saveData.Items.Add(new SavedItem(savedValuable)); } try { XmlSerializer xmlSerializer = new XmlSerializer(typeof(SaveData)); using StringWriter stringWriter = new StringWriter(); xmlSerializer.Serialize(stringWriter, saveData); string contents = stringWriter.ToString(); File.WriteAllText(currentSaveFilePath, contents); if (File.Exists(currentSaveFilePath)) { FileInfo fileInfo = new FileInfo(currentSaveFilePath); } else { Debug.LogError((object)("[ItemPersistenceMod] Failed to create save file despite no exceptions: " + currentSaveFilePath)); } } catch (Exception ex) { Debug.LogError((object)("[ItemPersistenceMod] Error serializing save data: " + ex.Message)); try { using (StreamWriter streamWriter = new StreamWriter(currentSaveFilePath)) { streamWriter.WriteLine($"ItemPersistenceMod Save File - {DateTime.Now}"); streamWriter.WriteLine("SaveID: " + currentSaveId); streamWriter.WriteLine($"Items: {savedValuables.Count}"); streamWriter.WriteLine("------------------------------------------"); foreach (SerializedValuable savedValuable2 in savedValuables) { streamWriter.WriteLine("Item: " + savedValuable2.prefabName); streamWriter.WriteLine($" Position: {savedValuable2.relativePosition}"); streamWriter.WriteLine($" Rotation: {savedValuable2.rotation}"); streamWriter.WriteLine($" Value: ${savedValuable2.dollarValueCurrent} (Original: ${savedValuable2.dollarValueOriginal})"); streamWriter.WriteLine("------------------------------------------"); } } Debug.Log((object)"[ItemPersistenceMod] Fallback to text format successful"); } catch (Exception ex2) { Debug.LogError((object)("[ItemPersistenceMod] Fallback save method also failed: " + ex2.Message)); } } } catch (Exception ex3) { Debug.LogError((object)("[ItemPersistenceMod] Error in SaveValuablesToFile: " + ex3.Message)); } } public static void LoadValuablesFromFile() { //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_03f6: Unknown result type (might be due to invalid IL or missing references) //IL_03f8: Unknown result type (might be due to invalid IL or missing references) //IL_03ff: Unknown result type (might be due to invalid IL or missing references) //IL_0401: Unknown result type (might be due to invalid IL or missing references) UpdateCurrentSaveId(); EnsureSaveFilesExist(); string currentSaveFilePath = GetCurrentSaveFilePath(); if (!File.Exists(currentSaveFilePath)) { hasSavedValuables = false; return; } try { string text = File.ReadAllText(currentSaveFilePath); try { XmlSerializer xmlSerializer = new XmlSerializer(typeof(SaveData)); SaveData saveData; using (StringReader textReader = new StringReader(text)) { saveData = (SaveData)xmlSerializer.Deserialize(textReader); } if (saveData != null && saveData.Items != null && saveData.Items.Count > 0) { savedValuables.Clear(); foreach (SavedItem item in saveData.Items) { savedValuables.Add(item.ToSerializedValuable()); } hasSavedValuables = true; } else { hasSavedValuables = false; } } catch (Exception ex) { Debug.LogError((object)("[ItemPersistenceMod] Error deserializing XML: " + ex.Message + ", trying fallback format")); if (text.StartsWith("ItemPersistenceMod Save File")) { Debug.Log((object)"[ItemPersistenceMod] Detected simple text format - parsing..."); savedValuables.Clear(); string[] array = text.Split(new char[1] { '\n' }); string text2 = null; Vector3 zero = Vector3.zero; Quaternion identity = Quaternion.identity; float result = 0f; float result2 = 0f; string[] array2 = array; foreach (string text3 in array2) { string text4 = text3.Trim(); if (text4.StartsWith("Item: ")) { text2 = text4.Substring(6); } else if (text4.StartsWith(" Position: ")) { string text5 = text4.Substring(12); text5 = text5.Trim('(', ')', ' '); string[] array3 = text5.Split(new char[1] { ',' }); if (array3.Length >= 3) { float num = float.Parse(array3[0].Trim()); float num2 = float.Parse(array3[1].Trim()); float num3 = float.Parse(array3[2].Trim()); ((Vector3)(ref zero))..ctor(num, num2, num3); } } else if (text4.StartsWith(" Rotation: ")) { string text6 = text4.Substring(12); text6 = text6.Trim('(', ')', ' '); string[] array4 = text6.Split(new char[1] { ',' }); if (array4.Length >= 4) { float num4 = float.Parse(array4[0].Trim()); float num5 = float.Parse(array4[1].Trim()); float num6 = float.Parse(array4[2].Trim()); float num7 = float.Parse(array4[3].Trim()); ((Quaternion)(ref identity))..ctor(num4, num5, num6, num7); } } else if (text4.StartsWith(" Value: $")) { int num8 = text4.IndexOf('$'); int num9 = text4.IndexOf('('); if (num8 >= 0 && num9 >= 0) { string s = text4.Substring(num8 + 1, num9 - num8 - 1).Trim(); float.TryParse(s, out result2); int num10 = text4.IndexOf('$', num9); if (num10 >= 0) { string s2 = text4.Substring(num10 + 1).Replace(")", "").Trim(); float.TryParse(s2, out result); } } } else if (text4.StartsWith("------------------------------------------") && text2 != null) { SerializedValuable serializedValuable = new SerializedValuable(); serializedValuable.prefabName = text2; serializedValuable.relativePosition = zero; serializedValuable.rotation = identity; serializedValuable.dollarValueOriginal = result; serializedValuable.dollarValueCurrent = result2; savedValuables.Add(serializedValuable); text2 = null; } } if (savedValuables.Count > 0) { hasSavedValuables = true; } else { Debug.Log((object)"[ItemPersistenceMod] No items found in text file"); hasSavedValuables = false; } } else { Debug.LogError((object)"[ItemPersistenceMod] Unknown file format - cannot load"); hasSavedValuables = false; } } } catch (Exception ex2) { Debug.LogError((object)("[ItemPersistenceMod] Error loading valuables from file: " + ex2.Message)); savedValuables.Clear(); hasSavedValuables = false; } if (hasSavedValuables && savedValuables.Count > 0) { forceLoadOnNextLevel = true; } } public static string GetCurrentSaveFilePath() { string path = ((saveFolderPath == null) ? Path.Combine(Paths.ConfigPath, "ItemPersistenceMod") : saveFolderPath); return Path.Combine(path, currentSaveId + ".xml"); } public static void EnsureSaveFilesExist() { string directoryName = Path.GetDirectoryName(GetCurrentSaveFilePath()); if (Directory.Exists(directoryName)) { string[] files = Directory.GetFiles(directoryName); } else { Debug.Log((object)("[ItemPersistenceMod] Save directory does not exist: " + directoryName)); } } public static void ResetModState() { savedValuables.Clear(); hasSavedValuables = false; truckInteriorReference = null; forceLoadOnNextLevel = false; string currentSaveFilePath = GetCurrentSaveFilePath(); if (File.Exists(currentSaveFilePath)) { try { File.Delete(currentSaveFilePath); if ((Object)(object)instance != (Object)null) { instance.mls.LogInfo((object)("Deleted save file: " + currentSaveFilePath)); } } catch (Exception ex) { if ((Object)(object)instance != (Object)null) { instance.mls.LogError((object)("Error deleting save file: " + ex.Message)); } } } if (!((Object)(object)instance != (Object)null)) { } } private void OnApplicationQuit() { if (hasSavedValuables && savedValuables.Count > 0) { SaveValuablesToFile(); } } private IEnumerator DelayedSceneScanner() { yield return (object)new WaitForSeconds(5f); ScanSceneForValuables(); } public static void ScanSceneForValuables() { if ((Object)(object)instance == (Object)null) { return; } ValuableObject[] array = Object.FindObjectsOfType<ValuableObject>(); ValuableObject[] array2 = array; foreach (ValuableObject val in array2) { string name = ((Object)((Component)val).gameObject).name; float num = 0f; float num2 = 0f; try { FieldInfo field = typeof(ValuableObject).GetField("dollarValueOriginal", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); FieldInfo field2 = typeof(ValuableObject).GetField("dollarValueCurrent", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null) { num = (float)field.GetValue(val); } if (field2 != null) { num2 = (float)field2.GetValue(val); } } catch { } try { string fullPath = GetFullPath(((Component)val).transform); } catch { } } string[] array3 = new string[9] { "Valuables", "Items", "Valuables/01 Tiny", "Valuables/02 Small", "Valuables/03 Medium", "Valuables/04 Big", "Valuables/05 Wide", "Valuables/06 Tall", "Valuables/07 Very Tall" }; string[] array4 = array3; foreach (string text in array4) { try { GameObject[] array5 = Resources.LoadAll<GameObject>(text); GameObject[] array6 = array5; foreach (GameObject val2 in array6) { } } catch (Exception) { } } } private static string GetFullPath(Transform transform) { if ((Object)(object)transform.parent == (Object)null) { return ((Object)transform).name; } return GetFullPath(transform.parent) + "/" + ((Object)transform).name; } } [Serializable] [XmlRoot("SaveData")] public class SaveData { [XmlElement("Items")] public List<SavedItem> Items { get; set; } = new List<SavedItem>(); } [Serializable] public class SavedItem { [XmlElement("PrefabName")] public string PrefabName { get; set; } [XmlElement("PosX")] public float PosX { get; set; } [XmlElement("PosY")] public float PosY { get; set; } [XmlElement("PosZ")] public float PosZ { get; set; } [XmlElement("RotX")] public float RotX { get; set; } [XmlElement("RotY")] public float RotY { get; set; } [XmlElement("RotZ")] public float RotZ { get; set; } [XmlElement("RotW")] public float RotW { get; set; } [XmlElement("DollarValueOriginal")] public float DollarValueOriginal { get; set; } [XmlElement("DollarValueCurrent")] public float DollarValueCurrent { get; set; } public SavedItem() { } public SavedItem(SerializedValuable valuable) { PrefabName = valuable.prefabName; PosX = valuable.relativePosition.x; PosY = valuable.relativePosition.y; PosZ = valuable.relativePosition.z; RotX = valuable.rotation.x; RotY = valuable.rotation.y; RotZ = valuable.rotation.z; RotW = valuable.rotation.w; DollarValueOriginal = valuable.dollarValueOriginal; DollarValueCurrent = valuable.dollarValueCurrent; } public SerializedValuable ToSerializedValuable() { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) SerializedValuable serializedValuable = new SerializedValuable(); serializedValuable.prefabName = PrefabName; serializedValuable.relativePosition = new Vector3(PosX, PosY, PosZ); serializedValuable.rotation = new Quaternion(RotX, RotY, RotZ, RotW); serializedValuable.dollarValueOriginal = DollarValueOriginal; serializedValuable.dollarValueCurrent = DollarValueCurrent; return serializedValuable; } } [Serializable] public class SerializedValuable { public string prefabName; public Vector3 relativePosition; public Quaternion rotation; public float dollarValueOriginal; public float dollarValueCurrent; public SerializedValuable() { } public SerializedValuable(GameObject valuableObj, Transform truckInterior) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: 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_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) prefabName = ((Object)valuableObj).name.Replace("(Clone)", "").Trim(); relativePosition = truckInterior.InverseTransformPoint(valuableObj.transform.position); rotation = Quaternion.Inverse(truckInterior.rotation) * valuableObj.transform.rotation; ValuableObject component = valuableObj.GetComponent<ValuableObject>(); if ((Object)(object)component != (Object)null) { dollarValueOriginal = component.dollarValueOriginal; dollarValueCurrent = component.dollarValueCurrent; if (dollarValueOriginal <= 0f || dollarValueCurrent <= 0f) { try { FieldInfo field = typeof(ValuableObject).GetField("dollarValueOriginal", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); FieldInfo field2 = typeof(ValuableObject).GetField("dollarValueCurrent", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null) { dollarValueOriginal = (float)field.GetValue(component); } else { dollarValueOriginal = 100f; } if (field2 != null) { dollarValueCurrent = (float)field2.GetValue(component); } else { dollarValueCurrent = 100f; } } catch (Exception ex) { dollarValueOriginal = 100f; dollarValueCurrent = 100f; if ((Object)(object)ItemPersistenceModBase.instance != (Object)null) { ItemPersistenceModBase.instance.mls.LogError((object)("Error accessing valuable values: " + ex.Message)); } } } if (!((Object)(object)ItemPersistenceModBase.instance != (Object)null)) { } } else { dollarValueOriginal = 100f; dollarValueCurrent = 100f; if ((Object)(object)ItemPersistenceModBase.instance != (Object)null) { ItemPersistenceModBase.instance.mls.LogWarning((object)("No ValuableObject component found on " + prefabName + ", using default values")); } } } } } namespace ItemPersistenceMod.Patches { [HarmonyPatch(typeof(StatsManager), "SaveFileDelete")] public class SaveFileDeletionPatch { [HarmonyPrefix] private static bool Prefix(string saveFileName) { try { if (!string.IsNullOrEmpty(saveFileName)) { bool flag = false; if ((Object)(object)RunManager.instance != (Object)null && ((Object)(object)RunManager.instance.levelCurrent == (Object)(object)RunManager.instance.levelShop || ((Object)(object)RunManager.instance.levelCurrent != (Object)(object)RunManager.instance.levelMainMenu && (Object)(object)RunManager.instance.levelCurrent != (Object)(object)RunManager.instance.levelLobbyMenu))) { flag = true; } ItemPersistenceModBase.DeleteSaveFile(saveFileName); FieldInfo fieldInfo = AccessTools.Field(typeof(StatsManager), "saveFileCurrent"); if (fieldInfo != null) { string text = (string)fieldInfo.GetValue(StatsManager.instance); if (saveFileName == text) { ItemPersistenceModBase.savedValuables.Clear(); ItemPersistenceModBase.hasSavedValuables = false; } } } return true; } catch (Exception ex) { ItemPersistenceModBase.instance.mls.LogError((object)("Error in SaveFileDeletionPatch: " + ex.Message)); return true; } } } public static class GameStateCheck { public static bool IsGameplayLevel() { //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Invalid comparison between Unknown and I4 //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Invalid comparison between Unknown and I4 try { if (IsArenaLevel() || isLobbyLevel()) { return false; } if ((Object)(object)RunManager.instance != (Object)null) { if ((Object)(object)RunManager.instance.levelCurrent == (Object)(object)RunManager.instance.levelMainMenu || (Object)(object)RunManager.instance.levelCurrent == (Object)(object)RunManager.instance.levelLobbyMenu) { return false; } if ((Object)(object)RunManager.instance.levelCurrent == (Object)(object)RunManager.instance.levelShop || (Object)(object)RunManager.instance.levelCurrent == (Object)(object)RunManager.instance.levelLobby) { return true; } } MainMenuOpen val = Object.FindObjectOfType<MainMenuOpen>(); if ((Object)(object)val != (Object)null) { if ((Object)(object)GameDirector.instance != (Object)null && ((int)GameDirector.instance.currentState == 2 || (int)GameDirector.instance.currentState == 3)) { return true; } return false; } TruckDoor val2 = Object.FindObjectOfType<TruckDoor>(); if ((Object)(object)val2 != (Object)null) { return true; } return true; } catch (Exception ex) { ItemPersistenceModBase.instance.mls.LogError((object)("Error in IsGameplayLevel: " + ex.Message)); return true; } } public static bool isLobbyLevel() { try { if ((Object)(object)RunManager.instance != (Object)null && (Object)(object)RunManager.instance.levelCurrent == (Object)(object)RunManager.instance.levelLobby) { return true; } return false; } catch (Exception ex) { ItemPersistenceModBase.instance.mls.LogError((object)("Error in IsLobbyLevel: " + ex.Message)); return false; } } public static bool IsArenaLevel() { try { if ((Object)(object)RunManager.instance != (Object)null && (Object)(object)RunManager.instance.levelCurrent == (Object)(object)RunManager.instance.levelArena) { return true; } return false; } catch (Exception ex) { ItemPersistenceModBase.instance.mls.LogError((object)("Error in IsArenaLevel: " + ex.Message)); return false; } } public static bool isShopLevel() { try { if ((Object)(object)RunManager.instance != (Object)null && (Object)(object)RunManager.instance.levelCurrent == (Object)(object)RunManager.instance.levelShop) { return true; } return false; } catch (Exception ex) { ItemPersistenceModBase.instance.mls.LogError((object)("Error in IsShopLevel: " + ex.Message)); return false; } } private static void DeleteSaveFileForArena() { try { ItemPersistenceModBase.UpdateCurrentSaveId(); string currentSaveFilePath = ItemPersistenceModBase.GetCurrentSaveFilePath(); if (File.Exists(currentSaveFilePath)) { File.Delete(currentSaveFilePath); if (File.Exists(currentSaveFilePath)) { ItemPersistenceModBase.instance.mls.LogError((object)"Failed to delete save file"); } } ItemPersistenceModBase.savedValuables.Clear(); ItemPersistenceModBase.hasSavedValuables = false; } catch (Exception ex) { ItemPersistenceModBase.instance.mls.LogError((object)("Error deleting save file for arena: " + ex.Message)); } } public static bool IsTruckReady() { try { TruckDoor val = Object.FindObjectOfType<TruckDoor>(); if ((Object)(object)val == (Object)null) { Transform val2 = GameDirectorPatch.FindTruckInterior(); return (Object)(object)val2 != (Object)null; } return true; } catch (Exception ex) { ItemPersistenceModBase.instance.mls.LogError((object)("Error in IsTruckReady: " + ex.Message)); return false; } } } [HarmonyPatch(typeof(GameDirector))] public class GameDirectorPatch { [HarmonyPatch("OutroStart")] [HarmonyPrefix] private static bool OutroStartPrefix(GameDirector __instance) { //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) try { if (!GameStateCheck.IsGameplayLevel()) { return true; } ItemPersistenceModBase.savedValuables.Clear(); ItemPersistenceModBase.hasSavedValuables = false; Transform val = FindTruckInterior(); if ((Object)(object)val == (Object)null) { return true; } ItemPersistenceModBase.truckInteriorReference = val; ValuableObject[] array = Object.FindObjectsOfType<ValuableObject>(); int num = 0; ValuableObject[] array2 = array; foreach (ValuableObject val2 in array2) { if ((Object)(object)val2 != (Object)null && IsInsideTruck(((Component)val2).gameObject, val)) { SerializedValuable serializedValuable = new SerializedValuable(((Component)val2).gameObject, val); serializedValuable.relativePosition = LevelGeneratorPatch.GetStandardizedPosition(((Component)val2).transform.position, val); ItemPersistenceModBase.savedValuables.Add(serializedValuable); num++; } } if (num > 0) { ItemPersistenceModBase.hasSavedValuables = true; if ((Object)(object)ItemPersistenceModBase.instance != (Object)null) { } ItemPersistenceModBase.SaveValuablesToFile(); string currentSaveFilePath = ItemPersistenceModBase.GetCurrentSaveFilePath(); if (File.Exists(currentSaveFilePath)) { FileInfo fileInfo = new FileInfo(currentSaveFilePath); } else { string directoryName = Path.GetDirectoryName(currentSaveFilePath); if (Directory.Exists(directoryName)) { string[] files = Directory.GetFiles(directoryName); string[] array3 = files; foreach (string text in array3) { } } } } return true; } catch (Exception ex) { ItemPersistenceModBase.instance.mls.LogError((object)("Error in OutroStartPrefix: " + ex.Message)); ItemPersistenceModBase.instance.mls.LogError((object)("Stack trace: " + ex.StackTrace)); return true; } } public static Transform FindTruckInterior() { RoomVolume[] array = Object.FindObjectsOfType<RoomVolume>(); RoomVolume[] array2 = array; foreach (RoomVolume val in array2) { if (val.Truck) { return ((Component)val).transform; } } GameObject[] array3 = (from go in Object.FindObjectsOfType<GameObject>() where ((Object)go).name.Contains("Truck") && (((Object)go).name.Contains("Interior") || ((Object)go).name.Contains("Inside") || ((Object)go).name.Contains("Room")) select go).ToArray(); if (array3.Length != 0) { ItemPersistenceModBase.instance.mls.LogInfo((object)("Found truck by name: " + ((Object)array3[0]).name)); return array3[0].transform; } TruckDoor val2 = Object.FindObjectOfType<TruckDoor>(); if ((Object)(object)val2 != (Object)null) { return ((Component)val2).transform; } return null; } private static bool IsInsideTruck(GameObject valuableObj, Transform truckReference, float padding = 0.5f) { //IL_0003: 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_009e: 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_0032: Unknown result type (might be due to invalid IL or missing references) //IL_007b: 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_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) Bounds val = default(Bounds); Collider[] componentsInChildren = ((Component)truckReference).GetComponentsInChildren<Collider>(); if (componentsInChildren.Length != 0) { Collider[] array = componentsInChildren; foreach (Collider val2 in array) { if (((Bounds)(ref val)).size == Vector3.zero) { val = val2.bounds; } else { ((Bounds)(ref val)).Encapsulate(val2.bounds); } } ((Bounds)(ref val)).Expand(padding); if (((Bounds)(ref val)).Contains(valuableObj.transform.position)) { return true; } } float num = Vector3.Distance(valuableObj.transform.position, truckReference.position); return num < 10f + padding; } } [HarmonyPatch(typeof(LevelGenerator))] public class LevelGeneratorPatch { [HarmonyPatch("GenerateDone")] [HarmonyPostfix] private static void GenerateDonePostfix(LevelGenerator __instance) { try { ((MonoBehaviour)__instance).StartCoroutine(DelayedGenerateDone(__instance)); } catch (Exception) { } } private static IEnumerator DelayedGenerateDone(LevelGenerator levelGenerator) { yield return null; ItemPersistenceModBase.LoadValuablesFromFile(); if (!ItemPersistenceModBase.hasSavedValuables || ItemPersistenceModBase.savedValuables.Count <= 0) { yield break; } ItemPersistenceModBase.forceLoadOnNextLevel = false; if ((Object)(object)Object.FindObjectOfType<MainMenuOpen>() != (Object)null) { ItemPersistenceModBase.instance.mls.LogInfo((object)"Main menu detected - skipping valuable spawning"); yield break; } float waitTime = 0f; while ((Object)(object)GameDirector.instance != (Object)null && (int)GameDirector.instance.currentState != 2 && waitTime < 10f) { waitTime += 0.5f; yield return (object)new WaitForSeconds(0.5f); } waitTime = 0f; bool truckFound = false; while (!truckFound && waitTime < 10f) { waitTime += 0.5f; Transform truck = GameDirectorPatch.FindTruckInterior(); if ((Object)(object)truck != (Object)null) { truckFound = true; } yield return (object)new WaitForSeconds(0.5f); } if (!truckFound) { } yield return (object)new WaitForSeconds(2f); yield return SpawnSavedValuablesCoroutine(levelGenerator); } public static Vector3 GetStandardizedPosition(Vector3 worldPos, Transform truckTransform) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: 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_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: 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) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004c: 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_0060: 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_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: 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) Vector3 forward = truckTransform.forward; forward.y = 0f; ((Vector3)(ref forward)).Normalize(); Vector3 right = truckTransform.right; right.y = 0f; ((Vector3)(ref right)).Normalize(); Vector3 val = worldPos - truckTransform.position; float num = Vector3.Dot(val, right); float num2 = worldPos.y - truckTransform.position.y; float num3 = Vector3.Dot(val, forward); return new Vector3(num, num2, num3); } public static Vector3 GetWorldPositionFromStandardized(Vector3 standardPos, Transform truckTransform) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: 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_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_003e: 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) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004e: 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_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: 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_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_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0075: 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_0079: Unknown result type (might be due to invalid IL or missing references) Vector3 forward = truckTransform.forward; forward.y = 0f; ((Vector3)(ref forward)).Normalize(); Vector3 right = truckTransform.right; right.y = 0f; ((Vector3)(ref right)).Normalize(); return truckTransform.position + right * standardPos.x + Vector3.up * standardPos.y + forward * standardPos.z; } private static IEnumerator SpawnSavedValuablesCoroutine(LevelGenerator levelGenerator) { ItemPersistenceModBase.instance.mls.LogInfo((object)$"Number of saved valuables: {ItemPersistenceModBase.savedValuables.Count}"); if (!GameStateCheck.IsGameplayLevel()) { yield break; } Transform truckInterior = GameDirectorPatch.FindTruckInterior(); if ((Object)(object)truckInterior == (Object)null) { yield break; } int spawnedCount = 0; int failedCount = 0; foreach (SerializedValuable serializedValuable in ItemPersistenceModBase.savedValuables) { string prefabName = serializedValuable.prefabName.Replace("(Clone)", "").Trim(); GameObject valuableObj = null; Vector3 standardizedPosition = serializedValuable.relativePosition; Vector3 spawnPosition = GetWorldPositionFromStandardized(standardizedPosition, truckInterior); spawnPosition.y += 1f; Quaternion spawnRotation = truckInterior.rotation * serializedValuable.rotation; try { bool spawnSuccessful = false; if (ItemPersistenceModBase.repoLibAvailable) { try { IReadOnlyList<GameObject> registeredValuables = Valuables.RegisteredValuables; GameObject prefab2 = ((IEnumerable<GameObject>)registeredValuables).FirstOrDefault((Func<GameObject, bool>)((GameObject go) => string.Equals(((Object)go).name.Replace("(Clone)", ""), prefabName, StringComparison.OrdinalIgnoreCase))); if ((Object)(object)prefab2 != (Object)null) { if (SemiFunc.IsMultiplayer()) { try { string valuablePrefabPath = ResourcesHelper.GetValuablePrefabPath(prefab2); if (!string.IsNullOrEmpty(valuablePrefabPath)) { valuableObj = PhotonNetwork.InstantiateRoomObject(valuablePrefabPath, spawnPosition, spawnRotation, (byte)0, (object[])null); spawnSuccessful = (Object)(object)valuableObj != (Object)null; } } catch (Exception) { valuableObj = Object.Instantiate<GameObject>(prefab2, spawnPosition, spawnRotation); spawnSuccessful = (Object)(object)valuableObj != (Object)null; } } else { valuableObj = Object.Instantiate<GameObject>(prefab2, spawnPosition, spawnRotation); spawnSuccessful = (Object)(object)valuableObj != (Object)null; } } } catch (Exception) { } } if (!spawnSuccessful) { string foundPath; GameObject prefab = TryLoadValuablePrefab(prefabName, out foundPath); if ((Object)(object)prefab != (Object)null) { if (SemiFunc.IsMultiplayer()) { try { if (!string.IsNullOrEmpty(foundPath)) { valuableObj = PhotonNetwork.InstantiateRoomObject(foundPath, spawnPosition, spawnRotation, (byte)0, (object[])null); } } catch (Exception) { valuableObj = Object.Instantiate<GameObject>(prefab, spawnPosition, spawnRotation); } } else { valuableObj = Object.Instantiate<GameObject>(prefab, spawnPosition, spawnRotation); } } foundPath = null; } if ((Object)(object)valuableObj != (Object)null) { SetValuableProperties(valuableObj, serializedValuable); valuableObj.GetComponent<ValuableObject>(); PhysGrabObjectImpactDetector impactDetector = valuableObj.GetComponent<PhysGrabObjectImpactDetector>(); impactDetector.changeInCart(); KeepInCartState(impactDetector, 60f); serializedValuable.relativePosition = GetStandardizedPosition(spawnPosition, truckInterior); spawnedCount++; } else { failedCount++; } } catch (Exception) { failedCount++; } } if (spawnedCount > 0) { ItemPersistenceModBase.SaveValuablesToFile(); } } private static GameObject TryLoadValuablePrefab(string searchName, out string foundPath) { foundPath = ""; string[] array = new string[7] { "01 Tiny", "02 Small", "03 Medium", "04 Big", "05 Wide", "06 Tall", "07 Very Tall" }; string[] array2 = array; foreach (string text in array2) { string text2 = "Valuables/" + text + "/" + searchName; GameObject val = Resources.Load<GameObject>(text2); if ((Object)(object)val != (Object)null) { foundPath = text2; return val; } } string text3 = "Items/Removed Items/" + searchName; GameObject val2 = Resources.Load<GameObject>(text3); if ((Object)(object)val2 != (Object)null) { foundPath = text3; return val2; } string text4 = "Items/" + searchName; GameObject val3 = Resources.Load<GameObject>(text4); if ((Object)(object)val3 != (Object)null) { foundPath = text4; return val3; } return null; } private static GameObject FindValuablePrefab(string prefabName) { prefabName = prefabName.Replace("(Clone)", ""); ValuableObject[] array = Object.FindObjectsOfType<ValuableObject>(); ValuableObject[] array2 = array; foreach (ValuableObject val in array2) { string text = ((Object)((Component)val).gameObject).name.Replace("(Clone)", ""); if (text.Equals(prefabName, StringComparison.OrdinalIgnoreCase) || text.Contains(prefabName) || prefabName.Contains(text)) { return ((Component)val).gameObject; } } GameObject[] array3 = Object.FindObjectsOfType<GameObject>(); GameObject[] array4 = array3; foreach (GameObject val2 in array4) { string text2 = ((Object)val2).name.Replace("(Clone)", ""); if ((text2.Equals(prefabName, StringComparison.OrdinalIgnoreCase) || text2.Contains(prefabName) || prefabName.Contains(text2)) && (Object)(object)val2.GetComponent<ValuableObject>() != (Object)null) { return val2; } } List<string> list = new List<string>(); string text3 = prefabName.Replace("Valuable ", "").Trim(); string[] array5 = new string[7] { "01 Tiny", "02 Small", "03 Medium", "04 Big", "05 Wide", "06 Tall", "07 Very Tall" }; string[] array6 = new string[3] { "", "Valuable ", "Valuable_" }; string[] array7 = array5; foreach (string text4 in array7) { string[] array8 = array6; foreach (string text5 in array8) { list.Add("Valuables/" + text4 + "/" + text5 + text3); } } string[] array9 = array6; foreach (string text6 in array9) { list.Add("Valuables/" + text6 + text3); list.Add("Items/" + text6 + text3); } foreach (string item in list) { try { GameObject val3 = Resources.Load<GameObject>(item); if ((Object)(object)val3 != (Object)null) { return val3; } } catch (Exception) { } } if (ItemPersistenceModBase.repoLibAvailable) { try { IReadOnlyList<GameObject> registeredValuables = Valuables.RegisteredValuables; foreach (GameObject item2 in registeredValuables) { if (((Object)item2).name.Contains(text3) || text3.Contains(((Object)item2).name.Replace("Valuable ", ""))) { return item2; } } } catch (Exception) { } } return null; } private static IEnumerator KeepInCartState(PhysGrabObjectImpactDetector impactDetector, float duration) { for (float timer = 0f; timer < duration; timer += 0.05f) { if (!((Object)(object)impactDetector != (Object)null)) { break; } impactDetector.changeInCart(); yield return (object)new WaitForSeconds(0.05f); } } private static void SetValuableProperties(GameObject valuableObj, SerializedValuable serializedValuable) { ValuableObject component = valuableObj.GetComponent<ValuableObject>(); if (!((Object)(object)component != (Object)null)) { return; } try { FieldInfo field = typeof(ValuableObject).GetField("dollarValueOriginal", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); FieldInfo field2 = typeof(ValuableObject).GetField("dollarValueCurrent", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); FieldInfo field3 = typeof(ValuableObject).GetField("dollarValueSet", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null) { field.SetValue(component, serializedValuable.dollarValueOriginal); } if (field2 != null) { field2.SetValue(component, serializedValuable.dollarValueCurrent); } if (field3 != null) { field3.SetValue(component, true); } else { try { MethodInfo method = typeof(ValuableObject).GetMethod("DollarValueSetLogic", BindingFlags.Instance | BindingFlags.NonPublic); if (method != null) { method.Invoke(component, null); } } catch (Exception) { } } float dollarValueOriginal = component.dollarValueOriginal; float dollarValueCurrent = component.dollarValueCurrent; try { FieldInfo field4 = typeof(ValuableObject).GetField("discovered", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field4 != null) { field4.SetValue(component, true); } component.Discover((State)0); } catch (Exception) { } } catch (Exception) { } } } [HarmonyPatch(typeof(RunManager))] public class RunManagerPatch { private static bool isGoingToMainMenu; [HarmonyPatch("ChangeLevel")] [HarmonyPrefix] private static void ChangeLevelPrefix(RunManager __instance, ChangeLevelType _changeLevelType) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0004: Invalid comparison between Unknown and I4 try { isGoingToMainMenu = (int)_changeLevelType == 4; if (isGoingToMainMenu && ItemPersistenceModBase.hasSavedValuables && ItemPersistenceModBase.savedValuables.Count > 0) { ItemPersistenceModBase.SaveValuablesToFile(); } } catch (Exception ex) { ItemPersistenceModBase.instance.mls.LogError((object)("Error in ChangeLevelPrefix: " + ex.Message)); } } [HarmonyPatch("ChangeLevel")] [HarmonyPostfix] private static void ChangeLevelPostfix(RunManager __instance, bool _completedLevel, bool _levelFailed, ChangeLevelType _changeLevelType) { try { ItemPersistenceModBase.UpdateCurrentSaveId(); } catch (Exception ex) { ItemPersistenceModBase.instance.mls.LogError((object)("Error in ChangeLevelPostfix: " + ex.Message)); } } [HarmonyPatch("UpdateLevel")] [HarmonyPostfix] private static void UpdateLevelPostfix(RunManager __instance, string _levelName, int _levelsCompleted, bool _gameOver) { try { ItemPersistenceModBase.UpdateCurrentSaveId(); } catch (Exception ex) { ItemPersistenceModBase.instance.mls.LogError((object)("Error in UpdateLevelPostfix: " + ex.Message)); } } [HarmonyPatch("ResetProgress")] [HarmonyPostfix] private static void ResetProgressPostfix(RunManager __instance) { try { if (isGoingToMainMenu) { ItemPersistenceModBase.UpdateCurrentSaveId(); } else { ItemPersistenceModBase.UpdateCurrentSaveId(); } } catch (Exception ex) { ItemPersistenceModBase.instance.mls.LogError((object)("Error in ResetProgressPostfix: " + ex.Message)); } } } }