Decompiled source of BagConfig v0.0.5

BepInEx/plugins/BagConfig.dll

Decompiled a week ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BagConfig.Dependency;
using BagConfig.Patches;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using HarmonyLib.Public.Patching;
using LethalConfig;
using LethalConfig.ConfigItems;
using LethalConfig.ConfigItems.Options;
using LobbyCompatibility.Enums;
using LobbyCompatibility.Features;
using Microsoft.CodeAnalysis;
using Mono.Cecil;
using Mono.Cecil.Cil;
using Mono.Collections.Generic;
using MonoMod.RuntimeDetour;
using MonoMod.Utils;
using Unity.Netcode;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp-firstpass")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: IgnoresAccessChecksTo("Unity.Netcode.Components")]
[assembly: IgnoresAccessChecksTo("Unity.Netcode.Runtime")]
[assembly: AssemblyCompany("BagConfig")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.0.5")]
[assembly: AssemblyInformationalVersion("0.0.5-beta+e7d81f5a424d08fe51b7d90704f57c344c149b36")]
[assembly: AssemblyProduct("BagConfig")]
[assembly: AssemblyTitle("BagConfig - My Assembly Title")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.5.0")]
[module: UnverifiableCode]
[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 BagConfig
{
	[BepInPlugin("mattymatty.BagConfig", "BagConfig", "0.0.5")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	internal class BagConfig : BaseUnityPlugin
	{
		internal static readonly ISet<Hook> Hooks = new HashSet<Hook>();

		internal static readonly Harmony Harmony = new Harmony("mattymatty.BagConfig");

		public const string GUID = "mattymatty.BagConfig";

		public const string NAME = "BagConfig";

		public const string VERSION = "0.0.5";

		internal static ManualLogSource Log;

		public static BagConfig INSTANCE { get; private set; }

		private void Awake()
		{
			INSTANCE = this;
			Log = ((BaseUnityPlugin)this).Logger;
			try
			{
				if (LobbyCompatibilityChecker.Enabled)
				{
					LobbyCompatibilityChecker.Init();
				}
				Log.LogInfo((object)"Initializing Configs");
				PluginConfig.Init();
				Log.LogInfo((object)"Patching Methods");
				PatchLateJoin.Init();
				Harmony.PatchAll();
				BeltBagPatch.Patch();
				Log.LogInfo((object)"BagConfig v0.0.5 Loaded!");
			}
			catch (Exception ex)
			{
				Log.LogError((object)("Exception while initializing: \n" + ex));
			}
		}
	}
	internal static class PluginConfig
	{
		public static class Misc
		{
			public static ConfigEntry<bool> Tooltip { get; internal set; }

			public static ConfigEntry<bool> DropAll { get; internal set; }

			public static ConfigEntry<bool> HideBag { get; internal set; }

			public static ConfigEntry<float> GrabRange { get; internal set; }
		}

		public static class Host
		{
			public static ConfigEntry<bool> Capacity { get; internal set; }

			public static ConfigEntry<bool> Category { get; internal set; }

			public static ConfigEntry<bool> Range { get; internal set; }
		}

		public static class Limits
		{
			public static StringDictionary ItemCategoryAssociations = new StringDictionary();

			public static readonly Dictionary<string, ICategoryConfig> CategoryConfigs = new Dictionary<string, ICategoryConfig>();

			public static ConfigEntry<int> Capacity { get; internal set; }

			public static ConfigEntry<string> ItemCategories { get; internal set; }
		}

		public interface ICategoryConfig
		{
			string CategoryName { get; }

			bool Allow { get; }

			int Limit { get; }
		}

		public class StaticCategoryConfig : ICategoryConfig
		{
			public string CategoryName { get; }

			public bool Allow { get; }

			public int Limit { get; }

			public StaticCategoryConfig(string categoryName, bool allow, int limit)
			{
				CategoryName = categoryName;
				Allow = allow;
				Limit = limit;
			}
		}

		public class BepInExCategoryConfig : ICategoryConfig
		{
			private readonly ConfigEntry<bool> _allowConfig;

			private readonly ConfigEntry<int> _limitConfig;

			public string CategoryName { get; }

			public bool Allow => _allowConfig.Value;

			public int Limit => _limitConfig.Value;

			public BepInExCategoryConfig(string categoryName, bool allow = false, int max = -1)
			{
				//IL_0039: Unknown result type (might be due to invalid IL or missing references)
				//IL_0043: Expected O, but got Unknown
				//IL_008e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0098: Expected O, but got Unknown
				CategoryName = categoryName;
				_allowConfig = ((BaseUnityPlugin)BagConfig.INSTANCE).Config.Bind<bool>("Limit." + CategoryName, "Allow", allow, new ConfigDescription("Allow grabbing this category!", (AcceptableValueBase)null, Array.Empty<object>()));
				_limitConfig = ((BaseUnityPlugin)BagConfig.INSTANCE).Config.Bind<int>("Limit." + CategoryName, "Max Amount", max, new ConfigDescription("How many items of this category can be stored at the same time?", (AcceptableValueBase)(object)new AcceptableValueRange<int>(-1, Limits.Capacity?.Value ?? int.MaxValue), Array.Empty<object>()));
				if (LethalConfigProxy.Enabled)
				{
					LethalConfigProxy.AddConfig(_allowConfig);
					LethalConfigProxy.AddConfig(_limitConfig);
				}
			}
		}

		private const string ToolsCategory = "Tools";

		private const string DenyCategory = "Deny";

		private const string OneHandedCategory = "One Handed Scrap";

		private const string TwoHandedCategory = "Two Handed Scrap";

		internal static void Init()
		{
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Expected O, but got Unknown
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Expected O, but got Unknown
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Expected O, but got Unknown
			ConfigFile config = ((BaseUnityPlugin)BagConfig.INSTANCE).Config;
			Misc.Tooltip = config.Bind<bool>("Miscellaneous", "Tooltip", true, "Show a tooltip if the target item cannot be stored");
			Misc.DropAll = config.Bind<bool>("Miscellaneous", "Add Empty Bag Action", true, "Add action to Drop the entire bag inventory");
			Misc.HideBag = config.Bind<bool>("Miscellaneous", "Hide Bag When Pocketed", false, "Hide the bag when in pocket ( also disables opening it by looking down )");
			Misc.GrabRange = config.Bind<float>("Miscellaneous", "Grab Range", 4f, new ConfigDescription("Max range for grabbing items with the bag", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 20f), Array.Empty<object>()));
			Host.Capacity = config.Bind<bool>("Host Settings", "Enforce Capacity", true, "Server-side check to limit the bag Capacity");
			Host.Category = config.Bind<bool>("Host Settings", "Enforce Restrictions", true, "Server-side check to limit the items allowed inside the Bag");
			Host.Range = config.Bind<bool>("Host Settings", "Enforce Range", true, "Server-side check to limit the grab range");
			Limits.Capacity = config.Bind<int>("Limits", "Capacity", 15, new ConfigDescription("How many items can the bag store", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, int.MaxValue), Array.Empty<object>()));
			Limits.ItemCategories = config.Bind<string>("Limits", "Item Categories", "Body: Deny", new ConfigDescription("Dictionary describing the association between a Item and a Category name", (AcceptableValueBase)null, Array.Empty<object>()));
			Limits.CategoryConfigs["Tools"] = new BepInExCategoryConfig("Tools", allow: true);
			Limits.CategoryConfigs["One Handed Scrap"] = new BepInExCategoryConfig("One Handed Scrap");
			Limits.CategoryConfigs["Two Handed Scrap"] = new BepInExCategoryConfig("Two Handed Scrap");
			Limits.CategoryConfigs["Deny"] = new StaticCategoryConfig("Deny", allow: false, 0);
			ProcessCategories(Limits.ItemCategories);
			Limits.ItemCategories.SettingChanged += delegate
			{
				ProcessCategories(Limits.ItemCategories);
			};
			if (LethalConfigProxy.Enabled)
			{
				LethalConfigProxy.AddConfig(Misc.Tooltip);
				LethalConfigProxy.AddConfig(Misc.DropAll, requiresRestart: true);
				LethalConfigProxy.AddConfig(Misc.HideBag);
				LethalConfigProxy.AddConfig(Misc.GrabRange);
				LethalConfigProxy.AddConfig(Limits.Capacity);
				LethalConfigProxy.AddConfig(Limits.ItemCategories);
				LethalConfigProxy.AddConfig(Host.Capacity);
				LethalConfigProxy.AddConfig(Host.Category);
				LethalConfigProxy.AddConfig(Host.Range);
			}
			CleanAndSave();
			static void ProcessCategories(ConfigEntry<string> entry)
			{
				Limits.ItemCategoryAssociations = ProcessDictionary(entry);
				foreach (string value3 in Limits.ItemCategoryAssociations.Values)
				{
					if (!Limits.CategoryConfigs.ContainsKey(value3))
					{
						Limits.CategoryConfigs[value3] = new BepInExCategoryConfig(value3, allow: true);
					}
				}
			}
			static StringDictionary ProcessDictionary(ConfigEntry<string> entry)
			{
				string value = entry.Value;
				StringDictionary stringDictionary = new StringDictionary();
				string[] array = value.Split(",");
				foreach (string text in array)
				{
					string text2 = text.Trim();
					string[] array2 = text2.Split(":");
					if (array2.Length != 2)
					{
						BagConfig.Log.LogError((object)("Item Association: malformed Entry! " + text2));
					}
					else
					{
						string text3 = array2[0].Trim();
						string value2 = array2[1].Trim();
						if (stringDictionary.ContainsKey(text3))
						{
							BagConfig.Log.LogWarning((object)("Item Association: " + text3 + " was already defined - overwriting!"));
						}
						stringDictionary[text3] = value2;
					}
				}
				return stringDictionary;
			}
		}

		internal static void CleanAndSave()
		{
			ConfigFile config = ((BaseUnityPlugin)BagConfig.INSTANCE).Config;
			PropertyInfo propertyInfo = AccessTools.Property(((object)config).GetType(), "OrphanedEntries");
			Dictionary<ConfigDefinition, string> dictionary = (Dictionary<ConfigDefinition, string>)propertyInfo.GetValue(config, null);
			dictionary.Clear();
			config.Save();
		}

		public static ICategoryConfig GetBagCategory(this GrabbableObject grabbable)
		{
			if (Limits.ItemCategoryAssociations.ContainsKey(grabbable.itemProperties.itemName))
			{
				return Limits.CategoryConfigs[Limits.ItemCategoryAssociations[grabbable.itemProperties.itemName]];
			}
			bool isScrap = grabbable.itemProperties.isScrap;
			bool twoHanded = grabbable.itemProperties.twoHanded;
			if (!isScrap)
			{
				return Limits.CategoryConfigs["Tools"];
			}
			if (!twoHanded)
			{
				return Limits.CategoryConfigs["One Handed Scrap"];
			}
			return Limits.CategoryConfigs["Two Handed Scrap"];
		}
	}
	public static class Utils
	{
		private static readonly MethodInfo BeginSendClientRpc = AccessTools.Method(typeof(NetworkBehaviour), "__beginSendClientRpc", (Type[])null, (Type[])null);

		private static readonly MethodInfo BeginSendServerRpc = AccessTools.Method(typeof(NetworkBehaviour), "__beginSendServerRpc", (Type[])null, (Type[])null);

		internal static bool TryGetRpcID(MethodInfo methodInfo, out uint rpcID)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: 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_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			Collection<Instruction> instructions = PatchManager.GetMethodPatcher((MethodBase)methodInfo).CopyOriginal().Definition.Body.Instructions;
			rpcID = 0u;
			for (int i = 0; i < instructions.Count; i++)
			{
				if (instructions[i].OpCode == OpCodes.Ldc_I4 && instructions[i - 1].OpCode == OpCodes.Ldarg_0)
				{
					rpcID = (uint)(int)instructions[i].Operand;
				}
				if (!(instructions[i].OpCode != OpCodes.Call))
				{
					object operand = instructions[i].Operand;
					MethodReference val = (MethodReference)((operand is MethodReference) ? operand : null);
					if (val != null && (Extensions.Is((MemberReference)(object)val, (MemberInfo)BeginSendClientRpc) || Extensions.Is((MemberReference)(object)val, (MemberInfo)BeginSendServerRpc)))
					{
						BagConfig.Log.LogDebug((object)$"Rpc Id found for {methodInfo.Name}: {rpcID}U");
						return true;
					}
				}
			}
			BagConfig.Log.LogFatal((object)("Cannot find Rpc ID for " + methodInfo.Name));
			return false;
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "mattymatty.BagConfig";

		public const string PLUGIN_NAME = "BagConfig";

		public const string PLUGIN_VERSION = "0.0.5";
	}
}
namespace BagConfig.Patches
{
	[HarmonyPatch]
	internal static class BeltBagPatch
	{
		private class CategoryCount
		{
			public int Count;
		}

		private static readonly Action<GrabbableObject, bool> BaseInteractMethod;

		private static readonly ConditionalWeakTable<BeltBagItem, ConditionalWeakTable<PluginConfig.ICategoryConfig, CategoryCount>> CategoryMemory;

		internal static void Patch()
		{
			//IL_0037: 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_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Expected O, but got Unknown
			MethodInfo methodInfo = AccessTools.Method(typeof(BeltBagItem), "ItemInteractLeftRight", (Type[])null, (Type[])null);
			MethodInfo methodInfo2 = AccessTools.Method(typeof(BeltBagPatch), "OverrideGrab", (Type[])null, (Type[])null);
			BagConfig.Hooks.Add(new Hook((MethodBase)methodInfo, methodInfo2, new HookConfig
			{
				Priority = -999
			}));
		}

		static BeltBagPatch()
		{
			CategoryMemory = new ConditionalWeakTable<BeltBagItem, ConditionalWeakTable<PluginConfig.ICategoryConfig, CategoryCount>>();
			MethodInfo meth = AccessTools.Method(typeof(GrabbableObject), "ItemInteractLeftRight", (Type[])null, (Type[])null);
			DynamicMethod dynamicMethod = new DynamicMethod("Base.ItemInteractLeftRight", null, new Type[2]
			{
				typeof(GrabbableObject),
				typeof(bool)
			}, typeof(BeltBagItem));
			ILGenerator iLGenerator = dynamicMethod.GetILGenerator();
			iLGenerator.Emit(OpCodes.Ldarg_0);
			iLGenerator.Emit(OpCodes.Ldarg_1);
			iLGenerator.Emit(OpCodes.Call, meth);
			iLGenerator.Emit(OpCodes.Ret);
			BaseInteractMethod = (Action<GrabbableObject, bool>)dynamicMethod.CreateDelegate(typeof(Action<GrabbableObject, bool>));
		}

		private static IEnumerator EmptyBagCoroutine(BeltBagItem @this)
		{
			while (@this.objectsInBag.Count > 0)
			{
				@this.RemoveObjectFromBag(0);
				yield return (object)new WaitForEndOfFrame();
			}
		}

		private static void OverrideGrab(Action<BeltBagItem, bool> orig, BeltBagItem @this, bool right)
		{
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			BaseInteractMethod((GrabbableObject)(object)@this, right);
			if (right)
			{
				if (PluginConfig.Misc.DropAll.Value)
				{
					((MonoBehaviour)@this).StartCoroutine(EmptyBagCoroutine(@this));
				}
			}
			else
			{
				if ((Object)(object)((GrabbableObject)@this).playerHeldBy == (Object)null || @this.tryingAddToBag)
				{
					return;
				}
				if (@this.objectsInBag.Count >= PluginConfig.Limits.Capacity.Value)
				{
					if (PluginConfig.Misc.Tooltip.Value)
					{
						HUDManager.Instance.DisplayTip("Belt bag Info", "This bag is Full!", false, false, "LC_Tip1");
					}
				}
				else
				{
					RaycastHit val = default(RaycastHit);
					if (!Physics.Raycast(((Component)((GrabbableObject)@this).playerHeldBy.gameplayCamera).transform.position, ((Component)((GrabbableObject)@this).playerHeldBy.gameplayCamera).transform.forward, ref val, PluginConfig.Misc.GrabRange.Value, GameNetworkManager.Instance.localPlayerController.interactableObjectsMask))
					{
						return;
					}
					ManualLogSource log = BagConfig.Log;
					Transform parent = ((Component)((RaycastHit)(ref val)).collider).transform.parent;
					log.LogDebug((object)("Grab Hit: " + ((parent != null) ? ((Object)parent).name : null) + "." + ((Object)((Component)((RaycastHit)(ref val)).collider).gameObject).name));
					if (((Component)((RaycastHit)(ref val)).collider).gameObject.layer == 8 || ((Component)((RaycastHit)(ref val)).collider).tag != "PhysicsProp")
					{
						return;
					}
					GrabbableObject component = ((Component)((RaycastHit)(ref val)).collider).gameObject.GetComponent<GrabbableObject>();
					if (!@this.CanBePutInBag(component))
					{
						return;
					}
					if (@this.CheckBagFilters(component, out var limited, out var disallowed))
					{
						@this.TryAddObjectToBag(component);
					}
					else if (PluginConfig.Misc.Tooltip.Value)
					{
						if (!disallowed && limited)
						{
							PluginConfig.ICategoryConfig bagCategory = component.GetBagCategory();
							HUDManager.Instance.DisplayTip("Belt bag Info", "Cannot store any more " + bagCategory.CategoryName + " inside of the bag!", false, false, "LC_Tip1");
						}
						else
						{
							HUDManager.Instance.DisplayTip("Belt bag Info", "Cannot store " + component.itemProperties.itemName + " inside of the bag!", false, false, "LC_Tip1");
						}
					}
				}
			}
		}

		private static bool CanBePutInBag(this BeltBagItem @this, GrabbableObject grabbable)
		{
			if (Object.op_Implicit((Object)(object)grabbable) && (Object)(object)grabbable != (Object)(object)@this && !grabbable.isHeld && !grabbable.isHeldByEnemy)
			{
				return grabbable.itemProperties.itemId != 123984;
			}
			return false;
		}

		private static bool CheckBagFilters(this BeltBagItem @this, GrabbableObject grabbable, out bool limited, out bool disallowed)
		{
			limited = false;
			PluginConfig.ICategoryConfig bagCategory = grabbable.GetBagCategory();
			disallowed = !bagCategory.Allow;
			int limit = bagCategory.Limit;
			if (limit < 0)
			{
				return !disallowed;
			}
			if (limit == 0)
			{
				limited = true;
				return false;
			}
			ConditionalWeakTable<PluginConfig.ICategoryConfig, CategoryCount> orCreateValue = CategoryMemory.GetOrCreateValue(@this);
			if (orCreateValue.TryGetValue(bagCategory, out var value) && value.Count >= limit)
			{
				limited = true;
				return false;
			}
			return !disallowed;
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(StartOfRound), "Start")]
		private static void AddBagTooltip(StartOfRound __instance)
		{
			if (!PluginConfig.Misc.DropAll.Value)
			{
				return;
			}
			BeltBagItem val = default(BeltBagItem);
			foreach (Item items in __instance.allItemsList.itemsList)
			{
				if (Object.op_Implicit((Object)(object)items.spawnPrefab) && items.spawnPrefab.TryGetComponent<BeltBagItem>(ref val))
				{
					Array.Resize(ref items.toolTips, items.toolTips.Length + 1);
					items.toolTips[^1] = "Empty Bag: [E]";
					break;
				}
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(BeltBagItem), "PutObjectInBagLocalClient")]
		private static void TriggerHeldActions(BeltBagItem __instance, GrabbableObject gObject)
		{
			LungProp val = (LungProp)(object)((gObject is LungProp) ? gObject : null);
			if (val != null)
			{
				if (val.isLungDocked)
				{
					val.isLungDocked = false;
					if (val.disconnectAnimation != null)
					{
						((MonoBehaviour)val).StopCoroutine(val.disconnectAnimation);
					}
					val.disconnectAnimation = ((MonoBehaviour)val).StartCoroutine(val.DisconnectFromMachinery());
				}
				if (val.isLungDockedInElevator)
				{
					val.isLungDockedInElevator = false;
					((Component)val).gameObject.GetComponent<AudioSource>().PlayOneShot(val.disconnectSFX);
				}
			}
			if (!((GrabbableObject)__instance).hasBeenHeld)
			{
				((GrabbableObject)__instance).hasBeenHeld = true;
				if (!((GrabbableObject)__instance).isInShipRoom && !StartOfRound.Instance.inShipPhase && StartOfRound.Instance.currentLevel.spawnEnemiesAndScrap)
				{
					RoundManager instance = RoundManager.Instance;
					instance.valueOfFoundScrapItems += ((GrabbableObject)__instance).scrapValue;
				}
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(BeltBagItem), "PutObjectInBagLocalClient")]
		private static void TrackAdd(BeltBagItem __instance, GrabbableObject gObject)
		{
			PluginConfig.ICategoryConfig bagCategory = gObject.GetBagCategory();
			ConditionalWeakTable<PluginConfig.ICategoryConfig, CategoryCount> orCreateValue = CategoryMemory.GetOrCreateValue(__instance);
			orCreateValue.GetOrCreateValue(bagCategory).Count++;
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(BeltBagItem), "RemoveFromBagLocalClientNonElevatorParent")]
		[HarmonyPatch(typeof(BeltBagItem), "RemoveFromBagLocalClient")]
		private static void TrackRemove(BeltBagItem __instance, NetworkObjectReference objectRef)
		{
			ConditionalWeakTable<PluginConfig.ICategoryConfig, CategoryCount> orCreateValue = CategoryMemory.GetOrCreateValue(__instance);
			NetworkObject val = default(NetworkObject);
			GrabbableObject grabbable = default(GrabbableObject);
			if (((NetworkObjectReference)(ref objectRef)).TryGet(ref val, (NetworkManager)null) && ((Component)val).TryGetComponent<GrabbableObject>(ref grabbable))
			{
				PluginConfig.ICategoryConfig bagCategory = grabbable.GetBagCategory();
				orCreateValue.GetOrCreateValue(bagCategory).Count--;
			}
			if (__instance.objectsInBag.Count == 0)
			{
				orCreateValue.Clear();
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(BeltBagItem), "TryAddObjectToBagServerRpc")]
		private static bool EnforceLimits(BeltBagItem __instance, NetworkObjectReference netObjectRef, int playerWhoAdded)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Invalid comparison between Unknown and I4
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)__instance).NetworkManager;
			if ((Object)(object)networkManager == (Object)null || !networkManager.IsListening)
			{
				return true;
			}
			if ((int)((NetworkBehaviour)__instance).__rpc_exec_stage != 1 || (!networkManager.IsServer && !networkManager.IsHost))
			{
				return true;
			}
			NetworkObject val = default(NetworkObject);
			if (!((NetworkObjectReference)(ref netObjectRef)).TryGet(ref val, (NetworkManager)null))
			{
				return true;
			}
			GrabbableObject component = ((Component)val).GetComponent<GrabbableObject>();
			if (!__instance.CanBePutInBag(component))
			{
				__instance.CancelAddObjectToBagClientRpc(playerWhoAdded);
				return false;
			}
			if (PluginConfig.Host.Capacity.Value && __instance.objectsInBag.Count >= PluginConfig.Limits.Capacity.Value)
			{
				__instance.CancelAddObjectToBagClientRpc(playerWhoAdded);
				return false;
			}
			if (PluginConfig.Host.Category.Value && !__instance.CheckBagFilters(component, out var _, out var _))
			{
				__instance.CancelAddObjectToBagClientRpc(playerWhoAdded);
				return false;
			}
			if (PluginConfig.Host.Range.Value)
			{
				Vector3 position = ((Component)component).transform.position;
				PlayerControllerB playerHeldBy = ((GrabbableObject)__instance).playerHeldBy;
				if (Vector3.Distance(position, (playerHeldBy != null) ? ((Component)playerHeldBy.gameplayCamera).transform.position : Vector3.positiveInfinity) > PluginConfig.Misc.GrabRange.Value)
				{
					__instance.CancelAddObjectToBagClientRpc(playerWhoAdded);
					return false;
				}
			}
			return true;
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(BeltBagItem), "CancelAddObjectToBagClientRpc")]
		private static void OnServerRefusal(int playerWhoAdded)
		{
			if (!((Object)(object)StartOfRound.Instance.allPlayerScripts[playerWhoAdded] != (Object)(object)GameNetworkManager.Instance.localPlayerController))
			{
				HUDManager.Instance.DisplayTip("Belt bag Info", "Host refused your grab request!", true, false, "LC_Tip1");
			}
		}

		[HarmonyTranspiler]
		[HarmonyPatch(typeof(BeltBagItem), "RemoveObjectFromBag")]
		private static IEnumerable<CodeInstruction> FixDrop(IEnumerable<CodeInstruction> instructions, ILGenerator ilGenerator)
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Expected O, but got Unknown
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Expected O, but got Unknown
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Expected O, but got Unknown
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Expected O, but got Unknown
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Expected O, but got Unknown
			List<CodeInstruction> list = instructions.ToList();
			MethodInfo methodInfo = AccessTools.Method(typeof(GrabbableObject), "GetItemFloorPosition", (Type[])null, (Type[])null);
			MethodInfo methodInfo2 = AccessTools.Method(typeof(BeltBagPatch), "FixVerticalOffset", (Type[])null, (Type[])null);
			CodeMatcher val = new CodeMatcher((IEnumerable<CodeInstruction>)list, ilGenerator);
			val.MatchForward(true, (CodeMatch[])(object)new CodeMatch[1]
			{
				new CodeMatch((OpCode?)OpCodes.Call, (object)methodInfo, (string)null)
			});
			if (val.IsInvalid)
			{
				BagConfig.Log.LogError((object)"Patch RemoveObjectFromBag, Fail - 1 ");
				return list;
			}
			val.Advance(1);
			val.InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[1]
			{
				new CodeInstruction(OpCodes.Ldarg_0, (object)null)
			});
			val.InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[1]
			{
				new CodeInstruction(OpCodes.Ldarg_1, (object)null)
			});
			val.InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[1]
			{
				new CodeInstruction(OpCodes.Call, (object)methodInfo2)
			});
			return val.Instructions();
		}

		private static Vector3 FixVerticalOffset(Vector3 position, BeltBagItem beltBagItem, int index)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: 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_0042: 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_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: 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_0025: Unknown result type (might be due to invalid IL or missing references)
			if (beltBagItem.objectsInBag.Count <= index)
			{
				return position;
			}
			GrabbableObject val = beltBagItem.objectsInBag[index];
			if (!Object.op_Implicit((Object)(object)val))
			{
				return position;
			}
			position += Vector3.down * ((GrabbableObject)beltBagItem).itemProperties.verticalOffset;
			position += Vector3.up * val.itemProperties.verticalOffset;
			return position;
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(BeltBagItem), "PocketItem")]
		private static void HideWhenInPocket(BeltBagItem __instance)
		{
			if (((NetworkBehaviour)__instance).IsOwner && PluginConfig.Misc.HideBag.Value)
			{
				((Component)__instance.useBagTrigger).GetComponent<Collider>().enabled = false;
				((GrabbableObject)__instance).EnableItemMeshes(false);
			}
		}
	}
	internal static class PatchLateJoin
	{
		private static uint _tryAddObjectToBagClientRpc;

		internal static void Init()
		{
			MethodInfo methodInfo = AccessTools.Method(typeof(BeltBagItem), "TryAddObjectToBagClientRpc", (Type[])null, (Type[])null);
			if (!Utils.TryGetRpcID(methodInfo, out _tryAddObjectToBagClientRpc))
			{
				throw new MissingMemberException("BeltBagItem", "TryAddObjectToBagClientRpc");
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(StartOfRound), "SyncAlreadyHeldObjectsClientRpc")]
		private static void SyncItemsInBags(StartOfRound __instance, NetworkObjectReference[] gObjects, int joiningClientId)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Invalid comparison between Unknown and I4
			//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_0084: 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_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)__instance).NetworkManager;
			if ((Object)(object)networkManager == (Object)null || !networkManager.IsListening || (int)((NetworkBehaviour)__instance).__rpc_exec_stage == 2 || (!networkManager.IsServer && !networkManager.IsHost))
			{
				return;
			}
			NetworkObject val2 = default(NetworkObject);
			BeltBagItem val3 = default(BeltBagItem);
			for (int i = 0; i < gObjects.Length; i++)
			{
				NetworkObjectReference val = gObjects[i];
				if (!((NetworkObjectReference)(ref val)).TryGet(ref val2, (NetworkManager)null) || !((Component)val2).TryGetComponent<BeltBagItem>(ref val3))
				{
					continue;
				}
				foreach (GrabbableObject item in val3.objectsInBag)
				{
					NetworkObjectReference val4 = NetworkObjectReference.op_Implicit(((NetworkBehaviour)item).NetworkObject);
					ClientRpcParams val5 = default(ClientRpcParams);
					val5.Send = new ClientRpcSendParams
					{
						TargetClientIds = new <>z__ReadOnlyArray<ulong>(new ulong[1] { (ulong)joiningClientId })
					};
					ClientRpcParams val6 = val5;
					FastBufferWriter val7 = ((NetworkBehaviour)val3).__beginSendClientRpc(_tryAddObjectToBagClientRpc, val6, (RpcDelivery)0);
					((FastBufferWriter)(ref val7)).WriteValueSafe<NetworkObjectReference>(ref val4, default(ForNetworkSerializable));
					BytePacker.WriteValueBitPacked(val7, ((GrabbableObject)val3).playerHeldBy.actualClientId);
					((NetworkBehaviour)val3).__endSendClientRpc(ref val7, _tryAddObjectToBagClientRpc, val6, (RpcDelivery)0);
				}
			}
		}
	}
}
namespace BagConfig.Dependency
{
	public static class LethalConfigProxy
	{
		private static bool? _enabled;

