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