Decompiled source of TryConnect v0.1.2

plugins/TryConnect.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using Extensions;
using HarmonyLib;
using Mirror;
using MoreMountains.Feedbacks;
using MoreMountains.Tools;
using TryConnect.Utils;
using UnityEngine;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("TryConnect")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("TryConnect")]
[assembly: AssemblyCopyright("Copyright ©  2023")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("763c314a-61d3-4716-bc7f-118e5a9364ce")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace TryConnect
{
	[DisallowMultipleComponent]
	public sealed class TryConnectInteractableProxy : MonoBehaviour, IInteractable
	{
		[SerializeField]
		private MonoBehaviour _targetBehaviour;

		private IInteractable Target
		{
			get
			{
				if ((Object)(object)_targetBehaviour == (Object)null || !(_targetBehaviour is IInteractable))
				{
					_targetBehaviour = ResolveTargetBehaviour();
				}
				MonoBehaviour targetBehaviour = _targetBehaviour;
				return (IInteractable)(object)((targetBehaviour is IInteractable) ? targetBehaviour : null);
			}
		}

		public float HoldDuration
		{
			get
			{
				return (Target != null) ? Target.HoldDuration : 0f;
			}
			set
			{
				IInteractable target = Target;
				if (target != null)
				{
					target.HoldDuration = value;
				}
			}
		}

		public bool HoldInteract
		{
			get
			{
				return Target != null && Target.HoldInteract;
			}
			set
			{
				IInteractable target = Target;
				if (target != null)
				{
					target.HoldInteract = value;
				}
			}
		}

		public bool IsInteractable
		{
			get
			{
				return Target != null && Target.IsInteractable;
			}
			set
			{
				IInteractable target = Target;
				if (target != null)
				{
					target.IsInteractable = value;
				}
			}
		}

		public bool MeetRequirements
		{
			get
			{
				return Target != null && Target.MeetRequirements;
			}
			set
			{
				IInteractable target = Target;
				if (target != null)
				{
					target.MeetRequirements = value;
				}
			}
		}

		public bool IsBeingHovered
		{
			get
			{
				return Target != null && Target.IsBeingHovered;
			}
			set
			{
				IInteractable target = Target;
				if (target != null)
				{
					target.IsBeingHovered = value;
				}
			}
		}

		public bool IsBeingHold
		{
			get
			{
				return Target != null && Target.IsBeingHold;
			}
			set
			{
				IInteractable target = Target;
				if (target != null)
				{
					target.IsBeingHold = value;
				}
			}
		}

		public float HoldProgress
		{
			get
			{
				return (Target != null) ? Target.HoldProgress : 0f;
			}
			set
			{
				IInteractable target = Target;
				if (target != null)
				{
					target.HoldProgress = value;
				}
			}
		}

		public string TooltipMessage
		{
			get
			{
				return (Target != null) ? Target.TooltipMessage : string.Empty;
			}
			set
			{
				IInteractable target = Target;
				if (target != null)
				{
					target.TooltipMessage = value;
				}
			}
		}

		public string InteractableName
		{
			get
			{
				return (Target != null) ? Target.InteractableName : string.Empty;
			}
			set
			{
				IInteractable target = Target;
				if (target != null)
				{
					target.InteractableName = value;
				}
			}
		}

		public CursorType CursorType
		{
			get
			{
				//IL_0012: Unknown result type (might be due to invalid IL or missing references)
				//IL_0017: 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)
				return (CursorType)((Target != null) ? ((int)Target.CursorType) : 0);
			}
			set
			{
				//IL_0012: Unknown result type (might be due to invalid IL or missing references)
				IInteractable target = Target;
				if (target != null)
				{
					target.CursorType = value;
				}
			}
		}

		public event Action<IInteractable> OnInteractableChanged
		{
			add
			{
				IInteractable target = Target;
				if (target != null)
				{
					target.OnInteractableChanged += value;
				}
			}
			remove
			{
				IInteractable target = Target;
				if (target != null)
				{
					target.OnInteractableChanged -= value;
				}
			}
		}

		internal void Bind(MonoBehaviour targetBehaviour)
		{
			_targetBehaviour = targetBehaviour;
		}

		public void OnHover(PlayerInteract playerInteract)
		{
			IInteractable target = Target;
			if (target != null)
			{
				target.OnHover(playerInteract);
			}
		}

		public void ServerOnHover(PlayerInteract playerInteract)
		{
			IInteractable target = Target;
			if (target != null)
			{
				target.ServerOnHover(playerInteract);
			}
		}

		public void OnHoverExit(PlayerInteract playerInteract)
		{
			IInteractable target = Target;
			if (target != null)
			{
				target.OnHoverExit(playerInteract);
			}
		}

		public void ServerOnHoverExit(PlayerInteract playerInteract)
		{
			IInteractable target = Target;
			if (target != null)
			{
				target.ServerOnHoverExit(playerInteract);
			}
		}

		public void OnHold(PlayerInteract playerInteract)
		{
			IInteractable target = Target;
			if (target != null)
			{
				target.OnHold(playerInteract);
			}
		}

		public void ServerOnHold(PlayerInteract playerInteract)
		{
			IInteractable target = Target;
			if (target != null)
			{
				target.ServerOnHold(playerInteract);
			}
		}

		public void OnHoldExit(PlayerInteract playerInteract)
		{
			IInteractable target = Target;
			if (target != null)
			{
				target.OnHoldExit(playerInteract);
			}
		}

		public void ServerOnHoldExit(PlayerInteract playerInteract)
		{
			IInteractable target = Target;
			if (target != null)
			{
				target.ServerOnHoldExit(playerInteract);
			}
		}

		public void OnInteract(PlayerInteract playerInteract)
		{
			IInteractable target = Target;
			if (target != null)
			{
				target.OnInteract(playerInteract);
			}
		}

		public void ServerOnInteract(PlayerInteract playerInteract)
		{
			IInteractable target = Target;
			if (target != null)
			{
				target.ServerOnInteract(playerInteract);
			}
		}

		public void RpcOnInteract(PlayerInteract playerInteract)
		{
			IInteractable target = Target;
			if (target != null)
			{
				target.RpcOnInteract(playerInteract);
			}
		}

		private MonoBehaviour ResolveTargetBehaviour()
		{
			Transform parent = ((Component)this).transform.parent;
			while ((Object)(object)parent != (Object)null)
			{
				MonoBehaviour[] components = ((Component)parent).GetComponents<MonoBehaviour>();
				foreach (MonoBehaviour val in components)
				{
					if ((Object)(object)val != (Object)null && val is IInteractable)
					{
						return val;
					}
				}
				parent = parent.parent;
			}
			return null;
		}
	}
	internal static class RuntimeItemRegistry
	{
		private sealed class CustomItemDefinition
		{
			internal string OwnerGuid;

			internal string Key;

			internal uint AssetId;

			internal GameObject BasePrefab;

			internal GameObject SpawnPrefab;

			internal int BasePrice;

			internal string Description;

			internal string DisplayName;

			internal GameObject MarkerPrefab;

			internal bool ApplyTint;

			internal Vector3 ModelScaleMultiplier;

			internal int PriceIncreasePerFloor;

			internal int ReplacementChancePercent;

			internal SpawnableSO Spawnable;

			internal Color Tint;
		}

		private sealed class CustomItemRequest
		{
			internal string OwnerGuid;

			internal string Key;

			internal int SpawnableId;

			internal uint AssetId;

			internal string DisplayName;

			internal string Description;

			internal SpawnableSO BaseSpawnable;

			internal int BaseSpawnableId;

			internal Type BaseItemComponentType;

			internal GameObject CustomPrefab;

			internal GameObject MarkerPrefab;

			internal bool ApplyTint;

			internal Color Tint;

			internal Vector3 ModelScaleMultiplier;

			internal int ReplacementChancePercent;

			internal int ExtraBasePrice;

			internal int ExtraFloorPrice;

			internal bool HasLoggedBuildFailure;
		}

		private const int TicketFizzSpawnableId = 900001;

		private const int LoadedChipSpawnableId = 900002;

		private static readonly Dictionary<int, CustomItemRequest> RequestsBySpawnableId = new Dictionary<int, CustomItemRequest>();

		private static readonly Dictionary<string, CustomItemRequest> RequestsByUniqueKey = new Dictionary<string, CustomItemRequest>(StringComparer.OrdinalIgnoreCase);

		private static readonly Dictionary<uint, CustomItemRequest> RequestsByAssetId = new Dictionary<uint, CustomItemRequest>();

		private static readonly Dictionary<int, CustomItemDefinition> DefinitionsBySpawnableId = new Dictionary<int, CustomItemDefinition>();

		private static readonly Dictionary<uint, CustomItemDefinition> DefinitionsByAssetId = new Dictionary<uint, CustomItemDefinition>();

		private static readonly Dictionary<GameObject, CustomItemDefinition> DefinitionsByMarkerPrefab = new Dictionary<GameObject, CustomItemDefinition>();

		private static readonly Dictionary<GameObject, List<CustomItemDefinition>> DefinitionsByBasePrefab = new Dictionary<GameObject, List<CustomItemDefinition>>();

		private static readonly MethodInfo SetParentHierarchyAfterDelayMethod = AccessTools.Method(typeof(ItemStamp), "SetParentHierarchyAfterDelay", (Type[])null, (Type[])null);

		private static readonly FieldInfo AssetIdField = AccessTools.Field(typeof(NetworkIdentity), "_assetId");

		private static readonly FieldInfo SpawnHandlersField = AccessTools.Field(typeof(NetworkClient), "spawnHandlers");

		private static TryConnectPlugin _plugin;

		private static bool _builtInRegistrationsAdded;

		internal static void Initialize(TryConnectPlugin plugin)
		{
			_plugin = plugin;
			EnsureBuiltInRegistrations();
		}

		internal static void Dispose()
		{
			foreach (CustomItemDefinition value in DefinitionsBySpawnableId.Values)
			{
				NetworkClient.UnregisterSpawnHandler(value.AssetId);
				if ((Object)(object)value.MarkerPrefab != (Object)null)
				{
					Object.Destroy((Object)(object)value.MarkerPrefab);
				}
				if ((Object)(object)value.Spawnable != (Object)null)
				{
					Object.Destroy((Object)(object)value.Spawnable);
				}
			}
			RequestsBySpawnableId.Clear();
			RequestsByUniqueKey.Clear();
			RequestsByAssetId.Clear();
			DefinitionsBySpawnableId.Clear();
			DefinitionsByAssetId.Clear();
			DefinitionsByMarkerPrefab.Clear();
			DefinitionsByBasePrefab.Clear();
			_builtInRegistrationsAdded = false;
			_plugin = null;
		}

		internal static TryConnectRegistrationResult RegisterCustomItem(TryConnectItemRegistration registration)
		{
			EnsureBuiltInRegistrations();
			if (!TryNormalizeRegistration(registration))
			{
				return TryConnectRegistrationResult.InvalidRegistration;
			}
			string key = BuildUniqueKey(registration.OwnerGuid, registration.Key);
			if (RequestsByUniqueKey.ContainsKey(key) || RequestsBySpawnableId.ContainsKey(registration.SpawnableId))
			{
				return TryConnectRegistrationResult.AlreadyRegistered;
			}
			AddRequest(CreateRequest(registration));
			TryRegisterRuntimeContent();
			return TryConnectRegistrationResult.Accepted;
		}

		internal static void TryRegisterRuntimeContent()
		{
			EnsureBuiltInRegistrations();
			if ((Object)(object)_plugin == (Object)null)
			{
				return;
			}
			SpawnableSettings val = Resources.Load<SpawnableSettings>("SpawnableSettings");
			if ((Object)(object)val == (Object)null || !val.isEnabled)
			{
				return;
			}
			ItemPriceSettings priceSettings = Resources.Load<ItemPriceSettings>("ItemPriceSettings");
			bool flag = false;
			foreach (CustomItemRequest value in RequestsBySpawnableId.Values)
			{
				flag |= EnsureDefinition(val, priceSettings, value);
			}
			TryEnsureAllClientRegistrations();
			if (flag)
			{
				val.NotifyChanged();
				TryConnectPlugin.Log.LogInfo((object)$"Registered {DefinitionsBySpawnableId.Count} runtime custom item(s).");
			}
		}

		internal static void TryEnsureAllClientRegistrations()
		{
			foreach (CustomItemDefinition value in DefinitionsBySpawnableId.Values)
			{
				EnsureClientSpawnHandler(value);
			}
		}

		internal static void TryEnsureClientRegistration(uint assetId)
		{
			if (!DefinitionsByAssetId.TryGetValue(assetId, out var value))
			{
				value = TryBuildDefinitionForAssetId(assetId);
			}
			if (value != null)
			{
				EnsureClientSpawnHandler(value);
			}
		}

		internal static SpawnableSO GetCustomSpawnable(int id)
		{
			if (!DefinitionsBySpawnableId.TryGetValue(id, out var value))
			{
				value = TryBuildDefinitionForSpawnableId(id);
			}
			return value?.Spawnable;
		}

		internal static bool TryGetRegisteredItemInfo(int spawnableId, out TryConnectRegisteredItemInfo itemInfo)
		{
			itemInfo = null;
			if (!RequestsBySpawnableId.TryGetValue(spawnableId, out var value))
			{
				return false;
			}
			CustomItemDefinition value2;
			bool flag = DefinitionsBySpawnableId.TryGetValue(spawnableId, out value2);
			itemInfo = new TryConnectRegisteredItemInfo(value.OwnerGuid, value.Key, value.SpawnableId, value.AssetId, value.DisplayName, value.Description, flag ? value2.Spawnable : null, flag);
			return true;
		}

		internal static TryConnectRegisteredItemInfo[] GetRegisteredItemInfos()
		{
			List<TryConnectRegisteredItemInfo> list = new List<TryConnectRegisteredItemInfo>(RequestsBySpawnableId.Count);
			foreach (CustomItemRequest value2 in RequestsBySpawnableId.Values)
			{
				CustomItemDefinition value;
				bool flag = DefinitionsBySpawnableId.TryGetValue(value2.SpawnableId, out value);
				list.Add(new TryConnectRegisteredItemInfo(value2.OwnerGuid, value2.Key, value2.SpawnableId, value2.AssetId, value2.DisplayName, value2.Description, flag ? value.Spawnable : null, flag));
			}
			list.Sort((TryConnectRegisteredItemInfo left, TryConnectRegisteredItemInfo right) => left.SpawnableId.CompareTo(right.SpawnableId));
			return list.ToArray();
		}

		internal static bool TryGetVanillaSpawnable(int spawnableId, out SpawnableSO spawnable)
		{
			spawnable = null;
			SpawnableSettings val = Resources.Load<SpawnableSettings>("SpawnableSettings");
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			return TryFindSpawnable(val, (SpawnableSO candidate) => (Object)(object)candidate != (Object)null && candidate.spawnableID == spawnableId, out spawnable);
		}

		internal static bool TryFindVanillaSpawnable(string searchTerm, out SpawnableSO spawnable)
		{
			spawnable = null;
			if (string.IsNullOrWhiteSpace(searchTerm))
			{
				return false;
			}
			SpawnableSettings val = Resources.Load<SpawnableSettings>("SpawnableSettings");
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			string trimmed = searchTerm.Trim();
			return TryFindSpawnable(val, delegate(SpawnableSO candidate)
			{
				if ((Object)(object)candidate == (Object)null)
				{
					return false;
				}
				if (string.Equals(candidate.spawnableName, trimmed, StringComparison.OrdinalIgnoreCase))
				{
					return true;
				}
				return string.Equals(((Object)candidate).name, trimmed, StringComparison.OrdinalIgnoreCase) || ((Object)(object)candidate.prefab != (Object)null && string.Equals(((Object)candidate.prefab).name, trimmed, StringComparison.OrdinalIgnoreCase));
			}, out spawnable);
		}

		internal static bool TryGetCustomBasePrice(SpawnableSO spawnableSO, ref int basePrice)
		{
			if (!TryGetDefinition(spawnableSO, out var definition))
			{
				definition = TryBuildDefinitionForSpawnableId(((Object)(object)spawnableSO != (Object)null) ? spawnableSO.spawnableID : 0);
				if (definition == null)
				{
					return false;
				}
			}
			basePrice = definition.BasePrice;
			return true;
		}

		internal static bool TryGetCustomFloorPrice(SpawnableSO spawnableSO, ref int priceIncreasePerFloor)
		{
			if (!TryGetDefinition(spawnableSO, out var definition))
			{
				definition = TryBuildDefinitionForSpawnableId(((Object)(object)spawnableSO != (Object)null) ? spawnableSO.spawnableID : 0);
				if (definition == null)
				{
					return false;
				}
			}
			priceIncreasePerFloor = definition.PriceIncreasePerFloor;
			return true;
		}

		internal static bool TryGetCustomDescription(SpawnableSO spawnableSO, ref string description)
		{
			if (!TryGetDefinition(spawnableSO, out var definition))
			{
				definition = TryBuildDefinitionForSpawnableId(((Object)(object)spawnableSO != (Object)null) ? spawnableSO.spawnableID : 0);
				if (definition == null)
				{
					return false;
				}
			}
			description = definition.Description;
			return true;
		}

		internal static GameObject GetShopReplacement(MMLootTableGameObjectSO lootTable, Vector3 stampPosition, GameObject fallbackPrefab)
		{
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)fallbackPrefab == (Object)null)
			{
				return null;
			}
			if (!DefinitionsByBasePrefab.TryGetValue(fallbackPrefab, out var value) || value.Count == 0)
			{
				return fallbackPrefab;
			}
			int seed = 0;
			if ((Object)(object)NetworkSingleton<SeededRandomManager>.Instance != (Object)null)
			{
				seed = NetworkSingleton<SeededRandomManager>.Instance.CurrentSeed;
			}
			string text = (((Object)(object)lootTable != (Object)null) ? ((Object)lootTable).name : "ItemStamp");
			int deterministicPercent = ModUtils.GetDeterministicPercent(stampPosition, seed, text + "|" + ((Object)fallbackPrefab).name);
			int num = 0;
			for (int i = 0; i < value.Count; i++)
			{
				num += value[i].ReplacementChancePercent;
				if (deterministicPercent < num)
				{
					return value[i].MarkerPrefab;
				}
			}
			return fallbackPrefab;
		}

		internal static bool TrySpawnCustomItemStampPrefab(ItemStamp stamp, GameObject prefab, Vector3 position, Quaternion rotation, Vector3 scale)
		{
			//IL_0012: 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_0014: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)stamp == (Object)null)
			{
				return false;
			}
			return TrySpawnRegisteredPrefab(prefab, position, rotation, scale, stamp);
		}

		internal static bool TrySpawnConsolePrefab(GameObject prefab, Vector3 position)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			return TrySpawnRegisteredPrefab(prefab, position, Quaternion.identity, Vector3.one, null);
		}

		private static bool TrySpawnRegisteredPrefab(GameObject prefab, Vector3 position, Quaternion rotation, Vector3 scale, ItemStamp stamp)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: 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)
			if ((Object)(object)prefab == (Object)null || !DefinitionsByMarkerPrefab.TryGetValue(prefab, out var value))
			{
				return false;
			}
			GameObject val = Object.Instantiate<GameObject>(value.SpawnPrefab, position, rotation);
			ApplyDefinitionToServerInstance(value, val, scale);
			NetworkServer.Spawn(val, value.AssetId, (NetworkConnectionToClient)null);
			TryConnectPlugin.Log.LogInfo((object)$"Spawned custom item '{value.DisplayName}'.");
			if ((Object)(object)stamp != (Object)null && (Object)(object)NetworkSingleton<ItemStampManager>.Instance != (Object)null)
			{
				NetworkSingleton<ItemStampManager>.Instance.RegisterSpawnedInstance(val, stamp);
				StartParentHierarchyCoroutine(stamp, val);
			}
			return true;
		}

		private static void StartParentHierarchyCoroutine(ItemStamp stamp, GameObject spawnedObject)
		{
			if (!(SetParentHierarchyAfterDelayMethod == null) && SetParentHierarchyAfterDelayMethod.Invoke(stamp, new object[1] { spawnedObject }) is IEnumerator enumerator)
			{
				((MonoBehaviour)stamp).StartCoroutine(enumerator);
			}
		}

		private static bool EnsureDefinition(SpawnableSettings spawnableSettings, ItemPriceSettings priceSettings, CustomItemRequest request)
		{
			if (request == null)
			{
				return false;
			}
			if (!DefinitionsBySpawnableId.TryGetValue(request.SpawnableId, out var value))
			{
				value = BuildDefinition(spawnableSettings, priceSettings, request);
				if (value == null)
				{
					return false;
				}
				CacheDefinition(value);
			}
			return EnsureDefinition(spawnableSettings, value);
		}

		private static bool EnsureDefinition(SpawnableSettings spawnableSettings, CustomItemDefinition definition)
		{
			if (definition == null || (Object)(object)definition.Spawnable == (Object)null)
			{
				return false;
			}
			bool flag = false;
			for (int i = 0; i < spawnableSettings.spawnables.Count; i++)
			{
				SpawnableSO val = spawnableSettings.spawnables[i];
				if ((Object)(object)val != (Object)null && val.spawnableID == definition.Spawnable.spawnableID)
				{
					flag = true;
					break;
				}
			}
			if (!flag)
			{
				spawnableSettings.spawnables.Add(definition.Spawnable);
				return true;
			}
			return false;
		}

		private static void EnsureBuiltInRegistrations()
		{
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: 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_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: Unknown result type (might be due to invalid IL or missing references)
			//IL_019b: Unknown result type (might be due to invalid IL or missing references)
			if (!_builtInRegistrationsAdded && !((Object)(object)_plugin == (Object)null) && TryConnectPlugin.EnableCustomItems != null && TryConnectPlugin.EnableCustomItems.Value)
			{
				_builtInRegistrationsAdded = true;
				CustomItemRequest customItemRequest = new CustomItemRequest();
				customItemRequest.OwnerGuid = "com.Try-4646.TryConnect";
				customItemRequest.Key = "ticket_fizz";
				customItemRequest.SpawnableId = 900001;
				customItemRequest.AssetId = ModUtils.GetStableAssetId("com.Try-4646.TryConnect", "ticket_fizz");
				customItemRequest.DisplayName = "Ticket Fizz";
				customItemRequest.Description = "A TryConnect house drink. Behaves like the vanilla Drink, but shows up as injected custom shop loot.";
				customItemRequest.BaseItemComponentType = typeof(Drink);
				customItemRequest.ApplyTint = true;
				customItemRequest.Tint = new Color(0.22f, 0.95f, 0.92f);
				customItemRequest.ModelScaleMultiplier = new Vector3(1.08f, 1.08f, 1.08f);
				customItemRequest.ReplacementChancePercent = ModUtils.ClampPercent(TryConnectPlugin.TicketFizzReplacementChance.Value);
				customItemRequest.ExtraBasePrice = 2;
				customItemRequest.ExtraFloorPrice = 1;
				AddRequest(customItemRequest);
				customItemRequest = new CustomItemRequest();
				customItemRequest.OwnerGuid = "com.Try-4646.TryConnect";
				customItemRequest.Key = "loaded_chip";
				customItemRequest.SpawnableId = 900002;
				customItemRequest.AssetId = ModUtils.GetStableAssetId("com.Try-4646.TryConnect", "loaded_chip");
				customItemRequest.DisplayName = "Loaded Chip";
				customItemRequest.Description = "A counterfeit high-roller token. Behaves like the vanilla Golden Chip when applied to a game.";
				customItemRequest.BaseItemComponentType = typeof(GoldenChip);
				customItemRequest.ApplyTint = true;
				customItemRequest.Tint = new Color(1f, 0.72f, 0.12f);
				customItemRequest.ModelScaleMultiplier = new Vector3(1.12f, 1.12f, 1.12f);
				customItemRequest.ReplacementChancePercent = ModUtils.ClampPercent(TryConnectPlugin.LoadedChipReplacementChance.Value);
				customItemRequest.ExtraBasePrice = 3;
				customItemRequest.ExtraFloorPrice = 1;
				AddRequest(customItemRequest);
			}
		}

		private static void AddRequest(CustomItemRequest request)
		{
			RequestsBySpawnableId.Add(request.SpawnableId, request);
			RequestsByUniqueKey.Add(BuildUniqueKey(request.OwnerGuid, request.Key), request);
			RequestsByAssetId.Add(request.AssetId, request);
		}

		private static CustomItemRequest CreateRequest(TryConnectItemRegistration registration)
		{
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			return new CustomItemRequest
			{
				OwnerGuid = registration.OwnerGuid,
				Key = registration.Key,
				SpawnableId = registration.SpawnableId,
				AssetId = ModUtils.GetStableAssetId(registration.OwnerGuid, registration.Key),
				DisplayName = registration.DisplayName,
				Description = (registration.Description ?? string.Empty),
				BaseSpawnable = registration.BaseSpawnable,
				BaseSpawnableId = registration.BaseSpawnableId,
				BaseItemComponentType = registration.BaseItemComponentType,
				CustomPrefab = registration.CustomPrefab,
				MarkerPrefab = registration.MarkerPrefab,
				ApplyTint = registration.ApplyTint,
				Tint = registration.Tint,
				ModelScaleMultiplier = registration.ModelScaleMultiplier,
				ReplacementChancePercent = ModUtils.ClampPercent(registration.ReplacementChancePercent),
				ExtraBasePrice = registration.ExtraBasePrice,
				ExtraFloorPrice = registration.ExtraFloorPrice
			};
		}

		private static bool TryNormalizeRegistration(TryConnectItemRegistration registration)
		{
			if (registration == null)
			{
				return false;
			}
			if (string.IsNullOrWhiteSpace(registration.OwnerGuid) || string.IsNullOrWhiteSpace(registration.Key) || string.IsNullOrWhiteSpace(registration.DisplayName))
			{
				return false;
			}
			if ((Object)(object)registration.CustomPrefab == (Object)null && (Object)(object)registration.BaseSpawnable == (Object)null && registration.BaseSpawnableId == 0 && registration.BaseItemComponentType == null)
			{
				return false;
			}
			if (registration.BaseItemComponentType != null && !typeof(Component).IsAssignableFrom(registration.BaseItemComponentType))
			{
				return false;
			}
			if ((Object)(object)registration.CustomPrefab != (Object)null && (Object)(object)registration.CustomPrefab.GetComponent<Item>() == (Object)null)
			{
				return false;
			}
			if ((Object)(object)registration.MarkerPrefab != (Object)null && (Object)(object)registration.MarkerPrefab.GetComponent<Item>() == (Object)null)
			{
				return false;
			}
			registration.OwnerGuid = registration.OwnerGuid.Trim();
			registration.Key = registration.Key.Trim();
			registration.DisplayName = registration.DisplayName.Trim();
			registration.Description = registration.Description ?? string.Empty;
			if (registration.SpawnableId == 0)
			{
				registration.SpawnableId = ModUtils.GetStableSpawnableId(registration.OwnerGuid, registration.Key);
			}
			if ((Object)(object)registration.CustomPrefab != (Object)null)
			{
				TryConnectApi.RefreshItemPrefab(registration.CustomPrefab);
			}
			if ((Object)(object)registration.MarkerPrefab != (Object)null)
			{
				TryConnectApi.RefreshItemPrefab(registration.MarkerPrefab);
			}
			return true;
		}

		private static string BuildUniqueKey(string ownerGuid, string key)
		{
			return ownerGuid + ":" + key;
		}

		private static void CacheDefinition(CustomItemDefinition definition)
		{
			DefinitionsBySpawnableId.Add(definition.Spawnable.spawnableID, definition);
			DefinitionsByAssetId.Add(definition.AssetId, definition);
			DefinitionsByMarkerPrefab.Add(definition.MarkerPrefab, definition);
			if ((Object)(object)definition.BasePrefab != (Object)null)
			{
				if (!DefinitionsByBasePrefab.TryGetValue(definition.BasePrefab, out var value))
				{
					value = new List<CustomItemDefinition>();
					DefinitionsByBasePrefab.Add(definition.BasePrefab, value);
				}
				value.Add(definition);
				value.Sort((CustomItemDefinition left, CustomItemDefinition right) => left.Spawnable.spawnableID.CompareTo(right.Spawnable.spawnableID));
			}
		}

		private static CustomItemDefinition TryBuildDefinitionForAssetId(uint assetId)
		{
			if (DefinitionsByAssetId.TryGetValue(assetId, out var value))
			{
				return value;
			}
			if (!RequestsByAssetId.TryGetValue(assetId, out var value2))
			{
				return null;
			}
			return TryBuildDefinition(value2);
		}

		private static CustomItemDefinition TryBuildDefinitionForSpawnableId(int spawnableId)
		{
			if (spawnableId == 0)
			{
				return null;
			}
			if (DefinitionsBySpawnableId.TryGetValue(spawnableId, out var value))
			{
				return value;
			}
			if (!RequestsBySpawnableId.TryGetValue(spawnableId, out var value2))
			{
				return null;
			}
			return TryBuildDefinition(value2);
		}

		private static CustomItemDefinition TryBuildDefinition(CustomItemRequest request)
		{
			SpawnableSettings val = Resources.Load<SpawnableSettings>("SpawnableSettings");
			if ((Object)(object)val == (Object)null || !val.isEnabled)
			{
				return null;
			}
			ItemPriceSettings priceSettings = Resources.Load<ItemPriceSettings>("ItemPriceSettings");
			EnsureDefinition(val, priceSettings, request);
			DefinitionsBySpawnableId.TryGetValue(request.SpawnableId, out var value);
			return value;
		}

		private static CustomItemDefinition BuildDefinition(SpawnableSettings spawnableSettings, ItemPriceSettings priceSettings, CustomItemRequest request)
		{
			//IL_0279: Unknown result type (might be due to invalid IL or missing references)
			//IL_027e: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02aa: Unknown result type (might be due to invalid IL or missing references)
			SpawnableSO val = ResolveBaseSpawnable(spawnableSettings, request);
			GameObject val2 = (((Object)(object)request.CustomPrefab != (Object)null) ? request.CustomPrefab : (((Object)(object)val != (Object)null) ? val.prefab : null));
			if ((Object)(object)val2 == (Object)null)
			{
				LogBuildFailureOnce(request, "Could not resolve a spawn prefab.");
				return null;
			}
			if ((Object)(object)request.CustomPrefab != (Object)null)
			{
				TryConnectApi.PrepareRuntimeNetworkTemplate(val2);
				TryConnectApi.RefreshItemPrefab(val2);
			}
			if ((Object)(object)val2.GetComponent<Item>() == (Object)null)
			{
				LogBuildFailureOnce(request, $"Custom prefab for '{request.DisplayName}' is missing an Item-derived component.");
				return null;
			}
			GameObject val3 = (((Object)(object)request.MarkerPrefab != (Object)null) ? request.MarkerPrefab : val2);
			GameObject val4 = Object.Instantiate<GameObject>(val3);
			((Object)val4).name = request.Key + "_Marker";
			((Object)val4).hideFlags = (HideFlags)61;
			val4.SetActive(false);
			Object.DontDestroyOnLoad((Object)(object)val4);
			TryConnectApi.PrepareRuntimeNetworkTemplate(val4);
			TryConnectApi.RefreshItemPrefab(val4);
			Item component = val4.GetComponent<Item>();
			if ((Object)(object)component == (Object)null)
			{
				Object.Destroy((Object)(object)val4);
				LogBuildFailureOnce(request, $"Marker prefab for '{request.DisplayName}' is missing an Item-derived component.");
				return null;
			}
			SpawnableSO val5 = ScriptableObject.CreateInstance<SpawnableSO>();
			((Object)val5).hideFlags = (HideFlags)61;
			((Object)val5).name = request.Key + "_SpawnableSO";
			val5.spawnableID = request.SpawnableId;
			val5.spawnableName = request.DisplayName;
			val5.spawnableDescription = request.Description;
			val5.prefab = val4;
			component.spawnableSo = val5;
			int basePrice = 4;
			int priceIncreasePerFloor = 1;
			if ((Object)(object)priceSettings != (Object)null && (Object)(object)val != (Object)null)
			{
				basePrice = Math.Max(1, priceSettings.GetBasePrice(val) + request.ExtraBasePrice);
				priceIncreasePerFloor = Math.Max(0, priceSettings.GetPriceIncreasePerFloor(val) + request.ExtraFloorPrice);
			}
			CustomItemDefinition customItemDefinition = new CustomItemDefinition();
			customItemDefinition.OwnerGuid = request.OwnerGuid;
			customItemDefinition.Key = request.Key;
			customItemDefinition.AssetId = request.AssetId;
			customItemDefinition.BasePrefab = (((Object)(object)val != (Object)null) ? val.prefab : null);
			customItemDefinition.SpawnPrefab = val2;
			customItemDefinition.BasePrice = basePrice;
			customItemDefinition.Description = request.Description;
			customItemDefinition.DisplayName = request.DisplayName;
			customItemDefinition.MarkerPrefab = val4;
			customItemDefinition.ApplyTint = request.ApplyTint;
			customItemDefinition.ModelScaleMultiplier = request.ModelScaleMultiplier;
			customItemDefinition.PriceIncreasePerFloor = priceIncreasePerFloor;
			customItemDefinition.ReplacementChancePercent = request.ReplacementChancePercent;
			customItemDefinition.Spawnable = val5;
			customItemDefinition.Tint = request.Tint;
			ApplyDefinitionToMarker(customItemDefinition, val4);
			EnsureClientSpawnHandler(customItemDefinition);
			return customItemDefinition;
		}

		private static void LogBuildFailureOnce(CustomItemRequest request, string message)
		{
			if (request != null && !request.HasLoggedBuildFailure)
			{
				request.HasLoggedBuildFailure = true;
				if (TryConnectPlugin.Log != null)
				{
					TryConnectPlugin.Log.LogWarning((object)$"Custom item '{request.DisplayName}' ({request.OwnerGuid}) could not be registered yet. {message}");
				}
			}
		}

		private static SpawnableSO ResolveBaseSpawnable(SpawnableSettings spawnableSettings, CustomItemRequest request)
		{
			if ((Object)(object)request.BaseSpawnable != (Object)null)
			{
				return request.BaseSpawnable;
			}
			if (request.BaseSpawnableId != 0)
			{
				return FindBaseSpawnableById(spawnableSettings, request.BaseSpawnableId);
			}
			if (request.BaseItemComponentType != null)
			{
				return FindBaseSpawnable(spawnableSettings, request.BaseItemComponentType);
			}
			return null;
		}

		private static bool TryFindSpawnable(SpawnableSettings spawnableSettings, Predicate<SpawnableSO> predicate, out SpawnableSO spawnable)
		{
			spawnable = null;
			if ((Object)(object)spawnableSettings == (Object)null || predicate == null)
			{
				return false;
			}
			for (int i = 0; i < spawnableSettings.spawnables.Count; i++)
			{
				SpawnableSO val = spawnableSettings.spawnables[i];
				if (predicate(val))
				{
					spawnable = val;
					return true;
				}
			}
			return false;
		}

		private static SpawnableSO FindBaseSpawnableById(SpawnableSettings spawnableSettings, int spawnableId)
		{
			SpawnableSO spawnable;
			return TryFindSpawnable(spawnableSettings, (SpawnableSO candidate) => (Object)(object)candidate != (Object)null && candidate.spawnableID == spawnableId, out spawnable) ? spawnable : null;
		}

		private static SpawnableSO FindBaseSpawnable(SpawnableSettings spawnableSettings, Type componentType)
		{
			SpawnableSO spawnable;
			return TryFindSpawnable(spawnableSettings, (SpawnableSO candidate) => (Object)(object)candidate != (Object)null && (Object)(object)candidate.prefab != (Object)null && (Object)(object)candidate.prefab.GetComponent(componentType) != (Object)null, out spawnable) ? spawnable : null;
		}

		private static void ApplyDefinitionToMarker(CustomItemDefinition definition, GameObject markerPrefab)
		{
			if (!((Object)(object)markerPrefab == (Object)null))
			{
				((Object)markerPrefab).name = definition.DisplayName;
				ApplyDefinitionVisuals(definition, markerPrefab.transform);
				Item component = markerPrefab.GetComponent<Item>();
				if ((Object)(object)component != (Object)null)
				{
					component.spawnableSo = definition.Spawnable;
				}
			}
		}

		private static void ApplyDefinitionToServerInstance(CustomItemDefinition definition, GameObject spawnedObject, Vector3 scaleMultiplier)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			ApplyDefinitionToInstance(definition, spawnedObject, Vector3.Scale(spawnedObject.transform.localScale, scaleMultiplier));
		}

		private static void ApplyDefinitionToClientInstance(CustomItemDefinition definition, GameObject spawnedObject, Vector3 scale)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			ApplyDefinitionToInstance(definition, spawnedObject, scale);
		}

		private static void ApplyDefinitionToInstance(CustomItemDefinition definition, GameObject spawnedObject, Vector3 resolvedScale)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			TryConnectApi.PrepareRuntimeNetworkTemplate(spawnedObject);
			TryConnectApi.RefreshItemPrefab(spawnedObject);
			((Object)spawnedObject).name = definition.DisplayName;
			spawnedObject.transform.localScale = resolvedScale;
			spawnedObject.SetActive(true);
			TryConnectApi.RefreshItemPrefab(spawnedObject);
			NetworkIdentity component = spawnedObject.GetComponent<NetworkIdentity>();
			if ((Object)(object)component != (Object)null)
			{
				SetNetworkAssetId(component, definition.AssetId);
			}
			Item component2 = spawnedObject.GetComponent<Item>();
			if ((Object)(object)component2 != (Object)null)
			{
				component2.spawnableSo = definition.Spawnable;
			}
			ApplyDefinitionVisuals(definition, spawnedObject.transform);
		}

		private static void ApplyDefinitionVisuals(CustomItemDefinition definition, Transform root)
		{
			//IL_0036: 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)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			Item component = ((Component)root).GetComponent<Item>();
			Transform val = (((Object)(object)component != (Object)null) ? component.modelTransform : root.Find("Model"));
			if ((Object)(object)val == (Object)null)
			{
				val = root;
			}
			val.localScale = Vector3.Scale(val.localScale, definition.ModelScaleMultiplier);
			if (!definition.ApplyTint)
			{
				return;
			}
			Renderer[] componentsInChildren = ((Component)root).GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val2 in componentsInChildren)
			{
				if ((Object)(object)val2 == (Object)null)
				{
					continue;
				}
				Material[] materials = val2.materials;
				foreach (Material val3 in materials)
				{
					if (ModUtils.TrySetMaterialTint(val3, definition.Tint) && val3.HasProperty("_Metallic"))
					{
						val3.SetFloat("_Metallic", Mathf.Clamp01(val3.GetFloat("_Metallic") + 0.15f));
					}
				}
				val2.materials = materials;
			}
		}

		private static void EnsureClientSpawnHandler(CustomItemDefinition definition)
		{
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Expected O, but got Unknown
			//IL_0071: Expected O, but got Unknown
			if (definition != null)
			{
				IDictionary dictionary = ((SpawnHandlersField != null) ? (SpawnHandlersField.GetValue(null) as IDictionary) : null);
				if (dictionary == null || !dictionary.Contains(definition.AssetId))
				{
					NetworkClient.RegisterSpawnHandler(definition.AssetId, new SpawnHandlerDelegate(SpawnCustomPrefab), new UnSpawnDelegate(UnspawnCustomPrefab));
					TryConnectPlugin.Log.LogInfo((object)$"Registered custom spawn handler for '{definition.DisplayName}' ({definition.AssetId}).");
				}
			}
		}

		private static void SetNetworkAssetId(NetworkIdentity networkIdentity, uint assetId)
		{
			if (AssetIdField != null)
			{
				AssetIdField.SetValue(networkIdentity, assetId);
			}
		}

		private static bool TryGetDefinition(SpawnableSO spawnableSO, out CustomItemDefinition definition)
		{
			definition = null;
			if ((Object)(object)spawnableSO == (Object)null)
			{
				return false;
			}
			return DefinitionsBySpawnableId.TryGetValue(spawnableSO.spawnableID, out definition);
		}

		private static GameObject SpawnCustomPrefab(SpawnMessage message)
		{
			//IL_0006: 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)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			if (!DefinitionsByAssetId.TryGetValue(message.assetId, out var value))
			{
				value = TryBuildDefinitionForAssetId(message.assetId);
				if (value == null)
				{
					return null;
				}
			}
			GameObject val = Object.Instantiate<GameObject>(value.SpawnPrefab, message.position, message.rotation);
			ApplyDefinitionToClientInstance(value, val, message.scale);
			return val;
		}

		private static void UnspawnCustomPrefab(GameObject spawnedObject)
		{
			if ((Object)(object)spawnedObject != (Object)null)
			{
				Object.Destroy((Object)(object)spawnedObject);
			}
		}
	}
	public static class TryConnectApi
	{
		public const int ApiVersion = 4;

		public const string PluginGuid = "com.Try-4646.TryConnect";

		private static readonly FieldInfo SceneIdField = typeof(NetworkIdentity).GetField("sceneId", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

		private static readonly FieldInfo HasSpawnedField = typeof(NetworkIdentity).GetField("hasSpawned", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

		private static readonly FieldInfo DestroyCalledField = typeof(NetworkIdentity).GetField("destroyCalled", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

		private static readonly FieldInfo NetIdField = typeof(NetworkIdentity).GetField("<netId>k__BackingField", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

		private static readonly FieldInfo AssetIdBackingField = typeof(NetworkIdentity).GetField("_assetId", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

		private static readonly FieldInfo IsClientField = typeof(NetworkIdentity).GetField("<isClient>k__BackingField", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

		private static readonly FieldInfo IsServerField = typeof(NetworkIdentity).GetField("<isServer>k__BackingField", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

		private static readonly FieldInfo IsLocalPlayerField = typeof(NetworkIdentity).GetField("<isLocalPlayer>k__BackingField", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

		private static readonly FieldInfo IsOwnedField = typeof(NetworkIdentity).GetField("<isOwned>k__BackingField", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

		private static readonly FieldInfo SpawnedFromInstantiateField = typeof(NetworkIdentity).GetField("<SpawnedFromInstantiate>k__BackingField", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

		private static readonly FieldInfo ConnectionToServerField = typeof(NetworkIdentity).GetField("<connectionToServer>k__BackingField", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

		private static readonly FieldInfo ConnectionToClientField = typeof(NetworkIdentity).GetField("_connectionToClient", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

		private static readonly FieldInfo ItemColliderCacheField = typeof(Item).GetField("_allColliders", BindingFlags.Instance | BindingFlags.NonPublic);

		public static bool IsInitialized => (Object)(object)TryConnectPlugin.Instance != (Object)null;

		public static int GenerateSpawnableId(string ownerGuid, string key)
		{
			ValidateIdentity(ownerGuid, key);
			return ModUtils.GetStableSpawnableId(ownerGuid, key);
		}

		public static TryConnectRegistrationResult RegisterCustomItem(TryConnectItemRegistration registration)
		{
			return RuntimeItemRegistry.RegisterCustomItem(registration);
		}

		public static bool TryGetCustomSpawnable(int spawnableId, out SpawnableSO spawnable)
		{
			spawnable = RuntimeItemRegistry.GetCustomSpawnable(spawnableId);
			return (Object)(object)spawnable != (Object)null;
		}

		public static bool TryGetRegisteredItem(int spawnableId, out TryConnectRegisteredItemInfo itemInfo)
		{
			return RuntimeItemRegistry.TryGetRegisteredItemInfo(spawnableId, out itemInfo);
		}

		public static bool TryGetVanillaSpawnable(int spawnableId, out SpawnableSO spawnable)
		{
			return RuntimeItemRegistry.TryGetVanillaSpawnable(spawnableId, out spawnable);
		}

		public static bool TryFindVanillaSpawnable(string searchTerm, out SpawnableSO spawnable)
		{
			return RuntimeItemRegistry.TryFindVanillaSpawnable(searchTerm, out spawnable);
		}

		public static bool TryFindVanillaSpawnable(Type componentType, out SpawnableSO spawnable)
		{
			spawnable = null;
			if (componentType == null)
			{
				throw new ArgumentNullException("componentType");
			}
			if (!typeof(Component).IsAssignableFrom(componentType))
			{
				throw new ArgumentException("componentType must derive from UnityEngine.Component.", "componentType");
			}
			SpawnableSettings val = Resources.Load<SpawnableSettings>("SpawnableSettings");
			if ((Object)(object)val == (Object)null || val.spawnables == null)
			{
				return false;
			}
			for (int i = 0; i < val.spawnables.Count; i++)
			{
				SpawnableSO val2 = val.spawnables[i];
				if ((Object)(object)val2 != (Object)null && (Object)(object)val2.prefab != (Object)null && (Object)(object)val2.prefab.GetComponent(componentType) != (Object)null)
				{
					spawnable = val2;
					return true;
				}
			}
			return false;
		}

		public static bool TryFindVanillaSpawnable<TComponent>(out SpawnableSO spawnable) where TComponent : Component
		{
			return TryFindVanillaSpawnable(typeof(TComponent), out spawnable);
		}

		public static SpawnableSO FindVanillaSpawnable<TComponent>() where TComponent : Component
		{
			SpawnableSO spawnable;
			return TryFindVanillaSpawnable<TComponent>(out spawnable) ? spawnable : null;
		}

		public static GameObject CreatePrefabTemplate(SpawnableSO baseSpawnable, string templateName = null)
		{
			if ((Object)(object)baseSpawnable == (Object)null || (Object)(object)baseSpawnable.prefab == (Object)null)
			{
				throw new ArgumentException("baseSpawnable and its prefab are required.", "baseSpawnable");
			}
			return CreatePrefabTemplate(baseSpawnable.prefab, templateName);
		}

		public static GameObject CreatePrefabTemplate(GameObject sourcePrefab, string templateName = null)
		{
			if ((Object)(object)sourcePrefab == (Object)null)
			{
				throw new ArgumentNullException("sourcePrefab");
			}
			GameObject val = Object.Instantiate<GameObject>(sourcePrefab);
			((Object)val).name = (string.IsNullOrWhiteSpace(templateName) ? (((Object)sourcePrefab).name + "_TryConnectTemplate") : templateName.Trim());
			((Object)val).hideFlags = (HideFlags)61;
			val.SetActive(false);
			Object.DontDestroyOnLoad((Object)(object)val);
			PrepareRuntimeNetworkTemplate(val);
			return val;
		}

		public static TTarget SwapPrefabComponent<TSource, TTarget>(GameObject prefab) where TSource : Component where TTarget : TSource
		{
			if ((Object)(object)prefab == (Object)null)
			{
				throw new ArgumentNullException("prefab");
			}
			TSource component = prefab.GetComponent<TSource>();
			if ((Object)(object)component == (Object)null)
			{
				throw new InvalidOperationException($"Prefab '{((Object)prefab).name}' is missing component '{typeof(TSource).FullName}'.");
			}
			TTarget val = prefab.AddComponent<TTarget>();
			CopyPrefabComponentState((Component)(object)component, (Component)(object)val);
			object obj = component;
			Behaviour val2 = (Behaviour)((obj is Behaviour) ? obj : null);
			object obj2 = val;
			Behaviour val3 = (Behaviour)((obj2 is Behaviour) ? obj2 : null);
			if ((Object)(object)val2 != (Object)null && (Object)(object)val3 != (Object)null)
			{
				val3.enabled = val2.enabled;
			}
			Object.DestroyImmediate((Object)(object)component);
			return val;
		}

		public static int RemoveNonTriggerColliders(GameObject root)
		{
			if ((Object)(object)root == (Object)null)
			{
				throw new ArgumentNullException("root");
			}
			List<Collider> list = CollectNonTriggerColliders(root);
			for (int i = 0; i < list.Count; i++)
			{
				Object.DestroyImmediate((Object)(object)list[i]);
			}
			RefreshItemPrefab(root);
			return list.Count;
		}

		public static void RefreshItemPrefab(GameObject prefab)
		{
			if ((Object)(object)prefab == (Object)null)
			{
				throw new ArgumentNullException("prefab");
			}
			Item[] componentsInChildren = prefab.GetComponentsInChildren<Item>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				RefreshItemState(componentsInChildren[i]);
			}
		}

		public static Transform GetPrefabVisualRoot(GameObject prefab)
		{
			if ((Object)(object)prefab == (Object)null)
			{
				throw new ArgumentNullException("prefab");
			}
			return ResolveVisualRoot(prefab);
		}

		public static GameObject ReplaceVisualsWithPrimitive(GameObject prefab, PrimitiveType primitiveType, Color color, Vector3 localScale, bool replaceColliders = true)
		{
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)prefab == (Object)null)
			{
				throw new ArgumentNullException("prefab");
			}
			Transform val = ResolveVisualRoot(prefab);
			int layer = ((((Component)val).gameObject.layer != 0) ? ((Component)val).gameObject.layer : prefab.layer);
			SetRenderersEnabled(val, isEnabled: false);
			if (replaceColliders)
			{
				RemoveNonTriggerColliders(prefab);
			}
			GameObject val2 = GameObject.CreatePrimitive(primitiveType);
			((Object)val2).name = ((object)(PrimitiveType)(ref primitiveType)).ToString() + "Visual";
			val2.layer = layer;
			val2.transform.SetParent(val, false);
			val2.transform.localPosition = Vector3.zero;
			val2.transform.localRotation = Quaternion.identity;
			val2.transform.localScale = localScale;
			Renderer component = val2.GetComponent<Renderer>();
			if ((Object)(object)component != (Object)null && (Object)(object)component.sharedMaterial != (Object)null)
			{
				Material val3 = Object.Instantiate<Material>(component.sharedMaterial);
				val3.color = color;
				component.sharedMaterial = val3;
			}
			RefreshItemPrefab(prefab);
			return val2;
		}

		public static GameObject ReplaceVisualsWithPrefab(GameObject prefab, GameObject visualPrefab, Vector3 localScale, bool replaceColliders = true)
		{
			//IL_0003: 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_000a: Unknown result type (might be due to invalid IL or missing references)
			return ReplaceVisualsWithPrefab(prefab, visualPrefab, localScale, replaceColliders, Vector3.zero, Vector3.zero);
		}

		public static GameObject ReplaceVisualsWithPrefab(GameObject prefab, GameObject visualPrefab, Vector3 localScale, bool replaceColliders, Vector3 localPosition, Vector3 localEulerAngles)
		{
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)prefab == (Object)null)
			{
				throw new ArgumentNullException("prefab");
			}
			if ((Object)(object)visualPrefab == (Object)null)
			{
				throw new ArgumentNullException("visualPrefab");
			}
			Transform val = ResolveVisualRoot(prefab);
			int layer = ((((Component)val).gameObject.layer != 0) ? ((Component)val).gameObject.layer : prefab.layer);
			SetRenderersEnabled(val, isEnabled: false);
			if (replaceColliders)
			{
				RemoveNonTriggerColliders(prefab);
			}
			GameObject val2 = Object.Instantiate<GameObject>(visualPrefab);
			((Object)val2).name = (string.IsNullOrWhiteSpace(((Object)visualPrefab).name) ? "CustomVisual" : ((Object)visualPrefab).name);
			RemoveNestedRigidbodies(val2);
			val2.transform.SetParent(val, false);
			val2.transform.localPosition = localPosition;
			val2.transform.localRotation = Quaternion.Euler(localEulerAngles);
			val2.transform.localScale = localScale;
			SetLayerRecursively(val2, layer);
			val2.SetActive(true);
			SetRenderersEnabled(val2.transform, isEnabled: true);
			RefreshItemPrefab(prefab);
			return val2;
		}

		public static TryConnectRegistrationResult RegisterBundledCustomItem<TBaseItem>(BaseUnityPlugin plugin, TryConnectBundledItemRegistration registration) where TBaseItem : Item
		{
			return RegisterBundledCustomItem<TBaseItem, TBaseItem>(plugin, registration);
		}

		public static TryConnectRegistrationResult RegisterBundledCustomItem<TBaseItem, TCustomItem>(BaseUnityPlugin plugin, TryConnectBundledItemRegistration registration) where TBaseItem : Item where TCustomItem : TBaseItem
		{
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0229: Unknown result type (might be due to invalid IL or missing references)
			//IL_0237: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)plugin == (Object)null)
			{
				throw new ArgumentNullException("plugin");
			}
			if (registration == null)
			{
				throw new ArgumentNullException("registration");
			}
			ValidateBundledRegistration(registration);
			SpawnableSO val = ResolveBundledBaseSpawnable<TBaseItem>(registration);
			if ((Object)(object)val == (Object)null)
			{
				throw new InvalidOperationException($"Could not resolve a base spawnable for '{typeof(TBaseItem).FullName}'.");
			}
			GameObject val2 = CreatePrefabTemplate(val, BuildTemplateName(registration.CustomPrefabName, registration.Key, "CustomPrefab"));
			GameObject val3 = CreatePrefabTemplate(val, BuildTemplateName(registration.MarkerPrefabName, registration.Key, "MarkerPrefab"));
			if (typeof(TBaseItem) != typeof(TCustomItem))
			{
				TryConnectApi.SwapPrefabComponent<TBaseItem, TCustomItem>(val2);
			}
			Material fallbackMaterial = (registration.UseBaseMaterialFallback ? CloneFirstMaterial(val2) : null);
			AssetBundle val4 = TryConnectAssetBundles.LoadRelativeToPlugin(plugin, registration.BundlePath);
			try
			{
				GameObject visualPrefab = TryConnectAssetBundles.LoadAsset<GameObject>(val4, registration.VisualPrefabName);
				GameObject root = ReplaceVisualsWithPrefab(val2, visualPrefab, registration.VisualLocalScale, registration.ReplaceColliders, registration.VisualLocalPosition, registration.VisualLocalEulerAngles);
				GameObject root2 = ReplaceVisualsWithPrefab(val3, visualPrefab, registration.VisualLocalScale, registration.ReplaceColliders, registration.VisualLocalPosition, registration.VisualLocalEulerAngles);
				EnsureVisibleMaterials(root, fallbackMaterial, registration.ForceVisualMaterial, registration.ApplyVisualColor, registration.VisualColor);
				EnsureVisibleMaterials(root2, fallbackMaterial, registration.ForceVisualMaterial, registration.ApplyVisualColor, registration.VisualColor);
			}
			finally
			{
				val4.Unload(false);
			}
			TryConnectItemRegistration tryConnectItemRegistration = new TryConnectItemRegistration();
			tryConnectItemRegistration.OwnerGuid = plugin.Info.Metadata.GUID;
			tryConnectItemRegistration.Key = registration.Key;
			tryConnectItemRegistration.SpawnableId = registration.SpawnableId;
			tryConnectItemRegistration.DisplayName = registration.DisplayName;
			tryConnectItemRegistration.Description = registration.Description;
			tryConnectItemRegistration.BaseSpawnable = val;
			tryConnectItemRegistration.BaseSpawnableId = registration.BaseSpawnableId;
			tryConnectItemRegistration.BaseItemComponentType = typeof(TBaseItem);
			tryConnectItemRegistration.CustomPrefab = val2;
			tryConnectItemRegistration.MarkerPrefab = val3;
			tryConnectItemRegistration.ApplyTint = registration.ApplyTint;
			tryConnectItemRegistration.Tint = registration.Tint;
			tryConnectItemRegistration.ModelScaleMultiplier = registration.ModelScaleMultiplier;
			tryConnectItemRegistration.ReplacementChancePercent = registration.ReplacementChancePercent;
			tryConnectItemRegistration.ExtraBasePrice = registration.ExtraBasePrice;
			tryConnectItemRegistration.ExtraFloorPrice = registration.ExtraFloorPrice;
			return RegisterCustomItem(tryConnectItemRegistration);
		}

		public static TryConnectRegisteredItemInfo[] GetRegisteredItems()
		{
			return RuntimeItemRegistry.GetRegisteredItemInfos();
		}

		internal static void PrepareRuntimeNetworkTemplate(GameObject prefab)
		{
			if ((Object)(object)prefab == (Object)null)
			{
				return;
			}
			NetworkIdentity[] componentsInChildren = prefab.GetComponentsInChildren<NetworkIdentity>(true);
			foreach (NetworkIdentity val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null))
				{
					if (SceneIdField != null)
					{
						SceneIdField.SetValue(val, 0uL);
					}
					if (HasSpawnedField != null)
					{
						HasSpawnedField.SetValue(val, false);
					}
					if (DestroyCalledField != null)
					{
						DestroyCalledField.SetValue(val, false);
					}
					if (NetIdField != null)
					{
						NetIdField.SetValue(val, 0u);
					}
					if (AssetIdBackingField != null)
					{
						AssetIdBackingField.SetValue(val, 0u);
					}
					if (IsClientField != null)
					{
						IsClientField.SetValue(val, false);
					}
					if (IsServerField != null)
					{
						IsServerField.SetValue(val, false);
					}
					if (IsLocalPlayerField != null)
					{
						IsLocalPlayerField.SetValue(val, false);
					}
					if (IsOwnedField != null)
					{
						IsOwnedField.SetValue(val, false);
					}
					if (SpawnedFromInstantiateField != null)
					{
						SpawnedFromInstantiateField.SetValue(val, false);
					}
					if (ConnectionToClientField != null)
					{
						ConnectionToClientField.SetValue(val, null);
					}
					if (ConnectionToServerField != null)
					{
						ConnectionToServerField.SetValue(val, null);
					}
				}
			}
		}

		private static void ValidateIdentity(string ownerGuid, string key)
		{
			if (string.IsNullOrWhiteSpace(ownerGuid))
			{
				throw new ArgumentException("ownerGuid is required.", "ownerGuid");
			}
			if (string.IsNullOrWhiteSpace(key))
			{
				throw new ArgumentException("key is required.", "key");
			}
		}

		private static void ValidateBundledRegistration(TryConnectBundledItemRegistration registration)
		{
			if (string.IsNullOrWhiteSpace(registration.Key))
			{
				throw new ArgumentException("registration.Key is required.", "registration");
			}
			if (string.IsNullOrWhiteSpace(registration.DisplayName))
			{
				throw new ArgumentException("registration.DisplayName is required.", "registration");
			}
			if (string.IsNullOrWhiteSpace(registration.BundlePath))
			{
				throw new ArgumentException("registration.BundlePath is required.", "registration");
			}
			if (string.IsNullOrWhiteSpace(registration.VisualPrefabName))
			{
				throw new ArgumentException("registration.VisualPrefabName is required.", "registration");
			}
		}

		private static SpawnableSO ResolveBundledBaseSpawnable<TBaseItem>(TryConnectBundledItemRegistration registration) where TBaseItem : Item
		{
			if ((Object)(object)registration.BaseSpawnable != (Object)null)
			{
				return registration.BaseSpawnable;
			}
			if (registration.BaseSpawnableId != 0 && TryGetVanillaSpawnable(registration.BaseSpawnableId, out var spawnable))
			{
				return spawnable;
			}
			return TryConnectApi.FindVanillaSpawnable<TBaseItem>();
		}

		private static string BuildTemplateName(string explicitName, string key, string suffix)
		{
			if (!string.IsNullOrWhiteSpace(explicitName))
			{
				return explicitName.Trim();
			}
			return key.Trim() + "_" + suffix;
		}

		private static Material CloneFirstMaterial(GameObject root)
		{
			if ((Object)(object)root == (Object)null)
			{
				return null;
			}
			Renderer[] componentsInChildren = root.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val in componentsInChildren)
			{
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				Material[] sharedMaterials = val.sharedMaterials;
				for (int j = 0; j < sharedMaterials.Length; j++)
				{
					if ((Object)(object)sharedMaterials[j] != (Object)null)
					{
						return Object.Instantiate<Material>(sharedMaterials[j]);
					}
				}
			}
			return null;
		}

		private static void EnsureVisibleMaterials(GameObject root, Material fallbackMaterial, bool forceMaterial, bool applyColor, Color color)
		{
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)root == (Object)null)
			{
				return;
			}
			Renderer[] componentsInChildren = root.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val in componentsInChildren)
			{
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				Material[] sharedMaterials = val.sharedMaterials;
				bool flag = sharedMaterials == null || sharedMaterials.Length == 0;
				if (!flag)
				{
					for (int j = 0; j < sharedMaterials.Length; j++)
					{
						if ((Object)(object)sharedMaterials[j] == (Object)null)
						{
							flag = true;
							break;
						}
					}
				}
				if (!forceMaterial && !applyColor && !flag)
				{
					val.enabled = true;
					continue;
				}
				int num = ((sharedMaterials == null || sharedMaterials.Length == 0) ? 1 : sharedMaterials.Length);
				Material[] array = (Material[])(object)new Material[num];
				for (int k = 0; k < num; k++)
				{
					Material sourceMaterial = ((sharedMaterials != null && k < sharedMaterials.Length) ? sharedMaterials[k] : null);
					Material val2 = CreateRendererMaterial(sourceMaterial, fallbackMaterial, forceMaterial);
					if ((Object)(object)val2 != (Object)null && applyColor)
					{
						ModUtils.TrySetMaterialTint(val2, color);
					}
					array[k] = val2;
				}
				val.sharedMaterials = array;
				val.enabled = true;
			}
		}

		private static Material CreateRendererMaterial(Material sourceMaterial, Material fallbackMaterial, bool forceMaterial)
		{
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			Material val = null;
			if (!forceMaterial && (Object)(object)sourceMaterial != (Object)null)
			{
				val = sourceMaterial;
			}
			else if ((Object)(object)fallbackMaterial != (Object)null)
			{
				val = fallbackMaterial;
			}
			else if ((Object)(object)sourceMaterial != (Object)null)
			{
				val = sourceMaterial;
			}
			if ((Object)(object)val != (Object)null)
			{
				return Object.Instantiate<Material>(val);
			}
			Shader val2 = Shader.Find("Standard") ?? Shader.Find("Universal Render Pipeline/Lit");
			return (!((Object)(object)val2 != (Object)null)) ? ((Material)null) : new Material(val2);
		}

		private static Transform ResolveVisualRoot(GameObject prefab)
		{
			Item val = (((Object)(object)prefab != (Object)null) ? prefab.GetComponent<Item>() : null);
			Transform val2 = (((Object)(object)val != (Object)null) ? val.modelTransform : null);
			if ((Object)(object)val2 == (Object)null && (Object)(object)prefab != (Object)null)
			{
				val2 = prefab.transform.Find("Model");
			}
			return val2 ?? (((Object)(object)prefab != (Object)null) ? prefab.transform : null);
		}

		private static void SetRenderersEnabled(Transform root, bool isEnabled)
		{
			if ((Object)(object)root == (Object)null)
			{
				return;
			}
			Renderer[] componentsInChildren = ((Component)root).GetComponentsInChildren<Renderer>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				if ((Object)(object)componentsInChildren[i] != (Object)null)
				{
					componentsInChildren[i].enabled = isEnabled;
				}
			}
		}

		private static void SetLayerRecursively(GameObject root, int layer)
		{
			if ((Object)(object)root == (Object)null)
			{
				return;
			}
			Transform[] componentsInChildren = root.GetComponentsInChildren<Transform>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				if ((Object)(object)componentsInChildren[i] != (Object)null)
				{
					((Component)componentsInChildren[i]).gameObject.layer = layer;
				}
			}
		}

		private static void RemoveNestedRigidbodies(GameObject root)
		{
			if ((Object)(object)root == (Object)null)
			{
				return;
			}
			Rigidbody[] componentsInChildren = root.GetComponentsInChildren<Rigidbody>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				if ((Object)(object)componentsInChildren[i] != (Object)null)
				{
					Object.DestroyImmediate((Object)(object)componentsInChildren[i]);
				}
			}
		}

		private static void RefreshItemState(Item item)
		{
			if (!((Object)(object)item == (Object)null))
			{
				Transform val = item.modelTransform;
				if ((Object)(object)val == (Object)null)
				{
					val = (item.modelTransform = ((Component)item).transform.Find("Model"));
				}
				item.handRig = ResolveHandRig(val);
				item.handMesh = ResolveHandMesh(item.handRig);
				item.onHandFb = ResolveFeedbackPlayer(((Component)item).transform, "OnHand");
				item.onDropFb = ResolveFeedbackPlayer(((Component)item).transform, "OnDrop");
				item.onThrowVfx = ResolveThrowVfx(((Component)item).transform);
				if (ItemColliderCacheField != null)
				{
					ItemColliderCacheField.SetValue(item, CollectNonTriggerColliders(item));
				}
				EnsureInteractableProxies(item);
			}
		}

		private static GameObject ResolveHandRig(Transform modelTransform)
		{
			if ((Object)(object)modelTransform == (Object)null)
			{
				return null;
			}
			Transform val = modelTransform.Find("HandRig");
			return ((Object)(object)val != (Object)null) ? ((Component)val).gameObject : null;
		}

		private static SkinnedMeshRenderer ResolveHandMesh(GameObject handRig)
		{
			if ((Object)(object)handRig == (Object)null)
			{
				return null;
			}
			SkinnedMeshRenderer[] componentsInChildren = handRig.GetComponentsInChildren<SkinnedMeshRenderer>(true);
			return (componentsInChildren.Length != 0) ? componentsInChildren[0] : null;
		}

		private static MMF_Player ResolveFeedbackPlayer(Transform itemTransform, string feedbackName)
		{
			Transform val = (((Object)(object)itemTransform != (Object)null) ? itemTransform.Find("Feedbacks") : null);
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			Transform val2 = val.Find(feedbackName);
			return ((Object)(object)val2 != (Object)null) ? ((Component)val2).GetComponent<MMF_Player>() : null;
		}

		private static ParticleSystem ResolveThrowVfx(Transform itemTransform)
		{
			Transform val = (((Object)(object)itemTransform != (Object)null) ? itemTransform.Find("Feedbacks") : null);
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			Transform val2 = val.Find("OnThrowVFX");
			return ((Object)(object)val2 != (Object)null) ? ((Component)val2).GetComponent<ParticleSystem>() : null;
		}

		private static List<Collider> CollectNonTriggerColliders(Item item)
		{
			return ((Object)(object)item != (Object)null) ? CollectNonTriggerColliders(((Component)item).gameObject) : new List<Collider>();
		}

		private static List<Collider> CollectNonTriggerColliders(GameObject root)
		{
			List<Collider> list = new List<Collider>();
			Collider[] array = (Collider[])(((Object)(object)root != (Object)null) ? ((Array)root.GetComponentsInChildren<Collider>(true)) : ((Array)new Collider[0]));
			foreach (Collider val in array)
			{
				if ((Object)(object)val != (Object)null && !val.isTrigger)
				{
					list.Add(val);
				}
			}
			return list;
		}

		private static void EnsureInteractableProxies(Item item)
		{
			if ((Object)(object)item == (Object)null)
			{
				return;
			}
			Collider[] componentsInChildren = ((Component)item).GetComponentsInChildren<Collider>(true);
			foreach (Collider val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null) && !val.isTrigger && !((Object)(object)((Component)val).transform == (Object)(object)((Component)item).transform) && ((Component)val).GetComponent<IInteractable>() == null)
				{
					TryConnectInteractableProxy tryConnectInteractableProxy = ((Component)val).GetComponent<TryConnectInteractableProxy>();
					if ((Object)(object)tryConnectInteractableProxy == (Object)null)
					{
						tryConnectInteractableProxy = ((Component)val).gameObject.AddComponent<TryConnectInteractableProxy>();
					}
					tryConnectInteractableProxy.Bind((MonoBehaviour)(object)item);
				}
			}
		}

		private static void CopyPrefabComponentState(Component source, Component target)
		{
			Type type = ((object)source).GetType();
			while (type != null && type != typeof(NetworkBehaviour))
			{
				FieldInfo[] fields = type.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				foreach (FieldInfo fieldInfo in fields)
				{
					if (!fieldInfo.IsStatic && !fieldInfo.IsInitOnly)
					{
						fieldInfo.SetValue(target, fieldInfo.GetValue(source));
					}
				}
				type = type.BaseType;
			}
		}
	}
	public sealed class TryConnectBundledItemRegistration
	{
		public string Key { get; set; }

		public int SpawnableId { get; set; }

		public string DisplayName { get; set; }

		public string Description { get; set; }

		public SpawnableSO BaseSpawnable { get; set; }

		public int BaseSpawnableId { get; set; }

		public string BundlePath { get; set; }

		public string VisualPrefabName { get; set; }

		public string CustomPrefabName { get; set; }

		public string MarkerPrefabName { get; set; }

		public Vector3 VisualLocalPosition { get; set; } = Vector3.zero;


		public Vector3 VisualLocalEulerAngles { get; set; } = Vector3.zero;


		public Vector3 VisualLocalScale { get; set; } = Vector3.one;


		public bool ReplaceColliders { get; set; }

		public bool UseBaseMaterialFallback { get; set; } = true;


		public bool ForceVisualMaterial { get; set; }

		public bool ApplyVisualColor { get; set; }

		public Color VisualColor { get; set; } = Color.white;


		public bool ApplyTint { get; set; }

		public Color Tint { get; set; } = Color.white;


		public Vector3 ModelScaleMultiplier { get; set; } = Vector3.one;


		public int ReplacementChancePercent { get; set; }

		public int ExtraBasePrice { get; set; }

		public int ExtraFloorPrice { get; set; }
	}
	public static class TryConnectAssetBundles
	{
		public static AssetBundle Load(string fullPath)
		{
			if (string.IsNullOrWhiteSpace(fullPath))
			{
				throw new ArgumentException("fullPath is required.", "fullPath");
			}
			string fullPath2 = Path.GetFullPath(fullPath.Trim());
			if (!File.Exists(fullPath2))
			{
				throw new FileNotFoundException("Asset bundle file was not found.", fullPath2);
			}
			AssetBundle val = AssetBundle.LoadFromFile(fullPath2);
			if ((Object)(object)val == (Object)null)
			{
				throw new InvalidOperationException($"Failed to load asset bundle '{fullPath2}'.");
			}
			return val;
		}

		public static AssetBundle LoadRelativeToPlugin(BaseUnityPlugin plugin, string relativePath)
		{
			return Load(ResolvePluginRelativePath(plugin, relativePath));
		}

		public static T LoadAsset<T>(AssetBundle bundle, string assetName) where T : Object
		{
			if ((Object)(object)bundle == (Object)null)
			{
				throw new ArgumentNullException("bundle");
			}
			if (string.IsNullOrWhiteSpace(assetName))
			{
				throw new ArgumentException("assetName is required.", "assetName");
			}
			T val = bundle.LoadAsset<T>(assetName.Trim());
			if ((Object)(object)val == (Object)null)
			{
				throw new InvalidOperationException($"Asset '{assetName}' of type '{typeof(T).FullName}' was not found in bundle '{((Object)bundle).name}'.");
			}
			return val;
		}

		public static GameObject CreatePrefabTemplateFromBundle(AssetBundle bundle, string prefabName, string templateName = null)
		{
			GameObject sourcePrefab = TryConnectAssetBundles.LoadAsset<GameObject>(bundle, prefabName);
			return TryConnectApi.CreatePrefabTemplate(sourcePrefab, templateName);
		}

		public static GameObject CreatePrefabTemplateFromBundle(BaseUnityPlugin plugin, string bundlePath, string prefabName, string templateName = null)
		{
			AssetBundle val = LoadRelativeToPlugin(plugin, bundlePath);
			try
			{
				return CreatePrefabTemplateFromBundle(val, prefabName, templateName);
			}
			finally
			{
				val.Unload(false);
			}
		}

		public static string ResolvePluginRelativePath(BaseUnityPlugin plugin, string relativePath)
		{
			if ((Object)(object)plugin == (Object)null)
			{
				throw new ArgumentNullException("plugin");
			}
			if (string.IsNullOrWhiteSpace(relativePath))
			{
				throw new ArgumentException("relativePath is required.", "relativePath");
			}
			string location = ((object)plugin).GetType().Assembly.Location;
			if (string.IsNullOrWhiteSpace(location))
			{
				throw new InvalidOperationException($"Could not resolve assembly location for plugin '{((object)plugin).GetType().FullName}'.");
			}
			string directoryName = Path.GetDirectoryName(location);
			if (string.IsNullOrWhiteSpace(directoryName))
			{
				throw new InvalidOperationException($"Could not resolve plugin directory for '{location}'.");
			}
			return Path.GetFullPath(Path.Combine(directoryName, relativePath.Trim()));
		}
	}
	public sealed class TryConnectItemRegistration
	{
		public string OwnerGuid { get; set; }

		public string Key { get; set; }

		public int SpawnableId { get; set; }

		public string DisplayName { get; set; }

		public string Description { get; set; }

		public SpawnableSO BaseSpawnable { get; set; }

		public int BaseSpawnableId { get; set; }

		public Type BaseItemComponentType { get; set; }

		public GameObject CustomPrefab { get; set; }

		public GameObject MarkerPrefab { get; set; }

		public bool ApplyTint { get; set; }

		public Color Tint { get; set; } = Color.white;


		public Vector3 ModelScaleMultiplier { get; set; } = Vector3.one;


		public int ReplacementChancePercent { get; set; }

		public int ExtraBasePrice { get; set; }

		public int ExtraFloorPrice { get; set; }
	}
	public sealed class TryConnectRegisteredItemInfo
	{
		public string OwnerGuid { get; private set; }

		public string Key { get; private set; }

		public int SpawnableId { get; private set; }

		public uint AssetId { get; private set; }

		public string DisplayName { get; private set; }

		public string Description { get; private set; }

		public SpawnableSO Spawnable { get; private set; }

		public bool IsRegistered { get; private set; }

		internal TryConnectRegisteredItemInfo(string ownerGuid, string key, int spawnableId, uint assetId, string displayName, string description, SpawnableSO spawnable, bool isRegistered)
		{
			OwnerGuid = ownerGuid;
			Key = key;
			SpawnableId = spawnableId;
			AssetId = assetId;
			DisplayName = displayName;
			Description = description;
			Spawnable = spawnable;
			IsRegistered = isRegistered;
		}
	}
	public enum TryConnectRegistrationResult
	{
		Accepted,
		AlreadyRegistered,
		InvalidRegistration
	}
	[BepInPlugin("com.Try-4646.TryConnect", "TryConnect", "1.0.0")]
	public sealed class TryConnectPlugin : BaseUnityPlugin
	{
		public const string PluginGuid = "com.Try-4646.TryConnect";

		public const string PluginDisplayName = "TryConnect";

		public const string PluginVersion = "1.0.0";

		internal const string MyGUID = "com.Try-4646.TryConnect";

		internal const string PluginName = "TryConnect";

		internal const string VersionString = "1.0.0";

		private Harmony _harmony;

		public static TryConnectPlugin Instance { get; private set; }

		internal static ManualLogSource Log { get; private set; }

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

		internal static ConfigEntry<int> TicketFizzReplacementChance { get; private set; }

		internal static ConfigEntry<int> LoadedChipReplacementChance { get; private set; }

		private void Awake()
		{
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			EnableCustomItems = ((BaseUnityPlugin)this).Config.Bind<bool>("Custom Items", "Enable", true, "Enable TryConnect runtime shop item registration.");
			TicketFizzReplacementChance = ((BaseUnityPlugin)this).Config.Bind<int>("Custom Items", "TicketFizzReplacementChance", 35, "Chance for shop item stamps to replace a vanilla Drink roll with Ticket Fizz.");
			LoadedChipReplacementChance = ((BaseUnityPlugin)this).Config.Bind<int>("Custom Items", "LoadedChipReplacementChance", 25, "Chance for shop item stamps to replace a vanilla Golden Chip roll with Loaded Chip.");
			RuntimeItemRegistry.Initialize(this);
			SceneManager.sceneLoaded += OnSceneLoaded;
			((BaseUnityPlugin)this).Logger.LogInfo((object)string.Format("PluginName: {0}, VersionString: {1} is loading...", "TryConnect", "1.0.0"));
			_harmony = new Harmony("com.Try-4646.TryConnect");
			_harmony.PatchAll();
			RuntimeItemRegistry.TryRegisterRuntimeContent();
			((BaseUnityPlugin)this).Logger.LogInfo((object)string.Format("PluginName: {0}, VersionString: {1} is loaded.", "TryConnect", "1.0.0"));
		}

		private void OnDestroy()
		{
			SceneManager.sceneLoaded -= OnSceneLoaded;
			RuntimeItemRegistry.Dispose();
			if (_harmony != null)
			{
				_harmony.UnpatchSelf();
			}
		}

		private static void OnSceneLoaded(Scene scene, LoadSceneMode mode)
		{
			RuntimeItemRegistry.TryRegisterRuntimeContent();
		}
	}
}
namespace TryConnect.Utils
{
	internal static class ModUtils
	{
		internal static uint GetStableAssetId(string key)
		{
			return GetStableAssetId("com.Try-4646.TryConnect", key);
		}

