Decompiled source of ParticleFusion v1.0.1
ParticleFusion.dll
Decompiled a day ago
The result has been truncated due to the large size, download it to view full contents!
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; } =