Bonelab mods are targeting MelonLoader version 0.5.7. Newer versions will not work!, so double-check your MelonLoader version if you're having issues.
Decompiled source of InventoryPersistence v1.0.0
Mods/InventoryPersistence.dll
Decompiled 2 months agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BoneLib; using BoneLib.BoneMenu; using BoneLib.BoneMenu.Elements; using BoneLib.Nullables; using HarmonyLib; using Il2CppSystem; using InventoryPersistence; using InventoryPersistence.Bonemenu; using InventoryPersistence.Data; using LabFusion.Data; using LabFusion.Network; using LabFusion.Representation; using LabFusion.Utilities; using MelonLoader; using MelonLoader.Preferences; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using SLZ; using SLZ.Interaction; using SLZ.Marrow.Data; using SLZ.Marrow.Pool; using SLZ.Marrow.SceneStreaming; using SLZ.Marrow.Warehouse; using UnhollowerBaseLib; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("A BONELAB mod which allows the player's inventory to persist from one level to the next and save between sessions!")] [assembly: AssemblyDescription("A BONELAB mod which allows the player's inventory to persist from one level to the next and save between sessions!")] [assembly: AssemblyCompany("SilverWare")] [assembly: AssemblyProduct("Inventory Persistence")] [assembly: AssemblyCopyright("Developed by KitchenBoy")] [assembly: AssemblyTrademark("SilverWare")] [assembly: AssemblyFileVersion("1.0.0")] [assembly: MelonInfo(typeof(Main), "Inventory Persistence", "1.0.0", "KitchenBoy", "https://github.com/KitchenBoy08/InventoryPersistence/releases")] [assembly: MelonColor(ConsoleColor.White)] [assembly: MelonGame("Stress Level Zero", "BONELAB")] [assembly: MelonOptionalDependencies(new string[] { "LabFusion" })] [assembly: MelonPriority(-1000)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace InventoryPersistence { internal class Hooking { internal static void InitializeHooks() { Hooking.OnLevelInitialized += OnLevelInitializedHook; } private static void OnLevelInitializedHook(LevelInfo levelInfo) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_004a: 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_0185: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Expected O, but got Unknown //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_0191: Unknown result type (might be due to invalid IL or missing references) //IL_0199: Unknown result type (might be due to invalid IL or missing references) //IL_019f: Expected O, but got Unknown //IL_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_01af: Unknown result type (might be due to invalid IL or missing references) //IL_01b4: Unknown result type (might be due to invalid IL or missing references) //IL_01bb: Unknown result type (might be due to invalid IL or missing references) //IL_01c1: Unknown result type (might be due to invalid IL or missing references) //IL_0204: Expected O, but got Unknown if (BoneMenuPreferences.LevelBlacklist.Value.Contains(levelInfo.barcode)) { ((MenuElement)BoneMenuPreferences.BlacklistLevelElement).SetName("Whitelist Current Level"); ((MenuElement)BoneMenuPreferences.BlacklistLevelElement).SetColor(Color.green); return; } ((MenuElement)BoneMenuPreferences.BlacklistLevelElement).SetName("Blacklist Current Level"); ((MenuElement)BoneMenuPreferences.BlacklistLevelElement).SetColor(Color.red); PlayerInventory playerInventory = JsonSaving.LoadInventory(); if (playerInventory == null) { return; } Player.rigManager.AmmoInventory.ClearAmmo(); Player.rigManager.AmmoInventory.AddCartridge(Player.rigManager.AmmoInventory.lightAmmoGroup, playerInventory.LightAmmoCount); Player.rigManager.AmmoInventory.AddCartridge(Player.rigManager.AmmoInventory.mediumAmmoGroup, playerInventory.MediumAmmoCount); Player.rigManager.AmmoInventory.AddCartridge(Player.rigManager.AmmoInventory.heavyAmmoGroup, playerInventory.HeavyAmmoCount); if (Main.HasFusion && NetworkInfo.HasServer) { foreach (KeyValuePair<string, string> inventoryBarcode in playerInventory.InventoryBarcodes) { SendFusionSpawn(inventoryBarcode.Value); } return; } foreach (KeyValuePair<string, string> item in playerInventory.InventoryBarcodes) { SlotContainer slotContainer = ((IEnumerable<SlotContainer>)Player.rigManager.inventory.bodySlots).Where((SlotContainer x) => ((Object)x).name == item.Key).First(); SpawnableCrateReference crateRef = new SpawnableCrateReference(item.Value); Spawnable val = new Spawnable { crateRef = crateRef }; AssetSpawner.Register(val); Transform playerHead = Player.playerHead; AssetSpawner.Spawn(val, playerHead.position + playerHead.forward, default(Quaternion), BoxedNullable<Vector3>.op_Implicit(new BoxedNullable<Vector3>((Vector3?)null)), false, BoxedNullable<int>.op_Implicit(new BoxedNullable<int>((int?)null)), Action<GameObject>.op_Implicit((Action<GameObject>)OnSpawn), (Action<GameObject>)null); void OnSpawn(GameObject go) { InteractableHost val2 = ((!((Object)(object)go.GetComponent<InteractableHost>() != (Object)null)) ? ((Component)go.transform).GetComponentInChildren<InteractableHost>() : go.GetComponent<InteractableHost>()); if (Object.op_Implicit((Object)(object)slotContainer.inventorySlotReceiver._slottedWeapon)) { slotContainer.inventorySlotReceiver.DespawnContents(); } slotContainer.inventorySlotReceiver.InsertInSlot(val2); } } } private static void SendFusionSpawn(string barcode) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown PooleeUtilities.RequestSpawn(barcode, new SerializedTransform(Player.playerHead.position + Player.playerHead.forward * 2.5f, Quaternion.identity), (byte?)PlayerIdManager.LocalSmallId, (Handedness)0); } } public class PlayerInventory { public int LightAmmoCount; public int MediumAmmoCount; public int HeavyAmmoCount; public Dictionary<string, string> InventoryBarcodes { get; set; } public static Dictionary<string, string> GetPlayerInventoryBarcodes() { if ((Object)(object)Player.rigManager == (Object)null) { return null; } Dictionary<string, string> dictionary = new Dictionary<string, string>(); foreach (SlotContainer item in (Il2CppArrayBase<SlotContainer>)(object)Player.rigManager.inventory.bodySlots) { if (Object.op_Implicit((Object)(object)item.inventorySlotReceiver) && Object.op_Implicit((Object)(object)item.inventorySlotReceiver._slottedWeapon)) { AssetPoolee val = ((!Object.op_Implicit((Object)(object)item.inventorySlotReceiver._slottedWeapon.interactableHost.manager)) ? ((Component)((Component)item.inventorySlotReceiver._slottedWeapon.interactableHost).transform).GetComponent<AssetPoolee>() : ((Component)((Component)item.inventorySlotReceiver._slottedWeapon.interactableHost.manager).transform).GetComponent<AssetPoolee>()); if (Object.op_Implicit((Object)(object)val)) { string iD = ((Scannable)val.spawnableCrate).Barcode.ID; dictionary.Add(((Object)item).name, iD); } } } return dictionary; } public static PlayerInventory GetPlayerInventory() { PlayerInventory playerInventory = new PlayerInventory(); if (BoneMenuPreferences.SaveAmmo.Value) { playerInventory.LightAmmoCount = Player.rigManager.AmmoInventory.GetCartridgeCount("light"); playerInventory.MediumAmmoCount = Player.rigManager.AmmoInventory.GetCartridgeCount("medium"); playerInventory.HeavyAmmoCount = Player.rigManager.AmmoInventory.GetCartridgeCount("heavy"); } if (BoneMenuPreferences.SaveItems.Value) { playerInventory.InventoryBarcodes = GetPlayerInventoryBarcodes(); } return playerInventory; } } internal class Main : MelonMod { internal const string Name = "Inventory Persistence"; internal const string Description = "A BONELAB mod which allows the player's inventory to persist from one level to the next and save between sessions!"; internal const string Author = "KitchenBoy"; internal const string Company = "SilverWare"; internal const string Version = "1.0.0"; internal const string DownloadLink = "https://github.com/KitchenBoy08/InventoryPersistence/releases"; internal static bool HasFusion; public override void OnLateInitializeMelon() { BoneMenuPreferences.InitializeBonemneu(); Hooking.InitializeHooks(); HasFusion = HelperMethods.CheckIfAssemblyLoaded("labfusion"); } } } namespace InventoryPersistence.Patches { [HarmonyPatch(typeof(SceneStreamer))] public class SceneStreamerPatches { [HarmonyPatch("Load", new Type[] { typeof(LevelCrateReference), typeof(LevelCrateReference) })] [HarmonyPrefix] public static void Load(LevelCrateReference level, LevelCrateReference loadLevel) { OnLoadLevel(((CrateReference)level).Barcode.ID); } [HarmonyPatch("Load", new Type[] { typeof(string), typeof(string) })] [HarmonyPrefix] public static void Load(string levelBarcode, string loadLevelBarcode) { OnLoadLevel(levelBarcode); } private static void OnLoadLevel(string levelBarcode) { if (!BoneMenuPreferences.LevelBlacklist.Value.Contains(((Scannable)SceneStreamer.Session.Level).Barcode.ID)) { JsonSaving.SaveInventory(PlayerInventory.GetPlayerInventory()); } } } } namespace InventoryPersistence.Data { public static class JsonSaving { public static readonly string SavePath = MelonUtils.UserDataDirectory + "/InventoryPersistenceData.json"; public static JsonSerializerSettings SerializationSettings = new JsonSerializerSettings { Formatting = (Formatting)1, CheckAdditionalContent = true, ReferenceLoopHandling = (ReferenceLoopHandling)2, PreserveReferencesHandling = (PreserveReferencesHandling)1 }; internal static void SaveInventory(PlayerInventory inventory) { string contents = JsonConvert.SerializeObject((object)inventory, SerializationSettings); File.WriteAllText(SavePath, contents); } public static PlayerInventory LoadInventory() { if (!File.Exists(SavePath)) { return null; } return JsonConvert.DeserializeObject<PlayerInventory>(File.ReadAllText(SavePath), SerializationSettings); } } } namespace InventoryPersistence.Bonemenu { internal class BoneMenuPreferences { internal static MenuCategory MainCategory; internal static MelonPreferences_Category PreferenceCategory; internal static MelonPreferences_Entry<bool> SaveAmmo; internal static MelonPreferences_Entry<bool> SaveItems; internal static MelonPreferences_Entry<List<string>> LevelBlacklist; internal static BoolElement SaveAmmoElement; internal static BoolElement SaveItemsElement; internal static FunctionElement BlacklistLevelElement; internal static void InitializeBonemneu() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) MainCategory = MenuManager.CreateCategory("Inventory Persistence", Color.white); PreferenceCategory = MelonPreferences.CreateCategory("InventoryPersistence", "Inventory Persistence", false, true); SaveAmmo = PreferenceCategory.CreateEntry<bool>("SaveAmmo", true, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); SaveItems = PreferenceCategory.CreateEntry<bool>("SaveItems", true, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); LevelBlacklist = PreferenceCategory.CreateEntry<List<string>>("LevelBlacklist", new List<string>(), (string)null, (string)null, false, false, (ValueValidator)null, (string)null); SaveAmmoElement = MainCategory.CreateBoolElement("Save Ammo", Color.white, true, (Action<bool>)delegate(bool save) { SaveAmmo.Value = save; ((MelonPreferences_Entry)SaveAmmo).Save(); }); SaveItemsElement = MainCategory.CreateBoolElement("Save Items", Color.white, true, (Action<bool>)delegate(bool save) { SaveItems.Value = save; ((MelonPreferences_Entry)SaveItems).Save(); }); BlacklistLevelElement = MainCategory.CreateFunctionElement("Blacklist Current Level", Color.red, (Action)delegate { //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) if (LevelBlacklist.Value.Contains(((Scannable)SceneStreamer.Session.Level).Barcode.ID)) { LevelBlacklist.Value.Remove(((Scannable)SceneStreamer.Session.Level).Barcode.ID); ((MenuElement)BlacklistLevelElement).SetName("Blacklist Current Level"); ((MenuElement)BlacklistLevelElement).SetColor(Color.red); } else { LevelBlacklist.Value.Add(((Scannable)SceneStreamer.Session.Level).Barcode.ID); ((MenuElement)BlacklistLevelElement).SetName("Whitelist Current Level"); ((MenuElement)BlacklistLevelElement).SetColor(Color.green); } ((MelonPreferences_Entry)LevelBlacklist).Save(); }); } } }