Decompiled source of SBGItemFramework v0.1.0

SBGItemFramework.dll

Decompiled 14 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using Cray.SBGItemFramework.Internal;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Localization;
using UnityEngine.Localization.Settings;
using UnityEngine.Localization.Tables;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("SBGItemFramework")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+b05c8ecd1dc994ba6a0215a8705814501bf7f713")]
[assembly: AssemblyProduct("SBGItemFramework")]
[assembly: AssemblyTitle("SBGItemFramework")]
[assembly: AssemblyVersion("1.0.0.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 Cray.SBGItemFramework
{
	public interface IItemHandler
	{
		void OnUse(PlayerInventory inventory);

		void OnEquip(PlayerInventory inventory);

		void OnUnequip(PlayerInventory inventory);
	}
	public abstract class ItemHandlerBase : IItemHandler
	{
		public abstract void OnUse(PlayerInventory inventory);

		public virtual void OnEquip(PlayerInventory inventory)
		{
		}

		public virtual void OnUnequip(PlayerInventory inventory)
		{
		}
	}
	public static class ItemKit
	{
		private static readonly Dictionary<ItemType, RegisteredItem> _items = new Dictionary<ItemType, RegisteredItem>();

		public static IReadOnlyCollection<RegisteredItem> All => _items.Values;

		public static bool IsRegistered(ItemType id)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			return _items.ContainsKey(id);
		}

		public static RegisteredItem Get(ItemType id)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			if (!_items.TryGetValue(id, out var value))
			{
				return null;
			}
			return value;
		}

		public static void Register(RegisteredItem item)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: 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_0046: Unknown result type (might be due to invalid IL or missing references)
			if (item == null)
			{
				throw new ArgumentNullException("item");
			}
			if (_items.ContainsKey(item.Id))
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)($"SBGItemFramework: Register({item.Id}, '{item.DisplayName}') ignored — that id is already taken by '{_items[item.Id].DisplayName}'. " + "If two mods are claiming the same ItemType, the second registration loses; pick a different id."));
				}
				return;
			}
			RegisteredItem registeredItem = ApplyConfigBindings(item);
			_items[registeredItem.Id] = registeredItem;
			ManualLogSource log2 = Plugin.Log;
			if (log2 != null)
			{
				log2.LogInfo((object)$"SBGItemFramework: registered {registeredItem.Id} '{registeredItem.DisplayName}' (MaxUses={registeredItem.MaxUses}).");
			}
			CollectionInjector.NotifyRegistered(registeredItem);
		}

		private static RegisteredItem ApplyConfigBindings(RegisteredItem item)
		{
			//IL_0110: 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_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
			if (item.ConsumerConfig == null)
			{
				return item;
			}
			int num = item.MaxUses;
			Dictionary<int, float> dictionary = null;
			string text = "Item: " + item.DisplayName;
			if (item.BindMaxUsesToConfig)
			{
				ConfigEntry<int> val = item.ConsumerConfig.Bind<int>(text, "MaxUses", item.MaxUses, "Number of charges this item starts with. Set to 1 for single-use items.");
				num = Math.Max(1, val.Value);
			}
			if (item.BindSpawnWeightsToConfig && item.SpawnWeights != null)
			{
				dictionary = new Dictionary<int, float>();
				foreach (KeyValuePair<int, float> spawnWeight in item.SpawnWeights)
				{
					string text2 = PoolLabel(spawnWeight.Key);
					ConfigEntry<float> val2 = item.ConsumerConfig.Bind<float>(text, "SpawnWeight." + text2, spawnWeight.Value, "Relative spawn weight of this item in pool '" + text2 + "' (0 disables).");
					dictionary[spawnWeight.Key] = Math.Max(0f, val2.Value);
				}
			}
			if (num == item.MaxUses && dictionary == null)
			{
				return item;
			}
			RegisteredItem.Builder builder = RegisteredItem.Define(item.Id, item.DisplayName).WithHandler(item.Handler).WithMaxUses(num);
			if (item.IconSourceVanillaItem.HasValue)
			{
				builder.WithIconFromVanillaItem(item.IconSourceVanillaItem.Value);
			}
			if ((Object)(object)item.IconOverride != (Object)null)
			{
				builder.WithIconOverride(item.IconOverride);
			}
			if (item.IconTint.HasValue)
			{
				builder.WithIconTint(item.IconTint.Value);
			}
			if (!string.IsNullOrEmpty(item.Tooltip))
			{
				builder.WithTooltip(item.Tooltip);
			}
			if (item.MimicVanillaItem.HasValue)
			{
				builder.WithMimicVanillaItem(item.MimicVanillaItem.Value);
			}
			else if (!item.SuppressVanillaSwingEligibility)
			{
				builder.AllowVanillaSwingEligibility();
			}
			if (item.ItemDataPostInit != null)
			{
				builder.WithItemDataPostInit(item.ItemDataPostInit);
			}
			Dictionary<int, float> dictionary2 = dictionary ?? ((item.SpawnWeights != null) ? new Dictionary<int, float>(item.SpawnWeights) : null);
			if (dictionary2 != null)
			{
				foreach (KeyValuePair<int, float> item2 in dictionary2)
				{
					builder.WithSpawnWeight(item2.Key, item2.Value);
				}
			}
			return builder.Done();
		}

		internal static string PoolLabel(int poolIndex)
		{
			return poolIndex switch
			{
				0 => "AheadOfOwnBall", 
				1 => "Far", 
				2 => "Mid", 
				3 => "Close", 
				4 => "Lead", 
				5 => "MobilityBoxes", 
				_ => $"Pool{poolIndex}", 
			};
		}

		internal static IEnumerable<RegisteredItem> Snapshot()
		{
			return _items.Values.ToList();
		}
	}
	[BepInPlugin("cray.sbg.itemframework", "SBGItemFramework", "0.1.0")]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string ModGuid = "cray.sbg.itemframework";

		public const string ModName = "SBGItemFramework";

		public const string ModVersion = "0.1.0";

		internal static ManualLogSource Log;

		internal static Plugin Instance;

		private void Awake()
		{
			//IL_0016: 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_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			new Harmony("cray.sbg.itemframework").PatchAll();
			GameObject val = new GameObject("SBGItemFramework.Host")
			{
				hideFlags = (HideFlags)61
			};
			Object.DontDestroyOnLoad((Object)val);
			val.AddComponent<LocalizationSeederHost>();
			Log.LogInfo((object)"SBGItemFramework v0.1.0 loaded.");
		}
	}
	internal sealed class LocalizationSeederHost : MonoBehaviour
	{
		private void Update()
		{
			LocalizationSeeder.TryRunOnce();
		}
	}
	public delegate void ItemDataPostInit(ItemData synthesized, ItemData source);
	public sealed class RegisteredItem
	{
		public sealed class Builder
		{
			internal readonly ItemType _id;

			internal readonly string _displayName;

			internal IItemHandler _handler;

			internal int _maxUses = 1;

			internal ItemType? _iconSource;

			internal Sprite _iconOverride;

			internal Color? _iconTint;

			internal string _tooltip;

			internal Dictionary<int, float> _spawnWeights;

			internal bool _suppressVanillaSwing = true;

			internal ItemType? _mimicVanillaItem;

			internal ItemDataPostInit _itemDataPostInit;

			internal ConfigFile _consumerConfig;

			internal bool _bindMaxUsesToConfig;

			internal bool _bindSpawnWeightsToConfig;

			internal Builder(ItemType id, string displayName)
			{
				//IL_0014: Unknown result type (might be due to invalid IL or missing references)
				//IL_0016: Invalid comparison between Unknown and I4
				//IL_0041: 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)
				if ((int)id <= 0)
				{
					throw new ArgumentException("Id must be a positive ItemType value (use a high integer like 1001+ to avoid colliding with vanilla item ids).", "id");
				}
				if (string.IsNullOrWhiteSpace(displayName))
				{
					throw new ArgumentException("displayName cannot be null or whitespace.", "displayName");
				}
				_id = id;
				_displayName = displayName;
			}

			public Builder WithHandler(IItemHandler handler)
			{
				_handler = handler ?? throw new ArgumentNullException("handler");
				return this;
			}

			public Builder WithMaxUses(int uses)
			{
				if (uses < 1)
				{
					throw new ArgumentOutOfRangeException("uses", "MaxUses must be >= 1.");
				}
				_maxUses = uses;
				return this;
			}

			public Builder WithIconFromVanillaItem(ItemType source)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				_iconSource = source;
				return this;
			}

			public Builder WithIconOverride(Sprite sprite)
			{
				_iconOverride = sprite;
				return this;
			}

			public Builder WithIconTint(Color tint)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				_iconTint = tint;
				return this;
			}

			public Builder WithTooltip(string text)
			{
				_tooltip = text;
				return this;
			}

			public Builder WithSpawnWeight(int poolIndex, float weight)
			{
				if (poolIndex < 0 || poolIndex > 5)
				{
					throw new ArgumentOutOfRangeException("poolIndex", "Pool index must be 0..5 (see RegisteredItem.PoolAhead..PoolMobility).");
				}
				if (weight < 0f)
				{
					throw new ArgumentOutOfRangeException("weight", "Weight must be >= 0.");
				}
				if (_spawnWeights == null)
				{
					_spawnWeights = new Dictionary<int, float>();
				}
				_spawnWeights[poolIndex] = weight;
				return this;
			}

			public Builder AllowVanillaSwingEligibility()
			{
				_suppressVanillaSwing = false;
				return this;
			}

			public Builder WithItemDataPostInit(ItemDataPostInit callback)
			{
				_itemDataPostInit = callback;
				return this;
			}

			public Builder WithMimicVanillaItem(ItemType mimic)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				_mimicVanillaItem = mimic;
				_suppressVanillaSwing = false;
				return this;
			}

			public Builder WithConfigBindings(ConfigFile consumerConfig, bool bindMaxUses = true, bool bindSpawnWeights = true)
			{
				_consumerConfig = consumerConfig ?? throw new ArgumentNullException("consumerConfig");
				_bindMaxUsesToConfig = bindMaxUses;
				_bindSpawnWeightsToConfig = bindSpawnWeights;
				return this;
			}

			public RegisteredItem Done()
			{
				if (_handler == null)
				{
					throw new InvalidOperationException("RegisteredItem requires WithHandler(...) before Done().");
				}
				if (_iconSource.HasValue && (Object)(object)_iconOverride != (Object)null)
				{
					throw new InvalidOperationException("WithIconFromVanillaItem and WithIconOverride are mutually exclusive — pick one.");
				}
				return new RegisteredItem(this);
			}
		}

		public const int PoolAhead = 0;

		public const int PoolFar = 1;

		public const int PoolMid = 2;

		public const int PoolClose = 3;

		public const int PoolLead = 4;

		public const int PoolMobility = 5;

		public ItemType Id { get; }

		public string DisplayName { get; }

		public IItemHandler Handler { get; }

		public int MaxUses { get; }

		public ItemType? IconSourceVanillaItem { get; }

		public Sprite IconOverride { get; }

		public Color? IconTint { get; }

		public string Tooltip { get; }

		public IReadOnlyDictionary<int, float> SpawnWeights { get; }

		public bool SuppressVanillaSwingEligibility { get; }

		public ItemType? MimicVanillaItem { get; }

		public ItemDataPostInit ItemDataPostInit { get; }

		public ConfigFile ConsumerConfig { get; }

		public bool BindMaxUsesToConfig { get; }

		public bool BindSpawnWeightsToConfig { get; }

		private RegisteredItem(Builder b)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			Id = b._id;
			DisplayName = b._displayName;
			Handler = b._handler;
			MaxUses = b._maxUses;
			IconSourceVanillaItem = b._iconSource;
			IconOverride = b._iconOverride;
			IconTint = b._iconTint;
			Tooltip = b._tooltip;
			SpawnWeights = ((b._spawnWeights == null) ? null : new Dictionary<int, float>(b._spawnWeights));
			SuppressVanillaSwingEligibility = b._suppressVanillaSwing;
			MimicVanillaItem = b._mimicVanillaItem;
			ItemDataPostInit = b._itemDataPostInit;
			ConsumerConfig = b._consumerConfig;
			BindMaxUsesToConfig = b._bindMaxUsesToConfig;
			BindSpawnWeightsToConfig = b._bindSpawnWeightsToConfig;
		}

		public static Builder Define(ItemType id, string displayName)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			return new Builder(id, displayName);
		}
	}
}
namespace Cray.SBGItemFramework.Internal
{
	internal static class IconTinter
	{
		private readonly struct TintCacheKey : IEquatable<TintCacheKey>
		{
			private readonly int _textureId;

			private readonly int _packedRgba;

			public TintCacheKey(int textureId, Color tint)
			{
				//IL_0007: 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)
				//IL_000d: 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)
				//IL_0018: Unknown result type (might be due to invalid IL or missing references)
				//IL_0022: Unknown result type (might be due to invalid IL or missing references)
				//IL_002b: Unknown result type (might be due to invalid IL or missing references)
				_textureId = textureId;
				Color32 val = Color32.op_Implicit(tint);
				_packedRgba = (val.r << 24) | (val.g << 16) | (val.b << 8) | val.a;
			}

			public bool Equals(TintCacheKey other)
			{
				if (_textureId == other._textureId)
				{
					return _packedRgba == other._packedRgba;
				}
				return false;
			}

			public override bool Equals(object obj)
			{
				if (obj is TintCacheKey other)
				{
					return Equals(other);
				}
				return false;
			}

			public override int GetHashCode()
			{
				return (_textureId * 397) ^ _packedRgba;
			}
		}

