Decompiled source of ParticleFusion v1.0.1

ParticleFusion.dll

Decompiled a day ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Text;
using System.Text.Json;
using BepInEx;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using FastText;
using Il2CppInterop.Runtime;
using Il2CppInterop.Runtime.Attributes;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSystem;
using Il2CppSystem.Collections.Generic;
using Microsoft.CodeAnalysis;
using Str;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
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("ParticleFusion")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("将粒子库存自动融合为更多效能 999 的成品。")]
[assembly: AssemblyFileVersion("1.0.1.0")]
[assembly: AssemblyInformationalVersion("1.0.1")]
[assembly: AssemblyProduct("ParticleFusion")]
[assembly: AssemblyTitle("ParticleFusion")]
[assembly: AssemblyVersion("1.0.1.0")]
[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
{
	internal sealed class AvailableParticles
	{
		private sealed record Source(int Minimum, int Maximum, int Capacity, bool CanBeEmpty, Dictionary<short, int> Traits)
		{
			internal bool HasThreeSlots { get; } = Capacity == 3 && Traits.Values.Sum() >= 3;

			internal bool SupportsTraits(IotaInstance item)
			{
				//IL_0000: 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)
				if (ParticleData.TraitCount(item) > 0 || CanBeEmpty)
				{
					return FitsTraits(item);
				}
				return false;
			}

			internal bool FitsTraits(IotaInstance item)
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				//IL_0052: Unknown result type (might be due to invalid IL or missing references)
				//IL_0014: 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)
				if (ParticleData.TraitCount(item) > Capacity)
				{
					return false;
				}
				for (int i = 0; i < ParticleData.TraitCount(item); i++)
				{
					short trait = ParticleData.GetTrait(item, i);
					int num = 1;
					for (int j = 0; j < i; j++)
					{
						if (ParticleData.GetTrait(item, j) == trait)
						{
							num++;
						}
					}
					if (trait <= 0 || Traits.GetValueOrDefault(trait) < num)
					{
						return false;
					}
				}
				return true;
			}

			[CompilerGenerated]
			private bool PrintMembers(StringBuilder builder)
			{
				RuntimeHelpers.EnsureSufficientExecutionStack();
				builder.Append("Minimum = ");
				builder.Append(Minimum.ToString());
				builder.Append(", Maximum = ");
				builder.Append(Maximum.ToString());
				builder.Append(", Capacity = ");
				builder.Append(Capacity.ToString());
				builder.Append(", CanBeEmpty = ");
				builder.Append(CanBeEmpty.ToString());
				builder.Append(", Traits = ");
				builder.Append(Traits);
				return true;
			}
		}

		private readonly Dictionary<ushort, List<Source>> sources = new Dictionary<ushort, List<Source>>();

		internal AvailableParticles(_NH owner)
		{
			//IL_006d: 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)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: 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)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: 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_01a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01be: 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)
			//IL_0297: Unknown result type (might be due to invalid IL or missing references)
			//IL_0299: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_020e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0213: Unknown result type (might be due to invalid IL or missing references)
			//IL_0215: Unknown result type (might be due to invalid IL or missing references)
			//IL_021f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0221: Unknown result type (might be due to invalid IL or missing references)
			//IL_024e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0253: Unknown result type (might be due to invalid IL or missing references)
			DataAccess val = owner._VNA();
			GameData val2 = ((val != null) ? val._lLA() : null);
			if ((Object)(object)val2 == (Object)null || (Object)(object)val._LLA() == (Object)null)
			{
				throw new InvalidOperationException("回想掉落定义尚未就绪。");
			}
			TraitCatalog.Validate(val2);
			List<EncounterId> val3 = new List<EncounterId>();
			owner._BOA(val3, -1);
			HashSet<int> hashSet = new HashSet<int>();
			Enumerator<EncounterId> enumerator = val3.GetEnumerator();
			while (enumerator.MoveNext())
			{
				EncounterId current = enumerator.Current;
				hashSet.Add(current.Value);
			}
			foreach (EncounterDetail item in (Il2CppArrayBase<EncounterDetail>)(object)val._LLA().encounterDetails)
			{
				if (!hashSet.Contains(item.Id.Value))
				{
					continue;
				}
				int lootTableIndex = item.LootTableIndex;
				if (lootTableIndex < 0 || lootTableIndex >= ((Il2CppArrayBase<LootIotaTable>)(object)val2.lootIotaTables).Length)
				{
					throw new InvalidOperationException($"回想 {item.Id.Value} 的掉落表无效。");
				}
				foreach (LootIotaTableRow item2 in (Il2CppArrayBase<LootIotaTableRow>)(object)((Il2CppArrayBase<LootIotaTable>)(object)val2.lootIotaTables)[lootTableIndex].Rows)
				{
					if (item2.Weight <= 0)
					{
						continue;
					}
					ushort value = item2.IotaId.Value;
					bool flag = ((value < 1 || value > 40) ? true : false);
					if (flag || item2.MinPotency < 1 || item2.MaxPotency > 999 || item2.MinPotency > item2.MaxPotency || item2.TraitRolls < 0)
					{
						throw new InvalidOperationException("粒子掉落定义已改变,需要适配。");
					}
					Dictionary<short, int> dictionary = new Dictionary<short, int>();
					bool canBeEmpty = item2.TraitRolls == 0;
					if (item2.TraitRolls > 0)
					{
						if (lootTableIndex >= ((Il2CppArrayBase<LootTraitTable>)(object)val2.lootTraitTables).Length)
						{
							throw new InvalidOperationException("技能掉落表编号无效。");
						}
						foreach (LootTraitTableRow item3 in (Il2CppArrayBase<LootTraitTableRow>)(object)((Il2CppArrayBase<LootTraitTable>)(object)val2.lootTraitTables)[lootTableIndex].Rows)
						{
							if (item3.Weight <= 0)
							{
								continue;
							}
							short value2 = item3.TraitId.Value;
							if (value2 <= 0)
							{
								canBeEmpty = true;
								continue;
							}
							if (value2 >= ((Il2CppArrayBase<TraitSpecification>)(object)val2.traits).Length || ((Il2CppArrayBase<TraitSpecification>)(object)val2.traits)[(int)value2].Id.Value != value2)
							{
								throw new InvalidOperationException("技能掉落表与技能定义不一致。");
							}
							dictionary[value2] = dictionary.GetValueOrDefault(value2) + 1;
						}
					}
					ushort value3 = item2.IotaId.Value;
					if (!sources.TryGetValue(value3, out List<Source> value4))
					{
						sources.Add(value3, value4 = new List<Source>());
					}
					value4.Add(new Source(item2.MinPotency, item2.MaxPotency, Math.Min(3, item2.TraitRolls), canBeEmpty, dictionary));
				}
			}
			if (sources.Count == 0)
			{
				throw new InvalidOperationException("尚无可读取掉落规则的已解锁回想。");
			}
		}

		internal int MaximumPotency(IotaInstance item)
		{
			//IL_0008: 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_0031: Unknown result type (might be due to invalid IL or missing references)
			int num = 0;
			if (sources.TryGetValue(ParticleData.Shape(item), out List<Source> value))
			{
				foreach (Source item2 in value)
				{
					if (item2.SupportsTraits(item) && ParticleData.Potency(item) >= item2.Minimum)
					{
						num = Math.Max(num, item2.Maximum);
					}
				}
			}
			return num;
		}

		internal bool Contains(IotaInstance item)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			if (!sources.TryGetValue(ParticleData.Shape(item), out List<Source> value))
			{
				return false;
			}
			foreach (Source item2 in value)
			{
				if (ParticleData.Potency(item) >= item2.Minimum && ParticleData.Potency(item) <= item2.Maximum && item2.SupportsTraits(item))
				{
					return true;
				}
			}
			return false;
		}

		internal IEnumerable<short> ThirdTraits(ushort shape)
		{
			if (!sources.TryGetValue(shape, out List<Source> value))
			{
				return Enumerable.Empty<short>();
			}
			return value.Where((Source source) => source.Capacity > 0).SelectMany((Source source) => source.Traits.Keys).Where(TraitDemand.IsThird)
				.Distinct();
		}

		internal bool CanCompleteThree(IotaInstance item)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			if (!sources.TryGetValue(ParticleData.Shape(item), out List<Source> value))
			{
				return false;
			}
			return value.Any((Source source) => source.HasThreeSlots && ParticleData.Potency(item) >= source.Minimum && ParticleData.Potency(item) <= source.Maximum && source.FitsTraits(item));
		}
	}
	internal static class FusionEngine
	{
		private sealed class Session
		{
			private readonly List<Particle> particles = new List<Particle>();

			private readonly AvailableParticles available;

			private readonly bool selectedMode;

			private readonly int[,] fullCounts = new int[41, 4];

			private readonly int[] upgraded = new int[4];

			private readonly List<Particle> targets;

			private readonly List<Particle> donors;

			private int donorCursor;

			private readonly List<Particle> remnants = new List<Particle>();

			private long freshSum;

			private long remnantSum;

			private int processed;

			private int decomposed;

			private long supplied;

			private long spent;

			internal List<FusionProgress> Steps { get; } = new List<FusionProgress>();

			internal Session(IReadOnlyList<IotaInstance> source, InventorySelection selection, AvailableParticles available)
			{
				//IL_006d: 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)
				//IL_0073: Unknown result type (might be due to invalid IL or missing references)
				//IL_007a: Unknown result type (might be due to invalid IL or missing references)
				//IL_009f: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
				//IL_0161: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d4: 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)
				//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
				//IL_0108: Unknown result type (might be due to invalid IL or missing references)
				//IL_0116: Unknown result type (might be due to invalid IL or missing references)
				this.available = available;
				selectedMode = selection.SelectedMode;
				Dictionary<IotaKey, int> dictionary = new Dictionary<IotaKey, int>(selection.Quantities);
				foreach (IotaInstance item2 in source)
				{
					IotaKey key = IotaKey.Of(item2);
					int num = Math.Min(item2.Count, dictionary.GetValueOrDefault(key));
					dictionary[key] = dictionary.GetValueOrDefault(key) - num;
					IotaInstance item = item2;
					item.Count = 1;
					int cap = available.MaximumPotency(item);
					for (int i = 0; i < item2.Count; i++)
					{
						bool flag = i < num;
						ParticleData.Potency(item);
						bool freshDonor = ((!selectedMode) ? FusionRules.IsSmartMaterial(item, cap) : (flag && FusionRules.CanDonate(item, cap)));
						bool target = ((!selectedMode) ? FusionRules.IsSmartTarget(item, cap) : (!flag && FusionRules.CanTarget(item, cap)));
						Particle particle = new Particle(item, freshDonor, target, cap);
						particles.Add(particle);
						if (particle.IsFull)
						{
							fullCounts[particle.Shape, particle.Skills]++;
						}
					}
				}
				targets = (from particle2 in particles
					where particle2.Target
					orderby particle2.Cost
					select particle2).ToList();
				donors = (from particle2 in particles
					where particle2.FreshDonor
					orderby particle2.DemandWeight, particle2.Potency descending
					select particle2).ToList();
				freshSum = ((IEnumerable<Particle>)donors).Sum((Func<Particle, long>)((Particle particle2) => particle2.Potency));
			}

			internal void Run(int limit)
			{
				if (limit < 0)
				{
					throw new ArgumentOutOfRangeException("limit");
				}
				int num = 0;
				while (true)
				{
					if (num < targets.Count && !targets[num].IsOpenTarget)
					{
						num++;
						continue;
					}
					if (num == targets.Count)
					{
						break;
					}
					Particle particle = PickTarget(num);
					int cost = particle.Cost;
					if (freshSum + remnantSum < cost)
					{
						break;
					}
					UpgradePlan upgradePlan = Plan(cost);
					if (upgradePlan == null)
					{
						particle.Skipped = true;
						continue;
					}
					if (processed + upgradePlan.Donors.Count((Particle donor) => !donor.Donor) > limit)
					{
						break;
					}
					Commit(particle, cost, upgradePlan);
				}
			}

			private Particle PickTarget(int start)
			{
				Particle particle = targets[start];
				for (int i = start + 1; i < targets.Count && targets[i].Cost == particle.Cost; i++)
				{
					Particle particle2 = targets[i];
					if (particle2.IsOpenTarget)
					{
						int num = FullTotal(particle2.Shape);
						int num2 = FullTotal(particle.Shape);
						if (num < num2 || (num == num2 && Deficit(particle2.Shape, particle2.Skills) > Deficit(particle.Shape, particle.Skills)))
						{
							particle = particle2;
						}
					}
				}
				return particle;
			}

			private int FullTotal(ushort shape)
			{
				int num = 0;
				for (int i = 0; i < 4; i++)
				{
					num += fullCounts[shape, i];
				}
				return num;
			}

			private double Deficit(ushort shape, int skills)
			{
				return FusionRules.SkillRatios[skills] * (double)(FullTotal(shape) + 1) - (double)fullCounts[shape, skills];
			}

			private UpgradePlan? Plan(int cost)
			{
				List<Particle> list = new List<Particle>();
				long num = 0L;
				foreach (Particle item in Candidates())
				{
					long num2 = num + item.Potency;
					if (num2 < cost)
					{
						list.Add(item);
						num = num2;
						continue;
					}
					int num3 = checked((int)(num2 - cost));
					Particle holder = null;
					if (num3 > 0 && (holder = FindHolder(item, list, num3)) == null)
					{
						continue;
					}
					list.Add(item);
					return new UpgradePlan(list, holder, num3);
				}
				return null;
			}

			private IEnumerable<Particle> Candidates()
			{
				foreach (Particle remnant in remnants)
				{
					yield return remnant;
				}
				for (int i = donorCursor; i < donors.Count; i++)
				{
					if (!donors[i].Donor)
					{
						yield return donors[i];
					}
				}
			}

			private Particle? FindHolder(Particle last, List<Particle> chosen, int excess)
			{
				if (Holds(last, excess))
				{
					return last;
				}
				for (int num = chosen.Count - 1; num >= 0; num--)
				{
					if (Holds(chosen[num], excess))
					{
						return chosen[num];
					}
				}
				return null;
			}

			private bool Holds(Particle holder, int excess)
			{
				//IL_0010: 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)
				if (excess <= holder.Potency)
				{
					return available.Contains(FusionRules.Remainder(holder.Item, excess));
				}
				return false;
			}

			private void Commit(Particle target, int cost, UpgradePlan plan)
			{
				//IL_0152: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
				//IL_00f8: 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)
				foreach (Particle donor in plan.Donors)
				{
					if (donor.Donor)
					{
						remnantSum -= donor.Potency;
					}
					else
					{
						donor.Donor = true;
						processed++;
						checked
						{
							supplied += donor.Potency;
						}
						freshSum -= donor.Potency;
					}
					if (donor != plan.Holder)
					{
						donor.Alive = false;
						decomposed++;
					}
				}
				remnants.RemoveAll((Particle remnant) => !remnant.Alive);
				if (plan.Holder != null)
				{
					plan.Holder.Item = FusionRules.Remainder(plan.Holder.Item, plan.Remainder);
					remnantSum += plan.Remainder;
					if (!remnants.Contains(plan.Holder))
					{
						remnants.Add(plan.Holder);
					}
				}
				ParticleData.SetPotency(ref target.Item, target.Cap);
				if (!available.Contains(target.Item))
				{
					throw new InvalidOperationException("强化结果不是单一已解锁来源的合法组合。");
				}
				fullCounts[target.Shape, target.Skills]++;
				upgraded[target.Skills]++;
				checked
				{
					spent += cost;
				}
				while (donorCursor < donors.Count && donors[donorCursor].Donor)
				{
					donorCursor++;
				}
				Steps.Add(new FusionProgress(processed, decomposed, Steps.Count + 1));
			}

			internal FusionResult Finish()
			{
				if (supplied != spent + remnantSum)
				{
					throw new InvalidOperationException("融合供体效能与强化费用、实体余料不守恒。");
				}
				List<IotaInstance> items = (from particle in particles
					where particle.Alive
					select particle.Item).ToList();
				ConsolidationResult consolidationResult = TraitConsolidator.Apply(items, available);
				return new FusionResult
				{
					Items = items,
					Processed = processed,
					Decomposed = decomposed,
					Supplied = supplied,
					Spent = spent,
					Remainder = remnantSum,
					RemainderCount = remnants.Count,
					Upgraded = upgraded,
					StacksBefore = consolidationResult.Before,
					StacksAfter = consolidationResult.After,
					SingleStacksBefore = consolidationResult.SinglesBefore,
					SingleStacksAfter = consolidationResult.SinglesAfter,
					Consolidated = consolidationResult.Changed
				};
			}
		}

		private sealed class Particle
		{
			internal IotaInstance Item;

			internal readonly bool FreshDonor;

			internal readonly bool Target;

			internal bool Alive = true;

			internal bool Donor;

			internal bool Skipped;

			internal readonly int Cap;

			internal readonly int Cost;

			internal ushort Shape => ParticleData.Shape(Item);

			internal int Potency => ParticleData.Potency(Item);

			internal int Skills => ParticleData.TraitCount(Item);

			internal bool IsFull
			{
				get
				{
					if (Cap > 0)
					{
						return Potency >= Cap;
					}
					return false;
				}
			}

			internal bool IsOpenTarget
			{
				get
				{
					if (Target && !IsFull)
					{
						return !Skipped;
					}
					return false;
				}
			}

			internal int DemandWeight
			{
				get
				{
					//IL_0008: Unknown result type (might be due to invalid IL or missing references)
					int num = 0;
					for (int i = 0; i < Skills; i++)
					{
						num += TraitDemand.Weight(ParticleData.GetTrait(Item, i));
					}
					return num;
				}
			}

			internal Particle(IotaInstance item, bool freshDonor, bool target, int cap)
			{
				//IL_000e: Unknown result type (might be due to invalid IL or missing references)
				//IL_000f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0031: Unknown result type (might be due to invalid IL or missing references)
				Item = item;
				FreshDonor = freshDonor;
				Target = target;
				Cap = cap;
				Cost = (target ? FusionRules.TotalCost(ParticleData.Potency(item), cap) : 0);
			}
		}

		private sealed record UpgradePlan(List<Particle> Donors, Particle? Holder, int Remainder);

		internal static FusionResult Prepare(IReadOnlyList<IotaInstance> source, InventorySelection selection, int limit, AvailableParticles available)
		{
			Session session = new Session(source, selection, available);
			session.Run(limit);
			return session.Finish();
		}

		internal static FusionForecast Forecast(IReadOnlyList<IotaInstance> source, InventorySelection selection, int limit, AvailableParticles available)
		{
			Session session = new Session(source, selection, available);
			session.Run(limit);
			return new FusionForecast(session.Steps);
		}
	}
	internal readonly record struct FusionProgress(int Processed, int Decomposed, int Strengthened);
	internal sealed class FusionForecast
	{
		private readonly IReadOnlyList<FusionProgress> steps;

		internal FusionForecast(IReadOnlyList<FusionProgress> steps)
		{
			this.steps = steps;
		}

		internal FusionProgress At(int limit)
		{
			int num = 0;
			int num2 = steps.Count;
			while (num < num2)
			{
				int num3 = (num + num2) / 2;
				if (steps[num3].Processed <= limit)
				{
					num = num3 + 1;
				}
				else
				{
					num2 = num3;
				}
			}
			if (num != 0)
			{
				return steps[num - 1];
			}
			return default(FusionProgress);
		}
	}
	internal sealed class FusionResult
	{
		internal List<IotaInstance> Items { get; init; } = new List<IotaInstance>();

		internal int Processed { get; init; }

		internal int Decomposed { get; init; }

		internal long Supplied { get; init; }

		internal long Spent { get; init; }

		internal long Remainder { get; init; }

		internal int RemainderCount { get; init; }

		internal IReadOnlyList<int> Upgraded { get; init; } = new int[4];

		internal int Strengthened => Upgraded.Sum();

		internal int StacksBefore { get; init; }

		internal int StacksAfter { get; init; }

		internal int SingleStacksBefore { get; init; }

		internal int SingleStacksAfter { get; init; }

		internal bool Consolidated { get; init; }
	}
	internal static class FusionRules
	{
		internal static readonly IReadOnlyList<double> SkillRatios = new double[4] { 0.4, 0.1, 0.2, 0.3 };

		internal const int TargetWindow = 99;

		internal static bool IsComplete(IotaInstance item, int cap)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			if (cap > 0)
			{
				return ParticleData.Potency(item) >= cap;
			}
			return false;
		}

		internal static bool CanDonate(IotaInstance item, int cap)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: 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)
			if (ParticleData.Potency(item) > 0 && !IsComplete(item, cap))
			{
				return ParticleData.TraitCount(item) < 3;
			}
			return false;
		}

		internal static bool CanTarget(IotaInstance item, int cap)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			if (cap > 0)
			{
				return ParticleData.Potency(item) < cap;
			}
			return false;
		}

		internal static bool IsSmartTarget(IotaInstance item, int cap)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			if (CanTarget(item, cap))
			{
				return ParticleData.Potency(item) >= cap - 99;
			}
			return false;
		}

		internal static bool IsSmartMaterial(IotaInstance item, int cap)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			if (CanDonate(item, cap))
			{
				return !IsSmartTarget(item, cap);
			}
			return false;
		}

		internal static int PointCost(int potency)
		{
			if ((potency < 1 || potency > 999) ? true : false)
			{
				throw new ArgumentOutOfRangeException("potency");
			}
			if (potency > 200)
			{
				return 6 + (potency - 101) / 100 * 4;
			}
			return 6;
		}

		internal static int TotalCost(int potency, int maximum)
		{
			int num = 0;
			for (int i = potency + 1; i <= maximum; i++)
			{
				num += PointCost(i);
			}
			return num;
		}

		internal static IotaInstance Remainder(IotaInstance item, int potency)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			item.BaseIotaIdPotency |= 3;
			item.TraitId1 = (item.TraitId2 = (item.TraitId3 = 0));
			item.Count = 1;
			ParticleData.SetPotency(ref item, potency);
			return item;
		}
	}
	public sealed class InventoryButtonBehaviour : MonoBehaviour
	{
		private sealed class ButtonBinding
		{
			internal readonly IotaInventoryLayer Owner;

			internal readonly UIButton Template;

			internal UIButton? Button;

			internal Localization Language;

			internal string? TextKey;

			internal bool? Enabled;

			internal ButtonBinding(IotaInventoryLayer owner, UIButton template)
			{
				Owner = owner;
				Template = template;
			}
		}

		private readonly List<ButtonBinding> bindings = new List<ButtonBinding>();

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

		private float nextDiscovery;

		private NativeModalSession? modalSession;

		private IotaInventoryLayer? dialogOwner;

		private FusionPreview? preview;

		private FusionForecast? forecast;

		private bool executeRequested;

		private int requestedFrame;

		private int releaseInputFrame = -1;

		private bool selectedMode;

		private int donorLimit;

		private UiMessage? pendingMessage;

		private string pendingTitleKey = "SmartTitle";

		private string TitleKey
		{
			get
			{
				if (!selectedMode)
				{
					return "SmartTitle";
				}
				return "SelectedTitle";
			}
		}

		private bool CanSetLimit
		{
			get
			{
				if (preview != null && !preview.Selection.SelectedMode && !executeRequested)
				{
					return modalSession?.IsOpen ?? false;
				}
				return false;
			}
		}

		private int LimitButtonStep
		{
			get
			{
				if (preview != null)
				{
					return Math.Max(1, preview.MaximumDecomposed / 20);
				}
				return 1;
			}
		}

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

		public void Update()
		{
			ObserveModalClosure();
			HandleLimitKeyboard();
			ExecuteApprovedFusion();
			TryShowPendingMessage();
			UpdateEntryButtons();
			DiscoverInventories();
		}

		private void ObserveModalClosure()
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Expected O, but got Unknown
			if (modalSession == null || modalSession.IsOpen)
			{
				return;
			}
			NativeModalSession nativeModalSession = modalSession;
			modalSession = null;
			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);
			}
			DestroyLimitButtons();
			releaseInputFrame = Time.frameCount;
			if (!executeRequested)
			{
				preview = null;
				forecast = null;
				dialogOwner = null;
			}
		}

		private void HandleLimitKeyboard()
		{
			if (CanSetLimit)
			{
				Keyboard current = Keyboard.current;
				if (current != null && ((ButtonControl)current.leftArrowKey).wasPressedThisFrame)
				{
					AdjustDonorLimit(-1);
				}
				Keyboard current2 = Keyboard.current;
				if (current2 != null && ((ButtonControl)current2.rightArrowKey).wasPressedThisFrame)
				{
					AdjustDonorLimit(1);
				}
			}
		}

		private void ExecuteApprovedFusion()
		{
			if (!executeRequested || Time.frameCount <= requestedFrame)
			{
				return;
			}
			NativeModalSession? nativeModalSession = modalSession;
			if (nativeModalSession != null && nativeModalSession.IsOpen)
			{
				return;
			}
			executeRequested = false;
			FusionPreview fusionPreview = preview;
			IotaInventoryLayer val = dialogOwner;
			preview = null;
			forecast = null;
			dialogOwner = null;
			try
			{
				if (fusionPreview == null || (Object)(object)val == (Object)null || !((Behaviour)val).isActiveAndEnabled || (Object)(object)InputManager.Instance == (Object)null || !InputManager.Instance.IsHeadOfStack((InputReceiver)(object)val))
				{
					throw new InvalidOperationException("粒子界面已经切换,未执行融合。");
				}
				QueueMessage(InventoryEditor.Apply(fusionPreview, val, donorLimit));
			}
			catch (Exception ex)
			{
				QueueMessage(new UiMessage("Failed", ex));
				Plugin.Logger.LogError((object)ex);
			}
		}

		private void TryShowPendingMessage()
		{
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Expected O, but got Unknown
			if (pendingMessage == null || modalSession != null)
			{
				return;
			}
			try
			{
				if (NativeModal.TryShowMessage(ModText.Get(pendingTitleKey), pendingMessage.ToString(), out NativeModalSession session))
				{
					modalSession = session;
					pendingMessage = null;
				}
			}
			catch (Exception ex)
			{
				pendingMessage = null;
				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 UpdateEntryButtons()
		{
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d2: 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)
			for (int num = bindings.Count - 1; num >= 0; num--)
			{
				ButtonBinding buttonBinding = bindings[num];
				if ((Object)(object)buttonBinding.Owner == (Object)null || (Object)(object)buttonBinding.Template == (Object)null)
				{
					if ((Object)(object)buttonBinding.Button != (Object)null)
					{
						Object.Destroy((Object)(object)((Component)buttonBinding.Button).gameObject);
					}
					bindings.RemoveAt(num);
				}
				else if (!((Object)(object)buttonBinding.Button == (Object)null))
				{
					bool flag = ((Behaviour)buttonBinding.Owner).isActiveAndEnabled && !((InputReceiver)buttonBinding.Owner).DisableInputEvents && ((Component)buttonBinding.Template).gameObject.activeInHierarchy;
					GameObject gameObject = ((Component)buttonBinding.Button).gameObject;
					if (gameObject.activeSelf != flag)
					{
						gameObject.SetActive(flag);
					}
					if (flag)
					{
						bool flag2 = !buttonBinding.Owner._fBA || (buttonBinding.Owner._OcA?.Count ?? 0) > 0;
						if (buttonBinding.Enabled != flag2)
						{
							NativeButtons.SetState(buttonBinding.Button, flag2);
							buttonBinding.Enabled = flag2;
						}
						string text = (buttonBinding.Owner._fBA ? "SelectedButton" : "SmartButton");
						if (buttonBinding.Language != ModText.Language || buttonBinding.TextKey != text)
						{
							NativeButtons.UpdateText(buttonBinding.Button, buttonBinding.Template, ModText.Get(text));
							buttonBinding.Language = ModText.Language;
							buttonBinding.TextKey = text;
						}
						Constrained2DTransform constrained2DTransform = buttonBinding.Template.constrained2D.constrained2DTransform;
						buttonBinding.Button.constrained2D._sQA(new Vector2(constrained2DTransform.offset.x, constrained2DTransform.offset.y + constrained2DTransform.sizeInPixels.y * 1.25f));
					}
				}
			}
		}

		private void DiscoverInventories()
		{
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Expected O, but got Unknown
			if (Time.realtimeSinceStartup < nextDiscovery)
			{
				return;
			}
			nextDiscovery = Time.realtimeSinceStartup + 0.5f;
			bool flag = default(bool);
			foreach (IotaInventoryLayer owner in Object.FindObjectsOfType<IotaInventoryLayer>())
			{
				if (!((Behaviour)owner).isActiveAndEnabled || (Object)(object)owner.selectMultipleButton == (Object)null || bindings.Any((ButtonBinding binding) => (Object)(object)binding.Owner == (Object)(object)owner))
				{
					continue;
				}
				ButtonBinding buttonBinding = new ButtonBinding(owner, owner.selectMultipleButton);
				bindings.Add(buttonBinding);
				try
				{
					buttonBinding.Button = CreateButton(buttonBinding.Template, owner);
					Plugin.Logger.LogDebug((object)"已建立粒子融合入口。");
				}
				catch (Exception ex)
				{
					ManualLogSource logger = Plugin.Logger;
					BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(11, 1, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("粒子融合按钮创建失败:");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
					}
					logger.LogError(val);
				}
			}
		}

		private UIButton CreateButton(UIButton template, IotaInventoryLayer owner)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)template.constrained2D == (Object)null || template.constrained2D.constrained2DTransform.sizeInPixels.y <= 0f)
			{
				throw new InvalidOperationException("批量选择按钮的布局不兼容,无法定位融合按钮。");
			}
			UIButton val = NativeButtons.Create(template, (InputReceiver)(object)owner, "ParticleFusion.Button", ModText.Get(owner._fBA ? "SelectedButton" : "SmartButton"), OpenPreview);
			try
			{
				Constrained2DTransform constrained2DTransform = template.constrained2D.constrained2DTransform;
				val.constrained2D._sQA(new Vector2(constrained2DTransform.offset.x, constrained2DTransform.offset.y + constrained2DTransform.sizeInPixels.y * 1.25f));
				return val;
			}
			catch
			{
				Object.Destroy((Object)(object)((Component)val).gameObject);
				throw;
			}
		}

		private void OpenPreview(UIButton button)
		{
			//IL_0276: Unknown result type (might be due to invalid IL or missing references)
			//IL_027d: Expected O, but got Unknown
			//IL_01af: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b5: Expected O, but got Unknown
			ButtonBinding buttonBinding = bindings.FirstOrDefault((ButtonBinding item) => (Object)(object)item.Button == (Object)(object)button);
			if (modalSession != null || pendingMessage != null || executeRequested || Time.frameCount == releaseInputFrame || buttonBinding == null || (Object)(object)buttonBinding.Owner == (Object)null || !((Behaviour)buttonBinding.Owner).isActiveAndEnabled || ((InputReceiver)buttonBinding.Owner).DisableInputEvents || !((Component)button).gameObject.activeInHierarchy)
			{
				return;
			}
			if (buttonBinding.Owner._fBA)
			{
				HashSet<IotaInstance> ocA = buttonBinding.Owner._OcA;
				if (ocA == null || ocA.Count == 0)
				{
					return;
				}
			}
			dialogOwner = buttonBinding.Owner;
			selectedMode = buttonBinding.Owner._fBA;
			bool flag = default(bool);
			try
			{
				preview = InventoryEditor.Preview(buttonBinding.Owner);
				if (preview.Selection.SelectedMode && preview.Selection.Count == 0)
				{
					throw new InvalidOperationException("库存或选择已经变化,请重新查看数量并确认。");
				}
				donorLimit = preview.MaximumDecomposed;
				forecast = InventoryEditor.Forecast(preview);
				if (!NativeModal.TryShowConfirmation(ModText.Get(TitleKey), ConfirmationBody(), CancelPreview, ConfirmPreview, out NativeModalSession session))
				{
					preview = null;
					forecast = null;
					dialogOwner = null;
					Plugin.Logger.LogDebug((object)"原版 Modal 正忙,未打开融合预览。");
					return;
				}
				modalSession = session;
				if (!selectedMode)
				{
					CreateLimitButtons();
				}
				ManualLogSource logger = Plugin.Logger;
				BepInExDebugLogInterpolatedStringHandler val = new BepInExDebugLogInterpolatedStringHandler(19, 3, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("融合预览:模式=");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(selectedMode ? "选中供体" : "智能");
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(",库存");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<long>(preview.Total);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("颗,供体上限");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(donorLimit);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("颗。");
				}
				logger.LogDebug(val);
			}
			catch (Exception ex)
			{
				modalSession?.Close();
				DestroyLimitButtons();
				preview = null;
				forecast = null;
				dialogOwner = null;
				QueueMessage(new UiMessage("Unavailable", ex));
				ManualLogSource logger2 = Plugin.Logger;
				BepInExWarningLogInterpolatedStringHandler val2 = new BepInExWarningLogInterpolatedStringHandler(7, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("融合预览失败:");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<Exception>(ex);
				}
				logger2.LogWarning(val2);
			}
		}

		private void CancelPreview()
		{
			preview = null;
			forecast = null;
			dialogOwner = null;
			executeRequested = false;
			releaseInputFrame = Time.frameCount;
			DestroyLimitButtons();
			Plugin.Logger.LogDebug((object)"融合预览已取消。");
		}

		private void ConfirmPreview()
		{
			executeRequested = true;
			requestedFrame = Time.frameCount;
			releaseInputFrame = Time.frameCount;
			DestroyLimitButtons();
		}

		private void CreateLimitButtons()
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: 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_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			UiModal modal = (modalSession ?? throw new InvalidOperationException("原版融合确认窗口尚未建立。")).Modal;
			UIButton obj = modal.leftButton ?? throw new InvalidOperationException("原版 Modal 缺少主按钮模板。");
			Transform parent = ((Component)obj).transform.parent;
			Constrained2DTransform constrained2DTransform = modal.leftButtonC2d.constrained2DTransform;
			Constrained2DTransform constrained2DTransform2 = modal.rightButtonC2d.constrained2DTransform;
			float num = Math.Max(36f, Math.Min(constrained2DTransform.sizeInPixels.y, constrained2DTransform2.sizeInPixels.y));
			float num2 = (constrained2DTransform.offset.x + constrained2DTransform2.offset.x) * 0.5f;
			float num3 = Math.Max(constrained2DTransform.offset.y, constrained2DTransform2.offset.y) + num * 1.25f;
			Vector2 val = default(Vector2);
			((Vector2)(ref val))..ctor(Math.Max(56f, num), num);
			UIButton val2 = NativeButtons.Create(obj, (InputReceiver)(object)modal, "ParticleFusion.DonorDecrease", "-", delegate
			{
				AdjustDonorLimit(-LimitButtonStep);
			});
			UIButton val3 = NativeButtons.Create(obj, (InputReceiver)(object)modal, "ParticleFusion.DonorIncrease", "+", delegate
			{
				AdjustDonorLimit(LimitButtonStep);
			});
			limitButtons.Add(val2);
			limitButtons.Add(val3);
			NativeButtons.Place(val2, parent, new Vector2(num2 - val.x * 0.65f, num3), val);
			NativeButtons.Place(val3, parent, new Vector2(num2 + val.x * 0.65f, num3), val);
			UpdateLimitButtons();
		}

		private void AdjustDonorLimit(int delta)
		{
			if (CanSetLimit && delta != 0)
			{
				int num = Math.Clamp(donorLimit + delta, 0, preview.MaximumDecomposed);
				if (num != donorLimit)
				{
					donorLimit = num;
					modalSession.UpdateBody(ConfirmationBody());
					UpdateLimitButtons();
				}
			}
		}

		private void UpdateLimitButtons()
		{
			if (limitButtons.Count == 2 && preview != null)
			{
				NativeButtons.SetState(limitButtons[0], donorLimit > 0);
				NativeButtons.SetState(limitButtons[1], donorLimit < preview.MaximumDecomposed);
			}
		}

		private void DestroyLimitButtons()
		{
			foreach (UIButton limitButton in limitButtons)
			{
				if ((Object)(object)limitButton != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)limitButton).gameObject);
				}
			}
			limitButtons.Clear();
		}

		private string ConfirmationBody()
		{
			FusionPreview fusionPreview = preview ?? throw new InvalidOperationException("融合预览已经失效。");
			FusionProgress fusionProgress = (forecast ?? throw new InvalidOperationException("融合预览已经失效。")).At(donorLimit);
			string text = new UiMessage(selectedMode ? "SelectedPreview" : "SmartPreview", fusionPreview.Total, fusionPreview.Selection.Count).ToString();
			text += "\n\n";
			if (!selectedMode)
			{
				text = text + ModText.Get("DonorLimit", donorLimit) + "\n";
			}
			return text + ModText.Get("Estimate", fusionProgress.Decomposed, fusionProgress.Strengthened);
		}

		[HideFromIl2Cpp]
		private void QueueMessage(UiMessage message)
		{
			pendingMessage = message;
			pendingTitleKey = TitleKey;
		}

		public void OnDestroy()
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Expected O, but got Unknown
			executeRequested = false;
			preview = null;
			forecast = null;
			pendingMessage = null;
			NativeModalSession nativeModalSession = modalSession;
			nativeModalSession?.Close();
			if (nativeModalSession?.Failure != null)
			{
				ManualLogSource logger = Plugin.Logger;
				bool flag = default(bool);
				BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(16, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("组件卸载时关闭原版融合窗口失败:");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(nativeModalSession.Failure);
				}
				logger.LogWarning(val);
			}
			modalSession = null;
			DestroyLimitButtons();
			foreach (ButtonBinding binding in bindings)
			{
				if ((Object)(object)binding.Button != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)binding.Button).gameObject);
				}
			}
			bindings.Clear();
		}
	}
	internal static class InventoryEditor
	{
		internal static FusionPreview Preview(IotaInventoryLayer layer)
		{
			//IL_0077: 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_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			_NH val = _NH._CEb ?? throw new InvalidOperationException("请先载入游戏存档。");
			EnsureNoOccupiedMaterials();
			EnsureLayout();
			IotaInventory val2 = val._UNA();
			UnorderedListVal<IotaInstance> val3 = ((val2 != null) ? val2.allIota : null);
			SingleFileSaveDataV2 val4 = val._DEb?._iEb;
			if (val2 == null || val3 == null || val4 == null)
			{
				throw new InvalidOperationException("粒子库存尚未就绪,请稍后重试。");
			}
			List<IotaInstance> list = new List<IotaInstance>(val3.Length);
			for (int i = 0; i < val3.Length; i++)
			{
				IotaInstance item = val3.RawBuffer[i];
				ushort baseIotaId = ((IotaInstance)(ref item)).BaseIotaId;
				bool flag = ((baseIotaId < 1 || baseIotaId > 40) ? true : false);
				if (flag || ((IotaInstance)(ref item)).Potency > 999 || ParticleData.Shape(item) != ((IotaInstance)(ref item)).BaseIotaId || ParticleData.Potency(item) != ((IotaInstance)(ref item)).Potency || ParticleData.TraitCount(item) != ((IotaInstance)(ref item)).TraitCount)
				{
					throw new InvalidOperationException("粒子编码或种类已改变,未修改库存。");
				}
				list.Add(item);
			}
			return new FusionPreview(((Il2CppObjectBase)val).Pointer, ((Il2CppObjectBase)val2).Pointer, ((Il2CppObjectBase)layer).Pointer, list, CaptureSelection(layer, list), new AvailableParticles(val));
		}

		private static InventorySelection CaptureSelection(IotaInventoryLayer layer, IReadOnlyList<IotaInstance> items)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			Dictionary<IotaKey, int> dictionary = new Dictionary<IotaKey, int>();
			if (layer._fBA && layer._OcA != null)
			{
				Enumerator<IotaInstance> enumerator = layer._OcA.GetEnumerator();
				while (enumerator.MoveNext())
				{
					IotaInstance current = enumerator.Current;
					IotaKey key = IotaKey.Of(current);
					dictionary[key] = checked(dictionary.GetValueOrDefault(key) + current.Count);
				}
			}
			Dictionary<IotaKey, int> inventory = items.GroupBy(IotaKey.Of).ToDictionary((IGrouping<IotaKey, IotaInstance> group) => group.Key, (IGrouping<IotaKey, IotaInstance> group) => group.Sum((IotaInstance item) => item.Count));
			if (dictionary.Any((KeyValuePair<IotaKey, int> pair) => pair.Value <= 0 || pair.Value > inventory.GetValueOrDefault(pair.Key)))
			{
				throw new InvalidOperationException("库存或选择已经变化,请重新查看数量并确认。");
			}
			return new InventorySelection(layer._fBA, dictionary);
		}

		internal static FusionForecast Forecast(FusionPreview preview)
		{
			_NH owner = _NH._CEb ?? throw new InvalidOperationException("请先载入游戏存档。");
			return FusionEngine.Forecast(preview.Items, preview.Selection, preview.MaximumDecomposed, new AvailableParticles(owner));
		}

		internal static UiMessage Apply(FusionPreview approved, IotaInventoryLayer layer, int limit)
		{
			//IL_0607: Unknown result type (might be due to invalid IL or missing references)
			//IL_060e: Expected O, but got Unknown
			//IL_018c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0277: Unknown result type (might be due to invalid IL or missing references)
			//IL_027c: 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_0287: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b5: 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_02e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fb: Expected O, but got Unknown
			//IL_030d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0312: Unknown result type (might be due to invalid IL or missing references)
			//IL_031b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0394: Unknown result type (might be due to invalid IL or missing references)
			//IL_0399: Unknown result type (might be due to invalid IL or missing references)
			//IL_03af: Unknown result type (might be due to invalid IL or missing references)
			//IL_05a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_05a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0562: Unknown result type (might be due to invalid IL or missing references)
			FusionPreview fusionPreview = Preview(layer);
			if (!approved.Matches(fusionPreview))
			{
				throw new InvalidOperationException("库存或选择已经变化,请重新查看数量并确认。");
			}
			if (limit < 0 || limit > approved.MaximumDecomposed)
			{
				throw new InvalidOperationException("供体限额超出确认范围。");
			}
			if (fusionPreview.Items.Count == 0)
			{
				return new UiMessage("NoInventory");
			}
			_NH cEb = _NH._CEb;
			IotaInventory val = cEb._UNA();
			AvailableParticles available = new AvailableParticles(cEb);
			FusionResult fusionResult = FusionEngine.Prepare(fusionPreview.Items, fusionPreview.Selection, limit, available);
			if (fusionResult.Items.Count + fusionResult.Decomposed != fusionPreview.Total || fusionResult.Supplied != fusionResult.Spent + fusionResult.Remainder)
			{
				throw new InvalidOperationException("融合数量或效能总量不守恒,未提交库存。");
			}
			Dictionary<IotaKey, int> dictionary = fusionPreview.Items.GroupBy(IotaKey.Of).ToDictionary((IGrouping<IotaKey, IotaInstance> group) => group.Key, (IGrouping<IotaKey, IotaInstance> group) => group.Sum((IotaInstance item) => item.Count));
			foreach (IGrouping<IotaKey, IotaInstance> item in fusionResult.Items.GroupBy(IotaKey.Of))
			{
				if (item.Count() > dictionary.GetValueOrDefault(item.Key) && !available.Contains(item.First()))
				{
					throw new InvalidOperationException("融合产生了无法从单一已解锁来源取得的粒子。");
				}
			}
			int num = fusionPreview.Items.Where((IotaInstance item) => !FusionRules.CanDonate(item, available.MaximumPotency(item))).Sum((IotaInstance item) => item.Count);
			if (fusionResult.Items.Count((IotaInstance item) => !FusionRules.CanDonate(item, available.MaximumPotency(item))) < num)
			{
				throw new InvalidOperationException("融合结果分解了满效能或三技能的粒子,未提交库存。");
			}
			if (fusionResult.Processed == 0 && fusionResult.Strengthened == 0 && !fusionResult.Consolidated)
			{
				return new UiMessage("NoAction");
			}
			if (fusionResult.Processed > limit)
			{
				throw new InvalidOperationException("融合消耗超过确认上界,未提交库存。");
			}
			Dictionary<(ulong, uint), IotaInstance> dictionary2 = new Dictionary<(ulong, uint), IotaInstance>();
			foreach (IotaInstance item2 in fusionResult.Items)
			{
				(ulong, uint) key = (item2.DataLowerHalf, item2.DataUpperHalf);
				if (dictionary2.TryGetValue(key, out var value))
				{
					value.Count = checked((ushort)(value.Count + 1));
					dictionary2[key] = value;
				}
				else
				{
					dictionary2.Add(key, item2);
				}
			}
			IotaInventory val2 = new IotaInventory
			{
				allIota = new UnorderedListVal<IotaInstance>(dictionary2.Count)
			};
			foreach (IotaInstance value3 in dictionary2.Values)
			{
				val2.allIota.Add(value3);
			}
			val2.OnDeserialized();
			val2.Initialize();
			List<(CraftingLayer, UnorderedListVal<IotaInstance>, UnorderedListVal<IotaInstance>)> list = new List<(CraftingLayer, UnorderedListVal<IotaInstance>, UnorderedListVal<IotaInstance>)>();
			foreach (CraftingLayer item3 in Object.FindObjectsOfType<CraftingLayer>())
			{
				if (item3._Fu())
				{
					UnorderedListVal<IotaInstance> val3 = new UnorderedListVal<IotaInstance>(fusionResult.Items.Count);
					for (int num2 = 0; num2 < fusionResult.Items.Count; num2++)
					{
						IotaInstance val4 = fusionResult.Items[num2];
						val4.UserData = checked((ushort)num2);
						val4.Count = 1;
						val3.Add(val4);
					}
					list.Add((item3, item3._dZ, val3));
				}
			}
			UnorderedListVal<IotaInstance> allIota = val.allIota;
			HashSet<IotaInstance> instanceExistsBaseIotaIdPotency = val.instanceExistsBaseIotaIdPotency;
			bool dirty = val.dirty;
			try
			{
				val.allIota = val2.allIota;
				val.instanceExistsBaseIotaIdPotency = val2.instanceExistsBaseIotaIdPotency;
				val.dirty = false;
				foreach (var item4 in list)
				{
					item4.Item1._dZ = item4.Item3;
				}
			}
			catch
			{
				val.allIota = allIota;
				val.instanceExistsBaseIotaIdPotency = instanceExistsBaseIotaIdPotency;
				val.dirty = dirty;
				foreach (var item5 in list)
				{
					item5.Item1._dZ = item5.Item2;
				}
				throw;
			}
			UiMessage uiMessage = new UiMessage("Result", fusionPreview.Total, fusionResult.Items.Count, fusionResult.Strengthened);
			Plugin.Logger.LogDebug((object)uiMessage);
			try
			{
				foreach (var item6 in list)
				{
					BottomInsetIotaScrollContainer bottomInsetIotaScrollContainer = item6.Item1.bottomInsetIotaScrollContainer;
					IotaDetails val5 = ((bottomInsetIotaScrollContainer != null) ? bottomInsetIotaScrollContainer._EC() : null);
					item6.Item1._ku();
					if (val5 != null)
					{
						ushort value2 = val5.Id.Value;
						if (value2 >= 1 && value2 <= 40)
						{
							item6.Item1._ju(ref val5, true);
						}
					}
				}
				IotaFilterParameters val6 = cEb._ioA();
				foreach (IotaInventoryLayer item7 in Object.FindObjectsOfType<IotaInventoryLayer>())
				{
					if (((Behaviour)item7).isActiveAndEnabled)
					{
						if (item7._fBA)
						{
							item7._Kw();
						}
						item7._ww(ref val6);
					}
				}
			}
			catch (Exception ex)
			{
				ManualLogSource logger = Plugin.Logger;
				bool flag = default(bool);
				BepInExWarningLogInterpolatedStringHandler val7 = new BepInExWarningLogInterpolatedStringHandler(13, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val7).AppendLiteral("融合已提交,界面刷新失败:");
					((BepInExLogInterpolatedStringHandler)val7).AppendFormatted<Exception>(ex);
				}
				logger.LogWarning(val7);
				uiMessage.Warning = "RefreshWarning";
			}
			return uiMessage;
		}

		private static void EnsureNoOccupiedMaterials()
		{
			foreach (CraftingLayer item in Object.FindObjectsOfType<CraftingLayer>())
			{
				if (item._Fu() && ((item._DZ?.Length ?? 0) > 0 || (Object)(object)item._Uz != (Object)null || (Object)(object)item._vz != (Object)null))
				{
					throw new InvalidOperationException("当前棋盘或拖拽操作仍占用粒子。请先收回这些材料,再确认融合;本次未修改库存。");
				}
			}
		}

		private static void EnsureLayout()
		{
			if (Marshal.SizeOf<IotaInstance>() != 16 || Marshal.OffsetOf<IotaInstance>("BaseIotaIdPotency").ToInt32() != 0 || Marshal.OffsetOf<IotaInstance>("TraitId1").ToInt32() != 4 || Marshal.OffsetOf<IotaInstance>("TraitId2").ToInt32() != 6 || Marshal.OffsetOf<IotaInstance>("TraitId3").ToInt32() != 8 || Marshal.OffsetOf<IotaInstance>("UserData").ToInt32() != 10 || Marshal.OffsetOf<IotaInstance>("Count").ToInt32() != 12 || Marshal.OffsetOf<IotaInstance>("DataLowerHalf").ToInt32() != 0 || Marshal.OffsetOf<IotaInstance>("DataUpperHalf").ToInt32() != 8)
			{
				throw new InvalidOperationException("游戏粒子结构已改变,未修改库存。");
			}
		}
	}
	internal sealed class FusionPreview
	{
		private readonly IntPtr owner;

		private readonly IntPtr inventory;

		private readonly IntPtr layer;

		internal IReadOnlyList<IotaInstance> Items { get; }

		internal InventorySelection Selection { get; }

		internal long Total { get; }

		internal int MaximumDecomposed { get; }

		internal FusionPreview(IntPtr owner, IntPtr inventory, IntPtr layer, IReadOnlyList<IotaInstance> items, InventorySelection selection, AvailableParticles available)
		{
			this.owner = owner;
			this.inventory = inventory;
			this.layer = layer;
			Items = items;
			Selection = selection;
			Total = ((IEnumerable<IotaInstance>)items).Sum((Func<IotaInstance, long>)((IotaInstance item) => item.Count));
			MaximumDecomposed = (selection.SelectedMode ? selection.Count : items.Where((IotaInstance item) => FusionRules.IsSmartMaterial(item, available.MaximumPotency(item))).Sum((IotaInstance item) => item.Count));
		}

		internal bool Matches(FusionPreview other)
		{
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: 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_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			if (owner != other.owner || inventory != other.inventory || layer != other.layer || Items.Count != other.Items.Count || !Selection.Matches(other.Selection))
			{
				return false;
			}
			for (int i = 0; i < Items.Count; i++)
			{
				if (Items[i].DataLowerHalf != other.Items[i].DataLowerHalf || Items[i].DataUpperHalf != other.Items[i].DataUpperHalf || Items[i].Count != other.Items[i].Count || Items[i]._Unused != other.Items[i]._Unused)
				{
					return false;
				}
			}
			return true;
		}
	}
	internal readonly record struct IotaKey(ulong Lower, uint Upper, ushort Unused)
	{
		internal static IotaKey Of(IotaInstance item)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			return new IotaKey(item.DataLowerHalf, item.DataUpperHalf, item._Unused);
		}
	}
	internal sealed class InventorySelection
	{
		internal bool SelectedMode { get; }

		internal Dictionary<IotaKey, int> Quantities { get; }

		internal int Count => Quantities.Values.Sum();

		internal InventorySelection(bool selectedMode, Dictionary<IotaKey, int> quantities)
		{
			SelectedMode = selectedMode;
			Quantities = quantities;
		}

		internal bool Matches(InventorySelection other)
		{
			if (SelectedMode == other.SelectedMode && Quantities.Count == other.Quantities.Count)
			{
				return Quantities.All((KeyValuePair<IotaKey, int> pair) => other.Quantities.GetValueOrDefault(pair.Key) == pair.Value);
			}
			return false;
		}
	}
	[BepInPlugin("menglei.infalsus.potency999", "In Falsus Particle Fusion", "1.0.1")]
	[BepInProcess("infalsus.exe")]
	public sealed class Plugin : BasePlugin
	{
		internal static ManualLogSource Logger { get; private set; }

		public override void Load()
		{
			Logger = ((BasePlugin)this).Log;
			WindowsConsoleEncoding.EnsureUtf8(((BasePlugin)this).Log);
			((BasePlugin)this).AddComponent<InventoryButtonBehaviour>();
			((BasePlugin)this).Log.LogInfo((object)"加载完成。");
		}
	}
	internal static class TraitConsolidator
	{
		private sealed class Stack
		{
			internal readonly IotaInstance Item;

			internal int Count;

			internal Stack(IotaInstance item, int count)
			{
				//IL_0007: Unknown result type (might be due to invalid IL or missing references)
				//IL_0008: Unknown result type (might be due to invalid IL or missing references)
				Item = item;
				Count = count;
			}
		}

		private const int CandidateBudget = 1000000;

		internal static ConsolidationResult Apply(List<IotaInstance> items, AvailableParticles available)
		{
			//IL_019f: Unknown result type (might be due to invalid IL or missing references)
			Dictionary<(ulong, uint), Stack> dictionary = CountStacks(items);
			int count = dictionary.Count;
			int num = dictionary.Values.Count((Stack stack) => stack.Count == 1);
			int budget = 1000000;
			TraitStock source = new TraitStock(items, available);
			List<IotaInstance> list = new List<IotaInstance>(items.Count);
			foreach (IGrouping<(int, ushort, ushort), IotaInstance> item in from item in items
				group item by (BaseIotaIdPotency: item.BaseIotaIdPotency, UserData: item.UserData, _Unused: item._Unused))
			{
				Dictionary<(ulong, uint), Stack> dictionary2 = CountStacks(item);
				Dictionary<(ulong, uint), Stack> dictionary3 = CountStacks(item.Select((IotaInstance item) => (!available.Contains(item)) ? item : Normalize(item)));
				TraitStock traitStock = new TraitStock(source);
				while (budget > 0 && Improve(dictionary3, available, traitStock, ref budget))
				{
				}
				int num2;
				if (dictionary3.Count >= dictionary2.Count)
				{
					if (dictionary3.Count == dictionary2.Count)
					{
						num2 = ((dictionary3.Values.Count((Stack stack) => stack.Count == 1) < dictionary2.Values.Count((Stack stack) => stack.Count == 1)) ? 1 : 0);
						if (num2 != 0)
						{
							goto IL_0173;
						}
					}
					else
					{
						num2 = 0;
					}
					goto IL_0177;
				}
				num2 = 1;
				goto IL_0173;
				IL_0173:
				source = traitStock;
				goto IL_0177;
				IL_0177:
				foreach (Stack value in ((num2 != 0) ? dictionary3 : dictionary2).Values)
				{
					for (int num3 = 0; num3 < value.Count; num3++)
					{
						list.Add(value.Item);
					}
				}
			}
			Dictionary<(ulong, uint), Stack> dictionary4 = CountStacks(list);
			int count2 = dictionary4.Count;
			int num4 = dictionary4.Values.Count((Stack stack) => stack.Count == 1);
			if (count2 >= count && (count2 != count || num4 >= num))
			{
				return new ConsolidationResult(count, count, num, num, Changed: false);
			}
			items.Clear();
			items.AddRange(list);
			return new ConsolidationResult(count, count2, num, num4, Changed: true);
		}

		private static Dictionary<(ulong, uint), Stack> CountStacks(IEnumerable<IotaInstance> items)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: 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_0047: Unknown result type (might be due to invalid IL or missing references)
			Dictionary<(ulong, uint), Stack> dictionary = new Dictionary<(ulong, uint), Stack>();
			foreach (IotaInstance item in items)
			{
				(ulong, uint) key = (item.DataLowerHalf, item.DataUpperHalf);
				if (dictionary.TryGetValue(key, out var value))
				{
					value.Count++;
				}
				else
				{
					dictionary.Add(key, new Stack(item, 1));
				}
			}
			return dictionary;
		}

		private static bool Improve(Dictionary<(ulong, uint), Stack> stacks, AvailableParticles available, TraitStock stock, ref int budget)
		{
			//IL_0065: 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_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02af: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02de: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0314: Unknown result type (might be due to invalid IL or missing references)
			//IL_0329: Unknown result type (might be due to invalid IL or missing references)
			//IL_0337: Unknown result type (might be due to invalid IL or missing references)
			//IL_0341: Unknown result type (might be due to invalid IL or missing references)
			//IL_039f: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a3: Unknown result type (might be due to invalid IL or missing references)
			KeyValuePair<(ulong, uint), Stack>[] array = stacks.OrderBy<KeyValuePair<(ulong, uint), Stack>, int>((KeyValuePair<(ulong, uint), Stack> pair) => pair.Value.Count).ToArray();
			for (int num = 0; num < array.Length; num++)
			{
				for (int num2 = num + 1; num2 < array.Length; num2++)
				{
					if (--budget < 0)
					{
						return false;
					}
					KeyValuePair<(ulong, uint), Stack> keyValuePair = array[num];
					KeyValuePair<(ulong, uint), Stack> keyValuePair2 = array[num2];
					if (!available.Contains(keyValuePair.Value.Item) || !available.Contains(keyValuePair2.Value.Item))
					{
						continue;
					}
					int num3 = ParticleData.TraitCount(keyValuePair.Value.Item);
					int num4 = Math.Min(keyValuePair.Value.Count, keyValuePair2.Value.Count);
					for (int num5 = 0; num5 < num3; num5++)
					{
						for (int num6 = 0; num6 < num3; num6++)
						{
							if (--budget < 0)
							{
								return false;
							}
							short trait = ParticleData.GetTrait(keyValuePair.Value.Item, num5);
							short trait2 = ParticleData.GetTrait(keyValuePair2.Value.Item, num6);
							if (trait == trait2)
							{
								continue;
							}
							IotaInstance item = keyValuePair.Value.Item;
							IotaInstance item2 = keyValuePair2.Value.Item;
							ParticleData.SetTrait(ref item, num5, trait2);
							ParticleData.SetTrait(ref item2, num6, trait);
							item = Normalize(item);
							item2 = Normalize(item2);
							(ulong, uint) tuple = (item.DataLowerHalf, item.DataUpperHalf);
							(ulong, uint) tuple2 = (item2.DataLowerHalf, item2.DataUpperHalf);
							(ulong, uint) tuple3 = tuple;
							(ulong, uint) tuple4 = tuple2;
							if ((tuple3.Item1 != tuple4.Item1 || tuple3.Item2 != tuple4.Item2) && !stacks.ContainsKey(tuple) && !stacks.ContainsKey(tuple2))
							{
								continue;
							}
							Dictionary<(ulong, uint), int> dictionary = new Dictionary<(ulong, uint), int>();
							dictionary[keyValuePair.Key] = -num4;
							dictionary[keyValuePair2.Key] = -num4;
							dictionary[tuple] = dictionary.GetValueOrDefault(tuple) + num4;
							dictionary[tuple2] = dictionary.GetValueOrDefault(tuple2) + num4;
							int num7 = 0;
							int num8 = 0;
							foreach (KeyValuePair<(ulong, uint), int> item3 in dictionary)
							{
								Stack value;
								int num9 = (stacks.TryGetValue(item3.Key, out value) ? value.Count : 0);
								int num10 = num9 + item3.Value;
								num7 += ((num10 > 0) ? 1 : 0) - ((num9 > 0) ? 1 : 0);
								num8 += ((num10 == 1) ? 1 : 0) - ((num9 == 1) ? 1 : 0);
							}
							if (num7 > 0 || (num7 == 0 && num8 >= 0) || !available.Contains(item) || !available.Contains(item2) || !stock.CanExchange((IotaInstance[])(object)new IotaInstance[2]
							{
								keyValuePair.Value.Item,
								keyValuePair2.Value.Item
							}, (IotaInstance[])(object)new IotaInstance[2] { item, item2 }, num4))
							{
								continue;
							}
							stock.Change(keyValuePair.Value.Item, -num4);
							stock.Change(keyValuePair2.Value.Item, -num4);
							stock.Change(item, num4);
							stock.Change(item2, num4);
							foreach (KeyValuePair<(ulong, uint), int> item4 in dictionary)
							{
								if (!stacks.TryGetValue(item4.Key, out Stack value2))
								{
									(ulong, uint) key = item4.Key;
									tuple4 = tuple;
									value2 = new Stack((key.Item1 == tuple4.Item1 && key.Item2 == tuple4.Item2) ? item : item2, 0);
									stacks.Add(item4.Key, value2);
								}
								value2.Count += item4.Value;
								if (value2.Count == 0)
								{
									stacks.Remove(item4.Key);
								}
							}
							return true;
						}
					}
				}
			}
			return false;
		}

		private static IotaInstance Normalize(IotaInstance item)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			short[] array = (from slot in Enumerable.Range(0, ParticleData.TraitCount(item))
				select ParticleData.GetTrait(item, slot)).ToArray();
			Array.Sort(array);
			for (int num = 0; num < array.Length; num++)
			{
				ParticleData.SetTrait(ref item, num, array[num]);
			}
			return item;
		}
	}
	internal readonly record struct ConsolidationResult(int Before, int After, int SinglesBefore, int SinglesAfter, bool Changed);
	internal static class TraitDemand
	{
		private static readonly Dictionary<short, int> counts = Load();

		private static Dictionary<short, int> Load()
		{
			using Stream utf8Json = Assembly.GetExecutingAssembly().GetManifestResourceStream("InFalsusMod.Data.trait-demand.json") ?? throw new InvalidOperationException("Missing trait demand resource.");
			using JsonDocument jsonDocument = JsonDocument.Parse(utf8Json);
			Dictionary<short, int> dictionary = new Dictionary<short, int>();
			foreach (JsonElement item in jsonDocument.RootElement.GetProperty("Skills").EnumerateArray())
			{
				short @int = item.GetProperty("Id").GetInt16();
				int int2 = item.GetProperty("Count").GetInt32();
				if (int2 < 0 || item.GetProperty("Weight").GetInt32() != int2 / 4 + 1)
				{
					throw new InvalidOperationException("Invalid trait demand weight.");
				}
				dictionary.Add(@int, int2);
			}
			if (!dictionary.Keys.ToHashSet().SetEquals(from info in TraitCatalog.Entries
				where info.Tier == 3
				select (short)info.Id))
			{
				throw new InvalidOperationException("Trait demand catalog mismatch.");
			}
			return dictionary;
		}

		internal static bool IsThird(short trait)
		{
			return counts.ContainsKey(trait);
		}

		internal static int Weight(short trait)
		{
			return counts.GetValueOrDefault(trait) / 4 + 1;
		}
	}
	internal sealed class TraitStock
	{
		private readonly Dictionary<ushort, int> quantities = new Dictionary<ushort, int>();

		private readonly Dictionary<(ushort Shape, short Trait), int> carriers = new Dictionary<(ushort, short), int>();

		private readonly Dictionary<ushort, short[]> traits;

		internal TraitStock(IEnumerable<IotaInstance> items, AvailableParticles available)
		{
			//IL_003a: 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_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			TraitStock traitStock = this;
			foreach (IotaInstance item in items)
			{
				Change(item, item.Count);
			}
			traits = quantities.Keys.ToDictionary((ushort shape) => shape, (ushort shape) => available.ThirdTraits(shape).Concat(from key in traitStock.carriers.Keys
				where key.Shape == shape
				select key.Trait).Distinct()
				.ToArray());
		}

		internal TraitStock(TraitStock source)
		{
			quantities = new Dictionary<ushort, int>(source.quantities);
			carriers = new Dictionary<(ushort, short), int>(source.carriers);
			traits = source.traits;
		}

		internal int Count(ushort shape, short trait)
		{
			return carriers.GetValueOrDefault((shape, trait));
		}

		internal static IEnumerable<short> ThirdTraits(IotaInstance item)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			for (int slot = 0; slot < ParticleData.TraitCount(item); slot++)
			{
				short trait = ParticleData.GetTrait(item, slot);
				if (TraitDemand.IsThird(trait))
				{
					bool flag = false;
					for (int i = 0; i < slot; i++)
					{
						flag |= ParticleData.GetTrait(item, i) == trait;
					}
					if (!flag)
					{
						yield return trait;
					}
				}
			}
		}

		internal void Change(IotaInstance item, int copies)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			ushort num = ParticleData.Shape(item);
			checked
			{
				quantities[num] = quantities.GetValueOrDefault(num) + copies;
				foreach (short item2 in ThirdTraits(item))
				{
					carriers[(num, item2)] = Count(num, item2) + copies;
				}
			}
		}

		internal bool CanExchange(IotaInstance[] before, IotaInstance[] after, int copies)
		{
			//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_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			Dictionary<(ushort Shape, short Trait), int> delta = new Dictionary<(ushort, short), int>();
			IotaInstance[] array = before;
			foreach (IotaInstance item in array)
			{
				foreach (short item3 in ThirdTraits(item))
				{
					(ushort, short) key = (ParticleData.Shape(item), item3);
					delta[key] = delta.GetValueOrDefault(key) - copies;
				}
			}
			array = after;
			foreach (IotaInstance item2 in array)
			{
				foreach (short item4 in ThirdTraits(item2))
				{
					(ushort, short) key2 = (ParticleData.Shape(item2), item4);
					delta[key2] = delta.GetValueOrDefault(key2) + copies;
				}
			}
			if (delta.Any((KeyValuePair<(ushort Shape, short Trait), int> entry) => Count(entry.Key.Shape, entry.Key.Trait) + entry.Value < Math.Min(3, Count(entry.Key.Shape, entry.Key.Trait))))
			{
				return false;
			}
			foreach (ushort shape in delta.Keys.Select(((ushort Shape, short Trait) tuple) => tuple.Shape).Distinct())
			{
				short[] valueOrDefault = traits.GetValueOrDefault(shape, Array.Empty<short>());
				int num = valueOrDefault.Sum((short id) => Math.Max(0, 3 - Count(shape, id)));
				if (valueOrDefault.Sum((short id) => Math.Max(0, 3 - Count(shape, id) - delta.GetValueOrDefault((shape, id)))) == num && Mismatch(shape, delta) > Mismatch(shape, null) + 1E-10)
				{
					return false;
				}
			}
			return true;
		}

		private double Mismatch(ushort shape, Dictionary<(ushort Shape, short Trait), int>? delta)
		{
			short[] valueOrDefault = traits.GetValueOrDefault(shape, Array.Empty<short>());
			int[] array = valueOrDefault.Select((short id) => Math.Max(0, Count(shape, id) + (delta?.GetValueOrDefault((shape, id)) ?? 0) - 3)).ToArray();
			double num = array.Sum();
			double num2 = ((IEnumerable<short>)valueOrDefault).Sum((Func<short, int>)TraitDemand.Weight);
			if (num == 0.0 || num2 == 0.0)
			{
				return 0.0;
			}
			double num3 = 0.0;
			for (int num4 = 0; num4 < valueOrDefault.Length; num4++)
			{
				double num5 = (double)TraitDemand.Weight(valueOrDefault[num4]) / num2;
				double num6 = (double)array[num4] / num - num5;
				num3 += num6 * num6 / num5;
			}
			return num3;
		}
	}
	internal sealed class UiMessage
	{
		private readonly string key;

		private readonly object[] args;

		internal string? Warning { get; set; }

		internal UiMessage(string key, params object[] args)
		{
			this.key = key;
			this.args = args;
		}

		public override string ToString()
		{
			object[] array = args.Select((object value) => (!(value is Exception exception)) ? value : ModText.Error(exception)).ToArray();
			string text = ModText.Get(key, array);
			if (Warning != null)
			{
				return text + "\n" + ModText.Get(Warning);
			}
			return text;
		}
	}
	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);
			}
			if (!((Object)(object)val != (Object)null) || val._StA())
			{
				return null;
			}
			return val;
		}

		private static TextParameters Direct(string text)
		{
			return TextParameters.CreateDirectString(text);
		}

		private static Action<UiModal> Convert(Action<UiModal> action)
		{
			return DelegateSupport.ConvertDelegate<Action<UiModal>>((Delegate)action) ?? throw new InvalidOperationException("无法建立原版 Modal 回调。");
		}
	}
	internal sealed class NativeModalSession
	{
		private readonly Action<UiModal> primaryAction;

		private readonly Action<UiModal>? secondaryAction;

		internal UiModal Modal { get; }

		internal Exception? Failure { get; private set; }

		internal bool IsOpen
		{
			get
			{
				try
				{
					bool result = (Object)(object)Modal != (Object)null && Modal._StA();
					GC.KeepAlive(primaryAction);
					GC.KeepAlive(secondaryAction);
					return result;
				}
				catch (Exception ex)
				{
					if (Failure == null)
					{
						Exception ex2 = (Failure = ex);
					}
					return false;
				}
			}
		}

		internal NativeModalSession(UiModal modal, Action<UiModal> primaryAction, Action<UiModal>? secondaryAction)
		{
			Modal = modal;
			this.primaryAction = primaryAction;
			this.secondaryAction = secondaryAction;
		}

		internal void UpdateBody(string body)
		{
			if (IsOpen)
			{
				Modal._ZtA(TextParameters.CreateDirectString(body));
			}
		}

		internal void Close()
		{
			try
			{
				if (IsOpen)
				{
					Modal._VtA();
				}
			}
			catch (Exception ex)
			{
				if (Failure == null)
				{
					Exception ex2 = (Failure = ex);
				}
			}
		}
	}
	internal static class ParticleData
	{
		internal static ushort Shape(IotaInstance item)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			return (ushort)((item.BaseIotaIdPotency >> 12) & 0x3F);
		}

		internal static int Potency(IotaInstance item)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			return (item.BaseIotaIdPotency >> 2) & 0x3FF;
		}

		internal static int TraitCount(IotaInstance item)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			return 3 - (item.BaseIotaIdPotency & 3);
		}

		internal static short GetTrait(IotaInstance item, int slot)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: 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)
			return slot switch
			{
				0 => item.TraitId1, 
				1 => item.TraitId2, 
				2 => item.TraitId3, 
				_ => throw new ArgumentOutOfRangeException("slot"), 
			};
		}

		internal static void SetTrait(ref IotaInstance item, int slot, short trait)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			if (slot < 0 || slot > TraitCount(item) || slot >= 3 || trait <= 0)
			{
				throw new ArgumentOutOfRangeException("slot");
			}
			switch (slot)
			{
			case 0:
				item.TraitId1 = trait;
				break;
			case 1:
				item.TraitId2 = trait;
				break;
			case 2:
				item.TraitId3 = trait;
				break;
			}
			if (slot == TraitCount(item))
			{
				item.BaseIotaIdPotency = (item.BaseIotaIdPotency & -4) | (3 - (slot + 1));
			}
		}

		internal static void SetPotency(ref IotaInstance item, int potency)
		{
			if ((potency < 1 || potency > 999) ? true : false)
			{
				throw new ArgumentOutOfRangeException("potency");
			}
			item.BaseIotaIdPotency = (item.BaseIotaIdPotency & -4093) | (potency << 2);
		}
	}
	internal static class TraitCatalog
	{
		internal static readonly TraitInfo[] Entries = Load();

		private static TraitInfo[] Load()
		{
			using Stream utf8Json = Assembly.GetExecutingAssembly().GetManifestResourceStream("InFalsusMod.Data.traits.json") ?? throw new InvalidOperationException("缺少技能定义资源。");
			return JsonSerializer.Deserialize<TraitInfo[]>(utf8Json) ?? throw new InvalidOperationException("技能定义资源为空。");
		}

		internal static void Validate(GameData game)
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: 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_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Invalid comparison between Unknown and I4
			TraitInfo[] entries = Entries;
			foreach (TraitInfo traitInfo in entries)
			{
				if (traitInfo.Id <= 0 || traitInfo.Id >= ((Il2CppArrayBase<TraitSpecification>)(object)game.traits).Length)
				{
					throw new InvalidOperationException("技能编号已改变,需要适配。");
				}
				TraitSpecification val = ((Il2CppArrayBase<TraitSpecification>)(object)game.traits)[traitInfo.Id];
				if (val.Id.Value != traitInfo.Id || val.Tier != traitInfo.Tier || val.EffectCount != traitInfo.Effects.Length)
				{
					throw new InvalidOperationException($"技能 {traitInfo.Id} 的身份或等级已改变。");
				}
				for (int j = 0; j < traitInfo.Effects.Length; j++)
				{
					TraitSpecificationEffect val2 = ((j == 0) ? val.Effect0 : val.Effect1);
					if (val2.TraitEffect != traitInfo.Effects[j] || (int)val2.TraitActivationCondition != traitInfo.Conditions[j])
					{
						throw new InvalidOperationException($"技能 {traitInfo.Id} 的效果或触发条件已改变。");
					}
				}
			}
		}
	}
	internal sealed class TraitInfo
	{
		public int Id { get; init; }

		public string Name { get; init; } =