		public static bool Enabled
		{
			get
			{
				bool valueOrDefault = _enabled.GetValueOrDefault();
				if (!_enabled.HasValue)
				{
					valueOrDefault = Chainloader.PluginInfos.ContainsKey("ainavt.lc.lethalconfig");
					_enabled = valueOrDefault;
				}
				return _enabled.Value;
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
		public static void AddConfig(ConfigEntry<string> entry, bool requiresRestart = false)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected O, but got Unknown
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			LethalConfigManager.AddConfigItem((BaseConfigItem)new TextInputFieldConfigItem(entry, new TextInputFieldOptions
			{
				RequiresRestart = requiresRestart
			}));
		}

		[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
		public static void AddConfig(ConfigEntry<bool> entry, bool requiresRestart = false)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected O, but got Unknown
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			LethalConfigManager.AddConfigItem((BaseConfigItem)new BoolCheckBoxConfigItem(entry, new BoolCheckBoxOptions
			{
				RequiresRestart = requiresRestart
			}));
		}

		[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
		public static void AddConfig(ConfigEntry<float> entry, bool requiresRestart = false)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected O, but got Unknown
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			LethalConfigManager.AddConfigItem((BaseConfigItem)new FloatInputFieldConfigItem(entry, new FloatInputFieldOptions
			{
				RequiresRestart = requiresRestart
			}));
		}

		[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
		public static void AddConfig(ConfigEntry<int> entry, bool requiresRestart = false)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected O, but got Unknown
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			LethalConfigManager.AddConfigItem((BaseConfigItem)new IntInputFieldConfigItem(entry, new IntInputFieldOptions
			{
				RequiresRestart = requiresRestart
			}));
		}
	}
	public static class LobbyCompatibilityChecker
	{
		private static bool? _enabled;

