Decompiled source of InventorySlotUpgrade v0.1.9

InventorySlotUpgrade.dll

Decompiled a month ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using REPOLib.Modules;
using Steamworks;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;

[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("InventorySlotUpgrade")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.1.9.0")]
[assembly: AssemblyInformationalVersion("0.1.9+0550e1161febd14822a2240968cabacf4c176ee0")]
[assembly: AssemblyProduct("InventorySlotUpgrade")]
[assembly: AssemblyTitle("InventorySlotUpgrade")]
[assembly: AssemblyVersion("0.1.9.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace InventorySlotUpgrade
{
	[HarmonyPatch]
	internal static class ExtraSlotPersistence
	{
		private static readonly Dictionary<string, Dictionary<int, int>> EquippedItems = new Dictionary<string, Dictionary<int, int>>();

		[HarmonyPostfix]
		[HarmonyPatch(typeof(StatsManager), "PlayerInventoryUpdate")]
		private static void TrackExtraSlot(string _steamID, string itemName, int spot)
		{
			if (!SemiFunc.IsMasterClientOrSingleplayer() || spot < 3)
			{
				return;
			}
			if (string.IsNullOrEmpty(itemName))
			{
				Erase(_steamID, spot);
			}
			else if (spot < InventorySlotController.GetSlotCount(_steamID))
			{
				if (!EquippedItems.TryGetValue(_steamID, out var value))
				{
					value = new Dictionary<int, int>();
					EquippedItems[_steamID] = value;
				}
				value[spot] = itemName.GetHashCode();
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(PunManager), "SetItemNameLOGIC", new Type[]
		{
			typeof(string),
			typeof(int),
			typeof(ItemAttributes)
		})]
		private static void RestoreExtraSlot(string _name, int photonViewID, ItemAttributes _itemAttributes)
		{
			if (!SemiFunc.IsMasterClientOrSingleplayer())
			{
				return;
			}
			ItemAttributes val = _itemAttributes;
			if ((Object)(object)val == (Object)null && SemiFunc.IsMultiplayer())
			{
				PhotonView obj = PhotonView.Find(photonViewID);
				val = ((obj != null) ? ((Component)obj).GetComponent<ItemAttributes>() : null);
			}
			ItemEquippable val2 = ((val != null) ? ((Component)val).GetComponent<ItemEquippable>() : null);
			if ((Object)(object)val2 == (Object)null)
			{
				return;
			}
			int nameHash = _name.GetHashCode();
			foreach (PlayerAvatar item in SemiFunc.PlayerGetList())
			{
				string text = SemiFunc.PlayerGetSteamID(item);
				if (!EquippedItems.TryGetValue(text, out var value))
				{
					continue;
				}
				KeyValuePair<int, int>? keyValuePair = value.FirstOrDefault((KeyValuePair<int, int> pair) => pair.Value == nameHash);
				if (keyValuePair.HasValue && keyValuePair.Value.Value == nameHash)
				{
					int key = keyValuePair.Value.Key;
					if (key >= InventorySlotController.GetSlotCount(text))
					{
						Erase(text, key);
						break;
					}
					int num = (SemiFunc.IsMultiplayer() ? item.photonView.ViewID : (-1));
					val2.RequestEquip(key, num);
					Erase(text, key);
					break;
				}
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(MainMenuOpen), "Start")]
		private static void ClearOnMainMenu()
		{
			EquippedItems.Clear();
		}

		private static void Erase(string steamId, int slot)
		{
			if (EquippedItems.TryGetValue(steamId, out var value))
			{
				value.Remove(slot);
				if (value.Count == 0)
				{
					EquippedItems.Remove(steamId);
				}
			}
		}
	}
	[HarmonyPatch]
	internal static class InventoryPatches
	{
		private static readonly FieldInfo InputDisableTimerField = AccessTools.Field(typeof(PlayerController), "InputDisableTimer");

		private static readonly FieldInfo GrabbedPhysObjectField = AccessTools.Field(typeof(PhysGrabber), "grabbedPhysGrabObject");

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Inventory), "Awake")]
		private static void InventoryAwakePostfix(Inventory __instance)
		{
			InventorySlotController.ExpandInternalListEarly(__instance);
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(InventoryUI), "Start")]
		private static void InventoryUiStartPostfix()
		{
			InventorySlotController.RequestRefresh();
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(InventorySpot), "Start")]
		private static void InventorySpotStartPrefix(InventorySpot __instance)
		{
			if (__instance.inventorySpotIndex >= 3)
			{
				BatteryVisualLogic componentInChildren = ((Component)__instance).GetComponentInChildren<BatteryVisualLogic>(true);
				if ((Object)(object)componentInChildren != (Object)null)
				{
					((Component)componentInChildren).gameObject.SetActive(true);
				}
				else
				{
					Plugin.Log.LogError((object)$"Inventory slot {__instance.inventorySpotIndex + 1} has no BatteryVisualLogic child.");
				}
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(InventorySpot), "Update")]
		private static void InventorySpotUpdatePrefix(InventorySpot __instance)
		{
			int inventorySpotIndex = __instance.inventorySpotIndex;
			if (inventorySpotIndex < 3 || inventorySpotIndex >= InventorySlotController.GetLocalSlotCount())
			{
				return;
			}
			Keyboard current = Keyboard.current;
			if (current == null)
			{
				return;
			}
			KeyControl val = (KeyControl)(inventorySpotIndex switch
			{
				3 => current.digit4Key, 
				4 => current.digit5Key, 
				5 => current.digit6Key, 
				6 => current.digit7Key, 
				7 => current.digit8Key, 
				8 => current.digit9Key, 
				9 => current.digit0Key, 
				_ => null, 
			});
			if (val == null || !((ButtonControl)val).wasPressedThisFrame || SemiFunc.RunIsArena() || (Object)(object)PlayerController.instance == (Object)null || IsPlayerInputDisabled())
			{
				return;
			}
			if (__instance.IsOccupied())
			{
				ItemEquippable currentItem = __instance.CurrentItem;
				if (currentItem != null)
				{
					currentItem.RequestUnequip();
				}
				return;
			}
			PhysGrabber instance = PhysGrabber.instance;
			object obj;
			if (!((Object)(object)instance != (Object)null) || !instance.grabbed)
			{
				obj = null;
			}
			else
			{
				object? obj2 = GrabbedPhysObjectField?.GetValue(instance);
				object? obj3 = ((obj2 is PhysGrabObject) ? obj2 : null);
				obj = ((obj3 != null) ? ((Component)obj3).GetComponent<ItemEquippable>() : null);
			}
			ItemEquippable val2 = (ItemEquippable)obj;
			if ((Object)(object)val2 != (Object)null)
			{
				int num = (((Object)(object)instance.photonView != (Object)null) ? instance.photonView.ViewID : (-1));
				val2.RequestEquip(inventorySpotIndex, num);
			}
		}

		private static bool IsPlayerInputDisabled()
		{
			if (InputDisableTimerField?.GetValue(PlayerController.instance) is float num)
			{
				return num > 0f;
			}
			return false;
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(Inventory), "GetFirstFreeInventorySpotIndex")]
		private static bool FirstFreeSpotPrefix(Inventory __instance, ref int __result)
		{
			List<InventorySpot> spots = InventorySlotController.GetSpots(__instance);
			int num = Math.Min(InventorySlotController.GetLocalSlotCount(), spots?.Count ?? 0);
			for (int i = 0; i < num; i++)
			{
				InventorySpot val = spots[i];
				if ((Object)(object)val != (Object)null && !val.IsOccupied())
				{
					__result = i;
					return false;
				}
			}
			__result = -1;
			return false;
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(ItemEquippable), "RPC_RequestEquip")]
		private static bool ValidateRequestedSlot(int spotIndex, int physGrabberPhotonViewID)
		{
			if (spotIndex < 3)
			{
				return true;
			}
			int num;
			string arg;
			if (!SemiFunc.IsMultiplayer())
			{
				num = InventorySlotController.GetLocalSlotCount();
				arg = "local player";
			}
			else
			{
				PhotonView val = PhotonView.Find(physGrabberPhotonViewID);
				PlayerAvatar val2 = ((val != null) ? ((Component)val).GetComponent<PlayerAvatar>() : null) ?? ((val != null) ? ((Component)val).GetComponentInParent<PlayerAvatar>() : null);
				if ((Object)(object)val2 == (Object)null)
				{
					Plugin.Log.LogWarning((object)$"Rejected inventory slot {spotIndex + 1}: requesting player could not be resolved.");
					return false;
				}
				num = InventorySlotController.GetSlotCount(val2);
				arg = SemiFunc.PlayerGetName(val2);
			}
			bool num2 = spotIndex < num;
			if (!num2)
			{
				Plugin.Log.LogWarning((object)$"Rejected inventory slot {spotIndex + 1} for {arg}; allowed slot count is {num}.");
			}
			return num2;
		}
	}
	internal static class InventorySlotController
	{
		private const float SlotSpacing = 40f;

		private static readonly FieldInfo InventorySpotsField = AccessTools.Field(typeof(Inventory), "inventorySpots");

		private static readonly FieldInfo UiChildrenField = AccessTools.Field(typeof(InventoryUI), "allChildren");

		private static readonly FieldInfo InitialPositionField = AccessTools.Field(typeof(SemiUI), "initialPosition");

		private static readonly FieldInfo HidePositionCurrentField = AccessTools.Field(typeof(SemiUI), "hidePositionCurrent");

		private static readonly FieldInfo HideTimerField = AccessTools.Field(typeof(SemiUI), "hideTimer");

		private static readonly FieldInfo ShowTimerField = AccessTools.Field(typeof(SemiUI), "showTimer");

		private static readonly FieldInfo PreviousHideTimerField = AccessTools.Field(typeof(SemiUI), "prevHideTimer");

		private static readonly FieldInfo PreviousShowTimerField = AccessTools.Field(typeof(SemiUI), "prevShowTimer");

		private static readonly FieldInfo ScootPositionField = AccessTools.Field(typeof(SemiUI), "scootPosition");

		private static readonly FieldInfo ScootPositionStartField = AccessTools.Field(typeof(SemiUI), "scootPositionStart");

		private static readonly FieldInfo ScootPositionPreviousField = AccessTools.Field(typeof(SemiUI), "scootPositionPrev");

		private static readonly FieldInfo ScootPositionCurrentField = AccessTools.Field(typeof(SemiUI), "scootPositionCurrent");

		private static readonly FieldInfo ScootTimerField = AccessTools.Field(typeof(SemiUI), "scootTimer");

		private static readonly FieldInfo PreviousScootTimerField = AccessTools.Field(typeof(SemiUI), "prevScootTimer");

		private static readonly FieldInfo ScootAnimationEvaluationField = AccessTools.Field(typeof(SemiUI), "scootAnimationEvaluation");

		private static readonly FieldInfo ScootEvaluationField = AccessTools.Field(typeof(SemiUI), "scootEval");

		private static int _localLevelHint;

		private static int _refreshGeneration;

		internal static int GetSlotCount(string steamId)
		{
			int num = ((!string.IsNullOrEmpty(steamId) && Plugin.SlotUpgrade != null) ? Plugin.SlotUpgrade.GetLevel(steamId) : 0);
			return Mathf.Clamp(3 + num, 3, Plugin.EffectiveMaximumSlots);
		}

		internal static int GetSlotCount(PlayerAvatar playerAvatar)
		{
			if (!((Object)(object)playerAvatar == (Object)null))
			{
				return GetSlotCount(SemiFunc.PlayerGetSteamID(playerAvatar));
			}
			return 3;
		}

		internal static int GetLocalSlotCount()
		{
			//IL_002a: 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)
			PlayerAvatar val = PlayerController.instance?.playerAvatarScript;
			if ((Object)(object)val != (Object)null)
			{
				return GetSlotCount(val);
			}
			try
			{
				if (SteamClient.IsValid)
				{
					return GetSlotCount(((object)SteamClient.SteamId/*cast due to .constrained prefix*/).ToString());
				}
			}
			catch
			{
			}
			return Mathf.Clamp(3 + _localLevelHint, 3, Plugin.EffectiveMaximumSlots);
		}

		internal static void ApplyUpgradeLevel(PlayerAvatar playerAvatar, int level)
		{
			if (!((Object)(object)playerAvatar == (Object)null) && !((Object)(object)playerAvatar != (Object)(object)PlayerController.instance?.playerAvatarScript))
			{
				_localLevelHint = level;
				RequestRefresh();
				Plugin.Log.LogInfo((object)$"Applied Inventory Slot level {level}; local inventory target is {GetSlotCount(playerAvatar)} slots.");
			}
		}

		internal static void RequestRefresh()
		{
			if (!((Object)(object)Plugin.Instance == (Object)null))
			{
				int generation = ++_refreshGeneration;
				((MonoBehaviour)Plugin.Instance).StartCoroutine(RefreshWhenReady(generation));
			}
		}

		internal static void ExpandInternalListEarly(Inventory inventory)
		{
			List<InventorySpot> spots = GetSpots(inventory);
			if (spots != null)
			{
				int localSlotCount = GetLocalSlotCount();
				while (spots.Count < localSlotCount)
				{
					spots.Add(null);
				}
			}
		}

		internal static List<InventorySpot> GetSpots(Inventory inventory)
		{
			if (!((Object)(object)inventory == (Object)null))
			{
				return InventorySpotsField.GetValue(inventory) as List<InventorySpot>;
			}
			return null;
		}

		private static IEnumerator RefreshWhenReady(int generation)
		{
			while (generation == _refreshGeneration && ((Object)(object)Inventory.instance == (Object)null || (Object)(object)InventoryUI.instance == (Object)null))
			{
				yield return null;
			}
			if (generation != _refreshGeneration)
			{
				yield break;
			}
			yield return null;
			if (generation != _refreshGeneration)
			{
				yield break;
			}
			int targetCount = GetLocalSlotCount();
			List<InventorySpot> newlyClonedSlots = ApplyVisuals(targetCount);
			yield return null;
			if (generation != _refreshGeneration)
			{
				yield break;
			}
			ApplyVisuals(targetCount);
			foreach (InventorySpot item in newlyClonedSlots)
			{
				ForceSlotShown(item);
			}
		}

		private static List<InventorySpot> ApplyVisuals(int targetCount)
		{
			List<InventorySpot> list = new List<InventorySpot>();
			Inventory instance = Inventory.instance;
			InventoryUI instance2 = InventoryUI.instance;
			List<InventorySpot> spots = GetSpots(instance);
			if ((Object)(object)instance == (Object)null || (Object)(object)instance2 == (Object)null || spots == null)
			{
				return list;
			}
			Transform transform = ((Component)instance2).transform;
			Transform val = transform.Find("Inventory Spot 1");
			if ((Object)(object)val == (Object)null)
			{
				Plugin.Log.LogError((object)"Could not find the vanilla 'Inventory Spot 1' UI template.");
				return list;
			}
			List<GameObject> list2 = UiChildrenField.GetValue(instance2) as List<GameObject>;
			HashSet<InventorySpot> hashSet = new HashSet<InventorySpot>();
			float num = (0f - (float)targetCount * 40f) / 2f + 20f;
			for (int i = 3; i < targetCount; i++)
			{
				Transform val2 = transform.Find($"Inventory Spot {i + 1}");
				bool flag = (Object)(object)val2 == (Object)null;
				if ((Object)(object)val2 == (Object)null)
				{
					val2 = Object.Instantiate<Transform>(val, val.parent);
					((Object)val2).name = $"Inventory Spot {i + 1}";
				}
				InventorySpot component = ((Component)val2).GetComponent<InventorySpot>();
				if ((Object)(object)component == (Object)null)
				{
					Plugin.Log.LogError((object)$"Cloned inventory slot {i + 1} has no InventorySpot component.");
					continue;
				}
				component.inventorySpotIndex = i;
				if (flag)
				{
					PrepareCloneForStart(((Component)val).GetComponent<InventorySpot>(), component, num + (float)i * 40f);
					hashSet.Add(component);
					list.Add(component);
				}
				SetKeyLabel(val2, component, i);
				((Component)val2).gameObject.SetActive(true);
				while (spots.Count <= i)
				{
					spots.Add(null);
				}
				spots[i] = component;
				if (list2 != null && !list2.Contains(((Component)val2).gameObject))
				{
					list2.Add(((Component)val2).gameObject);
				}
			}
			for (int j = 0; j < targetCount; j++)
			{
				Transform val3 = transform.Find($"Inventory Spot {j + 1}");
				if (!((Object)(object)val3 == (Object)null))
				{
					InventorySpot component2 = ((Component)val3).GetComponent<InventorySpot>();
					if (!hashSet.Contains(component2))
					{
						PositionStartedSlot(component2, num + (float)j * 40f);
					}
				}
			}
			return list;
		}

		private static void PrepareCloneForStart(InventorySpot template, InventorySpot clone, float desiredX)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: 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)
			//IL_00bc: 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_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: 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)
			//IL_00ce: 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_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: 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_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			Vector3 localPosition = ((Component)clone).transform.localPosition;
			float num = (((Object)(object)template == (Object)null || !((SemiUI)clone).animateTheEntireObject) ? localPosition.y : ((SemiUI)template).showPosition.y);
			((Component)clone).transform.localPosition = new Vector3(desiredX, num, localPosition.z);
			if (!((SemiUI)clone).animateTheEntireObject && (Object)(object)((SemiUI)clone).textRectTransform != (Object)null && (Object)(object)template != (Object)null)
			{
				Vector3 localPosition2 = ((SemiUI)clone).textRectTransform.localPosition;
				((SemiUI)clone).textRectTransform.localPosition = new Vector3(((SemiUI)template).showPosition.x, ((SemiUI)template).showPosition.y, localPosition2.z);
			}
			Vector2 val = (((Object)(object)template == (Object)null) ? Vector2.zero : (((SemiUI)template).hidePosition - ((SemiUI)template).showPosition));
			((SemiUI)clone).showPosition = Vector2.zero;
			((SemiUI)clone).hidePosition = val;
			InitialPositionField?.SetValue(clone, ((Component)clone).transform.localPosition);
			HidePositionCurrentField?.SetValue(clone, val);
			ScootPositionField?.SetValue(clone, Vector2.zero);
			ScootPositionStartField?.SetValue(clone, Vector2.zero);
			ScootPositionPreviousField?.SetValue(clone, Vector2.zero);
			ScootPositionCurrentField?.SetValue(clone, Vector2.zero);
			ScootTimerField?.SetValue(clone, -123f);
			PreviousScootTimerField?.SetValue(clone, -123f);
			ScootAnimationEvaluationField?.SetValue(clone, 0f);
			ScootEvaluationField?.SetValue(clone, 0f);
		}

		private static void PositionStartedSlot(InventorySpot slot, float desiredX)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: 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_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: 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_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: 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_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)slot == (Object)null)
			{
				return;
			}
			Transform transform = ((Component)slot).transform;
			Vector3 val = (Vector3)((InitialPositionField == null) ? transform.localPosition : ((Vector3)InitialPositionField.GetValue(slot)));
			val.x = desiredX;
			InitialPositionField?.SetValue(slot, val);
			if (!((SemiUI)slot).animateTheEntireObject)
			{
				Vector3 localPosition = transform.localPosition;
				transform.localPosition = new Vector3(desiredX, localPosition.y, localPosition.z);
				return;
			}
			float num = desiredX - ((SemiUI)slot).showPosition.x;
			if (!(Mathf.Abs(num) < 0.001f))
			{
				((SemiUI)slot).showPosition = ((SemiUI)slot).showPosition + new Vector2(num, 0f);
				((SemiUI)slot).hidePosition = ((SemiUI)slot).hidePosition + new Vector2(num, 0f);
				if (HidePositionCurrentField?.GetValue(slot) is Vector2 val2)
				{
					HidePositionCurrentField.SetValue(slot, val2 + new Vector2(num, 0f));
				}
				Vector3 localPosition2 = transform.localPosition;
				transform.localPosition = new Vector3(localPosition2.x + num, localPosition2.y, localPosition2.z);
			}
		}

		private static void ForceSlotShown(InventorySpot slot)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: 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_00b2: 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_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)slot == (Object)null))
			{
				((SemiUI)slot).Show();
				HidePositionCurrentField?.SetValue(slot, ((SemiUI)slot).showPosition);
				HideTimerField?.SetValue(slot, 0f);
				ShowTimerField?.SetValue(slot, 0.1f);
				PreviousHideTimerField?.SetValue(slot, 0f);
				PreviousShowTimerField?.SetValue(slot, 0.1f);
				Vector3 val = Vector2.op_Implicit(((SemiUI)slot).showPosition);
				if (((SemiUI)slot).animateTheEntireObject)
				{
					((Component)slot).transform.localPosition = new Vector3(val.x, val.y, ((Component)slot).transform.localPosition.z);
				}
				else if ((Object)(object)((SemiUI)slot).textRectTransform != (Object)null)
				{
					((SemiUI)slot).textRectTransform.localPosition = new Vector3(val.x, val.y, ((SemiUI)slot).textRectTransform.localPosition.z);
				}
			}
		}

		private static void SetKeyLabel(Transform slotTransform, InventorySpot slot, int index)
		{
			string text = ((index == 9) ? "0" : (index + 1).ToString());
			Transform obj = slotTransform.Find("Numbers");
			TextMeshProUGUI val = ((obj != null) ? ((Component)obj).GetComponent<TextMeshProUGUI>() : null);
			if ((Object)(object)val != (Object)null)
			{
				((TMP_Text)val).text = text;
			}
			if ((Object)(object)slot.noItem != (Object)null)
			{
				((TMP_Text)slot.noItem).text = text;
			}
		}
	}
	[BepInPlugin("mathe.inventoryslotupgrade", "Inventory Slot Upgrade", "0.1.9")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "mathe.inventoryslotupgrade";

		public const string PluginName = "Inventory Slot Upgrade";

		public const string PluginVersion = "0.1.9";

		public const string RepoLibGuid = "REPOLib";

		public const string UpgradeId = "InventorySlot";

		public const int BaseSlotCount = 3;

		public const int MinimumConfigurablePrice = 100000;

		public const int MaximumConfigurablePrice = 1000000;

		public const int PriceStep = 10000;

		public const float VanillaShopValueMultiplier = 4f;

		internal static readonly string[] PriceOptions = BuildPriceOptions();

		private Harmony _harmony;

		internal static Plugin Instance { get; private set; }

		internal static PlayerUpgrade SlotUpgrade { get; private set; }

		internal static Item UpgradeItemData { get; private set; }

		internal static ManualLogSource Log { get; private set; }

		internal ConfigEntry<string> MinimumPrice { get; private set; }

		internal ConfigEntry<string> MaximumPrice { get; private set; }

		internal ConfigEntry<int> MaximumSlots { get; private set; }

		internal ConfigEntry<int> MaxAmountInShop { get; private set; }

		internal ConfigEntry<bool> AllowTeamUpgrades { get; private set; }

		internal static int EffectiveMaximumSlots => Mathf.Clamp(Instance?.MaximumSlots.Value ?? 10, 4, 10);

		internal static bool TeamUpgradesEnabled => Instance?.AllowTeamUpgrades.Value ?? false;

		internal static float EffectiveMinimumPrice => ParseConfiguredPrice(Instance?.MinimumPrice.Value, 100000);

		internal static float EffectiveMaximumPrice => Mathf.Clamp(ParseConfiguredPrice(Instance?.MaximumPrice.Value, 100000), EffectiveMinimumPrice, 1000000f);

		private void Awake()
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Expected O, but got Unknown
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Expected O, but got Unknown
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Expected O, but got Unknown
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Expected O, but got Unknown
			//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e2: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			MinimumPrice = ((BaseUnityPlugin)this).Config.Bind<string>("Shop", "Minimum Price", "100000", new ConfigDescription("Minimum displayed shop price. The arrows change it in 10,000-dollar steps.", (AcceptableValueBase)(object)new AcceptableValueList<string>(PriceOptions), Array.Empty<object>()));
			MaximumPrice = ((BaseUnityPlugin)this).Config.Bind<string>("Shop", "Maximum Price", "100000", new ConfigDescription("Maximum displayed shop price. The arrows change it in 10,000-dollar steps. Values below Minimum Price use Minimum Price.", (AcceptableValueBase)(object)new AcceptableValueList<string>(PriceOptions), Array.Empty<object>()));
			MaxAmountInShop = ((BaseUnityPlugin)this).Config.Bind<int>("Shop", "Max Amount In Shop", 1, new ConfigDescription("Maximum number of Inventory Slot Upgrade boxes that can appear in one shop.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 4), Array.Empty<object>()));
			MaximumSlots = ((BaseUnityPlugin)this).Config.Bind<int>("Upgrade", "Maximum Slots", 10, new ConfigDescription("Maximum usable inventory slots. Slots 4-10 use keys 4-9 and 0.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(4, 10), Array.Empty<object>()));
			AllowTeamUpgrades = ((BaseUnityPlugin)this).Config.Bind<bool>("Upgrade", "Allow Team Upgrades", false, "Whether activating the upgrade grants one inventory slot to every current player instead of only the player using it. All players should use the same setting.");
			UpgradeItemData = UpgradeItemFactory.CreateItemData();
			MinimumPrice.SettingChanged += OnItemConfigurationChanged;
			MaximumPrice.SettingChanged += OnItemConfigurationChanged;
			MaxAmountInShop.SettingChanged += OnItemConfigurationChanged;
			MaximumSlots.SettingChanged += OnMaximumSlotsChanged;
			SlotUpgrade = Upgrades.RegisterUpgrade("InventorySlot", UpgradeItemData, (Action<PlayerAvatar, int>)InventorySlotController.ApplyUpgradeLevel, (Action<PlayerAvatar, int>)InventorySlotController.ApplyUpgradeLevel);
			if (SlotUpgrade == null)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)"Could not register REPOLib upgrade 'InventorySlot'. The plugin will not continue.");
				return;
			}
			_harmony = new Harmony("mathe.inventoryslotupgrade");
			_harmony.PatchAll();
			((MonoBehaviour)this).StartCoroutine(SharedUpgradesPlusCompatibility.InstallWhenReady(_harmony));
			((MonoBehaviour)this).StartCoroutine(UpgradeItemFactory.RegisterPrefabWhenReady());
			if (Chainloader.PluginInfos.ContainsKey("nickklmao.moreinventoryslots") || Chainloader.PluginInfos.ContainsKey("com.hiarlyscripter.bagexpander"))
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)"A fixed-count inventory slot mod is also loaded. Disable it to avoid duplicate UI and competing slot limits.");
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Inventory Slot Upgrade initialized. Waiting for the vanilla upgrade prefab.");
		}

		private void OnDestroy()
		{
			if (MinimumPrice != null)
			{
				MinimumPrice.SettingChanged -= OnItemConfigurationChanged;
			}
			if (MaximumPrice != null)
			{
				MaximumPrice.SettingChanged -= OnItemConfigurationChanged;
			}
			if (MaxAmountInShop != null)
			{
				MaxAmountInShop.SettingChanged -= OnItemConfigurationChanged;
			}
			if (MaximumSlots != null)
			{
				MaximumSlots.SettingChanged -= OnMaximumSlotsChanged;
			}
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			if ((Object)(object)Instance == (Object)(object)this)
			{
				Instance = null;
			}
		}

		private void OnItemConfigurationChanged(object sender, EventArgs args)
		{
			UpgradeItemFactory.ApplyConfiguredValues(UpgradeItemData);
		}

		private void OnMaximumSlotsChanged(object sender, EventArgs args)
		{
			UpgradeItemFactory.ApplyConfiguredValues(UpgradeItemData);
			InventorySlotController.RequestRefresh();
		}

		private static string[] BuildPriceOptions()
		{
			List<string> list = new List<string>();
			for (int i = 100000; i <= 1000000; i += 10000)
			{
				list.Add(i.ToString(CultureInfo.InvariantCulture));
			}
			return list.ToArray();
		}

		private static float ParseConfiguredPrice(string rawValue, int fallback)
		{
			if (!float.TryParse(rawValue, NumberStyles.Float, CultureInfo.InvariantCulture, out var result))
			{
				result = fallback;
			}
			result = Mathf.Clamp(result, 100000f, 1000000f);
			return Mathf.Round(result / 10000f) * 10000f;
		}
	}
	[HarmonyPatch]
	internal static class SaveLoadRecovery
	{
		[HarmonyPatch(typeof(StatsManager), "LoadGame")]
		private static class LoadGameDiagnostics
		{
			[HarmonyPrefix]
			private static void Prefix(string fileName)
			{
				Plugin.Log.LogInfo((object)("Loading save data '" + fileName + "'..."));
			}

			[HarmonyPostfix]
			private static void Postfix(StatsManager __instance, string fileName)
			{
				bool boolean = GetBoolean(SaveFileReadyField, __instance);
				Plugin.Log.LogInfo((object)$"Loaded save data '{fileName}'. Ready={boolean}.");
			}

			[HarmonyFinalizer]
			private static Exception Finalizer(Exception __exception, string fileName)
			{
				if (__exception != null)
				{
					Plugin.Log.LogError((object)$"Save data load '{fileName}' failed: {__exception}");
				}
				return __exception;
			}
		}

		private static readonly FieldInfo RestartingField = AccessTools.Field(typeof(RunManager), "restarting");

		private static readonly FieldInfo RestartingDoneField = AccessTools.Field(typeof(RunManager), "restartingDone");

		private static readonly FieldInfo WaitToChangeSceneField = AccessTools.Field(typeof(RunManager), "waitToChangeScene");

		private static readonly FieldInfo LobbyJoinField = AccessTools.Field(typeof(RunManager), "lobbyJoin");

		private static readonly FieldInfo SaveFileReadyField = AccessTools.Field(typeof(StatsManager), "saveFileReady");

		[HarmonyPrefix]
		[HarmonyPatch(typeof(SemiFunc), "MenuActionSingleplayerGame")]
		private static void BeforeSingleplayerLoad(string saveFileName)
		{
			PrepareMainMenuForLoad(saveFileName);
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(SemiFunc), "MenuActionHostGame")]
		private static void BeforePrivateGameLoad(string saveFileName)
		{
			PrepareMainMenuForLoad(saveFileName);
		}

		private static void PrepareMainMenuForLoad(string saveFileName)
		{
			RunManager instance = RunManager.instance;
			if (!string.IsNullOrEmpty(saveFileName) && !((Object)(object)instance == (Object)null) && SemiFunc.IsMainMenu())
			{
				bool num = GetBoolean(RestartingField, instance) || GetBoolean(RestartingDoneField, instance) || GetBoolean(WaitToChangeSceneField, instance) || GetBoolean(LobbyJoinField, instance);
				RestartingField?.SetValue(instance, false);
				RestartingDoneField?.SetValue(instance, false);
				WaitToChangeSceneField?.SetValue(instance, false);
				LobbyJoinField?.SetValue(instance, false);
				if (num)
				{
					Plugin.Log.LogWarning((object)("Cleared stale main-menu transition state before loading save '" + saveFileName + "'."));
				}
			}
		}

		private static bool GetBoolean(FieldInfo field, object instance)
		{
			object obj = field?.GetValue(instance);
			bool flag = default(bool);
			int num;
			if (obj is bool)
			{
				flag = (bool)obj;
				num = 1;
			}
			else
			{
				num = 0;
			}
			return (byte)((uint)num & (flag ? 1u : 0u)) != 0;
		}
	}
	internal static class SharedUpgradesPlusCompatibility
	{
		private const string PluginGuid = "Vippy.SharedUpgradesPlus";

		private const string CompatibilityTypeName = "SharedUpgradesPlus.Services.CompatibilityService";

		private static bool _installed;

		internal static IEnumerator InstallWhenReady(Harmony harmony)
		{
			if (!Chainloader.PluginInfos.ContainsKey("Vippy.SharedUpgradesPlus"))
			{
				yield break;
			}
			for (int attempt = 0; attempt < 120; attempt++)
			{
				if (_installed)
				{
					break;
				}
				Type type = AccessTools.TypeByName("SharedUpgradesPlus.Services.CompatibilityService");
				MethodInfo methodInfo = ((type == null) ? null : AccessTools.Method(type, "IsSharedByMoreUpgrades", (Type[])null, (Type[])null));
				if (methodInfo != null)
				{
					MethodInfo methodInfo2 = AccessTools.Method(typeof(SharedUpgradesPlusCompatibility), "OverrideDoubleShareCheck", (Type[])null, (Type[])null);
					harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					_installed = true;
					Plugin.Log.LogInfo((object)"SharedUpgradesPlus compatibility enabled: InventorySlot will not be distributed twice when Allow Team Upgrades is on.");
					yield break;
				}
				yield return null;
			}
			if (!_installed)
			{
				Plugin.Log.LogWarning((object)"SharedUpgradesPlus is installed, but its double-share compatibility hook could not be found.");
			}
		}

		private static void OverrideDoubleShareCheck(string upgradeKey, ref bool __result)
		{
			if (Plugin.TeamUpgradesEnabled && !string.IsNullOrEmpty(upgradeKey) && upgradeKey.EndsWith("InventorySlot", StringComparison.OrdinalIgnoreCase))
			{
				__result = true;
			}
		}
	}
	internal sealed class UpgradeBoxBridge : MonoBehaviour
	{
		private static readonly FieldInfo UpgradeIdField = AccessTools.Field(typeof(REPOLibItemUpgrade), "_upgradeId");

		private static readonly FieldInfo TogglePlayerPhotonIdField = AccessTools.Field(typeof(ItemToggle), "playerTogglePhotonID");

		private ItemToggle _itemToggle;

		private REPOLibItemUpgrade _repoLibUpgrade;

		private void Awake()
		{
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Expected O, but got Unknown
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Expected O, but got Unknown
			ItemUpgrade component = ((Component)this).GetComponent<ItemUpgrade>();
			_itemToggle = ((Component)this).GetComponent<ItemToggle>();
			_repoLibUpgrade = ((Component)this).GetComponent<REPOLibItemUpgrade>();
			if ((Object)(object)component == (Object)null || (Object)(object)_itemToggle == (Object)null || (Object)(object)_repoLibUpgrade == (Object)null || UpgradeIdField == null || TogglePlayerPhotonIdField == null)
			{
				Plugin.Log.LogError((object)"Spawned Inventory Slot Upgrade is missing its upgrade components.");
				return;
			}
			UpgradeIdField.SetValue(_repoLibUpgrade, "InventorySlot");
			ItemUpgrade val = component;
			if (val.upgradeEvent == null)
			{
				val.upgradeEvent = new UnityEvent();
			}
			((UnityEventBase)component.upgradeEvent).RemoveAllListeners();
			component.upgradeEvent.AddListener(new UnityAction(ApplyUpgrade));
		}

		private void ApplyUpgrade()
		{
			if (!Plugin.TeamUpgradesEnabled)
			{
				_repoLibUpgrade.Upgrade();
				return;
			}
			int num = (int)TogglePlayerPhotonIdField.GetValue(_itemToggle);
			PlayerAvatar val = SemiFunc.PlayerAvatarGetFromPhotonID(num);
			if ((Object)(object)val == (Object)null)
			{
				Plugin.Log.LogError((object)$"Could not apply the shared Inventory Slot Upgrade: player photon ID {num} was not found.");
			}
			else
			{
				if (SemiFunc.IsMultiplayer() && ((Object)(object)val.photonView == (Object)null || !val.photonView.IsMine))
				{
					return;
				}
				int num2 = Plugin.EffectiveMaximumSlots - 3;
				int num3 = 0;
				HashSet<string> hashSet = new HashSet<string>();
				foreach (PlayerAvatar item in SemiFunc.PlayerGetAll())
				{
					if (!((Object)(object)item == (Object)null))
					{
						string text = SemiFunc.PlayerGetSteamID(item);
						if (!string.IsNullOrEmpty(text) && hashSet.Add(text) && Plugin.SlotUpgrade.GetLevel(text) < num2)
						{
							Plugin.SlotUpgrade.AddLevel(item, 1);
							num3++;
						}
					}
				}
				Plugin.Log.LogInfo((object)("Shared Inventory Slot Upgrade activated by " + SemiFunc.PlayerGetName(val) + "; " + $"granted one level to {num3} current player(s), capped at {Plugin.EffectiveMaximumSlots} slots."));
			}
		}
	}
	internal static class UpgradeDecal
	{
		private const string ResourceName = "InventorySlotUpgrade.Assets.InventorySlotUpgrade_Albedo.png";

		private const string VanillaTextureName = "Upgrade_Health_Albedo";

		private static Texture2D _texture;

		internal static bool Apply(GameObject prefab)
		{
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: 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_00c2: Expected O, but got Unknown
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)prefab == (Object)null)
			{
				return false;
			}
			Texture2D val = LoadTexture();
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			int num = 0;
			Renderer[] componentsInChildren = prefab.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val2 in componentsInChildren)
			{
				Material[] sharedMaterials = val2.sharedMaterials;
				bool flag = false;
				for (int j = 0; j < sharedMaterials.Length; j++)
				{
					Material val3 = sharedMaterials[j];
					if (UsesVanillaHealthTexture(val3))
					{
						if ((Object)(object)val3.mainTexture != (Object)null)
						{
							((Texture)val).filterMode = val3.mainTexture.filterMode;
							((Texture)val).wrapMode = val3.mainTexture.wrapMode;
							((Texture)val).anisoLevel = val3.mainTexture.anisoLevel;
						}
						Material val4 = new Material(val3)
						{
							name = ((Object)val3).name + " - Inventory Slot Upgrade",
							mainTexture = (Texture)(object)val
						};
						sharedMaterials[j] = val4;
						flag = true;
						num++;
					}
				}
				if (flag)
				{
					val2.sharedMaterials = sharedMaterials;
				}
			}
			if (num == 0)
			{
				Plugin.Log.LogWarning((object)"Could not find a prefab material using 'Upgrade_Health_Albedo'. The vanilla health decal will remain visible.");
				return false;
			}
			Plugin.Log.LogInfo((object)$"Applied the embedded inventory-slot decal to {num} prefab material(s).");
			return true;
		}

		private static bool UsesVanillaHealthTexture(Material material)
		{
			if ((Object)(object)material == (Object)null || (Object)(object)material.mainTexture == (Object)null)
			{
				return false;
			}
			return ((Object)material.mainTexture).name.IndexOf("Upgrade_Health_Albedo", StringComparison.OrdinalIgnoreCase) >= 0;
		}

		private static Texture2D LoadTexture()
		{
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Expected O, but got Unknown
			if ((Object)(object)_texture != (Object)null)
			{
				return _texture;
			}
			using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("InventorySlotUpgrade.Assets.InventorySlotUpgrade_Albedo.png");
			if (stream == null)
			{
				Plugin.Log.LogError((object)"Embedded decal resource 'InventorySlotUpgrade.Assets.InventorySlotUpgrade_Albedo.png' was not found.");
				return null;
			}
			using MemoryStream memoryStream = new MemoryStream();
			stream.CopyTo(memoryStream);
			Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false)
			{
				name = "InventorySlotUpgrade_Albedo"
			};
			if (!ImageConversion.LoadImage(val, memoryStream.ToArray(), false))
			{
				Object.Destroy((Object)(object)val);
				Plugin.Log.LogError((object)"Unity could not decode the embedded inventory-slot decal PNG.");
				return null;
			}
			_texture = val;
			return _texture;
		}
	}
	[HarmonyPatch(typeof(StatsManager), "RunStartStats")]
	internal static class UpgradeDisplayPatch
	{
		private static readonly FieldInfo UpgradesInfoField = AccessTools.Field(typeof(StatsManager), "upgradesInfo");

		[HarmonyPostfix]
		private static void AddDisplayName(StatsManager __instance)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Expected O, but got Unknown
			if (UpgradesInfoField.GetValue(__instance) is Dictionary<string, UpgradeInfo> dictionary)
			{
				dictionary["playerUpgradeInventorySlot"] = new UpgradeInfo
				{
					displayName = "Inventory Slots"
				};
			}
		}
	}
	internal static class UpgradeItemFactory
	{
		internal const string AssetName = "InventorySlotUpgrade";

		internal const string DisplayName = "Inventory Slot Upgrade";

		private const string VanillaTemplateName = "Item Upgrade Player Health";

		private static GameObject _prefabRoot;

		internal static Item CreateItemData()
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			Item obj = ScriptableObject.CreateInstance<Item>();
			((Object)obj).name = "InventorySlotUpgrade";
			obj.itemName = "Inventory Slot Upgrade";
			obj.description = "Adds one inventory slot.";
			obj.itemType = (itemType)3;
			obj.emojiIcon = (emojiIcon)11;
			obj.itemVolume = (itemVolume)6;
			obj.value = ScriptableObject.CreateInstance<Value>();
			obj.minPlayerCount = 1;
			obj.maxPurchase = true;
			obj.physicalItem = true;
			ApplyConfiguredValues(obj);
			return obj;
		}

		internal static void ApplyConfiguredValues(Item item)
		{
			if (!((Object)(object)item == (Object)null))
			{
				if ((Object)(object)item.value == (Object)null)
				{
					item.value = ScriptableObject.CreateInstance<Value>();
				}
				int num = Plugin.EffectiveMaximumSlots - 3;
				item.value.valueMin = Plugin.EffectiveMinimumPrice / 4f;
				item.value.valueMax = Plugin.EffectiveMaximumPrice / 4f;
				item.maxAmount = num;
				item.maxAmountInShop = Mathf.Clamp(Plugin.Instance?.MaxAmountInShop.Value ?? 1, 1, 4);
				item.maxPurchaseAmount = num;
			}
		}

		internal static IEnumerator RegisterPrefabWhenReady()
		{
			Item template = null;
			int waits = 0;
			while ((Object)(object)template == (Object)null)
			{
				template = ((IEnumerable<Item>)Items.AllItems).FirstOrDefault((Func<Item, bool>)((Item item) => (Object)(object)item != (Object)null && ((Object)item).name == "Item Upgrade Player Health" && item.prefab != null && (Object)(object)((PrefabRef<GameObject>)(object)item.prefab).Prefab != (Object)null));
				if ((Object)(object)template == (Object)null)
				{
					waits++;
					if (waits == 120)
					{
						Plugin.Log.LogWarning((object)"Still waiting for vanilla prefab 'Item Upgrade Player Health'. Registration will keep retrying.");
					}
					yield return (object)new WaitForSeconds(0.25f);
				}
			}
			CopyTemplateMetadata(template, Plugin.UpgradeItemData);
			_prefabRoot = new GameObject("Inventory Slot Upgrade - Registered Prefabs");
			_prefabRoot.SetActive(false);
			Object.DontDestroyOnLoad((Object)(object)_prefabRoot);
			GameObject val = Object.Instantiate<GameObject>(((PrefabRef<GameObject>)(object)template.prefab).Prefab, _prefabRoot.transform, false);
			((Object)val).name = "InventorySlotUpgrade";
			UpgradeDecal.Apply(val);
			ItemAttributes component = val.GetComponent<ItemAttributes>();
			ItemUpgrade component2 = val.GetComponent<ItemUpgrade>();
			ItemToggle component3 = val.GetComponent<ItemToggle>();
			if ((Object)(object)component == (Object)null || (Object)(object)component2 == (Object)null || (Object)(object)component3 == (Object)null)
			{
				Plugin.Log.LogError((object)"The vanilla health-upgrade prefab no longer has the expected ItemAttributes, ItemUpgrade, and ItemToggle components.");
				Object.Destroy((Object)(object)_prefabRoot);
				_prefabRoot = null;
				yield break;
			}
			component.item = Plugin.UpgradeItemData;
			component2.isPlayerUpgrade = true;
			component2.upgradeEvent = new UnityEvent();
			REPOLibItemUpgrade val2 = val.GetComponent<REPOLibItemUpgrade>();
			if ((Object)(object)val2 == (Object)null)
			{
				val2 = val.AddComponent<REPOLibItemUpgrade>();
			}
			AccessTools.Field(typeof(REPOLibItemUpgrade), "_upgradeId").SetValue(val2, "InventorySlot");
			if ((Object)(object)val.GetComponent<UpgradeBoxBridge>() == (Object)null)
			{
				val.AddComponent<UpgradeBoxBridge>();
			}
			if (Items.RegisterItem(component) == null)
			{
				Plugin.Log.LogError((object)"REPOLib rejected the Inventory Slot Upgrade item prefab.");
			}
			else
			{
				Plugin.Log.LogInfo((object)("Registered '" + Plugin.UpgradeItemData.itemName + "' from vanilla prefab 'Item Upgrade Player Health' " + $"with a displayed price range of {Plugin.EffectiveMinimumPrice:0}-{Plugin.EffectiveMaximumPrice:0}."));
			}
		}

		private static void CopyTemplateMetadata(Item source, Item destination)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: 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_002d: 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_0045: Unknown result type (might be due to invalid IL or missing references)
			destination.disabled = false;
			destination.itemType = (itemType)3;
			destination.emojiIcon = source.emojiIcon;
			destination.itemVolume = source.itemVolume;
			destination.itemSecretShopType = source.itemSecretShopType;
			destination.colorPreset = source.colorPreset;
			destination.spawnRotationOffset = source.spawnRotationOffset;
			destination.physicalItem = source.physicalItem;
		}
	}
	[HarmonyPatch(typeof(ShopManager), "UpgradeValueGet")]
	internal static class UpgradePricePatch
	{
		[HarmonyPrefix]
		[HarmonyPriority(800)]
		private static bool Prefix(float _value, Item item, ref float __result)
		{
			if ((Object)(object)item == (Object)null || ((Object)item).name != "InventorySlotUpgrade")
			{
				return true;
			}
			__result = Mathf.Ceil(_value);
			return false;
		}
	}
}