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