		internal static uint GetStableAssetId(string ownerGuid, string key)
		{
			uint num = GetStableHash(ownerGuid + ":" + key);
			if (num == 0)
			{
				num = 1u;
			}
			return num;
		}

		internal static int GetStableSpawnableId(string ownerGuid, string key)
		{
			uint stableHash = GetStableHash(ownerGuid + ":" + key);
			return (int)(0x40000000 | (stableHash & 0x3FFFFFFF));
		}

		internal static int ClampPercent(int value)
		{
			return Mathf.Clamp(value, 0, 100);
		}

		internal static int GetDeterministicPercent(Vector3 position, int seed, string key)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			int num = seed;
			num = (num * 397) ^ Mathf.RoundToInt(position.x * 100f);
			num = (num * 397) ^ Mathf.RoundToInt(position.y * 100f);
			num = (num * 397) ^ Mathf.RoundToInt(position.z * 100f);
			for (int i = 0; i < key.Length; i++)
			{
				num = (num * 397) ^ key[i];
			}
			if (num == int.MinValue)
			{
				num = int.MaxValue;
			}
			return Mathf.Abs(num) % 100;
		}

		internal static bool TrySetMaterialTint(Material material, Color tint)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)material == (Object)null)
			{
				return false;
			}
			if (material.HasProperty("_BaseColor"))
			{
				material.SetColor("_BaseColor", tint);
				return true;
			}
			if (material.HasProperty("_Color"))
			{
				material.SetColor("_Color", tint);
				return true;
			}
			return false;
		}

		private static uint GetStableHash(string text)
		{
			uint num = 2166136261u;
			for (int i = 0; i < text.Length; i++)
			{
				num ^= text[i];
				num *= 16777619;
			}
			return num;
		}
	}
}
namespace TryConnect.Patches
{
	[HarmonyPatch(typeof(SpawnableSettings), "GetSpawnableSoById")]
	internal static class SpawnableSettingsPatches
	{
		private static void Postfix(int id, ref SpawnableSO __result)
		{
			if ((Object)(object)__result == (Object)null)
			{
				__result = RuntimeItemRegistry.GetCustomSpawnable(id);
			}
		}
	}
	[HarmonyPatch(typeof(ItemPriceSettings), "GetBasePrice")]
	internal static class ItemPriceSettingsBasePricePatches
	{
		private static bool Prefix(SpawnableSO spawnableSO, ref int __result)
		{
			return !RuntimeItemRegistry.TryGetCustomBasePrice(spawnableSO, ref __result);
		}
	}
	[HarmonyPatch(typeof(ItemPriceSettings), "GetPriceIncreasePerFloor")]
	internal static class ItemPriceSettingsFloorPricePatches
	{
		private static bool Prefix(SpawnableSO spawnableSO, ref int __result)
		{
			return !RuntimeItemRegistry.TryGetCustomFloorPrice(spawnableSO, ref __result);
		}
	}
	[HarmonyPatch(typeof(ItemDescriptionSettings), "GetDescription")]
	internal static class ItemDescriptionSettingsPatches
	{
		private static bool Prefix(SpawnableSO spawnableSO, ref string __result)
		{
			return !RuntimeItemRegistry.TryGetCustomDescription(spawnableSO, ref __result);
		}
	}
	[HarmonyPatch(typeof(ItemStampManager), "GetUniqueLoot", new Type[]
	{
		typeof(MMLootTableGameObjectSO),
		typeof(Vector3)
	})]
	internal static class ItemStampManagerLootPatches
	{
		private static void Postfix(MMLootTableGameObjectSO lootTable, Vector3 stampPosition, ref GameObject __result)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			__result = RuntimeItemRegistry.GetShopReplacement(lootTable, stampPosition, __result);
		}
	}
	[HarmonyPatch(typeof(ItemStamp), "SpawnItem")]
	internal static class ItemStampSpawnPatches
	{
		private static bool Prefix(ItemStamp __instance, GameObject prefab, Vector3 position, Quaternion rotation, Vector3 scale)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0004: 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)
			return !RuntimeItemRegistry.TrySpawnCustomItemStampPrefab(__instance, prefab, position, rotation, scale);
		}
	}
	[HarmonyPatch(typeof(NewConsole), "SpawnPrefabServer")]
	internal static class NewConsoleSpawnPatches
	{
		private static bool Prefix(GameObject prefab, Vector3 position)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			return !RuntimeItemRegistry.TrySpawnConsolePrefab(prefab, position);
		}
	}
	[HarmonyPatch]
	internal static class CustomNetworkManagerPatches
	{
		[CompilerGenerated]
		private sealed class <TargetMethods>d__0 : IEnumerable<MethodBase>, IEnumerable, IEnumerator<MethodBase>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private MethodBase <>2__current;

			private int <>l__initialThreadId;

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

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

			[DebuggerHidden]
			public <TargetMethods>d__0(int <>1__state)
			{
				this.<>1__state = <>1__state;
				<>l__initialThreadId = Environment.CurrentManagedThreadId;
			}

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

			private bool MoveNext()
			{
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = AccessTools.Method(typeof(CustomNetworkManager), "OnStartServer", (Type[])null, (Type[])null);
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					<>2__current = AccessTools.Method(typeof(CustomNetworkManager), "OnClientConnect", (Type[])null, (Type[])null);
					<>1__state = 2;
					return true;
				case 2:
					<>1__state = -1;
					<>2__current = AccessTools.Method(typeof(CustomNetworkManager), "OnClientSceneChanged", (Type[])null, (Type[])null);
					<>1__state = 3;
					return true;
				case 3:
					<>1__state = -1;
					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();
			}

			[DebuggerHidden]
			IEnumerator<MethodBase> IEnumerable<MethodBase>.GetEnumerator()
			{
				if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
				{
					<>1__state = 0;
					return this;
				}
				return new <TargetMethods>d__0(0);
			}

			[DebuggerHidden]
			IEnumerator IEnumerable.GetEnumerator()
			{
				return ((IEnumerable<MethodBase>)this).GetEnumerator();
			}
		}

		[IteratorStateMachine(typeof(<TargetMethods>d__0))]
		private static IEnumerable<MethodBase> TargetMethods()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <TargetMethods>d__0(-2);
		}

		private static void Postfix()
		{
			RuntimeItemRegistry.TryRegisterRuntimeContent();
		}
	}
	[HarmonyPatch]
	internal static class NetworkClientSpawnLifecyclePatches
	{
		[CompilerGenerated]
		private sealed class <TargetMethods>d__0 : IEnumerable<MethodBase>, IEnumerable, IEnumerator<MethodBase>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private MethodBase <>2__current;

			private int <>l__initialThreadId;

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

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

			[DebuggerHidden]
			public <TargetMethods>d__0(int <>1__state)
			{
				this.<>1__state = <>1__state;
				<>l__initialThreadId = Environment.CurrentManagedThreadId;
			}

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

			private bool MoveNext()
			{
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = AccessTools.Method(typeof(NetworkClient), "ClearSpawners", (Type[])null, (Type[])null);
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					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();
			}

			[DebuggerHidden]
			IEnumerator<MethodBase> IEnumerable<MethodBase>.GetEnumerator()
			{
				if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
				{
					<>1__state = 0;
					return this;
				}
				return new <TargetMethods>d__0(0);
			}

			[DebuggerHidden]
			IEnumerator IEnumerable.GetEnumerator()
			{
				return ((IEnumerable<MethodBase>)this).GetEnumerator();
			}
		}

		[IteratorStateMachine(typeof(<TargetMethods>d__0))]
		private static IEnumerable<MethodBase> TargetMethods()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <TargetMethods>d__0(-2);
		}

		private static void Postfix()
		{
			RuntimeItemRegistry.TryEnsureAllClientRegistrations();
		}
	}
	[HarmonyPatch(typeof(NetworkClient), "OnSpawn")]
	internal static class NetworkClientOnSpawnPatches
	{
		private static void Prefix(SpawnMessage message)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			RuntimeItemRegistry.TryEnsureClientRegistration(message.assetId);
		}
	}
}
namespace TryConnect.MonoBehaviours
{
	internal class TryConnectComponent : MonoBehaviour
	{
		public void Awake()
		{
		}

		public void Start()
		{
		}

		public void Update()
		{
		}

		public void LateUpdate()
		{
		}
	}
}