Decompiled source of BagBeltMod v1.1.0

BepInEx/plugins/BagBeltMod/BroMode.BagBeltMod.dll

Decompiled a month ago
using System;
using System.Collections;
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 System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Unity.Collections;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.UI;

[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("BroMode.BagBeltMod")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.1.0.0")]
[assembly: AssemblyInformationalVersion("1.1.0")]
[assembly: AssemblyProduct("BagBeltMod")]
[assembly: AssemblyTitle("BroMode.BagBeltMod")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.1.0.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.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]
	[Microsoft.CodeAnalysis.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]
	[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 BagBeltMod
{
	[BepInPlugin("BroMode.BagBeltMod", "BagBeltMod", "1.1.0")]
	public class BagBeltMod : BaseUnityPlugin
	{
		private const int RequiredPrice = 80;

		private static readonly string[] RequiredUtilityItems = new string[12]
		{
			"Flashlight", "Pro-flashlight", "Stun grenade", "Walkie-talkie", "TZP-Inhalant", "Lockpicker", "Zap gun", "Key", "Shotgun shells", "Shovel",
			"Yield sign", "Stop sign"
		};

		public static BagBeltMod Instance { get; private set; } = null;


		internal static ManualLogSource Logger { get; private set; } = null;


		internal static Harmony? Harmony { get; set; }

		internal static ConfigEntry<bool> Enabled { get; private set; } = null;


		internal static ConfigEntry<int> Price { get; private set; } = null;


		internal static ConfigEntry<int> ExtraSlotsGranted { get; private set; } = null;


		internal static ConfigEntry<string> UtilityWhitelist { get; private set; } = null;


		internal static ConfigEntry<bool> LogDebug { get; private set; } = null;


		private void Awake()
		{
			Logger = ((BaseUnityPlugin)this).Logger;
			Instance = this;
			Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable the Bag Belt item.");
			Price = ((BaseUnityPlugin)this).Config.Bind<int>("General", "Price", 80, "Price of Bag Belt in the store.");
			ExtraSlotsGranted = ((BaseUnityPlugin)this).Config.Bind<int>("General", "ExtraSlotsGranted", 2, "Extra hotbar slots granted when Bag Belt is equipped.");
			UtilityWhitelist = ((BaseUnityPlugin)this).Config.Bind<string>("General", "UtilityWhitelist", "Flashlight,Pro-flashlight,Stun grenade,Walkie-talkie,TZP-Inhalant,Lockpicker,Zap gun,Key,Shotgun shells,Shovel,Yield sign,Stop sign", "Comma-separated item names allowed in the utility-only slot.");
			LogDebug = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "LogDebug", false, "Enable debug logging for Bag Belt behavior.");
			EnsureUtilityWhitelistHasRequiredEntries();
			if (Price.Value != 80)
			{
				Logger.LogInfo((object)$"Bag Belt price reset to ${80} (was ${Price.Value}).");
				Price.Value = 80;
				((BaseUnityPlugin)this).Config.Save();
			}
			WarnIfDuplicateBagBeltDllsLoaded();
			Patch();
			Logger.LogInfo((object)"BroMode.BagBeltMod v1.1.0 has loaded!");
			Logger.LogInfo((object)$"Bag Belt enabled: {Enabled.Value}");
			Logger.LogInfo((object)$"Bag Belt price: ${Price.Value}");
		}

		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("BroMode.BagBeltMod");
			}
			Logger.LogDebug((object)"Patching...");
			Harmony.PatchAll();
			Logger.LogDebug((object)"Finished patching!");
		}

		private static void WarnIfDuplicateBagBeltDllsLoaded()
		{
			try
			{
				if (Directory.Exists(Paths.PluginPath))
				{
					string[] files = Directory.GetFiles(Paths.PluginPath, "*BagBeltMod.dll", SearchOption.AllDirectories);
					if (files.Length > 1)
					{
						string text = string.Join(", ", files.Select(Path.GetFileName));
						Logger.LogWarning((object)("Multiple BagBelt DLLs detected: " + text + ". Keep only one to avoid patch conflicts."));
					}
				}
			}
			catch (Exception ex)
			{
				Logger.LogDebug((object)("Bag Belt duplicate DLL check skipped: " + ex.Message));
			}
		}

		private void EnsureUtilityWhitelistHasRequiredEntries()
		{
			string text = UtilityWhitelist.Value ?? string.Empty;
			List<string> list = (from x in text.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries)
				select x.Trim() into x
				where x.Length > 0
				select x).ToList();
			HashSet<string> hashSet = new HashSet<string>(list, StringComparer.OrdinalIgnoreCase);
			bool flag = false;
			for (int i = 0; i < RequiredUtilityItems.Length; i++)
			{
				string item = RequiredUtilityItems[i];
				if (!hashSet.Contains(item))
				{
					list.Add(item);
					hashSet.Add(item);
					flag = true;
				}
			}
			if (flag)
			{
				UtilityWhitelist.Value = string.Join(",", list);
				((BaseUnityPlugin)this).Config.Save();
				Logger.LogInfo((object)"Bag Belt utility whitelist updated with required default items.");
			}
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "BroMode.BagBeltMod";

		public const string PLUGIN_NAME = "BagBeltMod";

		public const string PLUGIN_VERSION = "1.1.0";
	}
}
namespace BagBeltMod.Patches
{
	[HarmonyPatch(typeof(ItemDropship))]
	internal static class BagBeltDropshipSpawnPatch
	{
		private sealed class DeliverySnapshot
		{
			internal readonly HashSet<ulong> ExistingObjectIds = new HashSet<ulong>();

			internal readonly List<bool> BagFlags = new List<bool>();

			internal Transform? PropsContainer;

			internal Transform[] SpawnPositions = Array.Empty<Transform>();
		}

		[HarmonyPrefix]
		[HarmonyPatch("OpenShipDoorsOnServer")]
		private static void OpenShipDoorsOnServerPrefix(ItemDropship __instance, out DeliverySnapshot? __state)
		{
			__state = null;
			if (!BagBeltMod.Enabled.Value)
			{
				return;
			}
			Terminal value = Traverse.Create((object)__instance).Field("terminalScript").GetValue<Terminal>();
			StartOfRound value2 = Traverse.Create((object)__instance).Field("playersManager").GetValue<StartOfRound>();
			List<int> value3 = Traverse.Create((object)__instance).Field("itemsToDeliver").GetValue<List<int>>();
			if ((Object)(object)value == (Object)null || (Object)(object)value2 == (Object)null || (Object)(object)value2.propsContainer == (Object)null || value3 == null)
			{
				return;
			}
			DeliverySnapshot deliverySnapshot = new DeliverySnapshot
			{
				PropsContainer = value2.propsContainer,
				SpawnPositions = (__instance.itemSpawnPositions ?? Array.Empty<Transform>())
			};
			NetworkObject[] componentsInChildren = ((Component)value2.propsContainer).GetComponentsInChildren<NetworkObject>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				if ((Object)(object)componentsInChildren[i] != (Object)null)
				{
					deliverySnapshot.ExistingObjectIds.Add(componentsInChildren[i].NetworkObjectId);
				}
			}
			Item[] array = value.buyableItemsList ?? Array.Empty<Item>();
			for (int j = 0; j < value3.Count; j++)
			{
				int num = value3[j];
				if (num >= 0 && num < array.Length)
				{
					Item val = array[num];
					bool item = (Object)(object)val == (Object)(object)BagBeltRegistry.BagBeltItem || num == BagBeltRegistry.BagBeltBuyIndex;
					deliverySnapshot.BagFlags.Add(item);
				}
			}
			__state = deliverySnapshot;
		}

