Decompiled source of InventoryPersistence v1.0.0

Mods/InventoryPersistence.dll

Decompiled 2 months ago
using 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();
			});
		}
	}
}