		public static bool Enabled
		{
			get
			{
				bool valueOrDefault = _enabled.GetValueOrDefault();
				if (!_enabled.HasValue)
				{
					valueOrDefault = Chainloader.PluginInfos.ContainsKey("BMX.LobbyCompatibility");
					_enabled = valueOrDefault;
				}
				return _enabled.Value;
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
		public static void Init()
		{
			PluginHelper.RegisterPlugin("mattymatty.BagConfig", Version.Parse("0.0.5"), (CompatibilityLevel)0, (VersionStrictness)2);
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}
internal sealed class <>z__ReadOnlyArray<T> : IEnumerable, ICollection, IList, IEnumerable<T>, IReadOnlyCollection<T>, IReadOnlyList<T>, ICollection<T>, IList<T>
{
	int ICollection.Count => _items.Length;

	bool ICollection.IsSynchronized => false;

	object ICollection.SyncRoot => this;

	object IList.this[int index]
	{
		get
		{
			return _items[index];
		}
		set
		{
			throw new NotSupportedException();
		}
	}

	bool IList.IsFixedSize => true;

	bool IList.IsReadOnly => true;

	int IReadOnlyCollection<T>.Count => _items.Length;

	T IReadOnlyList<T>.this[int index] => _items[index];

	int ICollection<T>.Count => _items.Length;

	bool ICollection<T>.IsReadOnly => true;

	T IList<T>.this[int index]
	{
		get
		{
			return _items[index];
		}
		set
		{
			throw new NotSupportedException();
		}
	}

	public <>z__ReadOnlyArray(T[] items)
	{
		_items = items;
	}

	IEnumerator IEnumerable.GetEnumerator()
	{
		return ((IEnumerable)_items).GetEnumerator();
	}

	void ICollection.CopyTo(Array array, int index)
	{
		((ICollection)_items).CopyTo(array, index);
	}

	int IList.Add(object value)
	{
		throw new NotSupportedException();
	}

	void IList.Clear()
	{
		throw new NotSupportedException();
	}

	bool IList.Contains(object value)
	{
		return ((IList)_items).Contains(value);
	}

	int IList.IndexOf(object value)
	{
		return ((IList)_items).IndexOf(value);
	}

	void IList.Insert(int index, object value)
	{
		throw new NotSupportedException();
	}

	void IList.Remove(object value)
	{
		throw new NotSupportedException();
	}

	void IList.RemoveAt(int index)
	{
		throw new NotSupportedException();
	}

	IEnumerator<T> IEnumerable<T>.GetEnumerator()
	{
		return ((IEnumerable<T>)_items).GetEnumerator();
	}

	void ICollection<T>.Add(T item)
	{
		throw new NotSupportedException();
	}

	void ICollection<T>.Clear()
	{
		throw new NotSupportedException();
	}

	bool ICollection<T>.Contains(T item)
	{
		return ((ICollection<T>)_items).Contains(item);
	}

	void ICollection<T>.CopyTo(T[] array, int arrayIndex)
	{
		((ICollection<T>)_items).CopyTo(array, arrayIndex);
	}

	bool ICollection<T>.Remove(T item)
	{
		throw new NotSupportedException();
	}

	int IList<T>.IndexOf(T item)
	{
		return ((IList<T>)_items).IndexOf(item);
	}

	void IList<T>.Insert(int index, T item)
	{
		throw new NotSupportedException();
	}

	void IList<T>.RemoveAt(int index)
	{
		throw new NotSupportedException();
	}
}