Decompiled source of SmartContainersIgnore v1.3.0

SmartContainersIgnore.dll

Decompiled a day ago
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using HarmonyLib;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: AssemblyFileVersion("1.3.0.0")]
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyVersion("1.3.0.0")]
namespace SmartContainersIgnore;

internal static class ChestPolicy
{
	internal const string Key = "niclas.smartcontainers.ignore.v1";

	internal static bool IsExcluded(ZNetView view)
	{
		if (!Object.op_Implicit((Object)(object)view) || !view.IsValid())
		{
			return true;
		}
		ZDO zDO = view.GetZDO();
		if (zDO != null)
		{
			return zDO.GetBool("niclas.smartcontainers.ignore.v1", false);
		}
		return true;
	}

	internal static bool CanToggle(ZNetView view, bool hasAccess)
	{
		if (!hasAccess || !Object.op_Implicit((Object)(object)view) || !view.IsValid() || !view.IsOwner())
		{
			return false;
		}
		ZDO zDO = view.GetZDO();
		if (zDO != null)
		{
			return zDO.Persistent;
		}
		return false;
	}

	internal static bool TryToggle(ZNetView view, bool hasAccess, out bool excluded)
	{
		excluded = false;
		if (!CanToggle(view, hasAccess))
		{
			return false;
		}
		ZDO zDO = view.GetZDO();
		excluded = !zDO.GetBool("niclas.smartcontainers.ignore.v1", false);
		zDO.Set("niclas.smartcontainers.ignore.v1", excluded);
		return true;
	}
}
internal static class DirectTransferScope
{
	[ThreadStatic]
	private static int depth;

	internal static bool Active => depth > 0;

	internal static void Run(Action transfer)
	{
		if (transfer == null)
		{
			throw new ArgumentNullException("transfer");
		}
		depth++;
		try
		{
			transfer();
		}
		finally
		{
			depth--;
		}
	}
}
internal sealed class GroupingConfigGuard : IDisposable
{
	private readonly ConfigEntry<bool> entry;

	private readonly Action<Exception> report;

	private bool resaveAfterReload;

	internal GroupingConfigGuard(ConfigEntry<bool> entry, Action<Exception> report)
	{
		if (entry == null)
		{
			throw new ArgumentNullException("entry");
		}
		if (report == null)
		{
			throw new ArgumentNullException("report");
		}
		this.entry = entry;
		this.report = report;
		entry.SettingChanged += OnChanged;
		((ConfigEntryBase)entry).ConfigFile.ConfigReloaded += OnReloaded;
		ForceOff(reloaded: false);
		resaveAfterReload = false;
	}

	private void OnChanged(object sender, EventArgs args)
	{
		ForceOff(reloaded: false);
	}

	private void OnReloaded(object sender, EventArgs args)
	{
		ForceOff(reloaded: true);
	}

	private void ForceOff(bool reloaded)
	{
		try
		{
			bool value = entry.Value;
			if (value)
			{
				resaveAfterReload = true;
				entry.Value = false;
			}
			if ((reloaded && resaveAfterReload) || (value && !((ConfigEntryBase)entry).ConfigFile.SaveOnConfigSet))
			{
				((ConfigEntryBase)entry).ConfigFile.Save();
			}
			if (reloaded)
			{
				resaveAfterReload = false;
			}
		}
		catch (Exception obj)
		{
			report(obj);
		}
	}

	public void Dispose()
	{
		entry.SettingChanged -= OnChanged;
		((ConfigEntryBase)entry).ConfigFile.ConfigReloaded -= OnReloaded;
	}
}
[BepInProcess("valheim.exe")]
[BepInPlugin("niclas.smartcontainers.ignore", "SmartContainers Ignore", "1.3.0")]
[BepInDependency("flueno.SmartContainers", "1.8.3")]
public sealed class Plugin : BaseUnityPlugin
{
	internal const string Id = "niclas.smartcontainers.ignore";

	internal const string SmartId = "flueno.SmartContainers";

	private static Plugin instance;

	private Harmony harmony;

	private GroupingConfigGuard groupingGuard;

	private static FieldInfo currentContainer;

