Decompiled source of SelfSortingStoragePLUS v1.0.0

plugins/bobabulker.SelfSortingStoragePLUS.dll

Decompiled 3 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using SelfSortingStorage.Cupboard;
using SelfSortingStoragePLUS.Patches;
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: AssemblyCompany("bobabulker.SelfSortingStoragePLUS")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+7fd6b554aaf8bef849a0586ca749b5ec5b1a56d0")]
[assembly: AssemblyProduct("SelfSortingStoragePLUS")]
[assembly: AssemblyTitle("bobabulker.SelfSortingStoragePLUS")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[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 SelfSortingStoragePLUS
{
	[BepInPlugin("bobabulker.SelfSortingStoragePLUS", "SelfSortingStoragePLUS", "1.0.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class SelfSortingStoragePLUS : BaseUnityPlugin
	{
		public static SelfSortingStoragePLUS Instance { get; private set; }

		internal static ManualLogSource Logger { get; private set; }

		internal static Harmony? Harmony { get; private set; }

		internal static ConfigEntry<string> AutoStoreMoons { get; private set; }

		internal static ConfigEntry<bool> ProtectCupboardItems { get; private set; }

		internal static ConfigEntry<bool> VerboseLogging { get; private set; }

		private void Awake()
		{
			Logger = ((BaseUnityPlugin)this).Logger;
			Instance = this;
			AutoStoreMoons = ((BaseUnityPlugin)this).Config.Bind<string>("Terminal Purchases", "AutoStoreMoons", "71 Gordion", "Comma-separated list of moons where terminal purchases should be automatically stored in the SelfSortingStorage cupboard when possible (e.g. \"71 Gordion, Experimentation\"). A moon matches if its name contains any entry in this list, case-insensitive, so \"Gordion\" also matches \"71 Gordion\". Leave blank to disable AutoStore on every moon.");
			VerboseLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("Verbose Logging", "Log Info", false, "Enable to get information logging on different stages of the patch.");
			ProtectCupboardItems = ((BaseUnityPlugin)this).Config.Bind<bool>("Team Wipe Protection", "ProtectCupboardItems", true, "If enabled, items stored in the Smart Cupboard are hidden from RoundManager's end-of-round despawn sweep, so they're never destroyed by it for any reason -- including the team wipe case, where vanilla destroys all scrap regardless of whether it's safely on the ship.");
			Patch();
			Logger.LogInfo((object)"bobabulker.SelfSortingStoragePLUS v1.0.0 has loaded!");
		}

		internal static void Patch()
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			if (Harmony == null)
			{
				Harmony = new Harmony("bobabulker.SelfSortingStoragePLUS");
			}
			Harmony.PatchAll();
			EndOfRoundCupboardEffectsPatch.TryPatch(Harmony);
			Logger.LogDebug((object)"Finished patching!");
		}

		internal static void Unpatch()
		{
			Logger.LogDebug((object)"Unpatching...");
			Harmony? harmony = Harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			Logger.LogDebug((object)"Finished unpatching!");
		}

		internal static bool IsAutoStoreEnabledOnCurrentMoon()
		{
			string value = AutoStoreMoons.Value;
			if (string.IsNullOrWhiteSpace(value))
			{
				return false;
			}
			StartOfRound instance = StartOfRound.Instance;
			if ((Object)(object)instance == (Object)null)
			{
				return false;
			}
			if (!instance.shipHasLanded)
			{
				if (VerboseLogging.Value)
				{
					Logger.LogInfo((object)"[AutoStoreMoons] Ship has not landed yet. Using normal dropship storage.");
				}
				return false;
			}
			string text = instance.currentLevel?.PlanetName;
			if (string.IsNullOrEmpty(text))
			{
				if (VerboseLogging.Value)
				{
					Logger.LogInfo((object)"[AutoStoreMoons] Could not determine the current moon. Using normal dropship storage.");
				}
				return false;
			}
			string[] array = value.Split(',');
			foreach (string text2 in array)
			{
				string text3 = text2.Trim();
				if (text3.Length != 0 && text.IndexOf(text3, StringComparison.OrdinalIgnoreCase) >= 0)
				{
					return true;
				}
			}
			if (VerboseLogging.Value)
			{
				Logger.LogInfo((object)("[AutoStoreMoons] AutoStore is not enabled for the current moon \"" + text + "\". Using normal dropship storage."));
			}
			return false;
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "bobabulker.SelfSortingStoragePLUS";

		public const string PLUGIN_NAME = "SelfSortingStoragePLUS";

		public const string PLUGIN_VERSION = "1.0.0";
	}
}
namespace SelfSortingStoragePLUS.Patches
{
	[HarmonyPatch(typeof(Terminal))]
	internal static class BuyItemsServerRpcPatch
	{
		private static FieldInfo? PlacedItemsField;

		private static MethodInfo? SpawnItemMethod;

		private static MethodInfo? PlayDropSFXMethod;

		private static MethodInfo? UpdateNetworkQuantityMethod;

		private static MethodInfo? UpdateDisplayedQuantityMethod;

		private static MethodInfo? SetSizeMethod;

		private static bool ResolveSssMembers()
		{
			if (PlacedItemsField != null && SpawnItemMethod != null && PlayDropSFXMethod != null && UpdateNetworkQuantityMethod != null && UpdateDisplayedQuantityMethod != null && SetSizeMethod != null)
			{
				return true;
			}
			Type typeFromHandle = typeof(SmartCupboard);
			PlacedItemsField = AccessTools.Field(typeFromHandle, "placedItems");
			SpawnItemMethod = AccessTools.Method(typeFromHandle, "SpawnItem", new Type[3]
			{
				typeof(Data),
				typeof(int),
				typeof(bool)
			}, (Type[])null);
			PlayDropSFXMethod = AccessTools.Method(typeFromHandle, "PlayDropSFXClientRpc", new Type[1] { typeof(NetworkObjectReference) }, (Type[])null);
			UpdateNetworkQuantityMethod = AccessTools.Method(typeFromHandle, "UpdateNetworkQuantityClientRpc", new Type[2]
			{
				typeof(ulong),
				typeof(bool)
			}, (Type[])null);
			UpdateDisplayedQuantityMethod = AccessTools.Method(typeFromHandle, "UpdateDisplayedQuantityClientRpc", new Type[2]
			{
				typeof(int),
				typeof(int)
			}, (Type[])null);
			SetSizeMethod = AccessTools.Method(typeFromHandle, "SetSizeClientRpc", new Type[1] { typeof(int) }, (Type[])null);
			bool flag = PlacedItemsField != null && SpawnItemMethod != null && PlayDropSFXMethod != null && UpdateNetworkQuantityMethod != null && UpdateDisplayedQuantityMethod != null && SetSizeMethod != null;
			if (!flag)
			{
				SelfSortingStoragePLUS.Logger.LogError((object)"[AutoStoreTerminalPurchases] Could not resolve one or more SelfSortingStorage 1.5.3 private methods/fields.");
				SelfSortingStoragePLUS.Logger.LogError((object)($"[AutoStoreTerminalPurchases] placedItems={PlacedItemsField != null}, " + $"SpawnItem={SpawnItemMethod != null}, " + $"PlayDropSFXClientRpc={PlayDropSFXMethod != null}, " + $"UpdateNetworkQuantityClientRpc={UpdateNetworkQuantityMethod != null}, " + $"UpdateDisplayedQuantityClientRpc={UpdateDisplayedQuantityMethod != null}, " + $"SetSizeClientRpc={SetSizeMethod != null}"));
			}
			return flag;
		}

		private static SmartCupboard? FindCupboard()
		{
			SmartCupboard[] array = Object.FindObjectsOfType<SmartCupboard>();
			SmartCupboard[] array2 = array;
			foreach (SmartCupboard val in array2)
			{
				if ((Object)(object)val != (Object)null && ((NetworkBehaviour)val).IsSpawned && ((NetworkBehaviour)val).IsServer)
				{
					return val;
				}
			}
			return null;
		}

		[HarmonyPatch("BuyItemsServerRpc")]
		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Expected O, but got Unknown
			List<CodeInstruction> list = new List<CodeInstruction>(instructions);
			MethodInfo methodInfo = AccessTools.Method(typeof(List<int>), "AddRange", (Type[])null, (Type[])null);
			MethodInfo methodInfo2 = AccessTools.Method(typeof(BuyItemsServerRpcPatch), "HandlePurchasedItems", (Type[])null, (Type[])null);
			if (methodInfo == null || methodInfo2 == null)
			{
				SelfSortingStoragePLUS.Logger.LogError((object)"[AutoStoreTerminalPurchases] Could not resolve terminal purchase patch methods.");
				return list;
			}
			for (int i = 0; i < list.Count; i++)
			{
				if (CodeInstructionExtensions.Calls(list[i], methodInfo))
				{
					list[i] = new CodeInstruction(OpCodes.Call, (object)methodInfo2);
					SelfSortingStoragePLUS.Logger.LogDebug((object)"[AutoStoreTerminalPurchases] Successfully replaced terminal purchase AddRange().");
					return list;
				}
			}
			SelfSortingStoragePLUS.Logger.LogWarning((object)"[AutoStoreTerminalPurchases] Could not find terminal purchase AddRange().");
			return list;
		}

		[HarmonyPatch("LoadNewNodeIfAffordable")]
		[HarmonyPrefix]
		private static void LoadNewNodeIfAffordablePrefix(Terminal __instance, TerminalNode node, out int __state)
		{
			__state = ((((NetworkBehaviour)__instance).IsServer && node.buyItemIndex != -1) ? __instance.orderedItemsFromTerminal.Count : (-1));
		}

		[HarmonyPatch("LoadNewNodeIfAffordable")]
		[HarmonyPostfix]
		private static void LoadNewNodeIfAffordablePostfix(Terminal __instance, TerminalNode node, int __state)
		{
			if (__state < 0)
			{
				return;
			}
			int num = __instance.orderedItemsFromTerminal.Count - __state;
			if (num > 0)
			{
				List<int> range = __instance.orderedItemsFromTerminal.GetRange(__state, num);
				__instance.orderedItemsFromTerminal.RemoveRange(__state, num);
				int count = __instance.orderedItemsFromTerminal.Count;
				HandlePurchasedItems(__instance.orderedItemsFromTerminal, range);
				int num2 = __instance.orderedItemsFromTerminal.Count - count;
				int num3 = num - num2;
				if (num3 > 0)
				{
					__instance.numberOfItemsInDropship -= num3;
					__instance.SyncGroupCreditsClientRpc(__instance.groupCredits, __instance.numberOfItemsInDropship);
				}
			}
		}

		private static void HandlePurchasedItems(List<int> orderedItems, List<int> boughtItems)
		{
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_019a: Expected O, but got Unknown
			//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Expected O, but got Unknown
			if (boughtItems == null || boughtItems.Count == 0)
			{
				return;
			}
			if (!SelfSortingStoragePLUS.IsAutoStoreEnabledOnCurrentMoon())
			{
				orderedItems.AddRange(boughtItems);
				return;
			}
			if (!ResolveSssMembers())
			{
				orderedItems.AddRange(boughtItems);
				return;
			}
			SmartCupboard val = FindCupboard();
			if ((Object)(object)val == (Object)null)
			{
				SelfSortingStoragePLUS.Logger.LogWarning((object)"[AutoStoreTerminalPurchases] No spawned server-side Smart Cupboard found. Using normal dropship storage.");
				orderedItems.AddRange(boughtItems);
				return;
			}
			Terminal val2 = Object.FindObjectOfType<Terminal>();
			if ((Object)(object)val2 == (Object)null)
			{
				orderedItems.AddRange(boughtItems);
				return;
			}
			Dictionary<int, int> dictionary = new Dictionary<int, int>();
			List<int> list = new List<int>();
			foreach (int boughtItem in boughtItems)
			{
				if (dictionary.TryGetValue(boughtItem, out var value))
				{
					dictionary[boughtItem] = value + 1;
					continue;
				}
				dictionary[boughtItem] = 1;
				list.Add(boughtItem);
			}
			int num6 = default(int);
			foreach (int item in list)
			{
				int num = dictionary[item];
				try
				{
					if (item < 0 || item >= val2.buyableItemsList.Length)
					{
						for (int i = 0; i < num; i++)
						{
							orderedItems.Add(item);
						}
						continue;
					}
					Item val3 = val2.buyableItemsList[item];
					if ((Object)(object)val3 == (Object)null || (Object)(object)val3.spawnPrefab == (Object)null)
					{
						for (int j = 0; j < num; j++)
						{
							orderedItems.Add(item);
						}
						continue;
					}
					GrabbableObject component = val3.spawnPrefab.GetComponent<GrabbableObject>();
					if ((Object)(object)component == (Object)null)
					{
						for (int k = 0; k < num; k++)
						{
							orderedItems.Add(item);
						}
						continue;
					}
					Data val4 = new Data(component);
					List<Data> list2 = new List<Data>(num);
					for (int l = 0; l < num; l++)
					{
						Data val5 = new Data(component);
						if (val3.isScrap)
						{
							int num2 = Mathf.Min(val3.minValue, val3.maxValue);
							int num3 = Mathf.Max(val3.minValue, val3.maxValue);
							int num4 = Random.Range(num2, num3 + 1);
							val5.Values[0] = (((Object)(object)RoundManager.Instance != (Object)null) ? Mathf.RoundToInt((float)num4 * RoundManager.Instance.scrapValueMultiplier) : num4);
						}
						list2.Add(val5);
					}
					bool flag = false;
					int num5 = -1;
					for (int m = 0; m < list2.Count; m++)
					{
						bool flag2 = val.memory.StoreData(list2[m], ref num6, false);
						if (m == 0)
						{
							flag = flag2;
							num5 = num6;
						}
						else if (flag2)
						{
							SelfSortingStoragePLUS.Logger.LogWarning((object)("[AutoStoreTerminalPurchases] Batch purchase for " + val3.itemName + " unexpectedly created another " + $"cupboard slot at index {num6}."));
							orderedItems.Add(item);
						}
					}
					if (val.memory.IsFull())
					{
						SetSizeMethod.Invoke(val, new object[1] { val.memory.Size });
					}
					if (flag)
					{
						val4 = list2[0];
						val4.Quantity = num;
						SpawnItemMethod.Invoke(val, new object[3] { val4, num5, false });
					}
					else
					{
						HandleStackedItem(val, num5, num);
					}
				}
				catch (Exception arg)
				{
					SelfSortingStoragePLUS.Logger.LogError((object)("[AutoStoreTerminalPurchases] Failed to store purchased " + $"item index {item}: {arg}"));
					for (int n = 0; n < num; n++)
					{
						orderedItems.Add(item);
					}
				}
			}
		}

		private static void HandleStackedItem(SmartCupboard cupboard, int spawnIndex, int quantityToAdd)
		{
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			if (PlacedItemsField == null)
			{
				return;
			}
			object value = PlacedItemsField.GetValue(cupboard);
			if (!(value is Dictionary<int, GrabbableObject> dictionary) || !dictionary.TryGetValue(spawnIndex, out var value2) || (Object)(object)value2 == (Object)null)
			{
				return;
			}
			if (PlayDropSFXMethod != null && (Object)(object)((NetworkBehaviour)value2).NetworkObject != (Object)null)
			{
				PlayDropSFXMethod.Invoke(cupboard, new object[1] { (object)new NetworkObjectReference(((NetworkBehaviour)value2).NetworkObject) });
			}
			if (UpdateNetworkQuantityMethod != null && (Object)(object)((NetworkBehaviour)value2).NetworkObject != (Object)null)
			{
				for (int i = 0; i < quantityToAdd; i++)
				{
					UpdateNetworkQuantityMethod.Invoke(cupboard, new object[2]
					{
						((NetworkBehaviour)value2).NetworkObjectId,
						false
					});
				}
			}
			if (!(UpdateDisplayedQuantityMethod != null))
			{
				return;
			}
			FieldInfo fieldInfo = AccessTools.Field(typeof(SmartMemory), "ItemList");
			if (!(fieldInfo != null))
			{
				return;
			}
			object value3 = fieldInfo.GetValue(cupboard.memory);
			if (!(value3 is List<List<Data>> { Count: >0 } list) || list[0].Count <= 0)
			{
				return;
			}
			int count = list[0].Count;
			int num = spawnIndex / count;
			int num2 = spawnIndex % count;
			if (num >= 0 && num < list.Count && num2 >= 0 && num2 < list[num].Count)
			{
				Data val = list[num][num2];
				if (val.IsValid())
				{
					UpdateDisplayedQuantityMethod.Invoke(cupboard, new object[2] { spawnIndex, val.Quantity });
				}
			}
		}

		private static bool TryGetDisplayedQuantity(SmartCupboard cupboard, int spawnIndex, out int quantity)
		{
			quantity = 0;
			if (PlacedItemsField == null)
			{
				return false;
			}
			object value = PlacedItemsField.GetValue(cupboard);
			if (!(value is Dictionary<int, GrabbableObject> dictionary))
			{
				return false;
			}
			if (!dictionary.TryGetValue(spawnIndex, out var value2) || (Object)(object)value2 == (Object)null)
			{
				return false;
			}
			try
			{
				FieldInfo fieldInfo = AccessTools.Field(typeof(SmartMemory), "ItemList");
				if (fieldInfo == null)
				{
					return false;
				}
				object value3 = fieldInfo.GetValue(cupboard.memory);
				if (!(value3 is List<List<Data>> list))
				{
					return false;
				}
				int num = ((list.Count > 0) ? list[0].Count : 0);
				if (num <= 0)
				{
					return false;
				}
				int num2 = spawnIndex / num;
				int num3 = spawnIndex % num;
				if (num2 < 0 || num2 >= list.Count || num3 < 0 || num3 >= list[num2].Count)
				{
					return false;
				}
				Data val = list[num2][num3];
				if (!val.IsValid())
				{
					return false;
				}
				quantity = Math.Max(0, val.Quantity - GetCurrentPurchaseQuantity(cupboard));
				return true;
			}
			catch
			{
				return false;
			}
		}

		private static int GetCurrentPurchaseQuantity(SmartCupboard cupboard)
		{
			return 0;
		}
	}
	[HarmonyPatch(typeof(RoundManager))]
	internal static class DespawnPropsAtEndOfRoundPatch
	{
		private static FieldInfo? PlacedItemsField;

		private static FieldInfo? SpawnedSyncedObjectsField;

		private static bool ResolvedSpawnedSyncedObjectsField;

		private static readonly List<GameObject> HiddenItems = new List<GameObject>();

		private static bool ResolvePlacedItemsField()
		{
			if (PlacedItemsField != null)
			{
				return true;
			}
			PlacedItemsField = AccessTools.Field(typeof(SmartCupboard), "placedItems");
			if (PlacedItemsField == null)
			{
				SelfSortingStoragePLUS.Logger.LogError((object)"[ProtectCupboardItems] Could not resolve SelfSortingStorage's private placedItems field. Cupboard contents will not be protected from the end-of-round despawn sweep.");
			}
			return PlacedItemsField != null;
		}

		[HarmonyPatch("DespawnPropsAtEndOfRound")]
		[HarmonyPrefix]
		private static void Prefix()
		{
			HiddenItems.Clear();
			if (!SelfSortingStoragePLUS.ProtectCupboardItems.Value || !ResolvePlacedItemsField())
			{
				return;
			}
			SmartCupboard[] array = Object.FindObjectsOfType<SmartCupboard>();
			foreach (SmartCupboard obj in array)
			{
				if (!(PlacedItemsField.GetValue(obj) is Dictionary<int, GrabbableObject> dictionary))
				{
					continue;
				}
				foreach (GrabbableObject value in dictionary.Values)
				{
					if (!((Object)(object)value == (Object)null) && !((Object)(object)((Component)value).gameObject == (Object)null) && ((Component)value).gameObject.activeSelf)
					{
						((Component)value).gameObject.SetActive(false);
						HiddenItems.Add(((Component)value).gameObject);
					}
				}
			}
			if (HiddenItems.Count > 0 && SelfSortingStoragePLUS.VerboseLogging.Value)
			{
				SelfSortingStoragePLUS.Logger.LogInfo((object)($"[ProtectCupboardItems] Hiding {HiddenItems.Count} stored item(s) " + "from the end-of-round despawn sweep."));
			}
		}

		[HarmonyPatch("DespawnPropsAtEndOfRound")]
		[HarmonyPostfix]
		private static void Postfix(RoundManager __instance)
		{
			if (HiddenItems.Count == 0)
			{
				return;
			}
			if (!ResolvedSpawnedSyncedObjectsField)
			{
				SpawnedSyncedObjectsField = AccessTools.Field(typeof(RoundManager), "spawnedSyncedObjects");
				ResolvedSpawnedSyncedObjectsField = true;
			}
			ICollection<GameObject> collection = SpawnedSyncedObjectsField?.GetValue(__instance) as ICollection<GameObject>;
			foreach (GameObject hiddenItem in HiddenItems)
			{
				if (!((Object)(object)hiddenItem == (Object)null))
				{
					hiddenItem.SetActive(true);
					collection?.Remove(hiddenItem);
				}
			}
			HiddenItems.Clear();
		}
	}
	internal static class EndOfRoundCupboardEffectsPatch
	{
		private static ConfigEntry<bool>? PreventMemoryResetConfigEntry;

		private static bool SavedOriginalValue;

		internal static void TryPatch(Harmony harmony)
		{
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Expected O, but got Unknown
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Expected O, but got Unknown
			try
			{
				Type type = AccessTools.TypeByName("SelfSortingStorage.Utils.RoundManagerPatch");
				if (type == null)
				{
					SelfSortingStoragePLUS.Logger.LogError((object)"[ProtectCupboardItems] Could not resolve SelfSortingStorage.Utils.RoundManagerPatch. Team wipe scrap-clearing will not be prevented (cupboard contents may still be cleared by SelfSortingStorage itself on a team wipe).");
					return;
				}
				MethodInfo methodInfo = AccessTools.Method(type, "EndOfRoundCupboardEffects", (Type[])null, (Type[])null);
				if (methodInfo == null)
				{
					SelfSortingStoragePLUS.Logger.LogError((object)"[ProtectCupboardItems] Could not resolve EndOfRoundCupboardEffects on SelfSortingStorage.Utils.RoundManagerPatch. Team wipe scrap-clearing will not be prevented.");
					return;
				}
				HarmonyMethod val = new HarmonyMethod(typeof(EndOfRoundCupboardEffectsPatch), "Prefix", (Type[])null);
				HarmonyMethod val2 = new HarmonyMethod(typeof(EndOfRoundCupboardEffectsPatch), "Finalizer", (Type[])null);
				harmony.Patch((MethodBase)methodInfo, val, (HarmonyMethod)null, (HarmonyMethod)null, val2, (HarmonyMethod)null);
				SelfSortingStoragePLUS.Logger.LogDebug((object)"[ProtectCupboardItems] Patched SelfSortingStorage's EndOfRoundCupboardEffects.");
			}
			catch (Exception ex)
			{
				SelfSortingStoragePLUS.Logger.LogError((object)("[ProtectCupboardItems] Failed to patch SelfSortingStorage's EndOfRoundCupboardEffects. Team wipe scrap-clearing will not be prevented. Exception: " + ex));
			}
		}

		private static bool ResolvePreventMemoryResetConfigEntry()
		{
			if (PreventMemoryResetConfigEntry != null)
			{
				return true;
			}
			try
			{
				Type type = AccessTools.TypeByName("SelfSortingStorage.Plugin");
				object obj = AccessTools.Property(type, "config")?.GetValue(null);
				if (obj == null)
				{
					SelfSortingStoragePLUS.Logger.LogError((object)"[ProtectCupboardItems] Could not resolve SelfSortingStorage's config instance. Team wipe scrap-clearing will not be prevented.");
					return false;
				}
				Type type2 = obj.GetType();
				object obj2 = AccessTools.Property(type2, "preventMemoryReset")?.GetValue(obj) ?? AccessTools.Field(type2, "preventMemoryReset")?.GetValue(obj);
				PreventMemoryResetConfigEntry = obj2 as ConfigEntry<bool>;
				if (PreventMemoryResetConfigEntry == null)
				{
					SelfSortingStoragePLUS.Logger.LogError((object)"[ProtectCupboardItems] Could not resolve SelfSortingStorage's preventMemoryReset config entry. Team wipe scrap-clearing will not be prevented.");
				}
			}
			catch (Exception ex)
			{
				SelfSortingStoragePLUS.Logger.LogError((object)("[ProtectCupboardItems] Error resolving preventMemoryReset config entry: " + ex));
				return false;
			}
			return PreventMemoryResetConfigEntry != null;
		}

		private static void Prefix()
		{
			if (SelfSortingStoragePLUS.ProtectCupboardItems.Value && ResolvePreventMemoryResetConfigEntry())
			{
				SavedOriginalValue = PreventMemoryResetConfigEntry.Value;
				PreventMemoryResetConfigEntry.Value = true;
				if (SelfSortingStoragePLUS.VerboseLogging.Value)
				{
					SelfSortingStoragePLUS.Logger.LogInfo((object)"[ProtectCupboardItems] Temporarily forcing SelfSortingStorage's preventMemoryReset on for the team wipe cleanup pass.");
				}
			}
		}

		private static Exception? Finalizer(Exception? __exception)
		{
			if (SelfSortingStoragePLUS.ProtectCupboardItems.Value && PreventMemoryResetConfigEntry != null)
			{
				PreventMemoryResetConfigEntry.Value = SavedOriginalValue;
			}
			return __exception;
		}
	}
}