		[HarmonyPostfix]
		[HarmonyPatch("OpenShipDoorsOnServer")]
		private static void OpenShipDoorsOnServerPostfix(ItemDropship __instance, DeliverySnapshot? __state)
		{
			if (__state == null || (Object)(object)__state.PropsContainer == (Object)null || __state.BagFlags.Count == 0)
			{
				return;
			}
			List<GrabbableObject> list = new List<GrabbableObject>();
			GrabbableObject[] componentsInChildren = ((Component)__state.PropsContainer).GetComponentsInChildren<GrabbableObject>(true);
			foreach (GrabbableObject val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null))
				{
					NetworkObject component = ((Component)val).GetComponent<NetworkObject>();
					if (!((Object)(object)component == (Object)null) && !__state.ExistingObjectIds.Contains(component.NetworkObjectId))
					{
						list.Add(val);
					}
				}
			}
			if (list.Count == 0)
			{
				return;
			}
			HashSet<int> usedIndices = new HashSet<int>();
			int num = 0;
			for (int j = 0; j < __state.BagFlags.Count; j++)
			{
				GrabbableObject val2 = FindNearestUnassignedItem(list, usedIndices, __state.SpawnPositions, num);
				if ((Object)(object)val2 != (Object)null && __state.BagFlags[j])
				{
					if ((Object)(object)BagBeltRegistry.BagBeltItem != (Object)null)
					{
						val2.itemProperties = BagBeltRegistry.BagBeltItem;
					}
					BagBeltNetworkSync.MarkBagObjectOnHostAndBroadcast(val2);
					if (BagBeltMod.LogDebug.Value)
					{
						NetworkObject component2 = ((Component)val2).GetComponent<NetworkObject>();
						BagBeltMod.Logger.LogDebug((object)$"Bag Belt tagged after vanilla dropship spawn. netId={((component2 != null) ? new ulong?(component2.NetworkObjectId) : null)}");
					}
				}
				if (__state.SpawnPositions.Length != 0)
				{
					num = ((num < __state.SpawnPositions.Length - 1) ? (num + 1) : 0);
				}
			}
		}

		private static GrabbableObject? FindNearestUnassignedItem(List<GrabbableObject> items, HashSet<int> usedIndices, Transform[] spawnPositions, int spawnIndex)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			int num = -1;
			float num2 = float.MaxValue;
			Vector3 val = Vector3.zero;
			bool flag = spawnPositions.Length != 0 && spawnIndex >= 0 && spawnIndex < spawnPositions.Length && (Object)(object)spawnPositions[spawnIndex] != (Object)null;
			if (flag)
			{
				val = spawnPositions[spawnIndex].position;
			}
			for (int i = 0; i < items.Count; i++)
			{
				if (!usedIndices.Contains(i) && !((Object)(object)items[i] == (Object)null))
				{
					float num3;
					if (!flag)
					{
						num3 = i;
					}
					else
					{
						Vector3 val2 = ((Component)items[i]).transform.position - val;
						num3 = ((Vector3)(ref val2)).sqrMagnitude;
					}
					float num4 = num3;
					if (num4 < num2)
					{
						num2 = num4;
						num = i;
					}
				}
			}
			if (num < 0)
			{
				return null;
			}
			usedIndices.Add(num);
			return items[num];
		}
	}
	internal static class BagBeltDropSuppression
	{
		private const int UtilitySlotIndex = 4;

		private const int BagSlotIndex = 5;

		internal static bool TeleporterContext;

		internal static void DropAllHeldItemsPreserveBagBelt(PlayerControllerB player)
		{
			if (!BagBeltMod.Enabled.Value)
			{
				player.DropAllHeldItems(true, false);
				return;
			}
			GrabbableObject bag;
			int bagSlot;
			bool flag = TryFindBagBelt(player, out bag, out bagSlot);
			for (int i = 0; i < player.ItemSlots.Length; i++)
			{
				GrabbableObject val = player.ItemSlots[i];
				if (!((Object)(object)val == (Object)null) && !BagBeltInventoryPatch.IsBagBelt(val) && (!flag || i != 4))
				{
					BagBeltInventoryPatch.ForceDropItem(player, val, i);
				}
			}
			if ((Object)(object)bag != (Object)null)
			{
				player.currentItemSlot = bagSlot;
				player.currentlyHeldObjectServer = bag;
				player.isHoldingObject = true;
				player.twoHanded = false;
				player.twoHandedAnimation = false;
			}
		}

		private static bool TryFindBagBelt(PlayerControllerB player, out GrabbableObject? bag, out int bagSlot)
		{
			bag = null;
			bagSlot = -1;
			for (int i = 0; i < player.ItemSlots.Length; i++)
			{
				GrabbableObject val = player.ItemSlots[i];
				if (BagBeltInventoryPatch.IsBagBelt(val))
				{
					bag = val;
					bagSlot = i;
					return true;
				}
			}
			if (5 < player.ItemSlots.Length)
			{
				GrabbableObject val2 = player.ItemSlots[5];
				if (val2 is BeltBagItem)
				{
					bag = val2;
					bagSlot = 5;
					return true;
				}
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(ShipTeleporter))]
	internal static class BagBeltDropSuppressionPatch
	{
		[CompilerGenerated]
		private sealed class <WrapTeleporterContext>d__4 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public IEnumerator inner;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <WrapTeleporterContext>d__4(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					BagBeltDropSuppression.TeleporterContext = true;
					break;
				case 1:
					<>1__state = -1;
					break;
				}
				if (inner.MoveNext())
				{
					<>2__current = inner.Current;
					<>1__state = 1;
					return true;
				}
				BagBeltDropSuppression.TeleporterContext = false;
				return false;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch("TeleportPlayerOutWithInverseTeleporter")]
		private static void InverseTeleporterPrefix()
		{
			BagBeltDropSuppression.TeleporterContext = true;
		}

		[HarmonyPostfix]
		[HarmonyPatch("TeleportPlayerOutWithInverseTeleporter")]
		private static void InverseTeleporterPostfix()
		{
			BagBeltDropSuppression.TeleporterContext = false;
		}

		[HarmonyPostfix]
		[HarmonyPatch("beamUpPlayer")]
		private static void BeamUpPlayerPostfix(ref IEnumerator __result)
		{
			__result = WrapTeleporterContext(__result);
		}

		[HarmonyPostfix]
		[HarmonyPatch("teleportBodyOut")]
		private static void TeleportBodyOutPostfix(ref IEnumerator __result)
		{
			__result = WrapTeleporterContext(__result);
		}

		[IteratorStateMachine(typeof(<WrapTeleporterContext>d__4))]
		private static IEnumerator WrapTeleporterContext(IEnumerator inner)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <WrapTeleporterContext>d__4(0)
			{
				inner = inner
			};
		}
	}
	[HarmonyPatch(typeof(PlayerControllerB))]
	internal static class BagBeltDropAllHeldItemsPatch
	{
		[HarmonyPrefix]
		[HarmonyPatch("DropAllHeldItems")]
		private static bool DropAllHeldItemsPrefix(PlayerControllerB __instance)
		{
			if (BagBeltDropSuppression.TeleporterContext && BagBeltMod.Enabled.Value)
			{
				BagBeltDropSuppression.DropAllHeldItemsPreserveBagBelt(__instance);
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch]
	internal static class BagBeltInventoryPatch
	{
		private const int BaseSlots = 4;

		private static readonly Dictionary<int, bool> BagEquippedByPlayer = new Dictionary<int, bool>(4);

		private static string? _cachedWhitelist;

		private static HashSet<string>? _whitelistSet;

		private static bool IsEnabled => BagBeltMod.Enabled.Value;

		private static int ExtraSlots => Math.Max(0, BagBeltMod.ExtraSlotsGranted.Value);

		private static int UtilitySlotIndex => 4;

		private static int BagSlotIndex => 5;

		internal static bool IsBagBelt(GrabbableObject? item)
		{
			return BagBeltRegistry.IsBagBelt(item);
		}

		private static bool IsUtilityAllowed(GrabbableObject item)
		{
			if (_whitelistSet == null || _cachedWhitelist != BagBeltMod.UtilityWhitelist.Value)
			{
				_cachedWhitelist = BagBeltMod.UtilityWhitelist.Value ?? string.Empty;
				_whitelistSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
				string[] array = _cachedWhitelist.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries);
				for (int i = 0; i < array.Length; i++)
				{
					string text = array[i].Trim();
					if (text.Length > 0)
					{
						_whitelistSet.Add(NormalizeItemName(text));
					}
				}
			}
			if ((Object)(object)item.itemProperties != (Object)null)
			{
				return _whitelistSet.Contains(NormalizeItemName(item.itemProperties.itemName));
			}
			return false;
		}

		private static string NormalizeItemName(string? raw)
		{
			if (string.IsNullOrWhiteSpace(raw))
			{
				return string.Empty;
			}
			char[] array = raw.ToCharArray();
			char[] array2 = new char[array.Length];
			int num = 0;
			foreach (char c in array)
			{
				if (char.IsLetterOrDigit(c))
				{
					array2[num++] = char.ToLowerInvariant(c);
				}
			}
			if (num != 0)
			{
				return new string(array2, 0, num);
			}
			return string.Empty;
		}

		private static bool HasBagBeltEquipped(PlayerControllerB player)
		{
			int instanceID = ((Object)player).GetInstanceID();
			bool value;
			return BagEquippedByPlayer.TryGetValue(instanceID, out value) && value;
		}

		private static bool HasBagBeltInSlots(PlayerControllerB player)
		{
			if (player.ItemSlots == null)
			{
				return false;
			}
			for (int i = 0; i < player.ItemSlots.Length; i++)
			{
				if (IsBagBelt(player.ItemSlots[i]))
				{
					return true;
				}
			}
			return false;
		}

		private static void SetBagBeltEquipped(PlayerControllerB player, bool equipped)
		{
			BagEquippedByPlayer[((Object)player).GetInstanceID()] = equipped;
		}

		private static void EnsureExpandedSlots(PlayerControllerB player)
		{
			int num = 4 + ExtraSlots;
			if (num > 4 && player.ItemSlots != null)
			{
				if (player.ItemSlots.Length < num)
				{
					GrabbableObject[] array = (GrabbableObject[])(object)new GrabbableObject[num];
					Array.Copy(player.ItemSlots, array, player.ItemSlots.Length);
					player.ItemSlots = array;
				}
				if (((NetworkBehaviour)player).IsOwner)
				{
					EnsureHudSlots(num);
				}
			}
		}

		private static void EnsureHudSlots(int target)
		{
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: 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_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			HUDManager instance = HUDManager.Instance;
			if ((Object)(object)instance == (Object)null || instance.itemSlotIcons == null || instance.itemSlotIconFrames == null || (instance.itemSlotIcons.Length >= target && instance.itemSlotIconFrames.Length >= target))
			{
				return;
			}
			List<Image> list = new List<Image>(instance.itemSlotIcons);
			List<Image> list2 = new List<Image>(instance.itemSlotIconFrames);
			Vector2 val = Vector2.right * 55f;
			if (list.Count >= 2)
			{
				RectTransform rectTransform = ((Graphic)list[list.Count - 2]).rectTransform;
				RectTransform rectTransform2 = ((Graphic)list[list.Count - 1]).rectTransform;
				val = rectTransform2.anchoredPosition - rectTransform.anchoredPosition;
				if (val == Vector2.zero)
				{
					val = Vector2.right * 55f;
				}
			}
			while (list.Count < target)
			{
				Image val2 = list[list.Count - 1];
				Image val3 = list2[list2.Count - 1];
				Vector3 val4 = ((Transform)((Graphic)val2).rectTransform).position - ((Transform)((Graphic)val3).rectTransform).position;
				Image val5 = Object.Instantiate<Image>(val2, ((Component)val2).transform.parent);
				Image val6 = Object.Instantiate<Image>(val3, ((Component)val3).transform.parent);
				((Graphic)val5).rectTransform.anchoredPosition = ((Graphic)val2).rectTransform.anchoredPosition + val;
				RectTransform rectTransform3 = ((Graphic)val6).rectTransform;
				rectTransform3.anchoredPosition += val;
				((Transform)((Graphic)val5).rectTransform).position = ((Transform)((Graphic)val6).rectTransform).position + val4;
				((Behaviour)val5).enabled = false;
				((Behaviour)val6).enabled = true;
				list.Add(val5);
				list2.Add(val6);
			}
			instance.itemSlotIcons = list.ToArray();
			instance.itemSlotIconFrames = list2.ToArray();
		}

		private static int FindSlot(PlayerControllerB player, GrabbableObject item)
		{
			for (int i = 0; i < player.ItemSlots.Length; i++)
			{
				if ((Object)(object)player.ItemSlots[i] == (Object)(object)item)
				{
					return i;
				}
			}
			return -1;
		}

		private static int FindFirstEmptyBaseSlot(PlayerControllerB player)
		{
			int num = Math.Min(4, player.ItemSlots.Length);
			for (int i = 0; i < num; i++)
			{
				if ((Object)(object)player.ItemSlots[i] == (Object)null)
				{
					return i;
				}
			}
			return -1;
		}

		private static void UpdateSlotIcon(PlayerControllerB player, int slot)
		{
			if (((NetworkBehaviour)player).IsOwner && !((Object)(object)HUDManager.Instance == (Object)null) && slot >= 0 && slot < HUDManager.Instance.itemSlotIcons.Length)
			{
				GrabbableObject val = player.ItemSlots[slot];
				if ((Object)(object)val == (Object)null || (Object)(object)val.itemProperties == (Object)null || (Object)(object)val.itemProperties.itemIcon == (Object)null)
				{
					((Behaviour)HUDManager.Instance.itemSlotIcons[slot]).enabled = false;
					HUDManager.Instance.itemSlotIcons[slot].sprite = null;
				}
				else
				{
					HUDManager.Instance.itemSlotIcons[slot].sprite = val.itemProperties.itemIcon;
					((Behaviour)HUDManager.Instance.itemSlotIcons[slot]).enabled = true;
				}
			}
		}

		private static void MoveItemToSlot(PlayerControllerB player, GrabbableObject item, int fromSlot, int toSlot)
		{
			if (fromSlot != toSlot)
			{
				player.ItemSlots[toSlot] = item;
				player.ItemSlots[fromSlot] = null;
				if ((Object)(object)player.currentlyHeldObjectServer == (Object)(object)item)
				{
					player.currentItemSlot = toSlot;
				}
				UpdateSlotIcon(player, fromSlot);
				UpdateSlotIcon(player, toSlot);
			}
		}

		private static void SwapItemsBetweenSlots(PlayerControllerB player, int firstSlot, int secondSlot)
		{
			if (firstSlot != secondSlot)
			{
				GrabbableObject val = player.ItemSlots[firstSlot];
				GrabbableObject val2 = player.ItemSlots[secondSlot];
				player.ItemSlots[firstSlot] = val2;
				player.ItemSlots[secondSlot] = val;
				if ((Object)(object)player.currentlyHeldObjectServer == (Object)(object)val)
				{
					player.currentItemSlot = secondSlot;
				}
				else if ((Object)(object)player.currentlyHeldObjectServer == (Object)(object)val2)
				{
					player.currentItemSlot = firstSlot;
				}
				UpdateSlotIcon(player, firstSlot);
				UpdateSlotIcon(player, secondSlot);
			}
		}

		internal static void ForceDropItem(PlayerControllerB player, GrabbableObject item, int slot)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			if (((NetworkBehaviour)player).IsOwner && (Object)(object)player.currentlyHeldObjectServer == (Object)(object)item)
			{
				player.DiscardHeldObject(false, (NetworkObject)null, default(Vector3), true);
			}
			else
			{
				item.parentObject = null;
				item.heldByPlayerOnServer = false;
				if (player.isInElevator)
				{
					((Component)item).transform.SetParent(player.playersManager.elevatorTransform, true);
				}
				else
				{
					((Component)item).transform.SetParent(player.playersManager.propsContainer, true);
				}
				player.SetItemInElevator(player.isInHangarShipRoom, player.isInElevator, item);
				item.EnablePhysics(true);
				item.EnableItemMeshes(true);
				((Component)item).transform.localScale = item.originalScale;
				item.isHeld = false;
				item.isPocketed = false;
				item.startFallingPosition = ((Component)item).transform.parent.InverseTransformPoint(((Component)item).transform.position);
				item.FallToGround(true, false, default(Vector3));
				item.fallTime = Random.Range(-0.3f, 0.05f);
				if (((NetworkBehaviour)player).IsOwner)
				{
					item.DiscardItemOnClient();
				}
				else if (!item.itemProperties.syncDiscardFunction)
				{
					item.playerHeldBy = null;
				}
			}
			player.ItemSlots[slot] = null;
			UpdateSlotIcon(player, slot);
		}

		private static void ShrinkSlotsIfNeeded(PlayerControllerB player)
		{
			if (player.ItemSlots == null || player.ItemSlots.Length <= 4 || HasBagBeltInSlots(player))
			{
				return;
			}
			if (UtilitySlotIndex < player.ItemSlots.Length && (Object)(object)player.ItemSlots[UtilitySlotIndex] != (Object)null)
			{
				GrabbableObject item = player.ItemSlots[UtilitySlotIndex];
				int num = FindFirstEmptyBaseSlot(player);
				if (num != -1)
				{
					MoveItemToSlot(player, item, UtilitySlotIndex, num);
				}
				else
				{
					ForceDropItem(player, item, UtilitySlotIndex);
				}
			}
			if (BagSlotIndex < player.ItemSlots.Length && (Object)(object)player.ItemSlots[BagSlotIndex] != (Object)null)
			{
				GrabbableObject item2 = player.ItemSlots[BagSlotIndex];
				int num2 = FindFirstEmptyBaseSlot(player);
				if (num2 != -1)
				{
					MoveItemToSlot(player, item2, BagSlotIndex, num2);
				}
				else
				{
					ForceDropItem(player, item2, BagSlotIndex);
				}
			}
			GrabbableObject[] array = (GrabbableObject[])(object)new GrabbableObject[4];
			Array.Copy(player.ItemSlots, array, 4);
			player.ItemSlots = array;
			if (player.currentItemSlot >= 4)
			{
				player.currentItemSlot = 0;
			}
		}

		private static void SyncHudExtraSlotVisibility(PlayerControllerB player, bool showExtra)
		{
			if (!((NetworkBehaviour)player).IsOwner)
			{
				return;
			}
			HUDManager instance = HUDManager.Instance;
			if ((Object)(object)instance == (Object)null || instance.itemSlotIcons == null || instance.itemSlotIconFrames == null)
			{
				return;
			}
			int val = 4 + ExtraSlots;
			GrabbableObject[] itemSlots = player.ItemSlots;
			EnsureHudSlots(Math.Max(val, (itemSlots != null) ? itemSlots.Length : 4));
			GrabbableObject[] itemSlots2 = player.ItemSlots;
			int num = ((itemSlots2 != null) ? itemSlots2.Length : 4);
			int val2 = instance.itemSlotIcons.Length;
			int val3 = instance.itemSlotIconFrames.Length;
			int num2 = Math.Min(val2, val3);
			for (int i = 0; i < num2; i++)
			{
				bool flag = i >= 4;
				bool flag2 = !flag || showExtra;
				bool flag3 = i < num;
				Image val4 = instance.itemSlotIconFrames[i];
				if ((Object)(object)val4 != (Object)null)
				{
					((Behaviour)val4).enabled = flag2;
				}
				Image val5 = instance.itemSlotIcons[i];
				if ((Object)(object)val5 == (Object)null)
				{
					continue;
				}
				if (!flag2 || !flag3)
				{
					((Behaviour)val5).enabled = false;
					if (flag)
					{
						val5.sprite = null;
					}
					continue;
				}
				GrabbableObject val6 = player.ItemSlots[i];
				if ((Object)(object)val6 == (Object)null || (Object)(object)val6.itemProperties == (Object)null || (Object)(object)val6.itemProperties.itemIcon == (Object)null)
				{
					((Behaviour)val5).enabled = false;
					if (flag)
					{
						val5.sprite = null;
					}
				}
				else
				{
					val5.sprite = val6.itemProperties.itemIcon;
					((Behaviour)val5).enabled = true;
				}
			}
		}

		private static void EnsureBagBeltInDedicatedSlot(PlayerControllerB player)
		{
			if (player.ItemSlots == null || BagSlotIndex >= player.ItemSlots.Length)
			{
				return;
			}
			int num = -1;
			for (int i = 0; i < player.ItemSlots.Length; i++)
			{
				if (IsBagBelt(player.ItemSlots[i]))
				{
					num = i;
					break;
				}
			}
			if (num == -1 || num == BagSlotIndex || (Object)(object)player.ItemSlots[num] == (Object)(object)player.currentlyHeldObjectServer)
			{
				return;
			}
			if ((Object)(object)player.ItemSlots[BagSlotIndex] == (Object)null)
			{
				MoveItemToSlot(player, player.ItemSlots[num], num, BagSlotIndex);
				return;
			}
			int num2 = FindFirstEmptyBaseSlot(player);
			if (num2 != -1)
			{
				MoveItemToSlot(player, player.ItemSlots[BagSlotIndex], BagSlotIndex, num2);
				MoveItemToSlot(player, player.ItemSlots[num], num, BagSlotIndex);
			}
		}

		private static void ReconcileUtilitySlot(PlayerControllerB player)
		{
			if (player.ItemSlots == null || UtilitySlotIndex >= player.ItemSlots.Length)
			{
				return;
			}
			GrabbableObject val = player.ItemSlots[UtilitySlotIndex];
			if ((Object)(object)val != (Object)null && !IsUtilityAllowed(val))
			{
				int num = FindFirstEmptyBaseSlot(player);
				if (num != -1)
				{
					MoveItemToSlot(player, val, UtilitySlotIndex, num);
				}
				else
				{
					ForceDropItem(player, val, UtilitySlotIndex);
				}
				val = null;
			}
			if ((Object)(object)val != (Object)null)
			{
				return;
			}
			for (int i = 0; i < player.ItemSlots.Length; i++)
			{
				if (i == UtilitySlotIndex || i == BagSlotIndex)
				{
					continue;
				}
				GrabbableObject val2 = player.ItemSlots[i];
				if (!((Object)(object)val2 == (Object)null) && !IsBagBelt(val2) && IsUtilityAllowed(val2))
				{
					MoveItemToSlot(player, val2, i, UtilitySlotIndex);
					if (BagBeltMod.LogDebug.Value)
					{
						BagBeltMod.Logger.LogDebug((object)string.Format("Utility auto-slot: moved '{0}' to slot {1}.", val2.itemProperties?.itemName ?? "unknown", UtilitySlotIndex + 1));
					}
					break;
				}
			}
		}

		[HarmonyPatch(typeof(PlayerControllerB), "GrabObjectClientRpc")]
		[HarmonyPostfix]
		private static void GrabObjectClientRpcPostfix(PlayerControllerB __instance, bool grabValidated, NetworkObjectReference grabbedObject)
		{
			NetworkObject val = default(NetworkObject);
			if (!grabValidated || !IsEnabled || !((NetworkObjectReference)(ref grabbedObject)).TryGet(ref val, (NetworkManager)null))
			{
				return;
			}
			GrabbableObject componentInChildren = ((Component)val).gameObject.GetComponentInChildren<GrabbableObject>();
			if ((Object)(object)componentInChildren == (Object)null)
			{
				return;
			}
			if (IsBagBelt(componentInChildren))
			{
				SetBagBeltEquipped(__instance, equipped: true);
				EnsureExpandedSlots(__instance);
				int num = FindSlot(__instance, componentInChildren);
				if (num >= 0 && BagSlotIndex < __instance.ItemSlots.Length && num != BagSlotIndex)
				{
					if ((Object)(object)__instance.ItemSlots[BagSlotIndex] == (Object)null)
					{
						MoveItemToSlot(__instance, componentInChildren, num, BagSlotIndex);
					}
					else
					{
						SwapItemsBetweenSlots(__instance, num, BagSlotIndex);
					}
				}
				ReconcileUtilitySlot(__instance);
				SyncHudExtraSlotVisibility(__instance, showExtra: true);
			}
			else
			{
				if (!HasBagBeltEquipped(__instance) && !HasBagBeltInSlots(__instance))
				{
					return;
				}
				SetBagBeltEquipped(__instance, equipped: true);
				EnsureExpandedSlots(__instance);
				int num2 = FindSlot(__instance, componentInChildren);
				if (num2 == UtilitySlotIndex && !IsUtilityAllowed(componentInChildren))
				{
					int num3 = FindFirstEmptyBaseSlot(__instance);
					if (num3 != -1)
					{
						MoveItemToSlot(__instance, componentInChildren, num2, num3);
					}
					else
					{
						if (BagBeltMod.LogDebug.Value)
						{
							BagBeltMod.Logger.LogDebug((object)("Utility slot reject: " + componentInChildren.itemProperties.itemName));
						}
						ForceDropItem(__instance, componentInChildren, num2);
					}
				}
				else if (num2 >= 0 && num2 != UtilitySlotIndex && IsUtilityAllowed(componentInChildren) && UtilitySlotIndex < __instance.ItemSlots.Length)
				{
					if ((Object)(object)__instance.ItemSlots[UtilitySlotIndex] == (Object)null)
					{
						MoveItemToSlot(__instance, componentInChildren, num2, UtilitySlotIndex);
					}
					else
					{
						SwapItemsBetweenSlots(__instance, num2, UtilitySlotIndex);
					}
				}
				EnsureBagBeltInDedicatedSlot(__instance);
				SyncHudExtraSlotVisibility(__instance, showExtra: true);
			}
		}

		[HarmonyPatch(typeof(BeltBagItem), "EquipItem")]
		[HarmonyPostfix]
		private static void BeltBagEquipPostfix(BeltBagItem __instance)
		{
			if (IsEnabled && !((Object)(object)((GrabbableObject)__instance).playerHeldBy == (Object)null) && IsBagBelt((GrabbableObject?)(object)__instance))
			{
				SetBagBeltEquipped(((GrabbableObject)__instance).playerHeldBy, equipped: true);
				EnsureExpandedSlots(((GrabbableObject)__instance).playerHeldBy);
				SyncHudExtraSlotVisibility(((GrabbableObject)__instance).playerHeldBy, showExtra: true);
				if (BagBeltMod.LogDebug.Value)
				{
					BagBeltMod.Logger.LogDebug((object)"Bag Belt equipped.");
				}
			}
		}

		[HarmonyPatch(typeof(BeltBagItem), "DiscardItem")]
		[HarmonyPrefix]
		private static void BeltBagDiscardPrefix(BeltBagItem __instance, out PlayerControllerB? __state)
		{
			__state = ((GrabbableObject)__instance).playerHeldBy;
		}

		[HarmonyPatch(typeof(BeltBagItem), "DiscardItem")]
		[HarmonyPostfix]
		private static void BeltBagDiscardPostfix(BeltBagItem __instance, PlayerControllerB? __state)
		{
			if (!IsEnabled || (Object)(object)__state == (Object)null || !IsBagBelt((GrabbableObject?)(object)__instance))
			{
				return;
			}
			SetBagBeltEquipped(__state, equipped: false);
			if (UtilitySlotIndex < __state.ItemSlots.Length && (Object)(object)__state.ItemSlots[UtilitySlotIndex] != (Object)null)
			{
				GrabbableObject item = __state.ItemSlots[UtilitySlotIndex];
				int num = FindFirstEmptyBaseSlot(__state);
				if (num != -1)
				{
					MoveItemToSlot(__state, item, UtilitySlotIndex, num);
				}
				else
				{
					ForceDropItem(__state, item, UtilitySlotIndex);
				}
			}
			if (__state.ItemSlots.Length > 4)
			{
				GrabbableObject[] array = (GrabbableObject[])(object)new GrabbableObject[4];
				Array.Copy(__state.ItemSlots, array, 4);
				__state.ItemSlots = array;
				if (__state.currentItemSlot >= 4)
				{
					__state.currentItemSlot = 0;
				}
			}
			if (BagBeltMod.LogDebug.Value)
			{
				BagBeltMod.Logger.LogDebug((object)"Bag Belt unequipped.");
			}
			SyncHudExtraSlotVisibility(__state, showExtra: false);
		}

		[HarmonyPatch(typeof(BeltBagItem), "ItemActivate")]
		[HarmonyPrefix]
		private static bool BeltBagActivatePrefix(BeltBagItem __instance)
		{
			if (IsEnabled && IsBagBelt((GrabbableObject?)(object)__instance))
			{
				return false;
			}
			return true;
		}

		[HarmonyPatch(typeof(BeltBagItem), "ItemInteractLeftRight")]
		[HarmonyPrefix]
		private static bool BeltBagInteractPrefix(BeltBagItem __instance)
		{
			if (IsEnabled && IsBagBelt((GrabbableObject?)(object)__instance))
			{
				return false;
			}
			return true;
		}

		[HarmonyPatch(typeof(BeltBagItem), "TryCheckBagContents")]
		[HarmonyPrefix]
		private static bool BeltBagTryCheckPrefix(BeltBagItem __instance)
		{
			if (IsEnabled && IsBagBelt((GrabbableObject?)(object)__instance))
			{
				return false;
			}
			return true;
		}

		[HarmonyPatch(typeof(BeltBagItem), "TryCheckingBagServerRpc")]
		[HarmonyPrefix]
		private static bool BeltBagTryCheckServerPrefix(BeltBagItem __instance)
		{
			if (IsEnabled && IsBagBelt((GrabbableObject?)(object)__instance))
			{
				return false;
			}
			return true;
		}

		[HarmonyPatch(typeof(BeltBagItem), "CheckBagLocalClient")]
		[HarmonyPrefix]
		private static bool BeltBagCheckLocalPrefix(BeltBagItem __instance)
		{
			if (IsEnabled && IsBagBelt((GrabbableObject?)(object)__instance))
			{
				return false;
			}
			return true;
		}

		[HarmonyPatch(typeof(GrabbableObject), "DestroyObjectInHand")]
		[HarmonyPrefix]
		private static bool DestroyObjectInHandPrefix(GrabbableObject __instance)
		{
			return true;
		}

		[HarmonyPatch(typeof(PlayerControllerB), "Update")]
		[HarmonyPostfix]
		private static void PlayerUpdatePostfix(PlayerControllerB __instance)
		{
			if (IsEnabled && __instance.ItemSlots != null)
			{
				bool flag = HasBagBeltInSlots(__instance);
				bool flag2 = HasBagBeltEquipped(__instance);
				if (flag && !flag2)
				{
					SetBagBeltEquipped(__instance, equipped: true);
					EnsureExpandedSlots(__instance);
					EnsureBagBeltInDedicatedSlot(__instance);
					ReconcileUtilitySlot(__instance);
					SyncHudExtraSlotVisibility(__instance, showExtra: true);
				}
				else if (!flag && flag2)
				{
					SetBagBeltEquipped(__instance, equipped: false);
					ShrinkSlotsIfNeeded(__instance);
					SyncHudExtraSlotVisibility(__instance, showExtra: false);
				}
				else if (!flag)
				{
					ShrinkSlotsIfNeeded(__instance);
					SyncHudExtraSlotVisibility(__instance, showExtra: false);
				}
				else
				{
					EnsureBagBeltInDedicatedSlot(__instance);
					ReconcileUtilitySlot(__instance);
					SyncHudExtraSlotVisibility(__instance, showExtra: true);
				}
			}
		}
	}
	[HarmonyPatch(typeof(GameNetworkManager))]
	internal static class BagBeltNetworkSyncLifecyclePatch
	{
		[HarmonyPostfix]
		[HarmonyPatch("Start")]
		private static void StartPostfix()
		{
			BagBeltNetworkSync.Initialize();
		}

		[HarmonyPostfix]
		[HarmonyPatch("StartHost")]
		private static void StartHostPostfix()
		{
			BagBeltNetworkSync.Initialize();
		}

		[HarmonyPostfix]
		[HarmonyPatch("StartClient")]
		private static void StartClientPostfix()
		{
			BagBeltNetworkSync.Initialize();
		}

		[HarmonyPrefix]
		[HarmonyPatch("Disconnect")]
		private static void DisconnectPrefix()
		{
			BagBeltNetworkSync.ResetForDisconnect();
		}
	}
	[HarmonyPatch(typeof(HUDManager))]
	internal static class BagBeltNetworkSyncHeartbeatPatch
	{
		[HarmonyPostfix]
		[HarmonyPatch("Update")]
		private static void HudUpdatePostfix()
		{
			BagBeltNetworkSync.Tick();
		}
	}
	[HarmonyPatch(typeof(GrabbableObject))]
	internal static class BagBeltKnownObjectPatch
	{
		[HarmonyPostfix]
		[HarmonyPatch("Start")]
		private static void StartPostfix(GrabbableObject __instance)
		{
			BagBeltNetworkSync.TryApplyKnownBagIdentity(__instance);
		}
	}
	internal static class BagBeltNetworkSync
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static HandleNamedMessageDelegate <0>__OnBuyIndexMessageReceived;

			public static HandleNamedMessageDelegate <1>__OnBagObjectSpawnMessageReceived;

			public static Action<ulong> <2>__OnClientConnected;
		}

		private const string BuyIndexMessage = "BroMode.BagBelt/BuyIndex";

		private const string BagObjectSpawnMessage = "BroMode.BagBelt/ObjectSpawn";

		private static readonly HashSet<ulong> KnownBagObjectIds = new HashSet<ulong>();

		private static bool _initialized;

		private static int _hostBuyIndex = -1;

		private static float _nextHeartbeatTime;

		private static float _nextInitWarningTime;

		internal static int EffectiveBuyIndex(int localBuyIndex)
		{
			NetworkManager singleton = NetworkManager.Singleton;
			if ((Object)(object)singleton != (Object)null && !singleton.IsServer && _hostBuyIndex >= 0)
			{
				return _hostBuyIndex;
			}
			return localBuyIndex;
		}

		internal static bool IsKnownBagObject(GrabbableObject? item)
		{
			if ((Object)(object)item == (Object)null)
			{
				return false;
			}
			NetworkObject component = ((Component)item).GetComponent<NetworkObject>();
			if ((Object)(object)component != (Object)null)
			{
				return KnownBagObjectIds.Contains(component.NetworkObjectId);
			}
			return false;
		}

		internal static void PublishHostBuyIndex(int buyIndex)
		{
			_hostBuyIndex = buyIndex;
			NetworkManager singleton = NetworkManager.Singleton;
			if (!((Object)(object)singleton == (Object)null) && singleton.IsServer && _initialized)
			{
				SendBuyIndexToAll(buyIndex);
			}
		}

		internal static void MarkBagObjectOnHostAndBroadcast(GrabbableObject item)
		{
			NetworkObject component = ((Component)item).GetComponent<NetworkObject>();
			if (!((Object)(object)component == (Object)null))
			{
				ulong networkObjectId = component.NetworkObjectId;
				KnownBagObjectIds.Add(networkObjectId);
				TryApplyKnownBagIdentity(item);
				NetworkManager singleton = NetworkManager.Singleton;
				if ((Object)(object)singleton != (Object)null && singleton.IsServer && _initialized)
				{
					SendObjectSpawnToAll(networkObjectId);
				}
			}
		}

		internal static void TryApplyKnownBagIdentity(GrabbableObject item)
		{
			NetworkObject component = ((Component)item).GetComponent<NetworkObject>();
			if (!((Object)(object)component == (Object)null) && KnownBagObjectIds.Contains(component.NetworkObjectId) && !((Object)(object)BagBeltRegistry.BagBeltItem == (Object)null) && (Object)(object)item.itemProperties != (Object)(object)BagBeltRegistry.BagBeltItem)
			{
				item.itemProperties = BagBeltRegistry.BagBeltItem;
				if (BagBeltMod.LogDebug.Value)
				{
					BagBeltMod.Logger.LogDebug((object)$"Bag Belt sync: applied identity to netId={component.NetworkObjectId}");
				}
			}
		}

		internal static void OnRegistryReady()
		{
			if (_hostBuyIndex >= 0)
			{
				BagBeltRegistry.ApplySynchronizedBuyIndex(_hostBuyIndex);
			}
			TryApplyKnownBagIdentitiesToSpawnedObjects();
			VerifyBuyIndexAgainstTerminal("registry-ready");
		}

		internal static void Initialize()
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Expected O, but got Unknown
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Expected O, but got Unknown
			if (_initialized)
			{
				return;
			}
			NetworkManager singleton = NetworkManager.Singleton;
			if (!((Object)(object)singleton == (Object)null) && singleton.CustomMessagingManager != null)
			{
				CustomMessagingManager customMessagingManager = singleton.CustomMessagingManager;
				object obj = <>O.<0>__OnBuyIndexMessageReceived;
				if (obj == null)
				{
					HandleNamedMessageDelegate val = OnBuyIndexMessageReceived;
					<>O.<0>__OnBuyIndexMessageReceived = val;
					obj = (object)val;
				}
				customMessagingManager.RegisterNamedMessageHandler("BroMode.BagBelt/BuyIndex", (HandleNamedMessageDelegate)obj);
				CustomMessagingManager customMessagingManager2 = singleton.CustomMessagingManager;
				object obj2 = <>O.<1>__OnBagObjectSpawnMessageReceived;
				if (obj2 == null)
				{
					HandleNamedMessageDelegate val2 = OnBagObjectSpawnMessageReceived;
					<>O.<1>__OnBagObjectSpawnMessageReceived = val2;
					obj2 = (object)val2;
				}
				customMessagingManager2.RegisterNamedMessageHandler("BroMode.BagBelt/ObjectSpawn", (HandleNamedMessageDelegate)obj2);
				singleton.OnClientConnectedCallback += OnClientConnected;
				_initialized = true;
				if (BagBeltMod.LogDebug.Value)
				{
					BagBeltMod.Logger.LogDebug((object)"Bag Belt sync initialized.");
				}
			}
		}

		internal static void Tick()
		{
			if (!_initialized)
			{
				Initialize();
				if (!_initialized && Time.realtimeSinceStartup >= _nextInitWarningTime)
				{
					_nextInitWarningTime = Time.realtimeSinceStartup + 5f;
					if (BagBeltMod.LogDebug.Value)
					{
						BagBeltMod.Logger.LogWarning((object)"Bag Belt sync not initialized yet; will retry.");
					}
				}
			}
			else if (!(Time.realtimeSinceStartup < _nextHeartbeatTime))
			{
				_nextHeartbeatTime = Time.realtimeSinceStartup + 2f;
				if (KnownBagObjectIds.Count > 0)
				{
					TryApplyKnownBagIdentitiesToSpawnedObjects();
				}
				if (_hostBuyIndex >= 0)
				{
					VerifyBuyIndexAgainstTerminal("heartbeat");
				}
			}
		}

		internal static void ResetForDisconnect()
		{
			NetworkManager singleton = NetworkManager.Singleton;
			if (_initialized && (Object)(object)singleton != (Object)null)
			{
				if (singleton.CustomMessagingManager != null)
				{
					singleton.CustomMessagingManager.UnregisterNamedMessageHandler("BroMode.BagBelt/BuyIndex");
					singleton.CustomMessagingManager.UnregisterNamedMessageHandler("BroMode.BagBelt/ObjectSpawn");
				}
				singleton.OnClientConnectedCallback -= OnClientConnected;
			}
			_initialized = false;
			_hostBuyIndex = -1;
			KnownBagObjectIds.Clear();
			_nextHeartbeatTime = 0f;
			_nextInitWarningTime = 0f;
		}

		private static void OnClientConnected(ulong clientId)
		{
			NetworkManager singleton = NetworkManager.Singleton;
			if ((Object)(object)singleton == (Object)null || !singleton.IsServer || clientId == singleton.LocalClientId)
			{
				return;
			}
			if (_hostBuyIndex >= 0)
			{
				SendBuyIndexToClient(clientId, _hostBuyIndex);
			}
			foreach (ulong knownBagObjectId in KnownBagObjectIds)
			{
				SendObjectSpawnToClient(clientId, knownBagObjectId);
			}
			if (BagBeltMod.LogDebug.Value)
			{
				BagBeltMod.Logger.LogInfo((object)$"Bag Belt sync: sent snapshot to client {clientId}. buyIndex={_hostBuyIndex}, knownObjects={KnownBagObjectIds.Count}");
			}
		}

		private static void OnBuyIndexMessageReceived(ulong senderClientId, FastBufferReader reader)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			int num = default(int);
			((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref num, default(ForPrimitives));
			_hostBuyIndex = num;
			BagBeltRegistry.ApplySynchronizedBuyIndex(num);
			VerifyBuyIndexAgainstTerminal("buy-index-message");
			if (BagBeltMod.LogDebug.Value)
			{
				BagBeltMod.Logger.LogDebug((object)$"Bag Belt sync: received host buy index {num}");
			}
		}

		private static void OnBagObjectSpawnMessageReceived(ulong senderClientId, FastBufferReader reader)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			ulong num = default(ulong);
			((FastBufferReader)(ref reader)).ReadValueSafe<ulong>(ref num, default(ForPrimitives));
			KnownBagObjectIds.Add(num);
			TryApplyKnownBagIdentityToObjectId(num);
			if (BagBeltMod.LogDebug.Value)
			{
				BagBeltMod.Logger.LogDebug((object)$"Bag Belt sync: received bag object id {num}");
			}
		}

		private static void SendBuyIndexToAll(int buyIndex)
		{
			//IL_0025: 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_003c: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager singleton = NetworkManager.Singleton;
			if (((singleton != null) ? singleton.CustomMessagingManager : null) == null)
			{
				return;
			}
			FastBufferWriter val = default(FastBufferWriter);
			((FastBufferWriter)(ref val))..ctor(4, (Allocator)2, -1);
			try
			{
				((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref buyIndex, default(ForPrimitives));
				singleton.CustomMessagingManager.SendNamedMessageToAll("BroMode.BagBelt/BuyIndex", val, (NetworkDelivery)2);
			}
			finally
			{
				((IDisposable)(FastBufferWriter)(ref val)).Dispose();
			}
		}

		private static void SendBuyIndexToClient(ulong clientId, int buyIndex)
		{
			//IL_0025: 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_003d: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager singleton = NetworkManager.Singleton;
			if (((singleton != null) ? singleton.CustomMessagingManager : null) == null)
			{
				return;
			}
			FastBufferWriter val = default(FastBufferWriter);
			((FastBufferWriter)(ref val))..ctor(4, (Allocator)2, -1);
			try
			{
				((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref buyIndex, default(ForPrimitives));
				singleton.CustomMessagingManager.SendNamedMessage("BroMode.BagBelt/BuyIndex", clientId, val, (NetworkDelivery)2);
			}
			finally
			{
				((IDisposable)(FastBufferWriter)(ref val)).Dispose();
			}
		}

		private static void SendObjectSpawnToAll(ulong networkObjectId)
		{
			//IL_0025: 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_003c: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager singleton = NetworkManager.Singleton;
			if (((singleton != null) ? singleton.CustomMessagingManager : null) == null)
			{
				return;
			}
			FastBufferWriter val = default(FastBufferWriter);
			((FastBufferWriter)(ref val))..ctor(8, (Allocator)2, -1);
			try
			{
				((FastBufferWriter)(ref val)).WriteValueSafe<ulong>(ref networkObjectId, default(ForPrimitives));
				singleton.CustomMessagingManager.SendNamedMessageToAll("BroMode.BagBelt/ObjectSpawn", val, (NetworkDelivery)2);
			}
			finally
			{
				((IDisposable)(FastBufferWriter)(ref val)).Dispose();
			}
		}

		private static void SendObjectSpawnToClient(ulong clientId, ulong networkObjectId)
		{
			//IL_0025: 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_003d: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager singleton = NetworkManager.Singleton;
			if (((singleton != null) ? singleton.CustomMessagingManager : null) == null)
			{
				return;
			}
			FastBufferWriter val = default(FastBufferWriter);
			((FastBufferWriter)(ref val))..ctor(8, (Allocator)2, -1);
			try
			{
				((FastBufferWriter)(ref val)).WriteValueSafe<ulong>(ref networkObjectId, default(ForPrimitives));
				singleton.CustomMessagingManager.SendNamedMessage("BroMode.BagBelt/ObjectSpawn", clientId, val, (NetworkDelivery)2);
			}
			finally
			{
				((IDisposable)(FastBufferWriter)(ref val)).Dispose();
			}
		}

		private static void TryApplyKnownBagIdentityToObjectId(ulong networkObjectId)
		{
			NetworkManager singleton = NetworkManager.Singleton;
			if (((singleton != null) ? singleton.SpawnManager : null) != null && singleton.SpawnManager.SpawnedObjects.TryGetValue(networkObjectId, out var value) && !((Object)(object)value == (Object)null))
			{
				GrabbableObject componentInChildren = ((Component)value).GetComponentInChildren<GrabbableObject>();
				if ((Object)(object)componentInChildren != (Object)null)
				{
					TryApplyKnownBagIdentity(componentInChildren);
				}
			}
		}

		private static void TryApplyKnownBagIdentitiesToSpawnedObjects()
		{
			NetworkManager singleton = NetworkManager.Singleton;
			if (((singleton != null) ? singleton.SpawnManager : null) == null)
			{
				return;
			}
			foreach (KeyValuePair<ulong, NetworkObject> spawnedObject in singleton.SpawnManager.SpawnedObjects)
			{
				if (KnownBagObjectIds.Contains(spawnedObject.Key) && !((Object)(object)spawnedObject.Value == (Object)null))
				{
					GrabbableObject componentInChildren = ((Component)spawnedObject.Value).GetComponentInChildren<GrabbableObject>();
					if ((Object)(object)componentInChildren != (Object)null)
					{
						TryApplyKnownBagIdentity(componentInChildren);
					}
				}
			}
		}

		private static void VerifyBuyIndexAgainstTerminal(string context)
		{
			if (_hostBuyIndex < 0)
			{
				return;
			}
			Terminal val = Object.FindObjectOfType<Terminal>();
			if ((Object)(object)val == (Object)null || val.buyableItemsList == null || val.buyableItemsList.Length == 0)
			{
				return;
			}
			if (_hostBuyIndex >= val.buyableItemsList.Length)
			{
				BagBeltMod.Logger.LogWarning((object)$"Bag Belt sync: host buy index {_hostBuyIndex} out of range ({val.buyableItemsList.Length}) at {context}.");
				return;
			}
			Item val2 = val.buyableItemsList[_hostBuyIndex];
			if ((Object)(object)val2 == (Object)null)
			{
				BagBeltMod.Logger.LogWarning((object)$"Bag Belt sync: null item at host buy index {_hostBuyIndex} at {context}.");
			}
			else if (val2.itemId != 195801089 && !string.Equals(val2.itemName, "Bag Belt", StringComparison.OrdinalIgnoreCase))
			{
				BagBeltMod.Logger.LogWarning((object)$"Bag Belt sync: host buy index {_hostBuyIndex} maps to '{val2.itemName}' (id={val2.itemId}) at {context}. This can cause wrong purchase routing.");
			}
			else if (BagBeltMod.LogDebug.Value)
			{
				BagBeltMod.Logger.LogDebug((object)$"Bag Belt sync: verified host buy index {_hostBuyIndex} -> {val2.itemName} at {context}.");
			}
		}
	}
	[HarmonyPatch(typeof(Terminal))]
	internal static class BagBeltRegistryPatch
	{
		[HarmonyPrefix]
		[HarmonyPatch("Start")]
		private static void TerminalStartPrefix(Terminal __instance)
		{
			if (BagBeltMod.Enabled.Value)
			{
				BagBeltRegistry.EnsureRegistered(__instance);
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch("LoadNewNode")]
		private static void LoadNewNodePrefix(Terminal __instance, TerminalNode node)
		{
			if (!BagBeltMod.Enabled.Value || (Object)(object)node == (Object)null)
			{
				return;
			}
			BagBeltRegistry.UpdateDynamicNodeText(__instance, node);
			if (node.displayText != null && node.displayText.Contains("[buyableItemsList]"))
			{
				BagBeltRegistry.EnsureRegistered(__instance);
				if (BagBeltMod.LogDebug.Value)
				{
					BagBeltRegistry.LogBuyableItems(__instance);
				}
			}
		}
	}
	internal static class BagBeltRegistry
	{
		internal const int BagBeltItemId = 195801089;

		internal const string BagBeltName = "Bag Belt";

		internal static Item? VanillaBeltBagItem;

		internal static Item? BagBeltItem;

		internal static TerminalNode? BagBeltConfirmNode;

		internal static TerminalNode? BagBeltOrderedNode;

		internal static int BagBeltBuyIndex = -1;

		internal static bool Registered;

		internal static bool IsBagBelt(GrabbableObject? item)
		{
			if ((Object)(object)item == (Object)null || (Object)(object)item.itemProperties == (Object)null)
			{
				return false;
			}
			if ((Object)(object)BagBeltItem != (Object)null && (Object)(object)item.itemProperties == (Object)(object)BagBeltItem)
			{
				return true;
			}
			if (item.itemProperties.itemId == 195801089)
			{
				return true;
			}
			return BagBeltNetworkSync.IsKnownBagObject(item);
		}

		internal static bool IsVanillaBeltBag(GrabbableObject? item)
		{
			if ((Object)(object)item != (Object)null && (Object)(object)VanillaBeltBagItem != (Object)null)
			{
				return (Object)(object)item.itemProperties == (Object)(object)VanillaBeltBagItem;
			}
			return false;
		}

		internal static void EnsureRegistered(Terminal terminal)
		{
			if (Registered)
			{
				EnsureSalesArray(terminal);
				return;
			}
			if ((Object)(object)StartOfRound.Instance == (Object)null || (Object)(object)StartOfRound.Instance.allItemsList == (Object)null)
			{
				BagBeltMod.Logger.LogWarning((object)"Bag Belt: StartOfRound or allItemsList not ready.");
				return;
			}
			VanillaBeltBagItem = FindVanillaBeltBagItem(StartOfRound.Instance.allItemsList.itemsList);
			if ((Object)(object)VanillaBeltBagItem == (Object)null || (Object)(object)VanillaBeltBagItem.spawnPrefab == (Object)null)
			{
				BagBeltMod.Logger.LogError((object)"Bag Belt: failed to locate vanilla belt bag item/prefab.");
				return;
			}
			VanillaBeltBagItem.weight = 1f;
			BagBeltItem = Object.Instantiate<Item>(VanillaBeltBagItem);
			BagBeltItem.itemName = "Bag Belt";
			BagBeltItem.creditsWorth = BagBeltMod.Price.Value;
			BagBeltItem.weight = 1f;
			BagBeltItem.itemId = 195801089;
			AddToBuyableItems(terminal, BagBeltItem);
			EnsureTerminalKeyword(terminal, BagBeltItem);
			EnsureSalesArray(terminal);
			Registered = true;
			BagBeltNetworkSync.OnRegistryReady();
			BagBeltMod.Logger.LogInfo((object)"Bag Belt registered in terminal store.");
		}

		internal static void UpdateDynamicNodeText(Terminal terminal, TerminalNode node)
		{
			if (!((Object)(object)BagBeltItem == (Object)null) && !((Object)(object)node != (Object)(object)BagBeltConfirmNode))
			{
				int num = Math.Max(0, BagBeltItem.creditsWorth);
				int num2 = Math.Max(0, terminal.groupCredits - num);
				node.displayText = "You have requested to order " + BagBeltItem.itemName + ".\n" + $"Your new balance would be ${num2}.\n\n" + "Please CONFIRM or DENY.";
			}
		}

		internal static void ApplySynchronizedBuyIndex(int synchronizedBuyIndex)
		{
			if (synchronizedBuyIndex >= 0)
			{
				BagBeltBuyIndex = synchronizedBuyIndex;
				if ((Object)(object)BagBeltConfirmNode != (Object)null)
				{
					BagBeltConfirmNode.buyItemIndex = synchronizedBuyIndex;
				}
				if ((Object)(object)BagBeltOrderedNode != (Object)null)
				{
					BagBeltOrderedNode.buyItemIndex = synchronizedBuyIndex;
				}
			}
		}

		internal static void LogBuyableItems(Terminal terminal)
		{
			Item[] array = terminal.buyableItemsList ?? Array.Empty<Item>();
			BagBeltMod.Logger.LogDebug((object)$"Buyable items count: {array.Length}");
			for (int i = 0; i < array.Length; i++)
			{
				if ((Object)(object)array[i] != (Object)null)
				{
					BagBeltMod.Logger.LogDebug((object)$"[{i}] {array[i].itemName} (${array[i].creditsWorth})");
				}
			}
		}

		private static Item? FindVanillaBeltBagItem(List<Item> items)
		{
			for (int i = 0; i < items.Count; i++)
			{
				Item val = items[i];
				if (!((Object)(object)val == (Object)null) && !((Object)(object)val.spawnPrefab == (Object)null))
				{
					if (val.itemName != null && val.itemName.IndexOf("belt bag", StringComparison.OrdinalIgnoreCase) >= 0)
					{
						return val;
					}
					if ((Object)(object)val.spawnPrefab.GetComponentInChildren<BeltBagItem>() != (Object)null)
					{
						return val;
					}
				}
			}
			return null;
		}

		private static void AddToBuyableItems(Terminal terminal, Item newItem)
		{
			Item[] array = terminal.buyableItemsList ?? Array.Empty<Item>();
			for (int i = 0; i < array.Length; i++)
			{
				if ((Object)(object)array[i] == (Object)(object)newItem || ((Object)(object)array[i] != (Object)null && array[i].itemName == newItem.itemName))
				{
					return;
				}
			}
			Item[] array2 = (Item[])(object)new Item[array.Length + 1];
			Array.Copy(array, array2, array.Length);
			array2[^1] = newItem;
			terminal.buyableItemsList = array2;
		}

		private static void EnsureSalesArray(Terminal terminal)
		{
			Item[] buyableItemsList = terminal.buyableItemsList;
			int num = ((buyableItemsList != null) ? buyableItemsList.Length : 0);
			BuyableVehicle[] buyableVehicles = terminal.buyableVehicles;
			int num2 = num + ((buyableVehicles != null) ? buyableVehicles.Length : 0);
			if (num2 > 0 && (terminal.itemSalesPercentages == null || terminal.itemSalesPercentages.Length != num2))
			{
				int[] array = new int[num2];
				for (int i = 0; i < array.Length; i++)
				{
					array[i] = 100;
				}
				terminal.itemSalesPercentages = array;
			}
		}

		private static void EnsureTerminalKeyword(Terminal terminal, Item newItem)
		{
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Expected O, but got Unknown
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Expected O, but got Unknown
			TerminalNodesList terminalNodes = terminal.terminalNodes;
			if ((Object)(object)terminalNodes == (Object)null || terminalNodes.allKeywords == null)
			{
				BagBeltMod.Logger.LogWarning((object)"Bag Belt: terminalNodes not available.");
				return;
			}
			TerminalKeyword val = FindKeyword(terminalNodes, "buy", mustBeVerb: true);
			if ((Object)(object)val == (Object)null)
			{
				BagBeltMod.Logger.LogWarning((object)"Bag Belt: could not find 'buy' terminal keyword.");
				return;
			}
			int num = FindBuyIndex(terminal, newItem);
			if (num < 0)
			{
				BagBeltMod.Logger.LogWarning((object)"Bag Belt: could not find buy index.");
				return;
			}
			BagBeltBuyIndex = num;
			if ((Object)(object)NetworkManager.Singleton != (Object)null && NetworkManager.Singleton.IsServer)
			{
				BagBeltNetworkSync.PublishHostBuyIndex(num);
			}
			int num2 = BagBeltNetworkSync.EffectiveBuyIndex(num);
			TerminalKeyword val2 = FindKeyword(terminalNodes, "confirm", mustBeVerb: false);
			TerminalKeyword val3 = FindKeyword(terminalNodes, "deny", mustBeVerb: false);
			if ((Object)(object)val2 == (Object)null || (Object)(object)val3 == (Object)null)
			{
				BagBeltMod.Logger.LogWarning((object)"Bag Belt: missing confirm/deny keywords.");
				return;
			}
			TerminalNode val4 = (BagBeltOrderedNode = CreateTerminalNode("Ordered " + newItem.itemName + ".", num2, newItem.creditsWorth, isConfirmation: false));
			TerminalNode result = CreateTerminalNode("Cancelled order.", -1, 0, isConfirmation: false);
			TerminalNode val5 = CreateTerminalNode("You have requested to order " + newItem.itemName + ".\nYour new balance would be [playerCredits].\n\nPlease CONFIRM or DENY.", num2, newItem.creditsWorth, isConfirmation: true);
			val5.overrideOptions = true;
			val5.terminalOptions = (CompatibleNoun[])(object)new CompatibleNoun[2]
			{
				new CompatibleNoun
				{
					noun = val2,
					result = val4
				},
				new CompatibleNoun
				{
					noun = val3,
					result = result
				}
			};
			BagBeltConfirmNode = val5;
			CopyVanillaBuyAudioCue(val, val4);
			BagBeltMod.Logger.LogInfo((object)$"Bag Belt terminal node set. buyItemIndex={num2}, price={newItem.creditsWorth}");
			AddOrOverrideKeyword(terminalNodes, val, "bagbelt", val5);
			AddOrOverrideKeyword(terminalNodes, val, "beltbag", val5);
			AddOrOverrideKeyword(terminalNodes, val, "bag", val5);
		}

		private static TerminalKeyword? FindKeyword(TerminalNodesList nodes, string word, bool mustBeVerb)
		{
			TerminalKeyword[] array = nodes.allKeywords ?? Array.Empty<TerminalKeyword>();
			for (int i = 0; i < array.Length; i++)
			{
				if (!((Object)(object)array[i] == (Object)null) && string.Equals(array[i].word, word, StringComparison.OrdinalIgnoreCase) && (!mustBeVerb || array[i].isVerb))
				{
					return array[i];
				}
			}
			return null;
		}

		private static TerminalNode CreateTerminalNode(string text, int buyIndex, int itemCost, bool isConfirmation)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: 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_0021: 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_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: 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_0044: 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)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Expected O, but got Unknown
			return new TerminalNode
			{
				displayText = text,
				buyItemIndex = buyIndex,
				itemCost = itemCost,
				isConfirmationNode = isConfirmation,
				buyVehicleIndex = -1,
				buyRerouteToMoon = -1,
				shipUnlockableID = -1,
				buyUnlockable = false,
				returnFromStorage = false,
				acceptAnything = false,
				overrideOptions = false,
				terminalOptions = Array.Empty<CompatibleNoun>()
			};
		}

		private static void CopyVanillaBuyAudioCue(TerminalKeyword buyKeyword, TerminalNode orderedNode)
		{
			if (buyKeyword.compatibleNouns == null)
			{
				return;
			}
			for (int i = 0; i < buyKeyword.compatibleNouns.Length; i++)
			{
				TerminalNode val = buyKeyword.compatibleNouns[i]?.result;
				if (!((Object)(object)val == (Object)null))
				{
					TerminalNode val2 = FindBuySuccessNode(val, new HashSet<TerminalNode>());
					if (!((Object)(object)val2 == (Object)null))
					{
						orderedNode.playSyncedClip = val2.playSyncedClip;
						orderedNode.playClip = val2.playClip;
						break;
					}
				}
			}
		}

		private static TerminalNode? FindBuySuccessNode(TerminalNode node, HashSet<TerminalNode> visited)
		{
			if (!visited.Add(node))
			{
				return null;
			}
			if (node.buyItemIndex >= 0 && !node.isConfirmationNode && !string.IsNullOrEmpty(node.displayText) && node.displayText.IndexOf("ordered", StringComparison.OrdinalIgnoreCase) >= 0 && ((Object)(object)node.playClip != (Object)null || node.playSyncedClip >= 0))
			{
				return node;
			}
			CompatibleNoun[] array = node.terminalOptions ?? Array.Empty<CompatibleNoun>();
			for (int i = 0; i < array.Length; i++)
			{
				if (!((Object)(object)array[i]?.result == (Object)null))
				{
					TerminalNode val = FindBuySuccessNode(array[i].result, visited);
					if ((Object)(object)val != (Object)null)
					{
						return val;
					}
				}
			}
			return null;
		}

		private static int FindBuyIndex(Terminal terminal, Item newItem)
		{
			Item[] array = terminal.buyableItemsList ?? Array.Empty<Item>();
			for (int i = 0; i < array.Length; i++)
			{
				if ((Object)(object)array[i] == (Object)(object)newItem)
				{
					return i;
				}
			}
			return -1;
		}

		private static void AddOrOverrideKeyword(TerminalNodesList nodes, TerminalKeyword buyKeyword, string word, TerminalNode resultNode)
		{
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Expected O, but got Unknown
			//IL_0041: 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_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Expected O, but got Unknown
			for (int i = 0; i < nodes.allKeywords.Length; i++)
			{
				if (!((Object)(object)nodes.allKeywords[i] != (Object)null) || !string.Equals(nodes.allKeywords[i].word, word, StringComparison.OrdinalIgnoreCase))
				{
					continue;
				}
				TerminalKeyword val = nodes.allKeywords[i];
				CompatibleNoun val2 = new CompatibleNoun
				{
					noun = val,
					result = resultNode
				};
				CompatibleNoun[] array = buyKeyword.compatibleNouns ?? Array.Empty<CompatibleNoun>();
				for (int j = 0; j < array.Length; j++)
				{
					if (array[j] != null && (Object)(object)array[j].noun == (Object)(object)val)
					{
						array[j].result = resultNode;
						return;
					}
				}
				CompatibleNoun[] array2 = (CompatibleNoun[])(object)new CompatibleNoun[array.Length + 1];
				Array.Copy(array, array2, array.Length);
				array2[^1] = val2;
				buyKeyword.compatibleNouns = array2;
				return;
			}
			TerminalKeyword val3 = ScriptableObject.CreateInstance<TerminalKeyword>();
			val3.word = word;
			val3.isVerb = false;
			val3.compatibleNouns = Array.Empty<CompatibleNoun>();
			val3.defaultVerb = buyKeyword;
			val3.accessTerminalObjects = false;
			CompatibleNoun val4 = new CompatibleNoun
			{
				noun = val3,
				result = resultNode
			};
			CompatibleNoun[] array3 = buyKeyword.compatibleNouns ?? Array.Empty<CompatibleNoun>();
			CompatibleNoun[] array4 = (CompatibleNoun[])(object)new CompatibleNoun[array3.Length + 1];
			Array.Copy(array3, array4, array3.Length);
			array4[^1] = val4;
			buyKeyword.compatibleNouns = array4;
			TerminalKeyword[] array5 = nodes.allKeywords ?? Array.Empty<TerminalKeyword>();
			TerminalKeyword[] array6 = (TerminalKeyword[])(object)new TerminalKeyword[array5.Length + 1];
			Array.Copy(array5, array6, array5.Length);
			array6[^1] = val3;
			nodes.allKeywords = array6;
		}
	}
}