	private static FieldInfo containerView;

	private static FieldInfo grouping;

	private static FieldInfo master;

	private static FieldInfo buttonPosition;

	private static FieldInfo dragObject;

	private static Func<string, string, Vector2, Vector2, Transform> createButton;

	private static Func<Container, long, bool> checkAccess;

	private static Action<InventoryGui, InventoryGrid, ItemData, Vector2i, Modifier> selectItem;

	private static Button button;

	private static TMP_Text label;

	private static UITooltip tooltip;

	private static bool ready;

	private static bool uiFault;

	private static bool routingFaultLogged;

	private void Awake()
	{
		//IL_0475: Unknown result type (might be due to invalid IL or missing references)
		//IL_047f: Expected O, but got Unknown
		instance = this;
		try
		{
			if (!Chainloader.PluginInfos.TryGetValue("flueno.SmartContainers", out var value) || !Object.op_Implicit((Object)(object)value.Instance))
			{
				throw new NotSupportedException("SmartContainers 1.8.3 or newer is required.");
			}
			Assembly assembly = ((object)value.Instance).GetType().Assembly;
			Type type = assembly.GetType("SmartContainers.Mod", throwOnError: true);
			Type type2 = assembly.GetType("SmartContainers.Inventory_Patch", throwOnError: true);
			Type type3 = assembly.GetType("SmartContainers.Gui_Patch", throwOnError: true);
			currentContainer = Field(typeof(InventoryGui), "m_currentContainer", typeof(Container));
			dragObject = Field(typeof(InventoryGui), "m_dragGo", typeof(GameObject));
			selectItem = (Action<InventoryGui, InventoryGrid, ItemData, Vector2i, Modifier>)Delegate.CreateDelegate(typeof(Action<InventoryGui, InventoryGrid, ItemData, Vector2i, Modifier>), Method(typeof(InventoryGui), "OnSelectedItem", typeof(void), typeof(InventoryGrid), typeof(ItemData), typeof(Vector2i), typeof(Modifier)));
			containerView = Field(typeof(Container), "m_nview", typeof(ZNetView));
			checkAccess = (Func<Container, long, bool>)Delegate.CreateDelegate(typeof(Func<Container, long, bool>), Method(typeof(Container), "CheckAccess", typeof(bool), typeof(long)));
			grouping = Field(type, "groupingEnabled", typeof(ConfigEntry<bool>));
			master = Field(type, "modEnabled", typeof(ConfigEntry<bool>));
			buttonPosition = Field(type, "createGroupBtnPos", typeof(ConfigEntry<Vector2>));
			MethodInfo method = Method(assembly.GetType("SmartContainers.GuiFactory", throwOnError: true), "AddContainerGuiButton", typeof(Transform), typeof(string), typeof(string), typeof(Vector2), typeof(Vector2));
			createButton = (Func<string, string, Vector2, Vector2, Transform>)Delegate.CreateDelegate(typeof(Func<string, string, Vector2, Vector2, Transform>), method);
			MethodInfo methodInfo = Method(assembly.GetType("SmartContainers.ContainersTracker", throwOnError: true), "GetNearbyContainers", typeof(List<Container>), typeof(Vector3), typeof(bool));
			MethodInfo methodInfo2 = Method(type2, "AddItemToContainer", typeof(bool), typeof(ItemData), typeof(Container), typeof(bool));
			MethodInfo methodInfo3 = Method(type2, "TryAddToNearBy", typeof(bool), typeof(ItemData), typeof(bool), typeof(bool));
			MethodInfo methodInfo4 = Method(type3, "AddCreateGroupBtn", typeof(void), typeof(InventoryGui));
			MethodInfo methodInfo5 = Method(typeof(InventoryGui), "UpdateContainer", typeof(void), typeof(Player));
			MethodInfo methodInfo6 = Method(typeof(InventoryGui), "OnRightClickItem", typeof(void), typeof(InventoryGrid), typeof(ItemData), typeof(Vector2i));
			MethodInfo methodInfo7 = Method(type, "Start", typeof(void));
			MethodInfo methodInfo8 = Method(type2, "Postfix", typeof(void), typeof(Inventory), typeof(ItemData), typeof(bool).MakeByRefType());
			harmony = new Harmony("niclas.smartcontainers.ignore");
			harmony.Patch((MethodBase)methodInfo8, (HarmonyMethod)null, (HarmonyMethod)null, Patch("VerifyRoutingFailure"), (HarmonyMethod)null, (HarmonyMethod)null);
			harmony.Patch((MethodBase)methodInfo3, Patch("BeforeRouting"), (HarmonyMethod)null, Patch("WithoutGroups"), (HarmonyMethod)null, (HarmonyMethod)null);
			harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, Patch("FilterCandidates"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			harmony.Patch((MethodBase)methodInfo2, Patch("BeforeAutomaticAdd"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			harmony.Patch((MethodBase)methodInfo4, Patch("SkipGroupButton"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			harmony.Patch((MethodBase)methodInfo5, (HarmonyMethod)null, Patch("UpdateButton"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			harmony.Patch((MethodBase)methodInfo6, Patch("BeforeRightClick"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			harmony.Patch((MethodBase)methodInfo7, (HarmonyMethod)null, Patch("AfterSmartStarted"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			BindGroupingConfig();
			ready = true;
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Ready: shared persistent chest exclusion; same-item routing only; Auto button replaces groups.");
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Ctrl + right-click: native transfer to/from the open chest without SmartContainers routing.");
		}
		catch (Exception ex)
		{
			ready = false;
			if (groupingGuard != null)
			{
				groupingGuard.Dispose();
			}
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			((BaseUnityPlugin)this).Logger.LogError((object)("SmartContainers Ignore disabled: " + ex));
		}
	}

	private void BindGroupingConfig()
	{
		if (groupingGuard == null && grouping.GetValue(null) is ConfigEntry<bool> entry)
		{
			groupingGuard = new GroupingConfigGuard(entry, delegate(Exception error)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not save disabled grouping; group routing remains disabled: " + error));
			});
			((BaseUnityPlugin)this).Logger.LogInfo((object)"SmartContainers Grouping.enabled is forced off, including config changes and reloads.");
		}
	}

	private static void AfterSmartStarted()
	{
		if (!ready)
		{
			return;
		}
		try
		{
			instance.BindGroupingConfig();
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)instance).Logger.LogWarning((object)("Could not bind grouping config; group routing remains disabled: " + ex));
		}
	}

	private static IEnumerable<CodeInstruction> VerifyRoutingFailure(IEnumerable<CodeInstruction> instructions, MethodBase __originalMethod)
	{
		List<CodeInstruction> list = new List<CodeInstruction>(instructions);
		MethodInfo method = __originalMethod.DeclaringType.GetMethod("TryAddToNearBy", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[3]
		{
			typeof(ItemData),
			typeof(bool),
			typeof(bool)
		}, null);
		if (method == null || method.ReturnType != typeof(bool))
		{
			throw new NotSupportedException("SmartContainers routing signature changed.");
		}
		CheckRoutingFailure(list, method);
		return list;
	}

	private static void CheckRoutingFailure(IEnumerable<CodeInstruction> instructions, MethodInfo route)
	{
		List<CodeInstruction> list = new List<CodeInstruction>(instructions);
		int num = 0;
		for (int i = 0; i < list.Count; i++)
		{
			if (!(list[i].opcode != OpCodes.Call) && object.Equals(list[i].operand, route))
			{
				num++;
				if (i + 1 >= list.Count || (list[i + 1].opcode != OpCodes.Brfalse && list[i + 1].opcode != OpCodes.Brfalse_S))
				{
					throw new NotSupportedException("SmartContainers failed-transfer branch changed.");
				}
			}
		}
		if (num == 0)
		{
			throw new NotSupportedException("SmartContainers routing call missing.");
		}
	}

	private static FieldInfo Field(Type type, string name, Type expected)
	{
		FieldInfo fieldInfo = AccessTools.Field(type, name);
		if (fieldInfo == null || fieldInfo.FieldType != expected)
		{
			throw new MissingFieldException(type.FullName, name);
		}
		return fieldInfo;
	}

	private static MethodInfo Method(Type type, string name, Type result, params Type[] args)
	{
		MethodInfo methodInfo = AccessTools.Method(type, name, args, (Type[])null);
		if (methodInfo == null || methodInfo.ReturnType != result)
		{
			throw new MissingMethodException(type.FullName, name);
		}
		return methodInfo;
	}

	private static HarmonyMethod Patch(string name)
	{
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_0018: Expected O, but got Unknown
		return new HarmonyMethod(AccessTools.Method(typeof(Plugin), name, (Type[])null, (Type[])null));
	}

	private static IEnumerable<CodeInstruction> WithoutGroups(IEnumerable<CodeInstruction> instructions)
	{
		List<CodeInstruction> list = new List<CodeInstruction>(instructions);
		MethodInfo getMethod = typeof(ConfigEntry<bool>).GetProperty("Value").GetGetMethod();
		int num = -1;
		for (int i = 0; i < list.Count; i++)
		{
			if (!(list[i].opcode != OpCodes.Ldsfld) && object.Equals(list[i].operand, grouping))
			{
				if (num >= 0 || i + 1 >= list.Count || list[i + 1].opcode != OpCodes.Callvirt || !object.Equals(list[i + 1].operand, getMethod) || list[i].blocks.Count != 0 || list[i + 1].blocks.Count != 0 || list[i + 1].labels.Count != 0)
				{
					throw new NotSupportedException("SmartContainers grouping gate changed.");
				}
				num = i;
			}
		}
		if (num < 0)
		{
			throw new NotSupportedException("SmartContainers grouping gate missing.");
		}
		list[num].opcode = OpCodes.Ldc_I4_0;
		list[num].operand = null;
		list[num + 1].opcode = OpCodes.Nop;
		list[num + 1].operand = null;
		return list;
	}

	private static ZNetView View(Container container)
	{
		if (!Object.op_Implicit((Object)(object)container))
		{
			return null;
		}
		object? value = containerView.GetValue(container);
		return (ZNetView)((value is ZNetView) ? value : null);
	}

	private static void FilterCandidates(bool __1, ref List<Container> __result)
	{
		if (__1 || __result == null)
		{
			return;
		}
		try
		{
			__result.RemoveAll((Container c) => ChestPolicy.IsExcluded(View(c)));
		}
		catch (Exception error)
		{
			__result.Clear();
			RoutingFault(error);
		}
	}

	private static bool BeforeAutomaticAdd(Container __1, ref bool __result)
	{
		try
		{
			if (!ChestPolicy.IsExcluded(View(__1)))
			{
				return true;
			}
		}
		catch (Exception error)
		{
			RoutingFault(error);
		}
		__result = false;
		return false;
	}

	private static bool BeforeRouting(ref bool __result)
	{
		if (!DirectTransferScope.Active)
		{
			return true;
		}
		__result = false;
		return false;
	}

	private static bool BeforeRightClick(InventoryGui __instance, InventoryGrid __0, ItemData __1, Vector2i __2)
	{
		//IL_0024: 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 (!ready || !ZInput.GetMouseButton(1) || (!ZInput.GetKey((KeyCode)306, true) && !ZInput.GetKey((KeyCode)305, true)))
		{
			return true;
		}
		try
		{
			Player localPlayer = Player.m_localPlayer;
			if (!Object.op_Implicit((Object)(object)localPlayer) || !Object.op_Implicit((Object)(object)__instance) || (Object)(object)__instance != (Object)(object)InventoryGui.instance || !Object.op_Implicit((Object)(object)__0))
			{
				return true;
			}
			Container val = OpenContainer(__instance);
			if (!Object.op_Implicit((Object)(object)val))
			{
				return true;
			}
			if (__1 == null || __1.m_shared == null || Object.op_Implicit((Object)/*isinst with value type is only supported in some contexts*/))
			{
				return false;
			}
			Inventory inventory = __0.GetInventory();
			Inventory inventory2 = ((Humanoid)localPlayer).GetInventory();
			Inventory inventory3 = val.GetInventory();
			if (inventory == null || inventory3 == null || (!object.ReferenceEquals(inventory, inventory2) && !object.ReferenceEquals(inventory, inventory3)) || !inventory.ContainsItem(__1))
			{
				return false;
			}
			ZNetView val2 = View(val);
			if (!Object.op_Implicit((Object)(object)val2) || !val2.IsValid() || !val2.IsOwner() || !checkAccess(val, localPlayer.GetPlayerID()))
			{
				return false;
			}
			DirectTransferScope.Run(delegate
			{
				//IL_0018: Unknown result type (might be due to invalid IL or missing references)
				selectItem(__instance, __0, __1, __2, (Modifier)2);
			});
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)instance).Logger.LogWarning((object)("Direct chest transfer stopped: " + ex));
			Notice("Direkter Transfer abgebrochen. Siehe BepInEx-Log.");
		}
		return false;
	}

	private static void RoutingFault(Exception error)
	{
		if (!routingFaultLogged)
		{
			routingFaultLogged = true;
			((BaseUnityPlugin)instance).Logger.LogError((object)("Automatic destination blocked because exclusion could not be checked: " + error));
		}
	}

	private static bool SkipGroupButton()
	{
		return false;
	}

	private static Container OpenContainer(InventoryGui gui)
	{
		if (!Object.op_Implicit((Object)(object)gui) || !gui.IsContainerOpen())
		{
			return null;
		}
		object? value = currentContainer.GetValue(gui);
		return (Container)((value is Container) ? value : null);
	}

	private static bool SmartEnabled()
	{
		if (master.GetValue(null) is ConfigEntry<bool> val)
		{
			return val.Value;
		}
		return false;
	}

	private static void UpdateButton(InventoryGui __instance)
	{
		//IL_0106: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
		if (!ready || uiFault)
		{
			return;
		}
		try
		{
			Container val = OpenContainer(__instance);
			if (!Object.op_Implicit((Object)(object)val) || !Object.op_Implicit((Object)(object)Player.m_localPlayer) || !SmartEnabled())
			{
				if (Object.op_Implicit((Object)(object)button))
				{
					((Component)button).gameObject.SetActive(false);
				}
				return;
			}
			if (!Object.op_Implicit((Object)(object)button))
			{
				MakeButton(__instance);
			}
			((Component)button).gameObject.SetActive(true);
			ZNetView view = View(val);
			bool flag = ChestPolicy.IsExcluded(view);
			bool hasAccess = checkAccess(val, Player.m_localPlayer.GetPlayerID());
			((Selectable)button).interactable = ChestPolicy.CanToggle(view, hasAccess);
			string text = (flag ? "Auto\nAUS" : "Auto\nAN");
			if (label.text != text)
			{
				label.text = text;
			}
			((Graphic)label).color = (flag ? new Color(1f, 0.55f, 0.35f) : new Color(0.65f, 1f, 0.65f));
			if (Object.op_Implicit((Object)(object)tooltip))
			{
				tooltip.m_topic = "SmartContainers";
				tooltip.m_text = ((!((Selectable)button).interactable) ? "Truhe noch nicht bereit oder kein Zugriff. Erneut oeffnen." : (flag ? "Diese Truhe wird ignoriert. Klicken: automatisches Einsortieren wieder zulassen." : "Klicken: diese Truhe vom automatischen Einsortieren ausschliessen. Gilt fuer alle mit diesem Zusatz."));
			}
		}
		catch (Exception ex)
		{
			uiFault = true;
			if (Object.op_Implicit((Object)(object)button))
			{
				((Component)button).gameObject.SetActive(false);
			}
			((BaseUnityPlugin)instance).Logger.LogError((object)("Exclusion button unavailable; saved exclusions still apply: " + ex));
		}
	}

	private static void MakeButton(InventoryGui gui)
	{
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_0015: 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_0045: 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_0078: Unknown result type (might be due to invalid IL or missing references)
		//IL_0082: Expected O, but got Unknown
		//IL_0093: Unknown result type (might be due to invalid IL or missing references)
		//IL_009d: Expected O, but got Unknown
		//IL_006d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0142: Unknown result type (might be due to invalid IL or missing references)
		Vector2 arg = (Vector2)((!(buttonPosition.GetValue(null) is ConfigEntry<Vector2> val)) ? new Vector2(1.5f, 10.7f) : val.Value);
		Transform val2 = createButton("SmartContainersIgnoreButton", "Auto\nAN", new Vector2(45f, 30f), arg);
		button = ((Component)val2).GetComponent<Button>();
		if (!Object.op_Implicit((Object)(object)button))
		{
			throw new MissingComponentException("Container button template has no Button.");
		}
		button.onClick = new ButtonClickedEvent();
		((UnityEvent)button.onClick).AddListener(new UnityAction(ToggleCurrent));
		UIGamePad[] componentsInChildren = ((Component)val2).GetComponentsInChildren<UIGamePad>(true);
		foreach (UIGamePad val3 in componentsInChildren)
		{
			((Behaviour)val3).enabled = false;
			if (Object.op_Implicit((Object)(object)val3.m_hint))
			{
				val3.m_hint.SetActive(false);
			}
		}
		Transform val4 = val2.Find("gamepad_hint");
		if (Object.op_Implicit((Object)(object)val4))
		{
			((Component)val4).gameObject.SetActive(false);
		}
		val4 = val2.Find("GamepadHint");
		if (Object.op_Implicit((Object)(object)val4))
		{
			((Component)val4).gameObject.SetActive(false);
		}
		label = ((Component)val2).GetComponentInChildren<TMP_Text>(true);
		if (!Object.op_Implicit((Object)(object)label))
		{
			throw new MissingComponentException("Container button template has no TMP text.");
		}
		label.fontSize = 11f;
		label.enableAutoSizing = true;
		label.fontSizeMin = 8f;
		label.fontSizeMax = 11f;
		label.alignment = (TextAlignmentOptions)514;
		tooltip = ((Component)val2).GetComponent<UITooltip>();
		if (!Object.op_Implicit((Object)(object)tooltip))
		{
			UITooltip componentInChildren = ((Component)gui).GetComponentInChildren<UITooltip>(true);
			if (Object.op_Implicit((Object)(object)componentInChildren) && Object.op_Implicit((Object)(object)componentInChildren.m_tooltipPrefab))
			{
				tooltip = ((Component)val2).gameObject.AddComponent<UITooltip>();
				tooltip.m_tooltipPrefab = componentInChildren.m_tooltipPrefab;
			}
		}
	}

	private static void ToggleCurrent()
	{
		try
		{
			if (!ready || !SmartEnabled())
			{
				return;
			}
			InventoryGui val = InventoryGui.instance;
			Container val2 = OpenContainer(val);
			Player localPlayer = Player.m_localPlayer;
			if (Object.op_Implicit((Object)(object)val2) && Object.op_Implicit((Object)(object)localPlayer))
			{
				if (!ChestPolicy.TryToggle(View(val2), checkAccess(val2, localPlayer.GetPlayerID()), out var excluded))
				{
					Notice("Truhe noch nicht bereit oder kein Zugriff. Bitte erneut oeffnen.");
					return;
				}
				Notice(excluded ? "SmartContainers: Diese Truhe wird ignoriert." : "SmartContainers: Diese Truhe ist wieder zugelassen.");
				UpdateButton(val);
			}
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)instance).Logger.LogWarning((object)("Chest exclusion could not be changed: " + ex));
			Notice("Truhen-Sperre konnte nicht geaendert werden. Siehe BepInEx-Log.");
		}
	}

	private static void Notice(string text)
	{
		if (Object.op_Implicit((Object)(object)MessageHud.instance))
		{
			MessageHud.instance.ShowMessage((MessageType)2, text, 0, (Sprite)null, false, true);
		}
	}

	private void OnDestroy()
	{
		ready = false;
		if (groupingGuard != null)
		{
			groupingGuard.Dispose();
		}
		if (harmony != null)
		{
			harmony.UnpatchSelf();
		}
		if (Object.op_Implicit((Object)(object)button))
		{
			Object.Destroy((Object)(object)((Component)button).gameObject);
		}
	}
}