		private static readonly Dictionary<TintCacheKey, Sprite> _cache = new Dictionary<TintCacheKey, Sprite>();

		private static Material _colourMulMaterial;

		public static Sprite ApplyTint(Sprite source, Color tint)
		{
			//IL_0026: 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_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: 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_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)source == (Object)null || (Object)(object)source.texture == (Object)null)
			{
				return source;
			}
			TintCacheKey key = new TintCacheKey(((Object)source.texture).GetInstanceID(), tint);
			if (_cache.TryGetValue(key, out var value) && (Object)(object)value != (Object)null)
			{
				return value;
			}
			Texture2D val = (((Texture)source.texture).isReadable ? TintViaCpuPixels(source.texture, tint) : TintViaBlit(source.texture, tint));
			if ((Object)(object)val == (Object)null)
			{
				return source;
			}
			Rect rect = source.rect;
			float x = source.pivot.x;
			Rect rect2 = source.rect;
			float num = x / ((Rect)(ref rect2)).width;
			float y = source.pivot.y;
			rect2 = source.rect;
			Sprite val2 = Sprite.Create(val, rect, new Vector2(num, y / ((Rect)(ref rect2)).height), source.pixelsPerUnit);
			((Object)val2).name = ((Object)source).name + "__sbgkit_tinted";
			_cache[key] = val2;
			return val2;
		}

