Decompiled source of SkillSelection v1.0.1

SkillSelection.dll

Decompiled 13 hours ago
using System;
using System.Buffers.Binary;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text.Json;
using BepInEx;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using BepInEx.Unity.IL2CPP.Hook;
using FastText;
using FastText.Data;
using Il2CppInterop.Common;
using Il2CppInterop.Runtime;
using Il2CppInterop.Runtime.Attributes;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSystem;
using Microsoft.CodeAnalysis;
using MonoMod.RuntimeDetour;
using Str;
using UnityEngine;
using UnityEngine.SceneManagement;
using _K;
using _m;
using ifapp.Game;
using ifapp.Game.Common;
using ifapp.Game.Data;
using ifapp.Game.Data.Crafting;
using ifapp.Game.Input;
using ifapp.Game.Scenes;
using ifapp.Game.Scenes.Recipe;
using ifapp.Game.UI.Common;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("SkillSelection")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("在制卡界面按实际携带的技能筛选粒子。")]
[assembly: AssemblyFileVersion("1.0.1.0")]
[assembly: AssemblyInformationalVersion("1.0.1")]
[assembly: AssemblyProduct("SkillSelection")]
[assembly: AssemblyTitle("SkillSelection")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.1.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

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

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace InFalsusMod
{
	[BepInPlugin("menglei.infalsus.skillselection", "In Falsus Skill Selection", "1.0.1")]
	[BepInProcess("infalsus.exe")]
	public sealed class Plugin : BasePlugin
	{
		private SkillFilterNativeHooks? filterHooks;

		internal static ManualLogSource Logger { get; private set; }

		public override void Load()
		{
			Logger = ((BasePlugin)this).Log;
			WindowsConsoleEncoding.EnsureUtf8(((BasePlugin)this).Log);
			try
			{
				filterHooks = new SkillFilterNativeHooks();
				((BasePlugin)this).AddComponent<SkillFilterPanel>();
			}
			catch
			{
				filterHooks?.Dispose();
				filterHooks = null;
				throw;
			}
			((BasePlugin)this).Log.LogInfo((object)"加载完成。");
		}
	}
	internal static class PngRgba
	{
		private static readonly byte[] Signature = new byte[8] { 137, 80, 78, 71, 13, 10, 26, 10 };

		private const int BytesPerPixel = 4;

		internal static DecodedImage Decode(Stream stream)
		{
			using MemoryStream memoryStream = new MemoryStream();
			stream.CopyTo(memoryStream);
			Span<byte> span = memoryStream.GetBuffer().AsSpan(0, (int)memoryStream.Length);
			if (span.Length < Signature.Length || !span.Slice(0, Signature.Length).SequenceEqual(Signature))
			{
				throw new InvalidDataException("特性筛选入口图案不是 PNG。");
			}
			int num = 0;
			int num2 = 0;
			using MemoryStream memoryStream2 = new MemoryStream();
			int num3 = Signature.Length;
			while (true)
			{
				if (num3 + 12 > span.Length)
				{
					throw new InvalidDataException("特性筛选入口图案数据不完整。");
				}
				int num4 = checked((int)BinaryPrimitives.ReadUInt32BigEndian(span.Slice(num3)));
				Span<byte> span2 = span.Slice(num3 + 4, 4);
				if (num3 + 12 + num4 > span.Length)
				{
					throw new InvalidDataException("特性筛选入口图案数据不完整。");
				}
				Span<byte> span3 = span.Slice(num3 + 8, num4);
				checked
				{
					if (span2.SequenceEqual("IHDR"u8))
					{
						num = (int)BinaryPrimitives.ReadUInt32BigEndian(span3);
						num2 = (int)BinaryPrimitives.ReadUInt32BigEndian(span3.Slice(4));
						if (num <= 0 || num2 <= 0 || span3[8] != 8 || span3[9] != 6 || span3[10] != 0 || span3[11] != 0 || span3[12] != 0)
						{
							throw new InvalidDataException("特性筛选入口图案必须是 8 位 RGBA 非隔行 PNG。");
						}
					}
					else if (span2.SequenceEqual("IDAT"u8))
					{
						memoryStream2.Write(span3);
					}
					else if (span2.SequenceEqual("IEND"u8))
					{
						break;
					}
				}
				num3 += 12 + num4;
			}
			if (num == 0)
			{
				throw new InvalidDataException("特性筛选入口图案缺少 IHDR。");
			}
			int num5;
			byte[] array;
			checked
			{
				num5 = num * 4;
				array = new byte[(num5 + 1) * num2];
				memoryStream2.Position = 0L;
			}
			using (ZLibStream zLibStream = new ZLibStream(memoryStream2, CompressionMode.Decompress))
			{
				int num6;
				for (int i = 0; i < array.Length; i += num6)
				{
					if ((num6 = zLibStream.Read(array, i, array.Length - i)) == 0)
					{
						throw new InvalidDataException("特性筛选入口图案像素数据不完整。");
					}
				}
			}
			byte[] array2 = new byte[checked(num5 * num2)];
			byte[] array3 = new byte[num5];
			byte[] array4 = new byte[num5];
			for (int j = 0; j < num2; j++)
			{
				int num7 = j * (num5 + 1);
				byte filter = array[num7];
				array.AsSpan(num7 + 1, num5).CopyTo(array4);
				Unfilter(filter, array4, array3);
				array4.CopyTo(array2.AsSpan((num2 - 1 - j) * num5, num5));
				byte[] array5 = array4;
				array4 = array3;
				array3 = array5;
			}
			return new DecodedImage(num, num2, array2);
		}

		private static void Unfilter(byte filter, byte[] line, byte[] previous)
		{
			for (int i = 0; i < line.Length; i++)
			{
				int num = ((i >= 4) ? line[i - 4] : 0);
				int num2 = previous[i];
				int upLeft = ((i >= 4) ? previous[i - 4] : 0);
				int num3 = filter switch
				{
					0 => 0, 
					1 => num, 
					2 => num2, 
					3 => (num + num2) / 2, 
					4 => Paeth(num, num2, upLeft), 
					_ => throw new InvalidDataException("特性筛选入口图案使用了未知的 PNG 过滤类型。"), 
				};
				line[i] = (byte)(line[i] + num3);
			}
		}

		private static int Paeth(int left, int up, int upLeft)
		{
			int num = left + up - upLeft;
			int num2 = Math.Abs(num - left);
			int num3 = Math.Abs(num - up);
			int num4 = Math.Abs(num - upLeft);
			if (num2 > num3 || num2 > num4)
			{
				if (num3 > num4)
				{
					return upLeft;
				}
				return up;
			}
			return left;
		}
	}
	internal readonly record struct DecodedImage(int Width, int Height, byte[] BottomUpPixels);
	internal static class SkillFilter
	{
		internal static readonly HashSet<string> Families = new HashSet<string>(StringComparer.Ordinal);

		internal static readonly HashSet<int> Tiers = new HashSet<int>();

		internal static bool MatchAll;

		private static readonly Dictionary<int, TraitInfo> Traits = TraitCatalog.Entries.ToDictionary((TraitInfo info) => info.Id);

		private static bool TierLimited
		{
			get
			{
				int count = Tiers.Count;
				if (count > 0)
				{
					return count < 3;
				}
				return false;
			}
		}

		internal static bool Active
		{
			get
			{
				if (Families.Count <= 0)
				{
					return TierLimited;
				}
				return true;
			}
		}

		internal static bool AppliesSelection(_bH mode)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Invalid comparison between Unknown and I4
			if ((int)mode == 0 || (int)mode == 2)
			{
				return true;
			}
			return false;
		}

		internal static UnorderedListVal<IotaInstance> View(UnorderedListVal<IotaInstance> source)
		{
			//IL_0020: 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_0026: 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)
			if (!Active)
			{
				return source;
			}
			UnorderedListVal<IotaInstance> val = new UnorderedListVal<IotaInstance>(source.Length);
			for (int i = 0; i < source.Length; i++)
			{
				IotaInstance val2 = source.RawBuffer[i];
				if (Matches(val2))
				{
					val.Add(val2);
				}
			}
			return val;
		}

		internal static bool Matches(IotaInstance item)
		{
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			if (Families.Count == 0)
			{
				if (!TierLimited)
				{
					return true;
				}
				for (int i = 0; i < ParticleData.TraitCount(item); i++)
				{
					if (Traits.TryGetValue(ParticleData.GetTrait(item, i), out TraitInfo value) && Tiers.Contains(value.Tier))
					{
						return true;
					}
				}
				return false;
			}
			foreach (string family in Families)
			{
				bool flag = false;
				for (int j = 0; j < ParticleData.TraitCount(item); j++)
				{
					if (Traits.TryGetValue(ParticleData.GetTrait(item, j), out TraitInfo value2) && value2.Family == family && (!TierLimited || Tiers.Contains(value2.Tier)))
					{
						flag = true;
						break;
					}
				}
				if (flag && !MatchAll)
				{
					return true;
				}
				if (!flag && MatchAll)
				{
					return false;
				}
			}
			return MatchAll;
		}
	}
	internal static class SkillFilterCatalog
	{
		internal static readonly SkillFilterGroup[] Groups = new SkillFilterGroup[4]
		{
			new SkillFilterGroup("DamageTraits", new int[7] { 2, 5, 8, 11, 12, 13, 63 }),
			new SkillFilterGroup("HealingTraits", new int[6] { 22, 25, 28, 31, 32, 33 }),
			new SkillFilterGroup("BuffTraits", new int[8] { 36, 39, 37, 38, 40, 43, 46, 49 }),
			new SkillFilterGroup("DebuffTraits", new int[5] { 16, 18, 19, 20, 21 })
		};

		internal static readonly TraitInfo[] Families = LoadFamilies();

		private static TraitInfo[] LoadFamilies()
		{
			Dictionary<int, TraitInfo> entries = TraitCatalog.Entries.ToDictionary((TraitInfo info) => info.Id);
			TraitInfo[] array = (from id in Groups.SelectMany((SkillFilterGroup @group) => @group.TraitIds)
				select entries[id]).ToArray();
			HashSet<string> hashSet = TraitCatalog.Entries.Select((TraitInfo info) => info.Family).ToHashSet<string>(StringComparer.Ordinal);
			if (array.Select((TraitInfo info) => info.Family).Distinct<string>(StringComparer.Ordinal).Count() != array.Length || !hashSet.SetEquals(array.Select((TraitInfo info) => info.Family)))
			{
				throw new InvalidOperationException("特性展示分组与游戏技能目录不一致。");
			}
			return array;
		}
	}
	internal sealed record SkillFilterGroup(string TitleKey, int[] TraitIds);
	internal sealed class SkillFilterEntryVisuals : IDisposable
	{
		private Texture2D? texture;

		private Material? material;

		internal SkillFilterEntryVisuals(UIButton button, UIButton lastColor, UIButton previousColor)
		{
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: 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)
			//IL_0118: Expected O, but got Unknown
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Expected O, but got Unknown
			//IL_01d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0206: Unknown result type (might be due to invalid IL or missing references)
			//IL_0217: Unknown result type (might be due to invalid IL or missing references)
			//IL_0225: Unknown result type (might be due to invalid IL or missing references)
			//IL_0233: Unknown result type (might be due to invalid IL or missing references)
			//IL_0248: Unknown result type (might be due to invalid IL or missing references)
			//IL_024d: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				Transform val = ((Component)button).transform.Find("TraitsOnly") ?? throw new InvalidOperationException("原版特性入口缺少有特性图文层。");
				Transform obj = val.Find("btn-traitswitch-traitsonly");
				Constrained2D val2 = ((obj != null) ? ((Component)obj).GetComponent<Constrained2D>() : null) ?? throw new InvalidOperationException("原版特性入口缺少图案布局。");
				Constrained2D val3 = ((Component)((Component)lastColor).transform.GetChild(0)).GetComponent<Constrained2D>() ?? throw new InvalidOperationException("原版颜色按钮缺少图案布局。");
				for (int i = 0; i < ((Component)button).transform.childCount; i++)
				{
					Transform child = ((Component)button).transform.GetChild(i);
					((Component)child).gameObject.SetActive((Object)(object)child == (Object)(object)val);
				}
				using Stream stream = typeof(SkillFilterEntryVisuals).Assembly.GetManifestResourceStream("InFalsusMod.Assets.trait-filter-button.png") ?? throw new InvalidOperationException("缺少特性筛选入口图案资源。");
				DecodedImage decodedImage = PngRgba.Decode(stream);
				texture = new Texture2D(decodedImage.Width, decodedImage.Height, (TextureFormat)4, false)
				{
					name = "SkillSelection.Entry",
					hideFlags = (HideFlags)61,
					wrapMode = (TextureWrapMode)1,
					filterMode = (FilterMode)1
				};
				texture.LoadRawTextureData(new Il2CppStructArray<byte>(decodedImage.BottomUpPixels));
				texture.Apply(false, true);
				Material renderableTargetMaterial = val2.constrained2DTransform.renderableTargetMaterial;
				if ((Object)(object)renderableTargetMaterial == (Object)null)
				{
					throw new InvalidOperationException("原版特性入口缺少图案材质。");
				}
				material = new Material(renderableTargetMaterial)
				{
					name = "SkillSelection.Entry",
					hideFlags = (HideFlags)61,
					mainTexture = (Texture)(object)texture
				};
				val2._irA(material, false);
				((Component)button).transform.SetParent(((Component)lastColor).transform.parent, false);
				Constrained2DTransform constrained2DTransform = lastColor.constrained2D.constrained2DTransform;
				Constrained2DTransform constrained2DTransform2 = previousColor.constrained2D.constrained2DTransform;
				Constrained2DTransform constrained2DTransform3 = button.constrained2D.constrained2DTransform;
				float num = constrained2DTransform.offset.x - constrained2DTransform2.offset.x;
				float num2 = val2.constrained2DTransform.sizeInPixels.x - val3.constrained2DTransform.sizeInPixels.x;
				constrained2DTransform3.anchor = constrained2DTransform.anchor;
				constrained2DTransform3.parentAlignment = constrained2DTransform.parentAlignment;
				constrained2DTransform3.offset = constrained2DTransform.offset + new Vector2(num + num2 / 2f, 0f);
				button.constrained2D.constrained2DTransform = constrained2DTransform3;
				button.constrained2D._rQA();
				button.constrained2D._PQA((byte)63);
			}
			catch
			{
				Dispose();
				throw;
			}
		}

		public void Dispose()
		{
			if ((Object)(object)material != (Object)null)
			{
				Object.Destroy((Object)(object)material);
			}
			material = null;
			if ((Object)(object)texture != (Object)null)
			{
				Object.Destroy((Object)(object)texture);
			}
			texture = null;
		}
	}
	internal sealed class SkillFilterNativeHooks : IDisposable
	{
		[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
		private delegate void RefreshCall(IntPtr instance, IntPtr method);

		[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
		private delegate void InstancesCall(IntPtr instance, IntPtr details, byte force, IntPtr method);

		private static readonly IntPtr InstancesMethodInfo = MethodInfoPointer("_ju");

		private INativeDetour? refreshHook;

		private INativeDetour? instancesHook;

		private readonly RefreshCall originalRefresh;

		private readonly InstancesCall originalInstances;

		internal SkillFilterNativeHooks()
		{
			if (!OperatingSystem.IsWindows() || IntPtr.Size != 8)
			{
				throw new PlatformNotSupportedException("制卡筛选原生入口仅适用于 Windows x64。");
			}
			try
			{
				refreshHook = INativeDetour.Create<RefreshCall>(Marshal.ReadIntPtr(MethodInfoPointer("_ku")), (RefreshCall)Refresh);
				originalRefresh = ((IDetour)refreshHook).GenerateTrampoline<RefreshCall>();
				instancesHook = INativeDetour.Create<InstancesCall>(Marshal.ReadIntPtr(InstancesMethodInfo), (InstancesCall)Instances);
				originalInstances = ((IDetour)instancesHook).GenerateTrampoline<InstancesCall>();
				((IDetour)refreshHook).Apply();
				((IDetour)instancesHook).Apply();
			}
			catch
			{
				Dispose();
				throw;
			}
		}

		private static IntPtr MethodInfoPointer(string name)
		{
			if (!(Il2CppInteropUtils.GetIl2CppMethodInfoPointerFieldForGeneratedMethod((MethodBase)(typeof(CraftingLayer).GetMethod(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public) ?? throw new MissingMethodException(typeof(CraftingLayer).FullName, name)))?.GetValue(null) is IntPtr intPtr) || intPtr == IntPtr.Zero)
			{
				throw new InvalidOperationException("无法读取制卡入口 " + name + " 的 MethodInfo。");
			}
			if (Marshal.ReadIntPtr(intPtr) == IntPtr.Zero)
			{
				throw new InvalidOperationException("制卡入口 " + name + " 为空。");
			}
			return intPtr;
		}

		private void Refresh(IntPtr instance, IntPtr method)
		{
			WithFilteredInventory(instance, delegate
			{
				originalRefresh(instance, method);
			});
		}

		private void Instances(IntPtr instance, IntPtr details, byte force, IntPtr method)
		{
			WithFilteredInventory(instance, delegate
			{
				originalInstances(instance, details, force, method);
			});
		}

		private static void WithFilteredInventory(IntPtr instance, Action refresh)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Expected O, but got Unknown
			//IL_0024: 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)
			CraftingLayer val = null;
			UnorderedListVal<IotaInstance> val2 = null;
			UnorderedListVal<IotaInstance> obj = null;
			bool flag = false;
			try
			{
				if (SkillFilter.Active && instance != IntPtr.Zero)
				{
					val = new CraftingLayer(instance);
					if (SkillFilter.AppliesSelection(val._gZ.TraitFilter))
					{
						val2 = val._dZ;
						obj = (val._dZ = SkillFilter.View(val2));
						flag = true;
					}
				}
			}
			catch (Exception exception)
			{
				SkillFilterPanel.ReportFilterFailure(exception);
			}
			try
			{
				refresh();
			}
			finally
			{
				if (flag)
				{
					val._dZ = val2;
				}
				GC.KeepAlive(obj);
				GC.KeepAlive(val2);
			}
		}

		internal unsafe static void RefreshInstances(CraftingLayer owner, IotaDetails details)
		{
			byte b = 1;
			IntPtr* ptr = stackalloc IntPtr[2];
			*ptr = IL2CPP.il2cpp_object_unbox(((Il2CppObjectBase)details).Pointer);
			ptr[1] = (IntPtr)(&b);
			IntPtr zero = IntPtr.Zero;
			IL2CPP.il2cpp_runtime_invoke(InstancesMethodInfo, ((Il2CppObjectBase)owner).Pointer, (void**)ptr, ref zero);
			GC.KeepAlive(details);
			GC.KeepAlive(owner);
			Il2CppException.RaiseExceptionIfNecessary(zero);
		}

		public void Dispose()
		{
			((IDisposable)instancesHook)?.Dispose();
			instancesHook = null;
			((IDisposable)refreshHook)?.Dispose();
			refreshHook = null;
		}
	}
	public sealed class SkillFilterPanel : MonoBehaviour
	{
		private readonly record struct BuiltInElementState(GameObject Target, bool Active);

		private readonly record struct BuiltInLayoutState(Constrained2D Target, Constrained2DTransform Layout);

		private readonly record struct Heading(FastText Label, string Key);

		private const float SidebarWidth = 918f;

		private static readonly object failureSync = new object();

		private static string? pendingFilterFailure;

		private CraftingLayer? owner;

		private RecipeScene? recipeScene;

		private UIButton? entryButton;

		private UIButton? entryTextTemplate;

		private SkillFilterEntryVisuals? entryVisuals;

		private bool entryInputEnabled;

		private bool entryAttempted;

		private bool shellFailed;

		private bool entryTextDirty = true;

		private RecipeFilterLayer? filterLayer;

		private _wd? originalFilterChanged;

		private readonly List<BuiltInElementState> builtInElementStates = new List<BuiltInElementState>();

		private readonly List<BuiltInLayoutState> builtInLayoutStates = new List<BuiltInLayoutState>();

		private readonly List<Heading> headings = new List<Heading>();

		private TraitIcon? traitIconTemplate;

		private GameData? gameData;

		private int openRequestedFrame = -1;

		private bool open;

		private bool closing;

		private bool refresh;

		private float nextDiscovery;

		private Localization entryLanguage;

		private Localization controlsLanguage;

		private bool controlsDirty = true;

		private readonly TraitInfo[] familyTraits = SkillFilterCatalog.Families;

		private SkillFilterTooltip? tooltip;

		private int hoveredTrait = -1;

		private UIButton? resetButton;

		private readonly List<UIButton> tierButtons = new List<UIButton>();

		private readonly List<UIButton> traitButtons = new List<UIButton>();

		private readonly List<TraitIcon> traitIcons = new List<TraitIcon>();

		private readonly List<FastText> traitNames = new List<FastText>();

		private UIButton? matchAnyButton;

		private UIButton? matchAllButton;

		private string? pendingErrorKey;

		private NativeModalSession? errorSession;

		public SkillFilterPanel(IntPtr pointer)
			: base(pointer)
		{
		}

		public void Update()
		{
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			DiscoverOwner();
			if ((Object)(object)owner == (Object)null)
			{
				return;
			}
			ObserveFilterLayer();
			ObserveErrorModal();
			ConsumeFilterFailure();
			OpenRequestedPanel();
			UpdateEntry();
			if (open)
			{
				HideBuiltInFilterContent();
				if (!closing && (controlsDirty || controlsLanguage != ModText.Language))
				{
					TryRefreshControls();
				}
			}
			UpdateTooltip();
			RefreshCraftingList();
			TryShowError();
		}

		internal static void ReportFilterFailure(Exception exception)
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Expected O, but got Unknown
			SkillFilter.Families.Clear();
			lock (failureSync)
			{
				pendingFilterFailure = "FilterFailed";
			}
			ManualLogSource logger = Plugin.Logger;
			bool flag;
			BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(18, 1, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("技能筛选视图准备失败,已恢复不筛选:");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(exception);
			}
			logger.LogError(val);
		}

		private void DiscoverOwner()
		{
			if ((Object)(object)owner != (Object)null && ((Behaviour)owner).isActiveAndEnabled)
			{
				return;
			}
			CleanupOwner();
			if (Time.realtimeSinceStartup < nextDiscovery)
			{
				return;
			}
			nextDiscovery = Time.realtimeSinceStartup + 0.5f;
			foreach (CraftingLayer item in Object.FindObjectsOfType<CraftingLayer>())
			{
				if (((Behaviour)item).isActiveAndEnabled)
				{
					owner = item;
					break;
				}
			}
		}

		private void ObserveFilterLayer()
		{
			if (open && (!((Object)(object)filterLayer != (Object)null) || !filterLayer._bx()))
			{
				open = false;
				closing = false;
				ReleaseFilterLayer();
				controlsDirty = true;
			}
		}

		private void ObserveErrorModal()
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Expected O, but got Unknown
			if (errorSession == null || errorSession.IsOpen)
			{
				return;
			}
			if (errorSession.Failure != null)
			{
				ManualLogSource logger = Plugin.Logger;
				bool flag = default(bool);
				BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(24, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("原版技能筛选错误窗口状态读取失败,按已关闭清理:");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(errorSession.Failure);
				}
				logger.LogWarning(val);
			}
			errorSession = null;
		}

		private void ConsumeFilterFailure()
		{
			string text;
			lock (failureSync)
			{
				text = pendingFilterFailure;
				pendingFilterFailure = null;
			}
			if (text != null)
			{
				pendingErrorKey = text;
				controlsDirty = true;
				refresh = true;
				ClosePanel();
			}
		}

		private bool CanOpen()
		{
			if ((Object)(object)owner != (Object)null && ((Behaviour)owner).isActiveAndEnabled && !((InputReceiver)owner).DisableInputEvents && (Object)(object)InputManager.Instance != (Object)null)
			{
				return InputManager.Instance.IsHeadOfStack((InputReceiver)(object)owner);
			}
			return false;
		}

		private void UpdateEntry()
		{
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Expected O, but got Unknown
			//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0203: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)owner == (Object)null)
			{
				return;
			}
			UIButton iotaTraitFilterButton = owner.iotaTraitFilterButton;
			Il2CppReferenceArray<UIButton> colorFilterButtons = owner.colorFilterButtons;
			if ((Object)(object)iotaTraitFilterButton == (Object)null || (Object)(object)iotaTraitFilterButton.constrained2D == (Object)null || colorFilterButtons == null || ((Il2CppArrayBase<UIButton>)(object)colorFilterButtons).Length < 2)
			{
				return;
			}
			if (!entryAttempted)
			{
				entryAttempted = true;
				try
				{
					UIButton lastColor = ((Il2CppArrayBase<UIButton>)(object)colorFilterButtons)[((Il2CppArrayBase<UIButton>)(object)colorFilterButtons).Length - 1];
					entryTextTemplate = iotaTraitFilterButton;
					entryButton = NativeButtons.Create(entryTextTemplate, (InputReceiver)(object)owner, "SkillSelection.Button", ModText.Get("TraitsButton"), Toggle);
					entryVisuals = new SkillFilterEntryVisuals(entryButton, lastColor, ((Il2CppArrayBase<UIButton>)(object)colorFilterButtons)[((Il2CppArrayBase<UIButton>)(object)colorFilterButtons).Length - 2]);
					entryTextDirty = true;
					Plugin.Logger.LogDebug((object)"已建立技能选择入口。");
				}
				catch (Exception ex)
				{
					if ((Object)(object)entryButton != (Object)null)
					{
						Object.Destroy((Object)(object)((Component)entryButton).gameObject);
					}
					entryButton = null;
					entryTextTemplate = null;
					entryVisuals?.Dispose();
					entryVisuals = null;
					ManualLogSource logger = Plugin.Logger;
					bool flag = default(bool);
					BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(11, 1, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("技能选择入口创建失败:");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
					}
					logger.LogError(val);
				}
			}
			if ((Object)(object)entryButton == (Object)null || (Object)(object)entryTextTemplate == (Object)null)
			{
				return;
			}
			bool isActiveAndEnabled = ((Behaviour)owner).isActiveAndEnabled;
			if (((Component)entryButton).gameObject.activeSelf != isActiveAndEnabled)
			{
				((Component)entryButton).gameObject.SetActive(isActiveAndEnabled);
				entryTextDirty = isActiveAndEnabled;
				entryInputEnabled = false;
			}
			if (isActiveAndEnabled)
			{
				if (entryTextDirty || entryLanguage != ModText.Language)
				{
					SkillFilterVisuals.UpdateButtonText(entryButton, entryTextTemplate, ModText.Get("TraitsButton"));
					SkillFilterVisuals.AlignEntryLabel(entryButton);
					entryLanguage = ModText.Language;
					entryTextDirty = false;
				}
				bool flag2 = CanOpen() && openRequestedFrame < 0 && !shellFailed && errorSession == null && pendingErrorKey == null;
				NativeButtons.SetState(entryButton, flag2);
				if (flag2 && !entryInputEnabled)
				{
					UIManager._ftA()._ktA(entryButton);
					UIManager._ftA()._mtA(entryButton, (InputReceiver)(object)owner);
					InputManager.Instance.RequestLastMouseMoveReplay();
				}
				entryInputEnabled = flag2;
			}
		}

		private void Toggle(UIButton button)
		{
			if (!((Object)(object)button != (Object)(object)entryButton))
			{
				if (open)
				{
					ClosePanel();
				}
				else if (openRequestedFrame < 0 && CanOpen() && !shellFailed && errorSession == null && pendingErrorKey == null)
				{
					openRequestedFrame = Time.frameCount;
				}
			}
		}

		private void OpenRequestedPanel()
		{
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Expected O, but got Unknown
			//IL_005b: 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 (openRequestedFrame < 0 || Time.frameCount <= openRequestedFrame)
			{
				return;
			}
			openRequestedFrame = -1;
			if (open || !CanOpen() || shellFailed || errorSession != null || pendingErrorKey != null)
			{
				return;
			}
			try
			{
				EnsureFilterLayer();
				filterLayer._ZW((_Wd)0, SkillFilterVisuals.CenterOffset(filterLayer), (InputReceiver)null);
				filterLayer.self._sQA(SkillFilterVisuals.CenterOffset(filterLayer));
				if (!filterLayer._bx())
				{
					throw new InvalidOperationException("原版配方筛选浮窗未进入可见状态。");
				}
				open = true;
				closing = false;
				HideBuiltInFilterContent();
				CreateFilterControls();
				controlsDirty = true;
				RefreshControls();
				Plugin.Logger.LogDebug((object)"已打开技能选择浮窗。");
			}
			catch (Exception ex)
			{
				if ((Object)(object)filterLayer != (Object)null)
				{
					ForceCloseFilterLayer(filterLayer, ex);
				}
				ReleaseFilterLayer();
				open = false;
				closing = false;
				shellFailed = true;
				pendingErrorKey = "FilterRefreshFailed";
				ManualLogSource logger = Plugin.Logger;
				bool flag = default(bool);
				BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(16, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("原版技能筛选浮窗准备或打开失败:");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
				}
				logger.LogError(val);
			}
		}

		private void EnsureFilterLayer()
		{
			if ((Object)(object)filterLayer != (Object)null)
			{
				return;
			}
			if ((Object)(object)owner == (Object)null || (Object)(object)entryButton == (Object)null)
			{
				throw new InvalidOperationException("制卡筛选入口尚未就绪。");
			}
			RecipeFilterLayer val = (filterLayer = FindAvailableFilterLayer() ?? throw new InvalidOperationException("当前制卡场景没有空闲且完整绑定的 RecipeFilterLayer。"));
			originalFilterChanged = val.OnFilterChanged;
			try
			{
				val.OnFilterChanged = null;
				Constrained2D[] array = (Constrained2D[])(object)new Constrained2D[5]
				{
					val.self,
					val.contentContainer,
					val.backing,
					val.cornerBrackets,
					((Component)((Component)val.buttons.ResetAllButton).transform.parent).GetComponent<Constrained2D>()
				};
				foreach (Constrained2D val2 in array)
				{
					builtInLayoutStates.Add(new BuiltInLayoutState(val2, val2.constrained2DTransform));
				}
				RecipeScene? obj = recipeScene;
				object obj2;
				if (obj == null)
				{
					obj2 = null;
				}
				else
				{
					DataAccess dataAccess = obj.dataAccess;
					obj2 = ((dataAccess != null) ? dataAccess._lLA() : null);
				}
				if (obj2 == null)
				{
					throw new InvalidOperationException("当前游戏技能定义尚未就绪。");
				}
				gameData = (GameData?)obj2;
				TraitCatalog.Validate(gameData);
				traitIconTemplate = FindTraitIconTemplate() ?? throw new InvalidOperationException("场景中没有完整的原版技能图标模板。");
				HideBuiltInFilterContent();
			}
			catch
			{
				ReleaseFilterLayer();
				throw;
			}
		}

		private RecipeFilterLayer? FindAvailableFilterLayer()
		{
			//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ea: Expected O, but got Unknown
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)owner == (Object)null)
			{
				return null;
			}
			bool flag = default(bool);
			foreach (RecipeScene item in Resources.FindObjectsOfTypeAll<RecipeScene>())
			{
				if ((Object)(object)item == (Object)null)
				{
					continue;
				}
				Scene scene = ((Component)item).gameObject.scene;
				if (!((Scene)(ref scene)).IsValid() || (Object)(object)item.craftingLayer == (Object)null || ((Il2CppObjectBase)item.craftingLayer).Pointer != ((Il2CppObjectBase)owner).Pointer)
				{
					continue;
				}
				RecipeFilterLayer recipeFilterLayer = item.recipeFilterLayer;
				RecipeFilterLayerButtons val = ((recipeFilterLayer != null) ? recipeFilterLayer.buttons : null);
				if ((Object)(object)recipeFilterLayer == (Object)null || (Object)(object)recipeFilterLayer.self == (Object)null || (Object)(object)recipeFilterLayer.contentContainer == (Object)null || (Object)(object)recipeFilterLayer.backing == (Object)null || (Object)(object)recipeFilterLayer.cornerBrackets == (Object)null || (Object)(object)recipeFilterLayer.closeButton == (Object)null || (Object)(object)recipeFilterLayer.openAnimator == (Object)null || (Object)(object)recipeFilterLayer.closeAnimator == (Object)null || val == null || (Object)(object)val.ResetAllButton == (Object)null || val.ColorTypeButtons == null || ((Il2CppArrayBase<UIButton>)(object)val.ColorTypeButtons).Length == 0 || val.TierButtons == null || ((Il2CppArrayBase<UIButton>)(object)val.TierButtons).Length < 3 || val.TraitButtons == null || ((Il2CppArrayBase<UIButton>)(object)val.TraitButtons).Length < 2 || val.MasteryProgressButtons == null || ((Il2CppArrayBase<UIButton>)(object)val.MasteryProgressButtons).Length == 0 || ((Object)(object)((Component)recipeFilterLayer).transform.parent != (Object)null && !((Component)((Component)recipeFilterLayer).transform.parent).gameObject.activeInHierarchy))
				{
					continue;
				}
				try
				{
					if (!recipeFilterLayer._bx())
					{
						recipeScene = item;
						return recipeFilterLayer;
					}
				}
				catch (Exception ex)
				{
					ManualLogSource logger = Plugin.Logger;
					BepInExDebugLogInterpolatedStringHandler val2 = new BepInExDebugLogInterpolatedStringHandler(17, 1, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("跳过状态不可读的原版配方筛选浮窗:");
						((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(ex.Message);
					}
					logger.LogDebug(val2);
				}
			}
			return null;
		}

		private static TraitIcon? FindTraitIconTemplate()
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: 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_0090: Invalid comparison between Unknown and I4
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			TraitIcon val = null;
			float num = -1f;
			bool flag = false;
			foreach (TraitIcon item in Resources.FindObjectsOfTypeAll<TraitIcon>())
			{
				if ((Object)(object)item == (Object)null)
				{
					continue;
				}
				Scene scene = ((Component)item).gameObject.scene;
				if (((Scene)(ref scene)).IsValid() && !((Object)(object)item.self == (Object)null) && !((Object)(object)item.frame == (Object)null) && !((Object)(object)item.icon == (Object)null) && !((Object)(object)item.traitIconAssets == (Object)null))
				{
					bool flag2 = (int)item.style == 0;
					Vector2 sizeInPixels = item.self.constrained2DTransform.sizeInPixels;
					float num2 = Math.Abs(sizeInPixels.x * sizeInPixels.y);
					if ((!((Object)(object)val != (Object)null) || !(!flag2 || flag) || !(num2 <= num)) && (!flag || flag2))
					{
						val = item;
						num = num2;
						flag = flag2;
					}
				}
			}
			return val;
		}

		private void HideBuiltInFilterContent()
		{
			RecipeFilterLayer? obj = filterLayer;
			RecipeFilterLayerButtons val = ((obj != null) ? obj.buttons : null);
			if ((Object)(object)obj == (Object)null || val == null)
			{
				return;
			}
			if (builtInElementStates.Count == 0)
			{
				Transform parent = ((Component)val.ResetAllButton).transform.parent;
				Transform obj2 = parent.Find("TitleText");
				RememberBuiltInElement((obj2 != null) ? ((Component)obj2).gameObject : null);
				Transform obj3 = parent.Find("TitleTextShadow");
				RememberBuiltInElement((obj3 != null) ? ((Component)obj3).gameObject : null);
				RememberBuiltInElement(((Component)val.ResetAllButton).gameObject);
				RememberBuiltInElement(((Component)((Component)((Il2CppArrayBase<UIButton>)(object)val.TierButtons)[0]).transform.parent).gameObject);
				RememberBuiltInElement(((Component)((Component)((Il2CppArrayBase<UIButton>)(object)val.ColorTypeButtons)[0]).transform.parent).gameObject);
				RememberBuiltInElement(((Component)((Component)((Il2CppArrayBase<UIButton>)(object)val.TraitButtons)[0]).transform.parent).gameObject);
				RememberBuiltInElement(((Component)((Component)((Il2CppArrayBase<UIButton>)(object)val.MasteryProgressButtons)[0]).transform.parent).gameObject);
			}
			foreach (BuiltInElementState builtInElementState in builtInElementStates)
			{
				if ((Object)(object)builtInElementState.Target != (Object)null && builtInElementState.Target.activeSelf)
				{
					builtInElementState.Target.SetActive(false);
				}
			}
		}

		private void RememberBuiltInElement(GameObject? target)
		{
			if (!((Object)(object)target == (Object)null) && !builtInElementStates.Any((BuiltInElementState state) => ((Il2CppObjectBase)state.Target).Pointer == ((Il2CppObjectBase)target).Pointer))
			{
				builtInElementStates.Add(new BuiltInElementState(target, target.activeSelf));
			}
		}

		private void CreateFilterControls()
		{
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: 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_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_038a: Unknown result type (might be due to invalid IL or missing references)
			//IL_03cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c5: Unknown result type (might be due to invalid IL or missing references)
			RecipeFilterLayerButtons val = (filterLayer ?? throw new InvalidOperationException("原版筛选浮窗尚未建立。")).buttons ?? throw new InvalidOperationException("原版筛选浮窗缺少按钮定义。");
			Il2CppReferenceArray<UIButton> val2 = val.TierButtons;
			Il2CppReferenceArray<UIButton> val3 = val.TraitButtons;
			Transform parent = ((Component)val.ResetAllButton).transform.parent;
			Transform obj = ((Component)((Il2CppArrayBase<UIButton>)(object)val3)[0]).transform.parent.Find("TitleText");
			FastText template = ((obj != null) ? ((Component)obj).GetComponent<FastText>() : null) ?? throw new InvalidOperationException("原版特性分区缺少名称字体模板。");
			AddHeading(parent, parent, "TraitsButton", new Vector2(36f, -57f));
			resetButton = CreateIconControl(val.ResetAllButton, "Reset", delegate
			{
				ResetSelection();
			});
			SkillFilterVisuals.Place(resetButton, parent, new Vector2(459f, -165f));
			AddHeading(((Component)((Il2CppArrayBase<UIButton>)(object)val2)[0]).transform.parent, parent, "TierTitle", new Vector2(130f, -255f));
			for (int num = 0; num < 3; num++)
			{
				int tier = num + 1;
				UIButton val4 = CreateIconControl(((Il2CppArrayBase<UIButton>)(object)val2)[num], $"Tier{tier}", delegate
				{
					ToggleTier(tier);
				});
				tierButtons.Add(val4);
				SkillFilterVisuals.Place(val4, parent, new Vector2(459f + (float)(num - 1) * 250f, -375f));
			}
			int num2 = 0;
			for (int num3 = 0; num3 < SkillFilterCatalog.Groups.Length; num3++)
			{
				SkillFilterGroup skillFilterGroup = SkillFilterCatalog.Groups[num3];
				float num4 = -110f - (float)num3 * 200f;
				FastText obj2 = AddHeading(((Component)((Il2CppArrayBase<UIButton>)(object)val3)[0]).transform.parent, parent, skillFilterGroup.TitleKey, new Vector2(1160f, num4 - 14f));
				obj2.SetFontSize(3.2f, (UpdateType)1);
				obj2.SetAlignment((AlignmentOptions)5, (UpdateType)1);
				int num5 = 0;
				while (num5 < skillFilterGroup.TraitIds.Length)
				{
					int capturedIndex = num2;
					UIButton val5 = CreateIconControl(((Il2CppArrayBase<UIButton>)(object)val2)[0], $"Trait{num2 + 1:00}", delegate
					{
						ToggleTrait(capturedIndex);
					});
					traitButtons.Add(val5);
					val5._eSA(_fI.op_Implicit((Action<UIButton, bool>)delegate(UIButton _, bool isHovered)
					{
						SetHoveredTrait(capturedIndex, isHovered);
					}));
					SkillFilterVisuals.ResizeTraitButton(val5);
					SkillFilterVisuals.Place(val5, parent, new Vector2(1330f + (float)num5 * 290f, num4), activate: false);
					traitIcons.Add(CreateTraitIcon(traitIconTemplate, val5, num2));
					traitNames.Add(SkillFilterVisuals.CreateTraitName(template, val5, num2, ModText.TraitName(familyTraits[num2].Family)));
					((Component)val5).gameObject.SetActive(true);
					num5++;
					num2++;
				}
			}
			matchAnyButton = CreateTextControl(((Il2CppArrayBase<UIButton>)(object)val3)[0], "MatchAny", "MatchAnyCompact", delegate
			{
				SetMatchMode(matchAll: false);
			});
			SkillFilterVisuals.Place(matchAnyButton, parent, new Vector2(459f, -590f));
			matchAllButton = CreateTextControl(((Il2CppArrayBase<UIButton>)(object)val3)[1], "MatchAll", "MatchAllCompact", delegate
			{
				SetMatchMode(matchAll: true);
			});
			SkillFilterVisuals.Place(matchAllButton, parent, new Vector2(459f, -710f));
			CraftingLayer? obj3 = owner;
			TraitIconHoverContainer template2 = ((obj3 != null) ? obj3.traitIconHoverContainer : null) ?? throw new InvalidOperationException("当前制卡界面缺少原版特性说明组件。");
			tooltip = new SkillFilterTooltip(template2, parent, recipeScene.dataAccess);
		}

		private FastText AddHeading(Transform source, Transform parent, string key, Vector2 offset)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			Transform obj = source.Find("TitleText");
			FastText val = SkillFilterVisuals.CreateLabel(((obj != null) ? ((Component)obj).GetComponent<FastText>() : null) ?? throw new InvalidOperationException("原版筛选分区缺少标题文字。"), parent, key, ModText.Get(key), offset);
			headings.Add(new Heading(val, key));
			return val;
		}

		[HideFromIl2Cpp]
		private UIButton CreateTextControl(UIButton template, string name, string textKey, Action<UIButton> clicked)
		{
			return NativeButtons.Create(template, (InputReceiver)(object)filterLayer, "SkillSelection." + name, ModText.Get(textKey), clicked);
		}

		[HideFromIl2Cpp]
		private UIButton CreateIconControl(UIButton template, string name, Action<UIButton> clicked)
		{
			UIManager val = UIManager._ftA();
			RecipeFilterLayer val2 = filterLayer;
			if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null || (Object)(object)template.constrained2D == (Object)null)
			{
				throw new InvalidOperationException("原生图标按钮输入或布局尚未就绪。");
			}
			GameObject val3 = Object.Instantiate<GameObject>(((Component)template).gameObject, ((Component)template).transform.parent, false);
			((Object)val3).name = "InFalsus.SkillSelection." + name;
			val3.SetActive(false);
			try
			{
				UIButton component = val3.GetComponent<UIButton>();
				if ((Object)(object)component == (Object)null || (Object)(object)component.constrained2D == (Object)null || (Object)(object)component.ButtonCollider == (Object)null)
				{
					throw new InvalidOperationException("原生图标按钮缺少布局或碰撞体。");
				}
				component._Gjb = null;
				component._hjb = null;
				component._Hjb = null;
				component._ijb = null;
				component._Ijb = null;
				component.UserComponent = null;
				component._DSA(_EI.op_Implicit(clicked));
				component._dSA((_dI)1);
				val._mtA(component, (InputReceiver)(object)val2);
				return component;
			}
			catch
			{
				Object.Destroy((Object)(object)val3);
				throw;
			}
		}

		private static TraitIcon CreateTraitIcon(TraitIcon template, UIButton host, int slot)
		{
			//IL_0052: 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_0072: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = Object.Instantiate<GameObject>(((Component)template).gameObject, ((Component)host).transform, false);
			((Object)val).name = $"InFalsus.SkillSelection.TraitIcon{slot + 1:00}";
			val.SetActive(false);
			val.transform.localPosition = Vector3.zero;
			val.transform.localRotation = Quaternion.identity;
			val.transform.localScale = Vector3.one;
			try
			{
				SkillFilterVisuals.PrepareDisplayClone(val, ((Component)host).gameObject.layer);
				TraitIcon val2 = val.GetComponent<TraitIcon>() ?? val.GetComponentInChildren<TraitIcon>(true) ?? throw new InvalidOperationException("原版技能图标模板层级已改变。");
				if ((Object)(object)val2.self == (Object)null || (Object)(object)val2.frame == (Object)null || (Object)(object)val2.icon == (Object)null)
				{
					throw new InvalidOperationException("原版技能图标缺少布局组件。");
				}
				val2.style = (_BI)2;
				SkillFilterVisuals.CenterTraitIcon(val2);
				val.SetActive(true);
				val2.self._rQA();
				val2.self._PQA((byte)63);
				return val2;
			}
			catch
			{
				Object.Destroy((Object)(object)val);
				throw;
			}
		}

		private void TryRefreshControls()
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Expected O, but got Unknown
			try
			{
				RefreshControls();
			}
			catch (Exception ex)
			{
				pendingErrorKey = "FilterRefreshFailed";
				ClosePanel();
				ManualLogSource logger = Plugin.Logger;
				bool flag = default(bool);
				BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(13, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("技能筛选原版控件刷新失败:");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
				}
				logger.LogError(val);
			}
		}

		private void RefreshControls()
		{
			//IL_02dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0250: Unknown result type (might be due to invalid IL or missing references)
			//IL_0255: Unknown result type (might be due to invalid IL or missing references)
			RecipeFilterLayer? obj = filterLayer;
			RecipeFilterLayerButtons val = ((obj != null) ? obj.buttons : null);
			if (val == null || (Object)(object)gameData == (Object)null || (Object)(object)resetButton == (Object)null || (Object)(object)matchAnyButton == (Object)null || (Object)(object)matchAllButton == (Object)null || tierButtons.Count != 3 || traitButtons.Count != familyTraits.Length || traitIcons.Count != familyTraits.Length || traitNames.Count != familyTraits.Length)
			{
				throw new InvalidOperationException("技能筛选控件或图标未完整建立。");
			}
			NativeButtons.SetState(resetButton, enabled: true);
			foreach (Heading heading in headings)
			{
				SkillFilterVisuals.SetText(heading.Label, ModText.Get(heading.Key));
			}
			foreach (FastText componentsInChild in ((Component)resetButton).GetComponentsInChildren<FastText>(true))
			{
				SkillFilterVisuals.RefreshTextMesh(componentsInChild);
			}
			for (int i = 0; i < tierButtons.Count; i++)
			{
				NativeButtons.SetState(tierButtons[i], enabled: true, SkillFilter.Tiers.Contains(i + 1));
			}
			UpdateTextControl(matchAnyButton, ((Il2CppArrayBase<UIButton>)(object)val.TraitButtons)[0], ModText.Get("MatchAnyCompact"), enabled: true, !SkillFilter.MatchAll);
			UpdateTextControl(matchAllButton, ((Il2CppArrayBase<UIButton>)(object)val.TraitButtons)[1], ModText.Get("MatchAllCompact"), enabled: true, SkillFilter.MatchAll);
			for (int j = 0; j < familyTraits.Length; j++)
			{
				TraitInfo traitInfo = familyTraits[j];
				if (traitInfo.Id <= 0 || traitInfo.Id >= ((Il2CppArrayBase<TraitSpecification>)(object)gameData.traits).Length)
				{
					throw new InvalidOperationException($"技能图标编号 {traitInfo.Id} 已失效。");
				}
				TraitSpecification val2 = ((Il2CppArrayBase<TraitSpecification>)(object)gameData.traits)[traitInfo.Id];
				traitIcons[j]._qsA(ref val2, false, false, true);
				SkillFilterVisuals.CenterTraitIcon(traitIcons[j]);
				NativeButtons.SetState(traitButtons[j], enabled: true, SkillFilter.Families.Contains(traitInfo.Family));
				SkillFilterVisuals.SetText(traitNames[j], ModText.TraitName(traitInfo.Family));
			}
			controlsLanguage = ModText.Language;
			controlsDirty = false;
		}

		private static void UpdateTextControl(UIButton button, UIButton template, string text, bool enabled, bool selected)
		{
			SkillFilterVisuals.UpdateButtonText(button, template, text, centered: true);
			NativeButtons.SetState(button, enabled, selected);
		}

		private void SetMatchMode(bool matchAll)
		{
			if (SkillFilter.MatchAll != matchAll)
			{
				SkillFilter.MatchAll = matchAll;
				FilterChanged();
			}
		}

		private void ToggleTier(int tier)
		{
			if (!SkillFilter.Tiers.Remove(tier))
			{
				SkillFilter.Tiers.Add(tier);
			}
			FilterChanged();
		}

		private void ResetSelection()
		{
			if (SkillFilter.Families.Count != 0 || SkillFilter.Tiers.Count != 0 || SkillFilter.MatchAll)
			{
				SkillFilter.Families.Clear();
				SkillFilter.Tiers.Clear();
				SkillFilter.MatchAll = false;
				FilterChanged();
			}
		}

		private void ToggleTrait(int index)
		{
			if (index >= 0 && index < familyTraits.Length)
			{
				string family = familyTraits[index].Family;
				if (!SkillFilter.Families.Remove(family))
				{
					SkillFilter.Families.Add(family);
				}
				FilterChanged();
			}
		}

		private void FilterChanged()
		{
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Expected O, but got Unknown
			controlsDirty = true;
			refresh = true;
			string text = ((SkillFilter.Tiers.Count == 0) ? "全部" : string.Join(",", SkillFilter.Tiers.OrderBy((int tier) => tier)));
			ManualLogSource logger = Plugin.Logger;
			bool flag = default(bool);
			BepInExDebugLogInterpolatedStringHandler val = new BepInExDebugLogInterpolatedStringHandler(19, 3, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("特性筛选:已选");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(SkillFilter.Families.Count);
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("项,等级=");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(text);
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral(",匹配全部=");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<bool>(SkillFilter.MatchAll);
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("。");
			}
			logger.LogDebug(val);
		}

		private void SetHoveredTrait(int index, bool isHovered)
		{
			if (isHovered)
			{
				hoveredTrait = index;
			}
			else if (hoveredTrait == index)
			{
				hoveredTrait = -1;
			}
		}

		private void UpdateTooltip()
		{
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Expected O, but got Unknown
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			if (tooltip == null)
			{
				return;
			}
			try
			{
				if (!open || closing || (Object)(object)filterLayer == (Object)null || ((InputReceiver)filterLayer).DisableInputEvents || (Object)(object)InputManager.Instance == (Object)null || !InputManager.Instance.IsHeadOfStack((InputReceiver)(object)filterLayer))
				{
					hoveredTrait = -1;
				}
				if (hoveredTrait < 0 || hoveredTrait >= traitButtons.Count)
				{
					tooltip.Hide();
				}
				else
				{
					tooltip.Show(familyTraits[hoveredTrait], traitButtons[hoveredTrait].constrained2D.constrained2DTransform.offset, filterLayer.backing.constrained2DTransform.sizeInPixels);
				}
			}
			catch (Exception ex)
			{
				pendingErrorKey = "FilterRefreshFailed";
				ClosePanel();
				ManualLogSource logger = Plugin.Logger;
				bool flag = default(bool);
				BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(11, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("特性悬浮说明刷新失败:");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
				}
				logger.LogError(val);
			}
		}

		private void RefreshCraftingList()
		{
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			if (!refresh || (Object)(object)owner == (Object)null)
			{
				return;
			}
			refresh = false;
			try
			{
				BottomInsetIotaScrollContainer bottomInsetIotaScrollContainer = owner.bottomInsetIotaScrollContainer;
				IotaDetails val = ((bottomInsetIotaScrollContainer != null) ? bottomInsetIotaScrollContainer._EC() : null);
				owner._ku();
				if (val != null)
				{
					ushort value = val.Id.Value;
					if (value >= 1 && value <= 40)
					{
						SkillFilterNativeHooks.RefreshInstances(owner, val);
					}
				}
			}
			catch (Exception ex)
			{
				pendingErrorKey = "FilterRefreshFailed";
				ClosePanel();
				Plugin.Logger.LogError((object)ex);
			}
		}

		private void TryShowError()
		{
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Expected O, but got Unknown
			if (pendingErrorKey == null || errorSession != null || open)
			{
				return;
			}
			try
			{
				if (NativeModal.TryShowMessage(ModText.Get("TraitsTitle"), ModText.Get(pendingErrorKey), out NativeModalSession session))
				{
					errorSession = session;
					pendingErrorKey = null;
				}
			}
			catch (Exception ex)
			{
				pendingErrorKey = null;
				ManualLogSource logger = Plugin.Logger;
				bool flag = default(bool);
				BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(15, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("原版技能筛选错误窗口创建失败:");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
				}
				logger.LogError(val);
			}
		}

		private void ClosePanel()
		{
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Expected O, but got Unknown
			hoveredTrait = -1;
			tooltip?.Hide();
			if (!open || closing)
			{
				return;
			}
			if ((Object)(object)filterLayer == (Object)null)
			{
				open = false;
				return;
			}
			try
			{
				filterLayer._Ax();
				closing = true;
			}
			catch (Exception ex)
			{
				ForceCloseFilterLayer(filterLayer, ex, invokeClose: false);
				ReleaseFilterLayer();
				open = false;
				closing = false;
				ManualLogSource logger = Plugin.Logger;
				bool flag = default(bool);
				BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(13, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("原版技能筛选浮窗关闭失败:");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
				}
				logger.LogError(val);
			}
		}

		private static void ForceCloseFilterLayer(RecipeFilterLayer layer, Exception? failure, bool invokeClose = true)
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Expected O, but got Unknown
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Expected O, but got Unknown
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Expected O, but got Unknown
			bool flag = default(bool);
			if (invokeClose)
			{
				try
				{
					if ((Object)(object)layer._qcA != (Object)null)
					{
						layer._Ax();
					}
				}
				catch (Exception ex)
				{
					if (failure != null)
					{
						failure.Data["FilterLayerClose"] = ex.ToString();
					}
					else
					{
						ManualLogSource logger = Plugin.Logger;
						BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(12, 1, ref flag);
						if (flag)
						{
							((BepInExLogInterpolatedStringHandler)val).AppendLiteral("清理技能筛选输入层失败:");
							((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
						}
						logger.LogWarning(val);
					}
				}
			}
			try
			{
				InputManager instance = InputManager.Instance;
				if ((Object)(object)instance != (Object)null && instance.IsHeadOfStack((InputReceiver)(object)layer))
				{
					instance.ReleaseInputControl((InputReceiver)(object)layer);
				}
				layer._qcA = null;
			}
			catch (Exception ex2)
			{
				if (failure != null)
				{
					failure.Data["FilterLayerInputRelease"] = ex2.ToString();
				}
				else
				{
					ManualLogSource logger2 = Plugin.Logger;
					BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(14, 1, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("释放技能筛选输入所有权失败:");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex2);
					}
					logger2.LogWarning(val);
				}
			}
			try
			{
				if ((Object)(object)layer.contentContainer != (Object)null && ((Component)layer.contentContainer).gameObject.activeSelf)
				{
					((Component)layer.contentContainer).gameObject.SetActive(false);
				}
			}
			catch (Exception ex3)
			{
				if (failure != null)
				{
					failure.Data["FilterLayerHide"] = ex3.ToString();
					return;
				}
				ManualLogSource logger3 = Plugin.Logger;
				BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(13, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("隐藏技能筛选原版浮窗失败:");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex3);
				}
				logger3.LogWarning(val);
			}
		}

		private void ReleaseFilterLayer()
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Expected O, but got Unknown
			tooltip?.Dispose();
			tooltip = null;
			hoveredTrait = -1;
			RecipeFilterLayer val = filterLayer;
			if ((Object)(object)val != (Object)null)
			{
				try
				{
					val.OnFilterChanged = originalFilterChanged;
				}
				catch (Exception ex)
				{
					ManualLogSource logger = Plugin.Logger;
					bool flag = default(bool);
					BepInExDebugLogInterpolatedStringHandler val2 = new BepInExDebugLogInterpolatedStringHandler(13, 1, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("恢复原版配方筛选回调失败:");
						((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(ex.Message);
					}
					logger.LogDebug(val2);
				}
			}
			originalFilterChanged = null;
			foreach (BuiltInLayoutState builtInLayoutState in builtInLayoutStates)
			{
				if ((Object)(object)builtInLayoutState.Target != (Object)null)
				{
					builtInLayoutState.Target.constrained2DTransform = builtInLayoutState.Layout;
					builtInLayoutState.Target._PQA((byte)63);
				}
			}
			builtInLayoutStates.Clear();
			foreach (Heading heading in headings)
			{
				if ((Object)(object)heading.Label != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)heading.Label).gameObject);
				}
			}
			headings.Clear();
			foreach (BuiltInElementState builtInElementState in builtInElementStates)
			{
				if ((Object)(object)builtInElementState.Target != (Object)null && builtInElementState.Target.activeSelf != builtInElementState.Active)
				{
					builtInElementState.Target.SetActive(builtInElementState.Active);
				}
			}
			builtInElementStates.Clear();
			DestroyControl(resetButton);
			foreach (UIButton tierButton in tierButtons)
			{
				DestroyControl(tierButton);
			}
			foreach (UIButton traitButton in traitButtons)
			{
				DestroyControl(traitButton);
			}
			DestroyControl(matchAnyButton);
			DestroyControl(matchAllButton);
			filterLayer = null;
			gameData = null;
			traitIconTemplate = null;
			ClearControlReferences();
		}

		private static void DestroyControl(UIButton? button)
		{
			if ((Object)(object)button != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)button).gameObject);
			}
		}

		private void CleanupOwner()
		{
			if ((Object)(object)filterLayer != (Object)null)
			{
				ForceCloseFilterLayer(filterLayer, null, !closing);
			}
			ReleaseFilterLayer();
			openRequestedFrame = -1;
			open = false;
			closing = false;
			if ((Object)(object)entryButton != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)entryButton).gameObject);
			}
			entryButton = null;
			entryTextTemplate = null;
			entryVisuals?.Dispose();
			entryVisuals = null;
			entryInputEnabled = false;
			entryAttempted = false;
			entryTextDirty = true;
			shellFailed = false;
			owner = null;
			recipeScene = null;
			refresh = false;
			controlsDirty = true;
			SkillFilter.Families.Clear();
			SkillFilter.Tiers.Clear();
			SkillFilter.MatchAll = false;
		}

		private void ClearControlReferences()
		{
			resetButton = null;
			tierButtons.Clear();
			traitButtons.Clear();
			traitIcons.Clear();
			traitNames.Clear();
			matchAnyButton = null;
			matchAllButton = null;
		}

		public void OnDestroy()
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Expected O, but got Unknown
			NativeModalSession nativeModalSession = errorSession;
			nativeModalSession?.Close();
			if (nativeModalSession?.Failure != null)
			{
				ManualLogSource logger = Plugin.Logger;
				bool flag = default(bool);
				BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(20, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("组件卸载时关闭原版技能筛选错误窗口失败:");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(nativeModalSession.Failure);
				}
				logger.LogWarning(val);
			}
			errorSession = null;
			pendingErrorKey = null;
			CleanupOwner();
		}
	}
	internal sealed class SkillFilterTooltip : IDisposable
	{
		private readonly TraitIconHoverContainer view;

		private readonly DataAccess data;

		private readonly FastText title;

		private readonly FastText description;

		private string? shownFamily;

		private Localization language;

		internal SkillFilterTooltip(TraitIconHoverContainer template, Transform parent, DataAccess data)
		{
			//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0212: Unknown result type (might be due to invalid IL or missing references)
			//IL_024a: Unknown result type (might be due to invalid IL or missing references)
			//IL_025f: Unknown result type (might be due to invalid IL or missing references)
			//IL_026a: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cf: Unknown result type (might be due to invalid IL or missing references)
			this.data = data;
			GameObject val = Object.Instantiate<GameObject>(((Component)template).gameObject, parent, false);
			((Object)val).name = "InFalsus.SkillSelection.Tooltip";
			val.SetActive(false);
			try
			{
				view = val.GetComponent<TraitIconHoverContainer>() ?? throw new InvalidOperationException("原版特性说明副本缺少组件。");
				if ((Object)(object)view.self == (Object)null || (Object)(object)view.icon == (Object)null || (Object)(object)view.traitDescriptionContainer == (Object)null || (Object)(object)view.traitDescriptionBacking == (Object)null || (Object)(object)view.titleText == (Object)null || (Object)(object)view.descriptionText == (Object)null)
				{
					throw new InvalidOperationException("原版特性说明资源未完整绑定。");
				}
				SkillFilterVisuals.PrepareDisplayClone(val, ((Component)parent).gameObject.layer);
				title = ((Component)view.titleText).GetComponent<FastText>() ?? throw new InvalidOperationException("原版特性说明缺少标题文字。");
				description = ((Component)view.descriptionText).GetComponent<FastText>() ?? throw new InvalidOperationException("原版特性说明缺少效果文字。");
				Transform parent2 = ((Component)view.icon).transform.parent;
				for (int i = 0; i < parent2.childCount; i++)
				{
					Transform child = parent2.GetChild(i);
					((Component)child).gameObject.SetActive(((Il2CppObjectBase)child).Pointer == ((Il2CppObjectBase)((Component)view.icon).transform).Pointer || ((Il2CppObjectBase)child).Pointer == ((Il2CppObjectBase)((Component)view.traitDescriptionContainer).transform).Pointer);
				}
				Constrained2DTransform constrained2DTransform = view.self.constrained2DTransform;
				constrained2DTransform.anchor = new Vector2(0.5f, 0.5f);
				constrained2DTransform.parentAlignment = (Constrained2DAlignment)0;
				constrained2DTransform.offset = Vector2.zero;
				constrained2DTransform.renderableScale = Vector2.one;
				constrained2DTransform.zPosition = -0.5f;
				view.self.constrained2DTransform = constrained2DTransform;
				view.traitDescriptionContainer._sQA(Vector2.zero);
				view.icon.style = (_BI)2;
				Constrained2DTransform constrained2DTransform2 = view.traitDescriptionBacking.constrained2DTransform;
				constrained2DTransform2.anchor = new Vector2(0f, 1f);
				constrained2DTransform2.offset = new Vector2(144f, 0f);
				constrained2DTransform2.renderableScale = Vector2.one;
				view.traitDescriptionBacking.constrained2DTransform = constrained2DTransform2;
				ConfigureText(title, view.titleText, 3.6f, new Vector2(180f, -32f));
				ConfigureText(description, view.descriptionText, 3.25f, new Vector2(180f, -90f));
			}
			catch
			{
				Object.Destroy((Object)(object)val);
				throw;
			}
		}

		private static void ConfigureText(FastText label, Constrained2D constrained, float fontSize, Vector2 offset)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			Constrained2DTransform constrained2DTransform = constrained.constrained2DTransform;
			constrained2DTransform.anchor = new Vector2(0.5f, 0.5f);
			constrained2DTransform.parentAlignment = (Constrained2DAlignment)0;
			constrained2DTransform.offset = offset;
			constrained.constrained2DTransform = constrained2DTransform;
			label.SetFontSize(fontSize, (UpdateType)1);
			label.SetAlignment((AlignmentOptions)0, (UpdateType)1);
			label.presention = (FastTextPresentation)((label.presention | 0x40) & -33);
			label.SetMaxAutoLineBreakPixelWidth(900, (UpdateType)1);
		}

		internal void Show(TraitInfo family, Vector2 anchor, Vector2 availableSize)
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_026d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0274: Unknown result type (might be due to invalid IL or missing references)
			//IL_027b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0280: Unknown result type (might be due to invalid IL or missing references)
			//IL_0285: Unknown result type (might be due to invalid IL or missing references)
			//IL_028a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0291: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0311: Unknown result type (might be due to invalid IL or missing references)
			//IL_0333: Unknown result type (might be due to invalid IL or missing references)
			//IL_0362: Unknown result type (might be due to invalid IL or missing references)
			//IL_0367: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cf: Unknown result type (might be due to invalid IL or missing references)
			if (shownFamily == family.Family && language == ModText.Language)
			{
				return;
			}
			DynamicStringMapping val = data._QLA() ?? throw new InvalidOperationException("游戏特性说明本地化映射尚未就绪。");
			List<string> list = new List<string>();
			foreach (TraitInfo item in from info in TraitCatalog.Entries
				where info.Family == family.Family
				orderby info.Tier
				select info)
			{
				string text = val.Get((DynamicStringTypeFlags)512, ModText.Language, new TraitId
				{
					Value = (short)item.Id
				}).CreateString();
				if (string.IsNullOrWhiteSpace(text))
				{
					throw new InvalidOperationException($"技能 {item.Id} 缺少当前语言的效果说明。");
				}
				list.Add(new string('I', item.Tier) + "  " + text);
			}
			((Component)view).gameObject.SetActive(true);
			view.self._rQA();
			TraitSpecification val2 = ((Il2CppArrayBase<TraitSpecification>)(object)data._lLA().traits)[family.Id];
			view.icon._qsA(ref val2, false, false, true);
			SkillFilterVisuals.CenterTraitIcon(view.icon, 160f);
			view.icon.self._sQA(new Vector2(50f, -100f));
			SkillFilterVisuals.SetText(title, ModText.TraitName(family.Family));
			SkillFilterVisuals.SetText(description, string.Join("\n\n", list));
			view.titleText._PQA((byte)63);
			view.descriptionText._PQA((byte)63);
			view._eR();
			Constrained2DTransform constrained2DTransform = view.traitDescriptionBacking.constrained2DTransform;
			Vector2 val3 = Vector2.Scale(constrained2DTransform.sizeInPixels, Vector2.Scale(constrained2DTransform.renderableScale, constrained2DTransform.typeSpecificExtraScale));
			float num = 144f + val3.x;
			float num2 = Math.Max(180f, val3.y);
			float num3 = anchor.x + 120f;
			if (num3 + num > availableSize.x - 24f)
			{
				num3 = anchor.x - 100f - num;
			}
			num3 = Mathf.Clamp(num3, 54f, availableSize.x - 24f - num);
			float num4 = Mathf.Clamp(anchor.y + 110f, num2 + 24f - availableSize.y, -24f);
			view.self._sQA(new Vector2(num3, num4));
			view.self._PQA((byte)63);
			shownFamily = family.Family;
			language = ModText.Language;
		}

		internal void Hide()
		{
			shownFamily = null;
			if ((Object)(object)view != (Object)null && ((Component)view).gameObject.activeSelf)
			{
				((Component)view).gameObject.SetActive(false);
			}
		}

		public void Dispose()
		{
			if ((Object)(object)view != (Object)null)
			{
				((Component)view).gameObject.SetActive(false);
				Object.Destroy((Object)(object)((Component)view).gameObject);
			}
		}
	}
	internal static class SkillFilterVisuals
	{
		internal static Vector2 CenterOffset(RecipeFilterLayer layer)
		{
			//IL_000d: 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_0027: 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)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			Constrained2DTransform constrained2DTransform = layer.backing.constrained2DTransform;
			return -(constrained2DTransform.offset + Vector2.Scale(new Vector2(0.5f, 0.5f) - constrained2DTransform.anchor, constrained2DTransform.sizeInPixels));
		}

		internal static void Place(UIButton button, Transform parent, Vector2 offset, bool activate = true)
		{
			//IL_0024: 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)
			((Component)button).transform.SetParent(parent, false);
			Constrained2DTransform constrained2DTransform = button.constrained2D.constrained2DTransform;
			constrained2DTransform.anchor = new Vector2(0.5f, 0.5f);
			constrained2DTransform.parentAlignment = (Constrained2DAlignment)0;
			constrained2DTransform.offset = offset;
			constrained2DTransform.zPosition = -0.05f;
			button.constrained2D.constrained2DTransform = constrained2DTransform;
			((Component)button).gameObject.SetActive(activate);
			button.constrained2D._rQA();
			button.constrained2D._PQA((byte)63);
		}

		internal static void UpdateButtonText(UIButton button, UIButton template, string text, bool centered = false)
		{
			//IL_004b: 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)
			NativeButtons.UpdateText(button, template, text);
			foreach (FastText componentsInChild in ((Component)button).GetComponentsInChildren<FastText>(true))
			{
				Constrained2D obj = ((Component)componentsInChild).GetComponent<Constrained2D>() ?? throw new InvalidOperationException("原版按钮文字缺少布局组件。");
				Constrained2DTransform constrained2DTransform = obj.constrained2DTransform;
				if (centered)
				{
					constrained2DTransform.anchor = new Vector2(0.5f, 0.5f);
					constrained2DTransform.parentAlignment = (Constrained2DAlignment)0;
					constrained2DTransform.offset = new Vector2(0f, -8f);
					componentsInChild.SetAlignment((AlignmentOptions)4, (UpdateType)1);
				}
				constrained2DTransform.fastText = componentsInChild;
				constrained2DTransform.meshRenderer = ((Component)componentsInChild).GetComponent<MeshRenderer>();
				obj.constrained2DTransform = constrained2DTransform;
				RefreshTextMesh(componentsInChild);
				obj._PQA((byte)63);
			}
		}

		internal static void AlignEntryLabel(UIButton button)
		{
			//IL_0090: 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_00a8: Unknown result type (might be due to invalid IL or missing references)
			Transform obj = ((Component)button).transform.Find("AllPresent");
			object obj2;
			if (obj == null)
			{
				obj2 = null;
			}
			else
			{
				FastText componentInChildren = ((Component)obj).GetComponentInChildren<FastText>(true);
				obj2 = ((componentInChildren != null) ? ((Component)componentInChildren).GetComponent<Constrained2D>() : null);
			}
			if (obj2 == null)
			{
				throw new InvalidOperationException("原版特性入口缺少“全部”文字布局。");
			}
			Constrained2D val = (Constrained2D)obj2;
			Transform obj3 = ((Component)button).transform.Find("TraitsOnly") ?? throw new InvalidOperationException("原版特性入口缺少有特性图文层。");
			Constrained2DTransform constrained2DTransform = val.constrained2DTransform;
			foreach (FastText componentsInChild in ((Component)obj3).GetComponentsInChildren<FastText>(true))
			{
				Constrained2D obj4 = ((Component)componentsInChild).GetComponent<Constrained2D>() ?? throw new InvalidOperationException("原版按钮文字缺少布局组件。");
				Constrained2DTransform constrained2DTransform2 = obj4.constrained2DTransform;
				constrained2DTransform2.anchor = constrained2DTransform.anchor;
				constrained2DTransform2.parentAlignment = constrained2DTransform.parentAlignment;
				constrained2DTransform2.offset = constrained2DTransform.offset;
				obj4.constrained2DTransform = constrained2DTransform2;
				obj4._PQA((byte)63);
			}
		}

		internal static FastText CreateLabel(FastText template, Transform parent, string name, string text, Vector2 offset)
		{
			//IL_005c: 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)
			GameObject val = Object.Instantiate<GameObject>(((Component)template).gameObject, parent, false);
			((Object)val).name = "InFalsus.SkillSelection." + name;
			try
			{
				FastText component = val.GetComponent<FastText>();
				Constrained2D component2 = val.GetComponent<Constrained2D>();
				if ((Object)(object)component == (Object)null || (Object)(object)component2 == (Object)null)
				{
					throw new InvalidOperationException("原版分区标题缺少文字或布局。");
				}
				Constrained2DTransform constrained2DTransform = component2.constrained2DTransform;
				constrained2DTransform.anchor = new Vector2(0.5f, 0.5f);
				constrained2DTransform.parentAlignment = (Constrained2DAlignment)0;
				constrained2DTransform.offset = offset;
				constrained2DTransform.zPosition = -0.08f;
				constrained2DTransform.fastText = component;
				constrained2DTransform.meshRenderer = val.GetComponent<MeshRenderer>();
				component2.constrained2DTransform = constrained2DTransform;
				val.SetActive(true);
				SetText(component, text);
				component2._rQA();
				component2._PQA((byte)63);
				return component;
			}
			catch
			{
				Object.Destroy((Object)(object)val);
				throw;
			}
		}

		internal static FastText CreateTraitName(FastText template, UIButton host, int index, string text)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: 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_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			FastText obj = CreateLabel(template, ((Component)host).transform, $"TraitName{index + 1:00}", text, new Vector2(0f, -72f));
			Constrained2D component = ((Component)obj).GetComponent<Constrained2D>();
			Constrained2DTransform constrained2DTransform = component.constrained2DTransform;
			constrained2DTransform.color = Color.white;
			component.constrained2DTransform = constrained2DTransform;
			obj.SetFontSize(3f, (UpdateType)1);
			obj.SetAlignment((AlignmentOptions)1, (UpdateType)1);
			obj.SetTextColor(Color.white, (UpdateType)1);
			obj.presention = (FastTextPresentation)((obj.presention | 0x40) & -33);
			obj.SetMaxAutoLineBreakPixelWidth(280, (UpdateType)1);
			RefreshTextMesh(obj);
			component._PQA((byte)63);
			return obj;
		}

		internal static void SetText(FastText label, string text)
		{
			label.SetTextNonLocalized(text, (UpdateType)1);
			RefreshTextMesh(label);
		}

		internal static void RefreshTextMesh(FastText label)
		{
			//IL_0001: 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_002c: Unknown result type (might be due to invalid IL or missing references)
			label.targetLocalization = ModText.Language;
			label.meshRenderer = ((Component)label).GetComponent<MeshRenderer>();
			label.meshFilter = ((Component)label).GetComponent<MeshFilter>();
			label.dirtyFlags = (DirtyFlags)(label.dirtyFlags | 0xC);
			label.EnsureDirtyFlagsProcessed();
		}

		internal static void PrepareDisplayClone(GameObject root, int layer)
		{
			foreach (Transform componentsInChild in root.GetComponentsInChildren<Transform>(true))
			{
				((Component)componentsInChild).gameObject.layer = layer;
			}
			foreach (UIButton componentsInChild2 in root.GetComponentsInChildren<UIButton>(true))
			{
				componentsInChild2._Gjb = null;
				componentsInChild2._hjb = null;
				componentsInChild2._Hjb = null;
				componentsInChild2._ijb = null;
				componentsInChild2._Ijb = null;
				componentsInChild2.UserComponent = null;
				((Behaviour)componentsInChild2).enabled = false;
			}
			foreach (Collider componentsInChild3 in root.GetComponentsInChildren<Collider>(true))
			{
				componentsInChild3.enabled = false;
			}
			foreach (FastText componentsInChild4 in root.GetComponentsInChildren<FastText>(true))
			{
				Constrained2D component = ((Component)componentsInChild4).GetComponent<Constrained2D>();
				if ((Object)(object)component == (Object)null)
				{
					throw new InvalidOperationException("原版特性说明文字缺少布局组件。");
				}
				Constrained2DTransform constrained2DTransform = component.constrained2DTransform;
				constrained2DTransform.fastText = componentsInChild4;
				constrained2DTransform.meshRenderer = ((Component)componentsInChild4).GetComponent<MeshRenderer>();
				component.constrained2DTransform = constrained2DTransform;
				RefreshTextMesh(componentsInChild4);
			}
		}

		internal static void ResizeTraitButton(UIButton button)
		{
			//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_00a3: 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_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			for (int i = 0; i < ((Component)button).transform.childCount; i++)
			{
				Transform child = ((Component)button).transform.GetChild(i);
				if (((Object)child).name.StartsWith("icon-tier-", StringComparison.Ordinal))
				{
					((Component)child).gameObject.SetActive(false);
					continue;
				}
				Constrained2D component = ((Component)child).GetComponent<Constrained2D>();
				if (!((Object)(object)component == (Object)null))
				{
					Constrained2DTransform constrained2DTransform = component.constrained2DTransform;
					constrained2DTransform.sizeInPixels = new Vector2(128f, 128f);
					component.constrained2DTransform = constrained2DTransform;
					component._PQA((byte)63);
				}
			}
			BoxCollider obj = ((Il2CppObjectBase)button.ButtonCollider).TryCast<BoxCollider>() ?? throw new InvalidOperationException("原版特性筛选按钮的碰撞体类型已改变。");
			Vector3 size = obj.size;
			obj.size = new Vector3(size.x * 128f / 180f, size.y * 128f / 180f, size.z);
		}

		internal static void CenterTraitIcon(TraitIcon icon, float frameSize = 120f)
		{
			//IL_0017: 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_003f: 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_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: 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_012d: Unknown result type (might be due to invalid IL or missing references)
			Constrained2DTransform constrained2DTransform = icon.self.constrained2DTransform;
			constrained2DTransform.anchor = new Vector2(0.5f, 0.5f);
			constrained2DTransform.parentAlignment = (Constrained2DAlignment)0;
			constrained2DTransform.offset = Vector2.zero;
			constrained2DTransform.zPosition = -0.05f;
			constrained2DTransform.renderableScale = Vector2.one;
			constrained2DTransform.color = Color.white;
			icon.self.constrained2DTransform = constrained2DTransform;
			icon.self._PQA((byte)63);
			(Constrained2D, float, float)[] array = new(Constrained2D, float, float)[2]
			{
				(icon.frame, frameSize, 0f),
				(icon.icon, frameSize * 2f / 3f, -0.01f)
			};
			for (int i = 0; i < array.Length; i++)
			{
				(Constrained2D, float, float) tuple = array[i];
				Constrained2D item = tuple.Item1;
				float item2 = tuple.Item2;
				float item3 = tuple.Item3;
				Constrained2DTransform constrained2DTransform2 = item.constrained2DTransform;
				constrained2DTransform2.anchor = new Vector2(0.5f, 0.5f);
				constrained2DTransform2.parentAlignment = (Constrained2DAlignment)0;
				constrained2DTransform2.offset = Vector2.zero;
				constrained2DTransform2.zPosition = item3;
				constrained2DTransform2.sizeInPixels = new Vector2(item2, item2);
				constrained2DTransform2.renderableScale = Vector2.one;
				constrained2DTransform2.color = Color.white;
				constrained2DTransform2.spriteBlendEffect = (_Ti)0;
				item.constrained2DTransform = constrained2DTransform2;
				item._PQA((byte)63);
			}
		}
	}
	internal static class ModText
	{
		private static readonly Dictionary<string, string[]> messages = Load();

		private static readonly Dictionary<string, string> errorKeys = messages.Where<KeyValuePair<string, string[]>>((KeyValuePair<string, string[]> pair) => pair.Key.StartsWith("Error", StringComparison.Ordinal)).ToDictionary((KeyValuePair<string, string[]> pair) => pair.Value[0], (KeyValuePair<string, string[]> pair) => pair.Key);

		private static int frame = -1;

		private static Localization language = (Localization)1;

		private static Localization traitLanguage;

		private static readonly Dictionary<string, string> traitNames = new Dictionary<string, string>();

		internal static Localization Language
		{
			get
			{
				//IL_0031: Unknown result type (might be due to invalid IL or missing references)
				//IL_0016: Unknown result type (might be due to invalid IL or missing references)
				//IL_001b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0020: Unknown result type (might be due to invalid IL or missing references)
				//IL_0027: Unknown result type (might be due to invalid IL or missing references)
				//IL_002c: Unknown result type (might be due to invalid IL or missing references)
				if (frame != Time.frameCount)
				{
					frame = Time.frameCount;
					language = Strings.GetCurrentLocalization();
					if ((int)language == 0)
					{
						language = Strings.GetLocalizationForSystemLanguage();
					}
				}
				return language;
			}
		}

		private static Dictionary<string, string[]> Load()
		{
			using Stream utf8Json = Assembly.GetExecutingAssembly().GetManifestResourceStream("InFalsusMod.Data.ui-text.json") ?? throw new InvalidOperationException("Missing mod localization resource.");
			Dictionary<string, string[]>? obj = JsonSerializer.Deserialize<Dictionary<string, string[]>>(utf8Json) ?? throw new InvalidOperationException("Empty mod localization resource.");
			if (obj.Values.Any((string[] values) => values.Length != 5 || values.Any(string.IsNullOrWhiteSpace)))
			{
				throw new InvalidOperationException("Incomplete mod localization resource.");
			}
			return obj;
		}

		internal unsafe static string Get(string key, params object[] args)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected I4, but got Unknown
			Localization val = Language;
			object obj = (val - 2) switch
			{
				3 => (0, "zh-CN"), 
				2 => (1, "zh-TW"), 
				0 => (3, "ja-JP"), 
				1 => (4, "ko-KR"), 
				_ => (2, "en-US"), 
			};
			int item = ((ValueTuple<int, string>*)(&obj))->Item1;
			string item2 = ((ValueTuple<int, string>*)(&obj))->Item2;
			string text = messages[key][item];
			if (args.Length != 0)
			{
				return string.Format(CultureInfo.GetCultureInfo(item2), text, args);
			}
			return text;
		}

		internal static string Error(Exception exception)
		{
			if (errorKeys.TryGetValue(exception.Message, out string value))
			{
				return Get(value);
			}
			if (exception is InvalidOperationException && new string[6] { "粒子", "游戏粒子", "技能", "回想", "融合", "强化" }.Any((string prefix) => exception.Message.StartsWith(prefix, StringComparison.Ordinal)))
			{
				return Get("ErrorRules");
			}
			return Get("ErrorUnknown");
		}

		internal static string TraitName(string family)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: 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_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: 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_00e3: Unknown result type (might be due to invalid IL or missing references)
			Localization val = Language;
			if (traitLanguage != val)
			{
				traitNames.Clear();
				traitLanguage = val;
			}
			if (traitNames.TryGetValue(family, out string value))
			{
				return value;
			}
			TraitInfo traitInfo = (from entry in TraitCatalog.Entries
				where entry.Family == family
				orderby entry.Tier
				select entry).First();
			_NH cEb = _NH._CEb;
			object obj;
			if (cEb == null)
			{
				obj = null;
			}
			else
			{
				DataAccess obj2 = cEb._VNA();
				obj = ((obj2 != null) ? obj2._QLA() : null);
			}
			DynamicStringMapping val2 = (DynamicStringMapping)obj;
			if ((Object)(object)val2 == (Object)null)
			{
				return Get("TraitId", traitInfo.Id);
			}
			value = val2.Get((DynamicStringTypeFlags)8, val, new TraitId
			{
				Value = (short)traitInfo.Id
			}).CreateString();
			if (string.IsNullOrWhiteSpace(value))
			{
				return Get("TraitId", traitInfo.Id);
			}
			string[] array = new string[3] { " III", " II", " I" };
			foreach (string text in array)
			{
				if (value.EndsWith(text, StringComparison.Ordinal))
				{
					string text2 = value;
					int length = text.Length;
					value = text2.Substring(0, text2.Length - length);
					break;
				}
			}
			traitNames.Add(family, value);
			return value;
		}
	}
	internal static class NativeButtons
	{
		internal static void UpdateText(UIButton button, UIButton template, string text)
		{
			//IL_003e: 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_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			Il2CppArrayBase<FastText> componentsInChildren = ((Component)button).GetComponentsInChildren<FastText>(true);
			Il2CppArrayBase<FastText> componentsInChildren2 = ((Component)template).GetComponentsInChildren<FastText>(true);
			if (componentsInChildren.Length != componentsInChildren2.Length)
			{
				throw new InvalidOperationException("原版按钮文字层级已改变。");
			}
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				FastText obj = componentsInChildren[i];
				FastText val = componentsInChildren2[i];
				obj.style = val.style;
				obj.SetFontFamilyAsset(val.FontFamilyAsset);
				obj.SetFontSize(val.FontSize, (UpdateType)1);
				obj.SetTextNonLocalized(text, (UpdateType)0);
				obj.targetLocalization = val.targetLocalization;
				obj.dirtyFlags = (DirtyFlags)(obj.dirtyFlags | 0xC);
				obj.EnsureDirtyFlagsProcessed();
			}
		}

		internal static UIButton Create(UIButton template, InputReceiver owner, string name, string text, Action<UIButton> clicked)
		{
			UIManager val = UIManager._ftA();
			if ((Object)(object)val == (Object)null || (Object)(object)template.constrained2D == (Object)null)
			{
				throw new InvalidOperationException("原生按钮输入或布局尚未就绪。");
			}
			GameObject val2 = Object.Instantiate<GameObject>(((Component)template).gameObject, ((Component)template).transform.parent, false);
			((Object)val2).name = "InFalsus." + name;
			val2.SetActive(false);
			try
			{
				UIButton component = val2.GetComponent<UIButton>();
				Il2CppArrayBase<FastText> componentsInChildren = val2.GetComponentsInChildren<FastText>(true);
				if ((Object)(object)component == (Object)null || (Object)(object)component.constrained2D == (Object)null || (Object)(object)component.ButtonCollider == (Object)null || componentsInChildren.Length == 0)
				{
					throw new InvalidOperationException("原生按钮缺少布局、碰撞体或文字组件。");
				}
				component._Gjb = null;
				component._hjb = null;
				component._Hjb = null;
				component._ijb = null;
				component._Ijb = null;
				component.UserComponent = null;
				component._DSA(_EI.op_Implicit(clicked));
				component._dSA((_dI)1);
				UpdateText(component, template, text);
				val._mtA(component, owner);
				return component;
			}
			catch
			{
				Object.Destroy((Object)(object)val2);
				throw;
			}
		}

		internal static void Place(UIButton button, Transform parent, Vector2 offset, Vector2 size)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: 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_009c: Unknown result type (might be due to invalid IL or missing references)
			((Component)button).transform.SetParent(parent, false);
			Constrained2DTransform constrained2DTransform = button.constrained2D.constrained2DTransform;
			constrained2DTransform.anchor = new Vector2(0.5f, 0.5f);
			constrained2DTransform.offset = offset;
			constrained2DTransform.sizeInPixels = size;
			constrained2DTransform.parentAlignment = (Constrained2DAlignment)0;
			button.constrained2D.constrained2DTransform = constrained2DTransform;
			foreach (FastText componentsInChild in ((Component)button).GetComponentsInChildren<FastText>(true))
			{
				componentsInChild.presention = (FastTextPresentation)((componentsInChild.presention | 0x40) & -33);
				componentsInChild.SetMaxAutoLineBreakPixelWidth((int)Math.Max(24f, size.x - 24f), (UpdateType)1);
				componentsInChild.dirtyFlags = (DirtyFlags)(componentsInChild.dirtyFlags | 8);
				componentsInChild.EnsureDirtyFlagsProcessed();
			}
			((Component)button).gameObject.SetActive(true);
			button.constrained2D._rQA();
			button.constrained2D._PQA((byte)63);
		}

		internal static void SetState(UIButton button, bool enabled, bool selected = false)
		{
			button._dSA((_dI)(enabled ? ((!selected) ? 1 : 2) : 0));
		}
	}
	internal static class NativeModal
	{
		internal static bool TryShowMessage(string title, string body, out NativeModalSession? session, Action? closed = null)
		{
			session = null;
			UiModal available = GetAvailable();
			if ((Object)(object)available == (Object)null)
			{
				return false;
			}
			Action<UiModal> val = Convert(delegate(UiModal current)
			{
				current._VtA();
				closed?.Invoke();
			});
			try
			{
				available._TtA(Direct(title), Direct(body), (_yi)0, (Key)383, val, true);
			}
			catch (Exception ex)
			{
				try
				{
					if (available._StA())
					{
						available._VtA();
					}
				}
				catch (Exception ex2)
				{
					ex.Data["ModalCleanup"] = ex2.ToString();
				}
				throw;
			}
			session = new NativeModalSession(available, val, null);
			return true;
		}

		internal static bool TryShowConfirmation(string title, string body, Action cancelled, Action confirmed, out NativeModalSession? session)
		{
			session = null;
			UiModal available = GetAvailable();
			if ((Object)(object)available == (Object)null)
			{
				return false;
			}
			Action<UiModal> val = Convert(delegate(UiModal current)
			{
				current._VtA();
				cancelled();
			});
			Action<UiModal> val2 = Convert(delegate(UiModal current)
			{
				current._VtA();
				confirmed();
			});
			try
			{
				available._vtA(Direct(title), Direct(body), (_yi)0, (_yi)0, (Key)117, (Key)986, val, val2, true);
			}
			catch (Exception ex)
			{
				try
				{
					if (available._StA())
					{
						available._VtA();
					}
				}
				catch (Exception ex2)
				{
					ex.Data["ModalCleanup"] = ex2.ToString();
				}
				throw;
			}
			session = new NativeModalSession(available, val, val2);
			return true;
		}

		private static UiModal? GetAvailable()
		{
			UiModal val = UiModal._BJb;
			if ((Object)(object)val == (Object)null)
			{
				CoreScene obj = CoreScene._Xl ?? CoreScene._YI();
				val = ((obj != null) ? obj.UiModal : null);
			}