		private static Texture2D TintViaCpuPixels(Texture2D source, Color tint)
		{
			//IL_0007: 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)
			//IL_000d: 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)
			//IL_0019: 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_0022: 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_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: 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)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: 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_0098: 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_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Expected O, but got Unknown
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				Color32[] pixels = source.GetPixels32();
				Color32 val = Color32.op_Implicit(tint);
				for (int i = 0; i < pixels.Length; i++)
				{
					Color32 val2 = pixels[i];
					pixels[i] = new Color32((byte)(val2.r * val.r / 255), (byte)(val2.g * val.g / 255), (byte)(val2.b * val.b / 255), val2.a);
				}
				Texture2D val3 = new Texture2D(((Texture)source).width, ((Texture)source).height, source.format, false)
				{
					wrapMode = ((Texture)source).wrapMode,
					filterMode = ((Texture)source).filterMode
				};
				val3.SetPixels32(pixels);
				val3.Apply(false, false);
				return val3;
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("SBGItemFramework: CPU-pixel tint of '" + ((Object)source).name + "' failed (" + ex.GetType().Name + "); attempting GPU blit."));
				}
				return TintViaBlit(source, tint);
			}
		}

		private static Texture2D TintViaBlit(Texture2D source, Color tint)
		{
			//IL_0036: 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_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Expected O, but got Unknown
			RenderTexture active = RenderTexture.active;
			RenderTexture temporary = RenderTexture.GetTemporary(((Texture)source).width, ((Texture)source).height, 0, (RenderTextureFormat)0);
			try
			{
				RenderTexture.active = temporary;
				GL.Clear(false, true, new Color(0f, 0f, 0f, 0f));
				Material val = TempColourMultiplyMaterial(tint);
				Graphics.Blit((Texture)(object)source, temporary, val);
				Texture2D val2 = new Texture2D(((Texture)source).width, ((Texture)source).height, (TextureFormat)4, false);
				val2.ReadPixels(new Rect(0f, 0f, (float)((Texture)source).width, (float)((Texture)source).height), 0, 0);
				val2.Apply(false, false);
				return val2;
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("SBGItemFramework: GPU-blit tint of '" + ((Object)source).name + "' failed (" + ex.GetType().Name + "); icon will render untinted."));
				}
				return null;
			}
			finally
			{
				RenderTexture.active = active;
				RenderTexture.ReleaseTemporary(temporary);
			}
		}

		private static Material TempColourMultiplyMaterial(Color tint)
		{
			//IL_0034: 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_002f: Expected O, but got Unknown
			if ((Object)(object)_colourMulMaterial == (Object)null)
			{
				_colourMulMaterial = new Material(Shader.Find("UI/Default") ?? Shader.Find("Sprites/Default"));
			}
			_colourMulMaterial.color = tint;
			return _colourMulMaterial;
		}
	}
	internal static class CollectionInjector
	{
		private static readonly FieldInfo ItemsField = AccessTools.Field(typeof(ItemCollection), "items");

		private static readonly FieldInfo ItemDataTypeBacking = AccessTools.Field(typeof(ItemData), "<Type>k__BackingField");

		private static readonly FieldInfo ItemDataIconBacking = AccessTools.Field(typeof(ItemData), "<Icon>k__BackingField");

		private static readonly FieldInfo ItemDataMaxUsesBacking = AccessTools.Field(typeof(ItemData), "<MaxUses>k__BackingField");

		private static readonly FieldInfo ItemDataPrefabBacking = AccessTools.Field(typeof(ItemData), "<Prefab>k__BackingField");

		private static readonly FieldInfo ItemDataNonAimUseBacking = AccessTools.Field(typeof(ItemData), "<NonAimUse>k__BackingField");

		private static readonly Dictionary<ItemType, ItemData> _producedItemData = new Dictionary<ItemType, ItemData>();

		private static bool _initializeFired;

		private static ItemCollection _liveCollection;

		internal static void Apply(ItemCollection collection)
		{
			//IL_0042: 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)
			if ((Object)(object)collection == (Object)null || ItemsField == null || !(ItemsField.GetValue(collection) is ItemData[] array))
			{
				return;
			}
			HashSet<ItemType> hashSet = new HashSet<ItemType>();
			for (int i = 0; i < array.Length; i++)
			{
				if (array[i] != null)
				{
					hashSet.Add(array[i].Type);
				}
			}
			List<ItemData> list = null;
			foreach (RegisteredItem item in ItemKit.Snapshot())
			{
				if (hashSet.Contains(item.Id))
				{
					continue;
				}
				ItemData orBuildItemData = GetOrBuildItemData(item, array);
				if (orBuildItemData != null)
				{
					if (list == null)
					{
						list = new List<ItemData>();
					}
					list.Add(orBuildItemData);
				}
			}
			if (list != null)
			{
				ItemData[] array2 = (ItemData[])(object)new ItemData[array.Length + list.Count];
				Array.Copy(array, array2, array.Length);
				for (int j = 0; j < list.Count; j++)
				{
					array2[array.Length + j] = list[j];
				}
				ItemsField.SetValue(collection, array2);
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogInfo((object)$"SBGItemFramework: extended ItemCollection.items by {list.Count} entry(ies); total now {array2.Length}.");
				}
			}
		}

		private static ItemData GetOrBuildItemData(RegisteredItem reg, ItemData[] currentItems)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Expected O, but got Unknown
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			if (_producedItemData.TryGetValue(reg.Id, out var value) && value != null)
			{
				Sprite val = ResolveIcon(reg, currentItems);
				if ((Object)(object)val != (Object)null)
				{
					ItemDataIconBacking?.SetValue(value, val);
				}
				ItemDataMaxUsesBacking?.SetValue(value, reg.MaxUses);
				return value;
			}
			ItemData val2 = new ItemData();
			ItemDataTypeBacking?.SetValue(val2, reg.Id);
			ItemDataMaxUsesBacking?.SetValue(val2, reg.MaxUses);
			ItemDataNonAimUseBacking?.SetValue(val2, (object)(ItemNonAimingUse)0);
			ItemData val3 = ResolveSource(reg, currentItems);
			if (val3 != null)
			{
				if (ItemDataPrefabBacking != null)
				{
					ItemDataPrefabBacking.SetValue(val2, val3.Prefab);
				}
				Sprite val4 = ResolveIcon(reg, currentItems);
				if ((Object)(object)val4 != (Object)null)
				{
					ItemDataIconBacking?.SetValue(val2, val4);
				}
			}
			val2.Initialize();
			_producedItemData[reg.Id] = val2;
			if (reg.ItemDataPostInit != null)
			{
				try
				{
					reg.ItemDataPostInit(val2, val3);
				}
				catch (Exception arg)
				{
					ManualLogSource log = Plugin.Log;
					if (log != null)
					{
						log.LogError((object)$"SBGItemFramework: ItemDataPostInit for {reg.Id} threw: {arg}");
					}
				}
			}
			return val2;
		}

		private static ItemData ResolveSource(RegisteredItem reg, ItemData[] currentItems)
		{
			//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_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			if (!reg.IconSourceVanillaItem.HasValue)
			{
				return null;
			}
			ItemType value = reg.IconSourceVanillaItem.Value;
			for (int i = 0; i < currentItems.Length; i++)
			{
				if (currentItems[i] != null && currentItems[i].Type == value)
				{
					return currentItems[i];
				}
			}
			return null;
		}

		private static Sprite ResolveIcon(RegisteredItem reg, ItemData[] currentItems)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)reg.IconOverride != (Object)null)
			{
				if (!reg.IconTint.HasValue)
				{
					return reg.IconOverride;
				}
				return IconTinter.ApplyTint(reg.IconOverride, reg.IconTint.Value);
			}
			ItemData val = ResolveSource(reg, currentItems);
			if (val == null || (Object)(object)val.Icon == (Object)null)
			{
				return null;
			}
			if (!reg.IconTint.HasValue)
			{
				return val.Icon;
			}
			return IconTinter.ApplyTint(val.Icon, reg.IconTint.Value);
		}

		internal static void NotifyRegistered(RegisteredItem item)
		{
			if (_initializeFired && !((Object)(object)_liveCollection == (Object)null))
			{
				DeferredApply.Schedule(_liveCollection);
			}
		}

		internal static void OnInitializeRan(ItemCollection collection)
		{
			_initializeFired = true;
			_liveCollection = collection;
		}
	}
	[HarmonyPatch(typeof(ItemCollection), "Initialize")]
	internal static class Patch_ItemCollection_Initialize
	{
		private static void Prefix(ItemCollection __instance)
		{
			CollectionInjector.Apply(__instance);
		}

		private static void Postfix(ItemCollection __instance)
		{
			CollectionInjector.OnInitializeRan(__instance);
		}
	}
	[HarmonyPatch(typeof(ItemCollection), "OnEnable")]
	internal static class Patch_ItemCollection_OnEnable
	{
		private static void Prefix(ItemCollection __instance)
		{
			CollectionInjector.Apply(__instance);
		}
	}
	internal static class DeferredApply
	{
		private sealed class Runner : MonoBehaviour
		{
		}

		private static GameObject _runner;

		private static bool _scheduled;

		public static void Schedule(ItemCollection collection)
		{
			if (!_scheduled)
			{
				EnsureRunner();
				_scheduled = true;
				((MonoBehaviour)_runner.GetComponent<Runner>()).StartCoroutine(RunNext(collection));
			}
		}

		private static IEnumerator RunNext(ItemCollection collection)
		{
			yield return null;
			_scheduled = false;
			if (!((Object)(object)collection == (Object)null))
			{
				CollectionInjector.Apply(collection);
				AccessTools.Method(typeof(ItemCollection), "Initialize", (Type[])null, (Type[])null)?.Invoke(collection, null);
			}
		}

		private static void EnsureRunner()
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Expected O, but got Unknown
			if (!((Object)(object)_runner != (Object)null))
			{
				_runner = new GameObject("SBGItemFramework.DeferredApplyRunner");
				Object.DontDestroyOnLoad((Object)(object)_runner);
				((Object)_runner).hideFlags = (HideFlags)61;
				_runner.AddComponent<Runner>();
			}
		}
	}
	[HarmonyPatch(typeof(PlayerInventory), "TryUseItem")]
	internal static class Patch_PlayerInventory_TryUseItem
	{
		private static readonly MethodInfo GetEffectiveSlotMethod = AccessTools.Method(typeof(PlayerInventory), "GetEffectiveSlot", (Type[])null, (Type[])null);

		private static bool Prefix(PlayerInventory __instance, ref bool __result)
		{
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: 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)
			int equippedItemIndex = __instance.EquippedItemIndex;
			if (equippedItemIndex < 0 || GetEffectiveSlotMethod == null)
			{
				return true;
			}
			InventorySlot val;
			try
			{
				val = (InventorySlot)GetEffectiveSlotMethod.Invoke(__instance, new object[1] { equippedItemIndex });
			}
			catch
			{
				return true;
			}
			RegisteredItem registeredItem = ItemKit.Get(val.itemType);
			if (registeredItem == null)
			{
				return true;
			}
			__result = true;
			try
			{
				registeredItem.Handler.OnUse(__instance);
			}
			catch (Exception arg)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogError((object)$"SBGItemFramework: handler for {val.itemType} threw on OnUse: {arg}");
				}
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(PlayerInventory), "GetEffectivelyEquippedItem")]
	internal static class Patch_PlayerInventory_GetEffectivelyEquippedItem
	{
		private static void Postfix(bool ignoreEquipmentHiding, ref ItemType __result)
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Expected I4, but got Unknown
			RegisteredItem registeredItem = ItemKit.Get(__result);
			if (registeredItem != null)
			{
				if (registeredItem.MimicVanillaItem.HasValue)
				{
					__result = (ItemType)(int)registeredItem.MimicVanillaItem.Value;
				}
				else if (!ignoreEquipmentHiding && registeredItem.SuppressVanillaSwingEligibility)
				{
					__result = (ItemType)0;
				}
			}
		}
	}
	[HarmonyPatch(typeof(LocalizedString), "GetLocalizedString", new Type[] { })]
	internal static class Patch_LocalizedString_GetLocalizedString
	{
		private static void Postfix(LocalizedString __instance, ref string __result)
		{
			if (!string.IsNullOrEmpty(__result) && __result.StartsWith("ITEM_", StringComparison.Ordinal) && int.TryParse(__result.Substring("ITEM_".Length), out var result))
			{
				RegisteredItem registeredItem = ItemKit.Get((ItemType)result);
				if (registeredItem != null)
				{
					__result = registeredItem.DisplayName;
				}
			}
		}
	}
	[HarmonyPatch(typeof(HotkeyUi), "SetName")]
	internal static class Patch_HotkeyUi_SetName
	{
		private static void Prefix(ref LocalizedString localizedName)
		{
			if (localizedName != null)
			{
				_ = ((LocalizedReference)localizedName).IsEmpty;
			}
		}
	}
	[HarmonyPatch(typeof(PauseMenu), "UpdateItemProbabilites")]
	internal static class Patch_PauseMenu_UpdateItemProbabilites
	{
		private static readonly FieldInfo TilesField = AccessTools.Field(typeof(PauseMenu), "allItemProbabilities");

		private static readonly FieldInfo TooltipField = AccessTools.Field(typeof(PauseMenu), "itemProbabilityTooltip");

		private static readonly FieldInfo TooltipSourcesField = AccessTools.Field(typeof(UiTooltip), "tooltipSources");

		private static void Postfix(PauseMenu __instance)
		{
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			if (TilesField == null || TooltipField == null)
			{
				return;
			}
			GameObject[] array = TilesField.GetValue(__instance) as GameObject[];
			object? value = TooltipField.GetValue(__instance);
			UiTooltip val = (UiTooltip)((value is UiTooltip) ? value : null);
			if (array == null || (Object)(object)val == (Object)null)
			{
				return;
			}
			for (int i = 0; i < array.Length; i++)
			{
				if ((Object)(object)array[i] == (Object)null)
				{
					continue;
				}
				ItemData val2 = (((Object)(object)GameManager.AllItems != (Object)null && i < GameManager.AllItems.Count) ? GameManager.AllItems.GetItemAtIndex(i) : null);
				if (val2 == null)
				{
					continue;
				}
				RegisteredItem registeredItem = ItemKit.Get(val2.Type);
				if (registeredItem != null && !string.IsNullOrEmpty(registeredItem.Tooltip))
				{
					RectTransform component = array[i].GetComponent<RectTransform>();
					if (!((Object)(object)component == (Object)null))
					{
						string text = TryReadExistingTooltip(val, component);
						string text2 = (string.IsNullOrEmpty(text) ? registeredItem.Tooltip : (text + "\n<i>" + registeredItem.Tooltip + "</i>"));
						val.RegisterTooltip(component, text2, (string)null);
					}
				}
			}
		}

		private static string TryReadExistingTooltip(UiTooltip tooltip, RectTransform rt)
		{
			if (TooltipSourcesField == null)
			{
				return null;
			}
			object value = TooltipSourcesField.GetValue(tooltip);
			if (value == null)
			{
				return null;
			}
			MethodInfo method = value.GetType().GetMethod("get_Item", BindingFlags.Instance | BindingFlags.Public);
			MethodInfo method2 = value.GetType().GetMethod("ContainsKey", BindingFlags.Instance | BindingFlags.Public);
			if (method == null || method2 == null)
			{
				return null;
			}
			if (!(bool)method2.Invoke(value, new object[1] { rt }))
			{
				return null;
			}
			object obj = method.Invoke(value, new object[1] { rt });
			return obj.GetType().GetField("Item1")?.GetValue(obj) as string;
		}
	}
	[HarmonyPatch(typeof(ItemSpawnerSettings), "ResetRuntimeData")]
	internal static class Patch_ItemSpawnerSettings_ResetRuntimeData
	{
		private static readonly FieldInfo SpawnChancesField = AccessTools.Field(typeof(ItemPool), "spawnChances");

		private static readonly FieldInfo TotalWeightField = AccessTools.Field(typeof(ItemPool), "totalSpawnChanceWeight");

		private static void Postfix(ItemSpawnerSettings __instance)
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			if (SpawnChancesField == null || TotalWeightField == null)
			{
				return;
			}
			if ((Object)(object)__instance.AheadOfBallItemPool == (Object)null)
			{
				if (__instance.ItemPools != null && __instance.ItemPools.Count > 0)
				{
					InjectInto(__instance.ItemPools[0].pool, 5);
				}
				return;
			}
			InjectInto(__instance.AheadOfBallItemPool, 0);
			if (__instance.ItemPools != null)
			{
				for (int i = 0; i < __instance.ItemPools.Count; i++)
				{
					InjectInto(__instance.ItemPools[i].pool, i + 1);
				}
			}
		}

		private static void InjectInto(ItemPool pool, int poolIndex)
		{
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: 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_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)pool == (Object)null)
			{
				return;
			}
			List<ItemSpawnChance> list = null;
			foreach (RegisteredItem item in ItemKit.All)
			{
				if (item.SpawnWeights != null && item.SpawnWeights.TryGetValue(poolIndex, out var value) && !(value <= 0f))
				{
					if (list == null)
					{
						list = new List<ItemSpawnChance>();
					}
					list.Add(new ItemSpawnChance
					{
						item = item.Id,
						spawnChanceWeight = value
					});
				}
			}
			if (list != null && list.Count != 0)
			{
				ItemSpawnChance[] array = (SpawnChancesField.GetValue(pool) as ItemSpawnChance[]) ?? Array.Empty<ItemSpawnChance>();
				ItemSpawnChance[] array2 = (ItemSpawnChance[])(object)new ItemSpawnChance[array.Length + list.Count];
				Array.Copy(array, array2, array.Length);
				for (int i = 0; i < list.Count; i++)
				{
					array2[array.Length + i] = list[i];
				}
				SpawnChancesField.SetValue(pool, array2);
				float num = 0f;
				for (int j = 0; j < array2.Length; j++)
				{
					num += array2[j].spawnChanceWeight;
				}
				TotalWeightField.SetValue(pool, num);
			}
		}
	}
	internal static class LocalizationSeeder
	{
		private static bool _seeded;

		public static void TryRunOnce()
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Expected I4, but got Unknown
			if (_seeded)
			{
				return;
			}
			try
			{
				StringTable val = ((LocalizedDatabase<StringTable, StringTableEntry>)(object)LocalizationSettings.StringDatabase)?.GetTable(TableReference.op_Implicit("Data"), (Locale)null);
				if ((Object)(object)val == (Object)null)
				{
					return;
				}
				foreach (RegisteredItem item in ItemKit.All)
				{
					string text = "ITEM_" + (int)item.Id;
					if (((DetailedLocalizationTable<StringTableEntry>)(object)val).GetEntry(text) == null)
					{
						((DetailedLocalizationTable<StringTableEntry>)(object)val).AddEntry(text, item.DisplayName);
					}
				}
				_seeded = true;
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogInfo((object)"SBGItemFramework: seeded Localization 'Data' table with custom item names.");
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log2 = Plugin.Log;
				if (log2 != null)
				{
					log2.LogDebug((object)("SBGItemFramework: localization seed deferred (" + ex.GetType().Name + ": " + ex.Message + "); will retry next frame."));
				}
			}
		}
	}
}