Decompiled source of Weaver v1.2.0
Weaver.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; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Threading; using System.Threading.Tasks; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; using Weaver.Extensions; using Weaver.FatoryGraphs; using Weaver.Optimizations.LinearDataAccess; using Weaver.Optimizations.LinearDataAccess.Assemblers; using Weaver.Optimizations.LinearDataAccess.Belts; using Weaver.Optimizations.LinearDataAccess.Ejectors; using Weaver.Optimizations.LinearDataAccess.Fractionators; using Weaver.Optimizations.LinearDataAccess.Inserters; using Weaver.Optimizations.LinearDataAccess.Inserters.Types; using Weaver.Optimizations.LinearDataAccess.Labs; using Weaver.Optimizations.LinearDataAccess.Labs.Producing; using Weaver.Optimizations.LinearDataAccess.Labs.Researching; using Weaver.Optimizations.LinearDataAccess.Miners; using Weaver.Optimizations.LinearDataAccess.Monitors; using Weaver.Optimizations.LinearDataAccess.Pilers; using Weaver.Optimizations.LinearDataAccess.PowerSystems; using Weaver.Optimizations.LinearDataAccess.Silos; using Weaver.Optimizations.LinearDataAccess.Splitters; using Weaver.Optimizations.LinearDataAccess.Spraycoaters; using Weaver.Optimizations.LinearDataAccess.Stations; using Weaver.Optimizations.LinearDataAccess.Tanks; using Weaver.Optimizations.LinearDataAccess.Turrets; using Weaver.Optimizations.LinearDataAccess.WorkDistributors; using Weaver.Optimizations.LinearDataAccess.WorkDistributors.WorkChunks; using Weaver.Optimizations.Statistics; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("Weaver")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.0.1.0")] [assembly: AssemblyInformationalVersion("0.0.1+7ea0b25f30c9c790756600985b087a023faa9d2c")] [assembly: AssemblyProduct("Weaver")] [assembly: AssemblyTitle("Weaver")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.0.1.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class RequiresLocationAttribute : Attribute { } [CompilerGenerated] [Microsoft.CodeAnalysis.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] [Microsoft.CodeAnalysis.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] [Microsoft.CodeAnalysis.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 Weaver { internal static class HarmonyConstants { public const bool EXECUTE_ORIGINAL_METHOD = true; public const bool SKIP_ORIGINAL_METHOD = false; } public struct HashCode { private static readonly uint s_seed = 5122634u; private const uint Prime1 = 2654435761u; private const uint Prime2 = 2246822519u; private const uint Prime3 = 3266489917u; private const uint Prime4 = 668265263u; private const uint Prime5 = 374761393u; private uint _v1; private uint _v2; private uint _v3; private uint _v4; private uint _queue1; private uint _queue2; private uint _queue3; private uint _length; [MethodImpl(MethodImplOptions.AggressiveInlining)] private static void Initialize(out uint v1, out uint v2, out uint v3, out uint v4) { v1 = (uint)((int)s_seed + -1640531535 + -2048144777); v2 = s_seed + 2246822519u; v3 = s_seed; v4 = s_seed - 2654435761u; } [MethodImpl(MethodImplOptions.AggressiveInlining)] private static uint Round(uint hash, uint input) { return RotateLeft(hash + (uint)((int)input * -2048144777), 13) * 2654435761u; } [MethodImpl(MethodImplOptions.AggressiveInlining)] private static uint QueueRound(uint hash, uint queuedValue) { return RotateLeft(hash + (uint)((int)queuedValue * -1028477379), 17) * 668265263; } [MethodImpl(MethodImplOptions.AggressiveInlining)] private static uint MixState(uint v1, uint v2, uint v3, uint v4) { return RotateLeft(v1, 1) + RotateLeft(v2, 7) + RotateLeft(v3, 12) + RotateLeft(v4, 18); } private static uint MixEmptyState() { return s_seed + 374761393; } [MethodImpl(MethodImplOptions.AggressiveInlining)] private static uint MixFinal(uint hash) { hash ^= hash >> 15; hash *= 2246822519u; hash ^= hash >> 13; hash *= 3266489917u; hash ^= hash >> 16; return hash; } public void Add<T>(T value) { Add(value?.GetHashCode() ?? 0); } public void Add<T>(T value, IEqualityComparer<T> comparer) { Add((value != null) ? (comparer?.GetHashCode(value) ?? value.GetHashCode()) : 0); } private void Add(int value) { uint num = _length++; switch (num % 4) { case 0u: _queue1 = (uint)value; return; case 1u: _queue2 = (uint)value; return; case 2u: _queue3 = (uint)value; return; } if (num == 3) { Initialize(out _v1, out _v2, out _v3, out _v4); } _v1 = Round(_v1, _queue1); _v2 = Round(_v2, _queue2); _v3 = Round(_v3, _queue3); _v4 = Round(_v4, (uint)value); } public int ToHashCode() { uint length = _length; uint num = length % 4; uint num2 = ((length < 4) ? MixEmptyState() : MixState(_v1, _v2, _v3, _v4)); num2 += length * 4; if (num != 0) { num2 = QueueRound(num2, _queue1); if (num > 1) { num2 = QueueRound(num2, _queue2); if (num > 2) { num2 = QueueRound(num2, _queue3); } } } return (int)MixFinal(num2); } public static uint RotateLeft(uint value, int offset) { return (value << offset) | (value >> 32 - offset); } } public static class ReflectionExtensions { public static void RaiseActionEvent<T>(this T instance, string eventName) { Delegate[] array = (typeof(T).GetField(eventName, BindingFlags.Instance | BindingFlags.NonPublic).GetValue(instance) as MulticastDelegate)?.GetInvocationList(); if (array != null && array.Length != 0) { WeaverFixes.Logger.LogInfo((object)("Raised event " + eventName)); Delegate[] array2 = array; for (int i = 0; i < array2.Length; i++) { array2[i].DynamicInvoke(); } } } } internal static class ModInfo { public const string Guid = "Weaver"; public const string Name = "Weaver"; public const string Version = "1.2.0"; } internal static class ModDependencies { public const string SampleAndHoldSimId = "starfi5h.plugin.SampleAndHoldSim"; } [BepInPlugin("Weaver", "Weaver", "1.2.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class WeaverFixes : BaseUnityPlugin { internal static ManualLogSource Logger = Logger.CreateLogSource("Weaver"); private void Awake() { //IL_0005: 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_001a: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Expected O, but got Unknown Harmony val = new Harmony("Weaver"); val.PatchAll(typeof(ProductionStatisticsPatches)); val.PatchAll(typeof(KillStatisticsPatches)); val.PatchAll(typeof(TrafficStatisticsPatches)); OptimizedStarCluster.EnableOptimization(val); } } public static class MyPluginInfo { public const string PLUGIN_GUID = "Weaver"; public const string PLUGIN_NAME = "Weaver"; public const string PLUGIN_VERSION = "0.0.1"; } } namespace Weaver.Optimizations.Statistics { public class CustomChartsPatches { [HarmonyPrefix] [HarmonyPatch(typeof(CustomCharts), "GameTick")] private static bool GameTick_Parallelize(CustomCharts __instance) { if (!GameMain.multithreadSystem.multithreadSystemEnable) { return true; } new ParallelOptions().MaxDegreeOfParallelism = GameMain.multithreadSystem.usedThreadCnt; StatPlan[] buffer = __instance.statPlans.buffer; int cursor = __instance.statPlans.cursor; Parallel.For(1, cursor, delegate(int i) { if (buffer[i] != null && buffer[i].id == i) { buffer[i].GameTick(); } }); return false; } } public class KillStatisticsPatches { [HarmonyPrefix] [HarmonyPatch(typeof(KillStatistics), "PrepareTick")] private static bool PrepareTick_Parallelize(KillStatistics __instance) { if (!GameMain.multithreadSystem.multithreadSystemEnable) { return true; } ParallelOptions parallelOptions = new ParallelOptions { MaxDegreeOfParallelism = GameMain.multithreadSystem.usedThreadCnt }; Parallel.ForEach(__instance.starKillStatPool, parallelOptions, delegate(AstroKillStat x) { if (x != null) { x.PrepareTick(); } }); Parallel.ForEach(__instance.factoryKillStatPool, parallelOptions, delegate(AstroKillStat x) { if (x != null) { x.PrepareTick(); } }); AstroKillStat mechaKillStat = __instance.mechaKillStat; if (mechaKillStat != null) { mechaKillStat.PrepareTick(); } return false; } [HarmonyPrefix] [HarmonyPatch(typeof(KillStatistics), "GameTick")] private static bool GameTick_Parallelize(KillStatistics __instance, long time) { if (!GameMain.multithreadSystem.multithreadSystemEnable) { return true; } ParallelOptions parallelOptions = new ParallelOptions { MaxDegreeOfParallelism = GameMain.multithreadSystem.usedThreadCnt }; Parallel.ForEach(__instance.starKillStatPool, parallelOptions, delegate(AstroKillStat x) { if (x != null) { x.GameTick(time); } }); Parallel.ForEach(__instance.factoryKillStatPool, parallelOptions, delegate(AstroKillStat x) { if (x != null) { x.GameTick(time); } }); AstroKillStat mechaKillStat = __instance.mechaKillStat; if (mechaKillStat != null) { mechaKillStat.GameTick(time); } return false; } [HarmonyPrefix] [HarmonyPatch(typeof(KillStatistics), "AfterTick")] private static bool AfterTick_Parallelize(KillStatistics __instance) { if (!GameMain.multithreadSystem.multithreadSystemEnable) { return true; } ParallelOptions parallelOptions = new ParallelOptions { MaxDegreeOfParallelism = GameMain.multithreadSystem.usedThreadCnt }; Parallel.ForEach(__instance.starKillStatPool, parallelOptions, delegate(AstroKillStat x) { if (x != null) { x.AfterTick(); } }); Parallel.ForEach(__instance.factoryKillStatPool, parallelOptions, delegate(AstroKillStat x) { if (x != null) { x.AfterTick(); } }); AstroKillStat mechaKillStat = __instance.mechaKillStat; if (mechaKillStat != null) { mechaKillStat.AfterTick(); } return false; } } public class ProductionStatisticsPatches { [HarmonyPrefix] [HarmonyPatch(typeof(ProductionStatistics), "PrepareTick")] private static bool PrepareTick_Parallelize(ProductionStatistics __instance) { if (!GameMain.multithreadSystem.multithreadSystemEnable) { return true; } ParallelOptions parallelOptions = new ParallelOptions { MaxDegreeOfParallelism = GameMain.multithreadSystem.usedThreadCnt }; Parallel.For(0, __instance.gameData.factoryCount, parallelOptions, delegate(int i) { PlanetFactory val = GameMain.data.factories[i]; if (val.factorySystem == null || val.factorySystem.labCursor > 1 || val.factorySystem.assemblerCursor > 1 || val.factorySystem.minerCursor > 1 || val.factorySystem.fractionatorCursor > 1 || val.factorySystem.ejectorCursor > 1 || val.factorySystem.siloCursor > 1 || val.powerSystem.genCursor > 1 || val.powerSystem.excCursor > 1) { __instance.factoryStatPool[i].PrepareTick(); } }); return false; } [HarmonyPrefix] [HarmonyPatch(typeof(ProductionStatistics), "GameTick")] private static bool GameTick_Parallelize(ProductionStatistics __instance, long time) { if (!GameMain.multithreadSystem.multithreadSystemEnable) { return true; } new ParallelOptions().MaxDegreeOfParallelism = GameMain.multithreadSystem.usedThreadCnt; Parallel.For(0, __instance.gameData.factoryCount, delegate(int i) { PlanetFactory val = GameMain.data.factories[i]; if (val.factorySystem == null || val.factorySystem.labCursor > 1 || val.factorySystem.assemblerCursor > 1 || val.factorySystem.minerCursor > 1 || val.factorySystem.fractionatorCursor > 1 || val.factorySystem.ejectorCursor > 1 || val.factorySystem.siloCursor > 1 || val.powerSystem.genCursor > 1 || val.powerSystem.excCursor > 1) { __instance.factoryStatPool[i].GameTick(time); if (__instance.factoryStatPool[i].itemChanged) { try { __instance.RaiseActionEvent<ProductionStatistics>("onItemChange"); } catch (Exception ex) { WeaverFixes.Logger.LogError((object)ex); } } } }); __instance.extraInfoCalculator.GameTick(); return false; } } public sealed class TrafficStatisticsPatches { private static bool[] _isStarUpdated; private static bool[] _isPlanetUpdated; [HarmonyPrefix] [HarmonyPatch(typeof(TrafficStatistics), "PrepareTick")] public static void PrepareTick(TrafficStatistics __instance, long time) { if (_isStarUpdated == null || __instance.starTrafficPool.Length != _isStarUpdated.Length) { _isStarUpdated = new bool[__instance.starTrafficPool.Length]; } if (_isPlanetUpdated == null || __instance.factoryTrafficPool.Length != _isPlanetUpdated.Length) { _isPlanetUpdated = new bool[__instance.factoryTrafficPool.Length]; } } [HarmonyPrefix] [HarmonyPatch(typeof(TrafficStatistics), "GameTick")] private static bool GameTick_Parallelize(TrafficStatistics __instance, long time) { if (!GameMain.multithreadSystem.multithreadSystemEnable) { return true; } ParallelOptions parallelOptions = new ParallelOptions { MaxDegreeOfParallelism = GameMain.multithreadSystem.usedThreadCnt }; Parallel.For(0, __instance.starTrafficPool.Length, parallelOptions, delegate(int i) { AstroTrafficStat val2 = __instance.starTrafficPool[i]; if (val2 != null) { val2.GameTick(time); if (val2.itemChanged) { try { __instance.RaiseActionEvent<TrafficStatistics>("onItemChange"); } catch (Exception ex2) { WeaverFixes.Logger.LogError((object)ex2); } } } }); Parallel.For(0, __instance.factoryTrafficPool.Length, parallelOptions, delegate(int i) { AstroTrafficStat val = __instance.factoryTrafficPool[i]; if (val != null) { val.GameTick(time); if (val.itemChanged) { try { __instance.RaiseActionEvent<TrafficStatistics>("onItemChange"); } catch (Exception ex) { WeaverFixes.Logger.LogError((object)ex); } } } }); return false; } } } namespace Weaver.Optimizations.ObjectPools { public class ShrinkPools { private delegate TReturn PassStructAsRefFunc<TArgument, TReturn>(ArrayStructRef<TArgument> item) where TArgument : struct; private struct ArrayStructRef<T> where T : struct { private readonly T[] _array; private readonly int _index; public readonly ref T Value => ref _array[_index]; public ArrayStructRef(T[] array, int index) { _array = array; _index = index; } } private static int HasCalculatedData; private static bool HasOptimizedPools; [HarmonyPrefix] [HarmonyPatch(typeof(GameData), "GameTick")] private static void GameTick_DetectPoolHoles(GameData __instance) { if (DSPGame.IsMenuDemo || HasCalculatedData > 1) { return; } HasCalculatedData++; int totalSlots = 0; int usedSlots = 0; int unusedSlots = 0; int holes = 0; PlanetFactory[] factories = __instance.factories; foreach (PlanetFactory val in factories) { if (val == null) { continue; } if (val.factorySystem != null) { GatherPoolData<MinerComponent>(val.factorySystem.minerPool, (Func<MinerComponent, int>)((MinerComponent x) => x.id), ref totalSlots, ref usedSlots, ref unusedSlots, ref holes); GatherPoolData<InserterComponent>(val.factorySystem.inserterPool, (Func<InserterComponent, int>)((InserterComponent x) => x.id), ref totalSlots, ref usedSlots, ref unusedSlots, ref holes); GatherPoolData<AssemblerComponent>(val.factorySystem.assemblerPool, (Func<AssemblerComponent, int>)((AssemblerComponent x) => x.id), ref totalSlots, ref usedSlots, ref unusedSlots, ref holes); GatherPoolData<FractionatorComponent>(val.factorySystem.fractionatorPool, (Func<FractionatorComponent, int>)((FractionatorComponent x) => x.id), ref totalSlots, ref usedSlots, ref unusedSlots, ref holes); GatherPoolData<EjectorComponent>(val.factorySystem.ejectorPool, (Func<EjectorComponent, int>)((EjectorComponent x) => x.id), ref totalSlots, ref usedSlots, ref unusedSlots, ref holes); GatherPoolData<SiloComponent>(val.factorySystem.siloPool, (Func<SiloComponent, int>)((SiloComponent x) => x.id), ref totalSlots, ref usedSlots, ref unusedSlots, ref holes); GatherPoolData<LabComponent>(val.factorySystem.labPool, (Func<LabComponent, int>)((LabComponent x) => x.id), ref totalSlots, ref usedSlots, ref unusedSlots, ref holes); } if (val.factoryStorage != null) { GatherPoolDataForClass(val.factoryStorage.storagePool, (StorageComponent x) => x.id, ref totalSlots, ref usedSlots, ref unusedSlots, ref holes); GatherPoolData<TankComponent>(val.factoryStorage.tankPool, (Func<TankComponent, int>)((TankComponent x) => x.id), ref totalSlots, ref usedSlots, ref unusedSlots, ref holes); } if (val.cargoTraffic != null) { GatherPoolDataForClass(val.cargoTraffic.pathPool, (CargoPath x) => x.id, ref totalSlots, ref usedSlots, ref unusedSlots, ref holes); GatherPoolData<BeltComponent>(val.cargoTraffic.beltPool, (Func<BeltComponent, int>)((BeltComponent x) => x.id), ref totalSlots, ref usedSlots, ref unusedSlots, ref holes); GatherPoolData<SplitterComponent>(val.cargoTraffic.splitterPool, (Func<SplitterComponent, int>)((SplitterComponent x) => x.id), ref totalSlots, ref usedSlots, ref unusedSlots, ref holes); GatherPoolData<MonitorComponent>(val.cargoTraffic.monitorPool, (Func<MonitorComponent, int>)((MonitorComponent x) => x.id), ref totalSlots, ref usedSlots, ref unusedSlots, ref holes); GatherPoolData<SpraycoaterComponent>(val.cargoTraffic.spraycoaterPool, (Func<SpraycoaterComponent, int>)((SpraycoaterComponent x) => x.id), ref totalSlots, ref usedSlots, ref unusedSlots, ref holes); GatherPoolData<PilerComponent>(val.cargoTraffic.pilerPool, (Func<PilerComponent, int>)((PilerComponent x) => x.id), ref totalSlots, ref usedSlots, ref unusedSlots, ref holes); } if (val.transport != null) { GatherPoolDataForClass(val.transport.stationPool, (StationComponent x) => x.id, ref totalSlots, ref usedSlots, ref unusedSlots, ref holes); GatherPoolDataForClass(val.transport.dispenserPool, (DispenserComponent x) => x.id, ref totalSlots, ref usedSlots, ref unusedSlots, ref holes); } if (val.powerSystem != null) { GatherPoolData<PowerGeneratorComponent>(val.powerSystem.genPool, (Func<PowerGeneratorComponent, int>)((PowerGeneratorComponent x) => x.id), ref totalSlots, ref usedSlots, ref unusedSlots, ref holes); GatherPoolData<PowerNodeComponent>(val.powerSystem.nodePool, (Func<PowerNodeComponent, int>)((PowerNodeComponent x) => x.id), ref totalSlots, ref usedSlots, ref unusedSlots, ref holes); GatherPoolData<PowerConsumerComponent>(val.powerSystem.consumerPool, (Func<PowerConsumerComponent, int>)((PowerConsumerComponent x) => x.id), ref totalSlots, ref usedSlots, ref unusedSlots, ref holes); GatherPoolData<PowerAccumulatorComponent>(val.powerSystem.accPool, (Func<PowerAccumulatorComponent, int>)((PowerAccumulatorComponent x) => x.id), ref totalSlots, ref usedSlots, ref unusedSlots, ref holes); GatherPoolData<PowerExchangerComponent>(val.powerSystem.excPool, (Func<PowerExchangerComponent, int>)((PowerExchangerComponent x) => x.id), ref totalSlots, ref usedSlots, ref unusedSlots, ref holes); GatherPoolDataForClass(val.powerSystem.netPool, (PowerNetwork x) => x.id, ref totalSlots, ref usedSlots, ref unusedSlots, ref holes); } } WeaverFixes.Logger.LogInfo((object)$"Total: {totalSlots:N0}"); WeaverFixes.Logger.LogInfo((object)$"Used: {usedSlots:N0}"); WeaverFixes.Logger.LogInfo((object)$"Unused: {unusedSlots:N0}"); WeaverFixes.Logger.LogInfo((object)$"Holes: {holes:N0}"); WeaverFixes.Logger.LogInfo((object)$"Used Ratio: {(float)usedSlots / (float)totalSlots * 100f:N2}%"); } [HarmonyPostfix] [HarmonyPatch(typeof(GameData), "GameTick")] private static void GameTick_OptimizePools(GameData __instance) { if (DSPGame.IsMenuDemo || HasOptimizedPools) { return; } HasOptimizedPools = true; PlanetFactory[] factories = __instance.factories; foreach (PlanetFactory val in factories) { if (val == null) { continue; } if (val.factorySystem != null) { ResizePool<MinerComponent>(ref val.factorySystem.minerPool, (PassStructAsRefFunc<MinerComponent, int>)((ArrayStructRef<MinerComponent> x) => x.Value.id), (Action<int>)val.factorySystem.SetMinerCapacity, ref val.factorySystem.minerCursor, ref val.factorySystem.minerCapacity, ref val.factorySystem.minerRecycle, ref val.factorySystem.minerRecycleCursor); ResizePool<InserterComponent>(ref val.factorySystem.inserterPool, (PassStructAsRefFunc<InserterComponent, int>)((ArrayStructRef<InserterComponent> x) => x.Value.id), (Action<int>)val.factorySystem.SetInserterCapacity, ref val.factorySystem.inserterCursor, ref val.factorySystem.inserterCapacity, ref val.factorySystem.inserterRecycle, ref val.factorySystem.inserterRecycleCursor); ResizePool<AssemblerComponent>(ref val.factorySystem.assemblerPool, (PassStructAsRefFunc<AssemblerComponent, int>)((ArrayStructRef<AssemblerComponent> x) => x.Value.id), (Action<int>)val.factorySystem.SetAssemblerCapacity, ref val.factorySystem.assemblerCursor, ref val.factorySystem.assemblerCapacity, ref val.factorySystem.assemblerRecycle, ref val.factorySystem.assemblerRecycleCursor); ResizePool<FractionatorComponent>(ref val.factorySystem.fractionatorPool, (PassStructAsRefFunc<FractionatorComponent, int>)((ArrayStructRef<FractionatorComponent> x) => x.Value.id), (Action<int>)val.factorySystem.SetFractionatorCapacity, ref val.factorySystem.fractionatorCursor, ref val.factorySystem.fractionatorCapacity, ref val.factorySystem.fractionatorRecycle, ref val.factorySystem.fractionatorRecycleCursor); ResizePool<EjectorComponent>(ref val.factorySystem.ejectorPool, (PassStructAsRefFunc<EjectorComponent, int>)((ArrayStructRef<EjectorComponent> x) => x.Value.id), (Action<int>)val.factorySystem.SetEjectorCapacity, ref val.factorySystem.ejectorCursor, ref val.factorySystem.ejectorCapacity, ref val.factorySystem.ejectorRecycle, ref val.factorySystem.ejectorRecycleCursor); ResizePool<SiloComponent>(ref val.factorySystem.siloPool, (PassStructAsRefFunc<SiloComponent, int>)((ArrayStructRef<SiloComponent> x) => x.Value.id), (Action<int>)val.factorySystem.SetSiloCapacity, ref val.factorySystem.siloCursor, ref val.factorySystem.siloCapacity, ref val.factorySystem.siloRecycle, ref val.factorySystem.siloRecycleCursor); ResizePool<LabComponent>(ref val.factorySystem.labPool, (PassStructAsRefFunc<LabComponent, int>)((ArrayStructRef<LabComponent> x) => x.Value.id), (Action<int>)val.factorySystem.SetLabCapacity, ref val.factorySystem.labCursor, ref val.factorySystem.labCapacity, ref val.factorySystem.labRecycle, ref val.factorySystem.labRecycleCursor); } if (val.factoryStorage != null) { ResizePoolForClass(ref val.factoryStorage.storagePool, (Func<StorageComponent, int>)((StorageComponent x) => x.id), (Action<int>)val.factoryStorage.SetStorageCapacity, ref val.factoryStorage.storageCursor, ref val.factoryStorage.storageCapacity, ref val.factoryStorage.storageRecycle, ref val.factoryStorage.storageRecycleCursor); ResizePool<TankComponent>(ref val.factoryStorage.tankPool, (PassStructAsRefFunc<TankComponent, int>)((ArrayStructRef<TankComponent> x) => x.Value.id), (Action<int>)val.factoryStorage.SetTankCapacity, ref val.factoryStorage.tankCursor, ref val.factoryStorage.tankCapacity, ref val.factoryStorage.tankRecycle, ref val.factoryStorage.tankRecycleCursor); } if (val.cargoTraffic != null) { ResizePoolForClass(ref val.cargoTraffic.pathPool, (Func<CargoPath, int>)((CargoPath x) => x.id), (Action<int>)val.cargoTraffic.SetPathCapacity, ref val.cargoTraffic.pathCursor, ref val.cargoTraffic.pathCapacity, ref val.cargoTraffic.pathRecycle, ref val.cargoTraffic.pathRecycleCursor); ResizePool<BeltComponent>(ref val.cargoTraffic.beltPool, (PassStructAsRefFunc<BeltComponent, int>)((ArrayStructRef<BeltComponent> x) => x.Value.id), (Action<int>)val.cargoTraffic.SetBeltCapacity, ref val.cargoTraffic.beltCursor, ref val.cargoTraffic.beltCapacity, ref val.cargoTraffic.beltRecycle, ref val.cargoTraffic.beltRecycleCursor); ResizePool<SplitterComponent>(ref val.cargoTraffic.splitterPool, (PassStructAsRefFunc<SplitterComponent, int>)((ArrayStructRef<SplitterComponent> x) => x.Value.id), (Action<int>)val.cargoTraffic.SetSplitterCapacity, ref val.cargoTraffic.splitterCursor, ref val.cargoTraffic.splitterCapacity, ref val.cargoTraffic.splitterRecycle, ref val.cargoTraffic.splitterRecycleCursor); ResizePool<MonitorComponent>(ref val.cargoTraffic.monitorPool, (PassStructAsRefFunc<MonitorComponent, int>)((ArrayStructRef<MonitorComponent> x) => x.Value.id), (Action<int>)val.cargoTraffic.SetMonitorCapacity, ref val.cargoTraffic.monitorCursor, ref val.cargoTraffic.monitorCapacity, ref val.cargoTraffic.monitorRecycle, ref val.cargoTraffic.monitorRecycleCursor); ResizePool<SpraycoaterComponent>(ref val.cargoTraffic.spraycoaterPool, (PassStructAsRefFunc<SpraycoaterComponent, int>)((ArrayStructRef<SpraycoaterComponent> x) => x.Value.id), (Action<int>)val.cargoTraffic.SetSpraycoaterCapacity, ref val.cargoTraffic.spraycoaterCursor, ref val.cargoTraffic.spraycoaterCapacity, ref val.cargoTraffic.spraycoaterRecycle, ref val.cargoTraffic.spraycoaterRecycleCursor); ResizePool<PilerComponent>(ref val.cargoTraffic.pilerPool, (PassStructAsRefFunc<PilerComponent, int>)((ArrayStructRef<PilerComponent> x) => x.Value.id), (Action<int>)val.cargoTraffic.SetPilerCapacity, ref val.cargoTraffic.pilerCursor, ref val.cargoTraffic.pilerCapacity, ref val.cargoTraffic.pilerRecycle, ref val.cargoTraffic.pilerRecycleCursor); } if (val.transport != null) { ResizePoolForClass(ref val.transport.stationPool, (Func<StationComponent, int>)((StationComponent x) => x.id), (Action<int>)val.transport.SetStationCapacity, ref val.transport.stationCursor, ref val.transport.stationCapacity, ref val.transport.stationRecycle, ref val.transport.stationRecycleCursor); ResizePoolForClass(ref val.transport.dispenserPool, (Func<DispenserComponent, int>)((DispenserComponent x) => x.id), (Action<int>)val.transport.SetDispenserCapacity, ref val.transport.dispenserCursor, ref val.transport.dispenserCapacity, ref val.transport.dispenserRecycle, ref val.transport.dispenserRecycleCursor); } if (val.powerSystem != null) { ResizePool<PowerGeneratorComponent>(ref val.powerSystem.genPool, (PassStructAsRefFunc<PowerGeneratorComponent, int>)((ArrayStructRef<PowerGeneratorComponent> x) => x.Value.id), (Action<int>)val.powerSystem.SetGeneratorCapacity, ref val.powerSystem.genCursor, ref val.powerSystem.genCapacity, ref val.powerSystem.genRecycle, ref val.powerSystem.genRecycleCursor); ResizePool<PowerNodeComponent>(ref val.powerSystem.nodePool, (PassStructAsRefFunc<PowerNodeComponent, int>)((ArrayStructRef<PowerNodeComponent> x) => x.Value.id), (Action<int>)val.powerSystem.SetNodeCapacity, ref val.powerSystem.nodeCursor, ref val.powerSystem.nodeCapacity, ref val.powerSystem.nodeRecycle, ref val.powerSystem.nodeRecycleCursor); ResizePool<PowerConsumerComponent>(ref val.powerSystem.consumerPool, (PassStructAsRefFunc<PowerConsumerComponent, int>)((ArrayStructRef<PowerConsumerComponent> x) => x.Value.id), (Action<int>)val.powerSystem.SetConsumerCapacity, ref val.powerSystem.consumerCursor, ref val.powerSystem.consumerCapacity, ref val.powerSystem.consumerRecycle, ref val.powerSystem.consumerRecycleCursor); ResizePool<PowerAccumulatorComponent>(ref val.powerSystem.accPool, (PassStructAsRefFunc<PowerAccumulatorComponent, int>)((ArrayStructRef<PowerAccumulatorComponent> x) => x.Value.id), (Action<int>)val.powerSystem.SetAccumulatorCapacity, ref val.powerSystem.accCursor, ref val.powerSystem.accCapacity, ref val.powerSystem.accRecycle, ref val.powerSystem.accRecycleCursor); ResizePool<PowerExchangerComponent>(ref val.powerSystem.excPool, (PassStructAsRefFunc<PowerExchangerComponent, int>)((ArrayStructRef<PowerExchangerComponent> x) => x.Value.id), (Action<int>)val.powerSystem.SetExchangerCapacity, ref val.powerSystem.excCursor, ref val.powerSystem.excCapacity, ref val.powerSystem.excRecycle, ref val.powerSystem.excRecycleCursor); ResizePoolForClass(ref val.powerSystem.netPool, (Func<PowerNetwork, int>)((PowerNetwork x) => x.id), (Action<int>)val.powerSystem.SetNetworkCapacity, ref val.powerSystem.netCursor, ref val.powerSystem.netCapacity, ref val.powerSystem.netRecycle, ref val.powerSystem.netRecycleCursor); } } WeaverFixes.Logger.LogInfo((object)"Optimized pools"); } private static void GatherPoolData<T>(T[] pool, Func<T, int> getId, ref int totalSlots, ref int usedSlots, ref int unusedSlots, ref int holes) where T : struct { totalSlots += pool.Length; int num = 0; for (int i = 1; i < pool.Length; i++) { if (getId(pool[i]) == i) { usedSlots++; num = i; } else { unusedSlots++; } } for (int j = 1; j <= num; j++) { if (getId(pool[j]) != j) { holes++; } } } private static void GatherPoolDataForClass<T>(T[] pool, Func<T, int> getId, ref int totalSlots, ref int usedSlots, ref int unusedSlots, ref int holes) where T : class { totalSlots += pool.Length; int num = 0; for (int i = 1; i < pool.Length; i++) { if (pool[i] != null && getId(pool[i]) == i) { usedSlots++; num = i; } else { unusedSlots++; } } for (int j = 1; j <= num; j++) { if (pool[j] == null || getId(pool[j]) != j) { holes++; } } } private static void ResizePool<T>(ref T[] pool, PassStructAsRefFunc<T, int> getId, Action<int> setCapacity, ref int cursor, ref int capacity, ref int[] recycle, ref int recycleCursor) where T : struct { int num = cursor - 1; while (num >= 1 && getId(new ArrayStructRef<T>(pool, num)) != num) { num--; } cursor = num + 1; setCapacity(cursor); } private static void ResizePoolForClass<T>(ref T[] pool, Func<T, int> getId, Action<int> setCapacity, ref int cursor, ref int capacity, ref int[] recycle, ref int recycleCursor) where T : class { int num = cursor - 1; while (num >= 1 && getId(pool[num]) != num) { num--; } cursor = num + 1; setCapacity(cursor); } } } namespace Weaver.Optimizations.LinearDataAccess { internal static class HarmonyExtensions { public static void ReplaceCode(this CodeMatcher codeMatcher, CodeMatch[] start, bool replaceStart, CodeMatch[] end, bool replaceEnd, CodeInstruction[] replaceWith) { codeMatcher.MatchForward(!replaceStart, start).ThrowIfNotMatch("Failed to find start", Array.Empty<CodeMatch>()); int pos = codeMatcher.Pos; codeMatcher.MatchForward(replaceEnd, end).ThrowIfNotMatch("Failed to find end", Array.Empty<CodeMatch>()); int pos2 = codeMatcher.Pos; codeMatcher.Start().Advance(pos).RemoveInstructions(pos2 - pos + 1) .Insert(replaceWith); } public static void PrintRelativeRangeOfInstructions(this CodeMatcher codeMatcher, int startOffset, int length) { codeMatcher.Advance(startOffset); for (int i = 0; i < length; i++) { WeaverFixes.Logger.LogMessage((object)codeMatcher.Instruction); codeMatcher.Advance(1); } } } internal interface IOptimizedPlanet { OptimizedPlanetStatus Status { get; } int OptimizeDelayInTicks { get; set; } void Save(); void Initialize(); bool RequestDysonSpherePower(); void TransportGameTick(long time, Vector3 playerPos); WorkStep[] GetMultithreadedWork(int maxParallelism); } internal struct NetworkIdAndState<T> where T : Enum { private const int IndexBitCount = 24; private const uint IndexBitMask = 16777215u; private const uint StateTypeMask = 255u; private uint _value; public int State { get { return (int)(_value >> 24); } set { _value = (_value & 0xFFFFFFu) | (uint)(value << 24); } } public readonly int Index => (int)(0xFFFFFF & _value); public NetworkIdAndState(int state, int index) { if ((uint)state < 0u || (uint)state > 255u) { throw new ArgumentOutOfRangeException("index", $"{state} was outside the range {0} to {255u:N0}"); } if (index < 0 || (long)index > 16777215L) { throw new ArgumentOutOfRangeException("index", $"{index} was outside the range {0} to {16777215u:N0}"); } _value = (uint)(state << 24) | (0xFFFFFFu & (uint)index); } } internal sealed class OptimizedGasPlanet : IOptimizedPlanet { private readonly PlanetFactory _planet; private GasPlanetWideStationExecutor _planetWideStationExecutor; private WorkStep[] _workSteps; private int _workStepsParallelism; public OptimizedPlanetStatus Status { get; private set; } = OptimizedPlanetStatus.Stopped; public int OptimizeDelayInTicks { get; set; } public OptimizedGasPlanet(PlanetFactory planet) { _planet = planet; } public static bool IsGasPlanet(PlanetFactory planet) { for (int i = 1; i < planet.transport.stationCursor; i++) { StationComponent val = planet.transport.stationPool[i]; if (val != null && val.id == i && val.isCollector) { return true; } } return false; } public void Initialize() { _planetWideStationExecutor = new GasPlanetWideStationExecutor(); _planetWideStationExecutor.Initialize(_planet); Status = OptimizedPlanetStatus.Running; _workSteps = null; _workStepsParallelism = -1; } public void Save() { _workSteps = null; _workStepsParallelism = -1; Status = OptimizedPlanetStatus.Stopped; } public bool RequestDysonSpherePower() { return false; } public void TransportGameTick(long time, Vector3 playerPos) { MiningFlags miningFlags = new MiningFlags(); _planetWideStationExecutor.StationGameTick(_planet, time, ref miningFlags); PlanetFactory planet = _planet; planet._miningFlag |= miningFlags.MiningFlag; PlanetFactory planet2 = _planet; planet2._veinMiningFlag |= miningFlags.VeinMiningFlag; } public WorkStep[] GetMultithreadedWork(int maxParallelism) { if (_workStepsParallelism != maxParallelism) { _workSteps = CreateMultithreadedWork(maxParallelism); _workStepsParallelism = maxParallelism; } return _workSteps; } private WorkStep[] CreateMultithreadedWork(int maxParallelism) { if (Status == OptimizedPlanetStatus.Stopped) { return CreateParallelWorkForNonRunningOptimizedPlanet(maxParallelism); } List<WorkStep> list = new List<WorkStep>(); list.Add(new WorkStep(new IWorkChunk[1] { new PlanetWideTransport(this) })); return list.ToArray(); } private WorkStep[] CreateParallelWorkForNonRunningOptimizedPlanet(int maxParallelism) { List<WorkStep> list = new List<WorkStep>(); if (_planet.transport.stationCursor > 0) { IWorkChunk[] workChunks = UnOptimizedPlanetWorkChunk.CreateDuplicateChunks(_planet, WorkType.TransportData, 1); list.Add(new WorkStep(workChunks)); } return list.ToArray(); } } internal enum OptimizedPlanetStatus { Running, Stopped } internal static class OptimizedStarCluster { private static readonly Dictionary<PlanetFactory, IOptimizedPlanet> _planetToOptimizedPlanet = new Dictionary<PlanetFactory, IOptimizedPlanet>(); private static readonly Queue<PlanetFactory> _newPlanets = new Queue<PlanetFactory>(); private static readonly Queue<PlanetFactory> _planetsToReOptimize = new Queue<PlanetFactory>(); public static readonly StarClusterResearchManager _starClusterResearchManager = new StarClusterResearchManager(); private static readonly WorkStealingMultiThreadedFactorySimulation _workStealingMultiThreadedFactorySimulation = new WorkStealingMultiThreadedFactorySimulation(_starClusterResearchManager); private static bool _clearOptimizedPlanetsOnNextTick = false; private static readonly Random random = new Random(); private static bool _debugEnableHeavyReOptimization = false; public static void EnableOptimization(Harmony harmony) { harmony.PatchAll(typeof(OptimizedStarCluster)); } public static void DebugEnableHeavyReOptimization() { _debugEnableHeavyReOptimization = true; } public static IOptimizedPlanet GetOptimizedPlanet(PlanetFactory planet) { return _planetToOptimizedPlanet[planet]; } [HarmonyPrefix] [HarmonyPatch(typeof(GameMain), "End")] public static void End() { WeaverFixes.Logger.LogInfo((object)"Marking optimized planets to be cleared."); _clearOptimizedPlanetsOnNextTick = true; } [HarmonyPriority(1)] [HarmonyPostfix] [HarmonyPatch(typeof(GameSave), "LoadCurrentGame")] private static void LoadCurrentGame_Postfix() { WeaverFixes.Logger.LogInfo((object)"Initializing OptimizedStarCluster"); _planetToOptimizedPlanet.Clear(); _workStealingMultiThreadedFactorySimulation.Clear(); _clearOptimizedPlanetsOnNextTick = false; for (int i = 0; i < GameMain.data.factoryCount; i++) { TryAddNewPlanet(GameMain.data.factories[i]); } } private static void TryAddNewPlanet(PlanetFactory planet) { if (planet.factorySystem != null) { if (OptimizedGasPlanet.IsGasPlanet(planet)) { _planetToOptimizedPlanet.Add(planet, new OptimizedGasPlanet(planet)); } else { _planetToOptimizedPlanet.Add(planet, new OptimizedTerrestrialPlanet(planet, _starClusterResearchManager)); } } } [HarmonyPrefix] [HarmonyPatch(typeof(GameSave), "SaveCurrentGame")] private static void SaveCurrentGame_Prefix() { WeaverFixes.Logger.LogInfo((object)"Saving optimized planets"); foreach (KeyValuePair<PlanetFactory, IOptimizedPlanet> item in _planetToOptimizedPlanet) { if (item.Value.Status == OptimizedPlanetStatus.Running) { WeaverFixes.Logger.LogInfo((object)("Saving planet: " + item.Key.planet.displayName)); item.Value.Save(); } } } [HarmonyPrefix] [HarmonyPatch(typeof(GameData), "GameTick")] public static void GameData_GameTick() { if (_clearOptimizedPlanetsOnNextTick) { _clearOptimizedPlanetsOnNextTick = false; _planetToOptimizedPlanet.Clear(); _workStealingMultiThreadedFactorySimulation.Clear(); } lock (_newPlanets) { while (_newPlanets.Count > 0) { PlanetFactory val = _newPlanets.Dequeue(); WeaverFixes.Logger.LogInfo((object)("Adding planet: " + val.planet.displayName)); TryAddNewPlanet(val); } } foreach (KeyValuePair<PlanetFactory, IOptimizedPlanet> item in _planetToOptimizedPlanet) { if (GameMain.localPlanet?.factory != item.Key) { if (item.Value.Status == OptimizedPlanetStatus.Stopped && (item.Value.OptimizeDelayInTicks <= 0 || item.Value.OptimizeDelayInTicks-- <= 0)) { WeaverFixes.Logger.LogInfo((object)("Optimizing planet: " + item.Key.planet.displayName)); item.Value.Initialize(); } } else if (item.Value.Status != OptimizedPlanetStatus.Stopped) { WeaverFixes.Logger.LogInfo((object)("DeOptimizing planet: " + item.Key.planet.displayName)); item.Value.Save(); } } if (_planetsToReOptimize.Count > 0) { PlanetFactory val2 = _planetsToReOptimize.Dequeue(); IOptimizedPlanet optimizedPlanet = _planetToOptimizedPlanet[val2]; if (optimizedPlanet.Status == OptimizedPlanetStatus.Stopped) { return; } WeaverFixes.Logger.LogInfo((object)("DeOptimizing planet: " + val2.planet.displayName)); optimizedPlanet.Save(); } if (_debugEnableHeavyReOptimization && GameMain.gameTick % 10 == 0L) { PlanetFactory[] array = _planetToOptimizedPlanet.Keys.ToArray(); int num = random.Next(0, array.Length); _planetsToReOptimize.Enqueue(array[num]); } } [HarmonyPostfix] [HarmonyPatch(typeof(PlanetFactory), "Init")] public static void PlanetFactory_Init(PlanetFactory __instance) { lock (_newPlanets) { _newPlanets.Enqueue(__instance); } } [HarmonyPrefix] [HarmonyPatch(typeof(PlanetFactory), "AddEntityDataWithComponents")] public static void PlanetFactory_AddEntityDataWithComponents(PlanetFactory __instance) { DeOptimizeDueToNonPlayerAction(__instance); } [HarmonyPrefix] [HarmonyPatch(typeof(PlanetFactory), "RemoveEntityWithComponents")] public static void PlanetFactory_RemoveEntityWithComponents(PlanetFactory __instance) { DeOptimizeDueToNonPlayerAction(__instance); } [HarmonyPrefix] [HarmonyPatch(typeof(PlanetFactory), "UpgradeEntityWithComponents")] public static void PlanetFactory_UpgradeEntityWithComponents(PlanetFactory __instance) { DeOptimizeDueToNonPlayerAction(__instance); } [HarmonyTranspiler] [HarmonyPatch(typeof(FactorySystem), "GameTickLabResearchMode")] private static IEnumerable<CodeInstruction> DeferResearchUnlockToStarClusterResearchManager(IEnumerable<CodeInstruction> instructions, ILGenerator generator) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Expected O, but got Unknown //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Expected O, but got Unknown //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Expected O, but got Unknown //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Expected O, but got Unknown //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Expected O, but got Unknown //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Expected O, but got Unknown //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Expected O, but got Unknown //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Expected O, but got Unknown //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Expected O, but got Unknown //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Expected O, but got Unknown //IL_0175: Unknown result type (might be due to invalid IL or missing references) //IL_017b: Expected O, but got Unknown //IL_0189: Unknown result type (might be due to invalid IL or missing references) //IL_018f: Expected O, but got Unknown //IL_019d: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Expected O, but got Unknown //IL_01c0: Unknown result type (might be due to invalid IL or missing references) //IL_01c6: Expected O, but got Unknown CodeMatcher val = new CodeMatcher(instructions, generator); CodeMatch[] start = (CodeMatch[])(object)new CodeMatch[6] { new CodeMatch((OpCode?)OpCodes.Ldloc_1, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Ldfld, (object)AccessTools.Field(typeof(GameHistoryData), "techStates"), (string)null), new CodeMatch((OpCode?)OpCodes.Ldarg_0, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Ldfld, (object)AccessTools.Field(typeof(FactorySystem), "researchTechId"), (string)null), new CodeMatch((OpCode?)OpCodes.Ldloc_S, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Callvirt, (object)AccessTools.PropertySetter(typeof(Dictionary<int, TechState>), "Item"), (string)null) }; CodeMatch[] end = (CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Callvirt, (object)AccessTools.Method(typeof(GameHistoryData), "NotifyTechUnlock", (Type[])null, (Type[])null), (string)null) }; CodeInstruction[] replaceWith = (CodeInstruction[])(object)new CodeInstruction[8] { new CodeInstruction(OpCodes.Callvirt, (object)AccessTools.PropertySetter(typeof(Dictionary<int, TechState>), "Item")), new CodeInstruction(OpCodes.Ldsfld, (object)AccessTools.Field(typeof(OptimizedStarCluster), "_starClusterResearchManager")), new CodeInstruction(OpCodes.Ldarg_0, (object)null), new CodeInstruction(OpCodes.Ldfld, (object)AccessTools.Field(typeof(FactorySystem), "researchTechId")), new CodeInstruction(OpCodes.Ldloc_S, (object)29), new CodeInstruction(OpCodes.Ldloc_S, (object)13), new CodeInstruction(OpCodes.Ldloc_S, (object)12), new CodeInstruction(OpCodes.Callvirt, (object)AccessTools.Method(typeof(StarClusterResearchManager), "AddResearchedTech", (Type[])null, (Type[])null)) }; val.ReplaceCode(start, replaceStart: false, end, replaceEnd: false, replaceWith); val.ReplaceCode(start, replaceStart: false, end, replaceEnd: false, replaceWith); return val.InstructionEnumeration(); } [HarmonyTranspiler] [HarmonyPatch(typeof(GameData), "GameTick")] private static IEnumerable<CodeInstruction> ReplaceMultithreadedSimulationLogic(IEnumerable<CodeInstruction> instructions, ILGenerator generator) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Expected O, but got Unknown //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Expected O, but got Unknown //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Expected O, but got Unknown //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Expected O, but got Unknown //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Expected O, but got Unknown //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Expected O, but got Unknown //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Expected O, but got Unknown //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Expected O, but got Unknown //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Expected O, but got Unknown //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Expected O, but got Unknown CodeMatcher val = new CodeMatcher(instructions, generator); CodeMatch[] array = (CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Ldfld, (object)AccessTools.Field(typeof(MultithreadSystem), "multithreadSystemEnable"), (string)null) }; CodeMatch[] start = (CodeMatch[])(object)new CodeMatch[2] { new CodeMatch((OpCode?)OpCodes.Ldc_I4_S, (object)(sbyte)9, (string)null), new CodeMatch((OpCode?)OpCodes.Call, (object)AccessTools.Method(typeof(PerformanceMonitor), "BeginSample", (Type[])null, (Type[])null), (string)null) }; CodeMatch[] end = (CodeMatch[])(object)new CodeMatch[2] { new CodeMatch((OpCode?)OpCodes.Ldc_I4_S, (object)(sbyte)32, (string)null), new CodeMatch((OpCode?)OpCodes.Call, (object)AccessTools.Method(typeof(PerformanceMonitor), "EndSample", (Type[])null, (Type[])null), (string)null) }; PluginInfo value; CodeInstruction[] replaceWith = (CodeInstruction[])(object)((!Chainloader.PluginInfos.TryGetValue("starfi5h.plugin.SampleAndHoldSim", out value)) ? new CodeInstruction[3] { new CodeInstruction(OpCodes.Ldarg_0, (object)null), new CodeInstruction(OpCodes.Ldfld, (object)AccessTools.Field(typeof(GameData), "factories")), new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(OptimizedStarCluster), "ExecuteSimulation", (Type[])null, (Type[])null)) } : new CodeInstruction[2] { new CodeInstruction(OpCodes.Ldsfld, (object)AccessTools.Field(AccessTools.TypeByName("SampleAndHoldSim.GameData_Patch"), "workFactories")), new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(OptimizedStarCluster), "ExecuteSimulation", (Type[])null, (Type[])null)) }); val.MatchForward(true, array).ThrowIfNotMatch("Failed to find multithreadedIfCondition", Array.Empty<CodeMatch>()); val.ReplaceCode(start, replaceStart: true, end, replaceEnd: true, replaceWith); return val.InstructionEnumeration(); } [HarmonyTranspiler] [HarmonyPatch(typeof(GameData), "GameTick")] private static IEnumerable<CodeInstruction> ReplaceDefenseSystemLogic(IEnumerable<CodeInstruction> instructions, ILGenerator generator) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Expected O, but got Unknown //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Expected O, but got Unknown //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Expected O, but got Unknown //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Expected O, but got Unknown CodeMatcher val = new CodeMatcher(instructions, generator); CodeMatch[] start = (CodeMatch[])(object)new CodeMatch[2] { new CodeMatch((OpCode?)OpCodes.Ldc_I4_S, (object)(sbyte)34, (string)null), new CodeMatch((OpCode?)OpCodes.Call, (object)AccessTools.Method(typeof(PerformanceMonitor), "BeginSample", (Type[])null, (Type[])null), (string)null) }; CodeMatch[] end = (CodeMatch[])(object)new CodeMatch[2] { new CodeMatch((OpCode?)OpCodes.Ldc_I4_S, (object)(sbyte)34, (string)null), new CodeMatch((OpCode?)OpCodes.Call, (object)AccessTools.Method(typeof(PerformanceMonitor), "EndSample", (Type[])null, (Type[])null), (string)null) }; CodeInstruction[] replaceWith = (CodeInstruction[])(object)new CodeInstruction[1] { new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(OptimizedStarCluster), "ExecuteParallelDefense", (Type[])null, (Type[])null)) }; val.ReplaceCode(start, replaceStart: true, end, replaceEnd: true, replaceWith); return val.InstructionEnumeration(); } [HarmonyPrefix] [HarmonyPatch(typeof(PowerSystem), "RequestDysonSpherePower")] public static bool PowerSystem_RequestDysonSpherePower(PowerSystem __instance) { return GetOptimizedPlanet(__instance.factory).RequestDysonSpherePower(); } public static void ReOptimizeAllPlanets() { lock (_planetsToReOptimize) { foreach (PlanetFactory item in from x in _planetToOptimizedPlanet where x.Value.Status == OptimizedPlanetStatus.Running select x.Key) { _planetsToReOptimize.Enqueue(item); } } } private static void ExecuteSimulation(PlanetFactory?[] planets) { _workStealingMultiThreadedFactorySimulation.Simulate(planets); } private static void ExecuteParallelDefense() { PerformanceMonitor.BeginSample((ECpuWorkEntry)34); long gameTick = GameMain.gameTick; foreach (IOptimizedPlanet value in _planetToOptimizedPlanet.Values) { if (value is OptimizedTerrestrialPlanet optimizedTerrestrialPlanet) { optimizedTerrestrialPlanet.GameTickDefense(gameTick); optimizedTerrestrialPlanet.DefenseGameTickUIThread(gameTick); } } PerformanceMonitor.EndSample((ECpuWorkEntry)34); } private static void DeOptimizeDueToNonPlayerAction(PlanetFactory planet) { IOptimizedPlanet optimizedPlanet = _planetToOptimizedPlanet[planet]; if (optimizedPlanet.Status == OptimizedPlanetStatus.Running) { WeaverFixes.Logger.LogInfo((object)("DeOptimizing planet: " + planet.planet.displayName)); optimizedPlanet.Save(); } optimizedPlanet.OptimizeDelayInTicks = 200; } } internal sealed class OptimizedSubFactory { private readonly PlanetFactory _planet; private readonly OptimizedTerrestrialPlanet _optimizedPlanet; private readonly StarClusterResearchManager _starClusterResearchManager; public InserterExecutor<OptimizedBiInserter> _optimizedBiInserterExecutor; public InserterExecutor<OptimizedInserter> _optimizedInserterExecutor; public AssemblerExecutor _assemblerExecutor; public VeinMinerExecutor<BeltMinerOutput> _beltVeinMinerExecutor; public VeinMinerExecutor<StationMinerOutput> _stationVeinMinerExecutor; public OilMinerExecutor _oilMinerExecutor; public WaterMinerExecutor _waterMinerExecutor; public EjectorExecutor _ejectorExecutor; public SiloExecutor _siloExecutor; public ProducingLabExecutor _producingLabExecutor; public NetworkIdAndState<LabState>[] _producingLabNetworkIdAndStates; public OptimizedProducingLab[] _optimizedProducingLabs; public ProducingLabRecipe[] _producingLabRecipes; public Dictionary<int, int> _producingLabIdToOptimizedIndex; public ResearchingLabExecutor _researchingLabExecutor; public NetworkIdAndState<LabState>[] _researchingLabNetworkIdAndStates; public OptimizedResearchingLab[] _optimizedResearchingLabs; public Dictionary<int, int> _researchingLabIdToOptimizedIndex; public MonitorExecutor _monitorExecutor; public SpraycoaterExecutor _spraycoaterExecutor; public PilerExecutor _pilerExecutor; public FractionatorExecutor _fractionatorExecutor; public StationExecutor _stationExecutor; public TankExecutor _tankExecutor; public BeltExecutor _beltExecutor; public SplitterExecutor _splitterExecutor; public OptimizedSubFactory(PlanetFactory planet, OptimizedTerrestrialPlanet optimizedTerrestrialPlanet, StarClusterResearchManager starClusterResearchManager) { _planet = planet; _optimizedPlanet = optimizedTerrestrialPlanet; _starClusterResearchManager = starClusterResearchManager; } public void Save(CargoContainer cargoContainer) { _beltExecutor.Save(cargoContainer); _beltVeinMinerExecutor.Save(_planet); _stationVeinMinerExecutor.Save(_planet); _oilMinerExecutor.Save(_planet); _waterMinerExecutor.Save(_planet); _optimizedBiInserterExecutor.Save(_planet); _optimizedInserterExecutor.Save(_planet); _assemblerExecutor.Save(_planet); _producingLabExecutor.Save(_planet); _researchingLabExecutor.Save(_planet); _spraycoaterExecutor.Save(_planet); _fractionatorExecutor.Save(_planet); _tankExecutor.Save(_planet); } public void Initialize(Graph subFactoryGraph, OptimizedPowerSystemBuilder optimizedPowerSystemBuilder, PlanetWideBeltExecutor planetWideBeltExecutor, TurretExecutorBuilder turretExecutorBuilder) { optimizedPowerSystemBuilder.AddSubFactory(this); InitializeBelts(subFactoryGraph, planetWideBeltExecutor); InitializeAssemblers(subFactoryGraph, optimizedPowerSystemBuilder); InitializeMiners(subFactoryGraph, optimizedPowerSystemBuilder, _beltExecutor); InitializeStations(subFactoryGraph, _beltExecutor, _stationVeinMinerExecutor); InitializeEjectors(subFactoryGraph); InitializeSilos(subFactoryGraph); InitializeLabAssemblers(subFactoryGraph, optimizedPowerSystemBuilder); InitializeResearchingLabs(subFactoryGraph, optimizedPowerSystemBuilder); InitializeInserters(subFactoryGraph, optimizedPowerSystemBuilder, _beltExecutor); InitializeMonitors(subFactoryGraph, optimizedPowerSystemBuilder, _beltExecutor); InitializeSpraycoaters(subFactoryGraph, optimizedPowerSystemBuilder, _beltExecutor); InitializePilers(subFactoryGraph, optimizedPowerSystemBuilder, _beltExecutor); InitializeFractionators(subFactoryGraph, optimizedPowerSystemBuilder, _beltExecutor); InitializeTanks(subFactoryGraph, _beltExecutor); InitializeSplitters(subFactoryGraph, _beltExecutor); turretExecutorBuilder.Initialize(_planet, subFactoryGraph, _beltExecutor); } private void InitializeInserters(Graph subFactoryGraph, OptimizedPowerSystemBuilder optimizedPowerSystemBuilder, BeltExecutor beltExecutor) { _optimizedBiInserterExecutor = new InserterExecutor<OptimizedBiInserter>(_assemblerExecutor._assemblerNetworkIdAndStates, _producingLabNetworkIdAndStates, _researchingLabNetworkIdAndStates); _optimizedBiInserterExecutor.Initialize(_planet, this, subFactoryGraph, (InserterComponent x) => x.bidirectional, optimizedPowerSystemBuilder.CreateBiInserterBuilder(), beltExecutor); _optimizedInserterExecutor = new InserterExecutor<OptimizedInserter>(_assemblerExecutor._assemblerNetworkIdAndStates, _producingLabNetworkIdAndStates, _researchingLabNetworkIdAndStates); _optimizedInserterExecutor.Initialize(_planet, this, subFactoryGraph, (InserterComponent x) => !x.bidirectional, optimizedPowerSystemBuilder.CreateInserterBuilder(), beltExecutor); } private void InitializeAssemblers(Graph subFactoryGraph, OptimizedPowerSystemBuilder optimizedPowerSystemBuilder) { _assemblerExecutor = new AssemblerExecutor(); _assemblerExecutor.InitializeAssemblers(_planet, subFactoryGraph, optimizedPowerSystemBuilder); } private void InitializeMiners(Graph subFactoryGraph, OptimizedPowerSystemBuilder optimizedPowerSystemBuilder, BeltExecutor beltExecutor) { _beltVeinMinerExecutor = new VeinMinerExecutor<BeltMinerOutput>(); _beltVeinMinerExecutor.Initialize(_planet, subFactoryGraph, optimizedPowerSystemBuilder.CreateBeltVeinMinerBuilder(), beltExecutor); _stationVeinMinerExecutor = new VeinMinerExecutor<StationMinerOutput>(); _stationVeinMinerExecutor.Initialize(_planet, subFactoryGraph, optimizedPowerSystemBuilder.CreateStationVeinMinerBuilder(), beltExecutor); _oilMinerExecutor = new OilMinerExecutor(); _oilMinerExecutor.Initialize(_planet, subFactoryGraph, optimizedPowerSystemBuilder, beltExecutor); _waterMinerExecutor = new WaterMinerExecutor(); _waterMinerExecutor.Initialize(_planet, subFactoryGraph, optimizedPowerSystemBuilder, beltExecutor); } private void InitializeEjectors(Graph subFactoryGraph) { _ejectorExecutor = new EjectorExecutor(); _ejectorExecutor.Initialize(_planet, subFactoryGraph); } private void InitializeSilos(Graph subFactoryGraph) { _siloExecutor = new SiloExecutor(); _siloExecutor.Initialize(_planet, subFactoryGraph); } private void InitializeLabAssemblers(Graph subFactoryGraph, OptimizedPowerSystemBuilder optimizedPowerSystemBuilder) { _producingLabExecutor = new ProducingLabExecutor(); _producingLabExecutor.Initialize(_planet, subFactoryGraph, optimizedPowerSystemBuilder); _producingLabNetworkIdAndStates = _producingLabExecutor._networkIdAndStates; _optimizedProducingLabs = _producingLabExecutor._optimizedLabs; _producingLabRecipes = _producingLabExecutor._producingLabRecipes; _producingLabIdToOptimizedIndex = _producingLabExecutor._labIdToOptimizedLabIndex; } private void InitializeResearchingLabs(Graph subFactoryGraph, OptimizedPowerSystemBuilder optimizedPowerSystemBuilder) { _researchingLabExecutor = new ResearchingLabExecutor(_starClusterResearchManager); _researchingLabExecutor.Initialize(_planet, subFactoryGraph, optimizedPowerSystemBuilder); _researchingLabNetworkIdAndStates = _researchingLabExecutor._networkIdAndStates; _optimizedResearchingLabs = _researchingLabExecutor._optimizedLabs; _researchingLabIdToOptimizedIndex = _researchingLabExecutor._labIdToOptimizedLabIndex; } private void InitializeMonitors(Graph subFactoryGraph, OptimizedPowerSystemBuilder optimizedPowerSystemBuilder, BeltExecutor beltExecutor) { _monitorExecutor = new MonitorExecutor(); _monitorExecutor.Initialize(_planet, subFactoryGraph, optimizedPowerSystemBuilder, beltExecutor); } private void InitializeSpraycoaters(Graph subFactoryGraph, OptimizedPowerSystemBuilder optimizedPowerSystemBuilder, BeltExecutor beltExecutor) { _spraycoaterExecutor = new SpraycoaterExecutor(); _spraycoaterExecutor.Initialize(_planet, this, subFactoryGraph, optimizedPowerSystemBuilder, beltExecutor); } private void InitializePilers(Graph subFactoryGraph, OptimizedPowerSystemBuilder optimizedPowerSystemBuilder, BeltExecutor beltExecutor) { _pilerExecutor = new PilerExecutor(); _pilerExecutor.Initialize(_planet, subFactoryGraph, optimizedPowerSystemBuilder, beltExecutor); } private void InitializeFractionators(Graph subFactoryGraph, OptimizedPowerSystemBuilder optimizedPowerSystemBuilder, BeltExecutor beltExecutor) { _fractionatorExecutor = new FractionatorExecutor(); _fractionatorExecutor.Initialize(_planet, subFactoryGraph, optimizedPowerSystemBuilder, beltExecutor); } private void InitializeStations(Graph subFactoryGraph, BeltExecutor beltExecutor, VeinMinerExecutor<StationMinerOutput> stationVeinMinerExecutor) { _stationExecutor = new StationExecutor(); _stationExecutor.Initialize(_planet, subFactoryGraph, beltExecutor, stationVeinMinerExecutor); } private void InitializeTanks(Graph subFactoryGraph, BeltExecutor beltExecutor) { _tankExecutor = new TankExecutor(); _tankExecutor.Initialize(_planet, subFactoryGraph, beltExecutor); } private void InitializeBelts(Graph subFactoryGraph, PlanetWideBeltExecutor planetWideBeltExecutor) { _beltExecutor = new BeltExecutor(); _beltExecutor.Initialize(_planet, subFactoryGraph); planetWideBeltExecutor.AddBeltExecutor(_beltExecutor); } private void InitializeSplitters(Graph subFactoryGraph, BeltExecutor beltExecutor) { _splitterExecutor = new SplitterExecutor(); _splitterExecutor.Initialize(_planet, subFactoryGraph, beltExecutor); } public void GameTick(WorkerTimings workerTimings, long time) { MiningFlags miningFlags = new MiningFlags(); workerTimings.StartTimer(); _beltVeinMinerExecutor.GameTick(_planet, ref miningFlags); _stationVeinMinerExecutor.GameTick(_planet, ref miningFlags); _oilMinerExecutor.GameTick(_planet); _waterMinerExecutor.GameTick(_planet); _assemblerExecutor.GameTick(_planet); _fractionatorExecutor.GameTick(_planet); _ejectorExecutor.GameTick(_planet, time); _siloExecutor.GameTick(_planet); _producingLabExecutor.GameTickLabProduceMode(_planet); _producingLabExecutor.GameTickLabOutputToNext(); workerTimings.RecordTime(WorkType.Assembler); workerTimings.StartTimer(); _researchingLabExecutor.GameTickLabResearchMode(_planet); _researchingLabExecutor.GameTickLabOutputToNext(); workerTimings.RecordTime(WorkType.LabResearchMode); workerTimings.StartTimer(); _stationExecutor.StationGameTick(_planet, time, _stationVeinMinerExecutor, ref miningFlags); workerTimings.RecordTime(WorkType.TransportData); workerTimings.StartTimer(); _stationExecutor.InputFromBelt(_planet, time); workerTimings.RecordTime(WorkType.InputFromBelt); workerTimings.StartTimer(); _optimizedBiInserterExecutor.GameTickInserters(_planet); _optimizedInserterExecutor.GameTickInserters(_planet); workerTimings.RecordTime(WorkType.InserterData); workerTimings.StartTimer(); _tankExecutor.GameTick(); workerTimings.RecordTime(WorkType.Storage); workerTimings.StartTimer(); _beltExecutor.GameTick(_planet); workerTimings.RecordTime(WorkType.CargoPathsData); workerTimings.StartTimer(); _splitterExecutor.GameTick(_planet, this, _beltExecutor, time); workerTimings.RecordTime(WorkType.Splitter); workerTimings.StartTimer(); _monitorExecutor.GameTick(_planet); workerTimings.RecordTime(WorkType.Monitor); workerTimings.StartTimer(); _spraycoaterExecutor.GameTick(_planet); workerTimings.RecordTime(WorkType.Spraycoater); workerTimings.StartTimer(); _pilerExecutor.GameTick(_planet); workerTimings.RecordTime(WorkType.Piler); workerTimings.StartTimer(); _stationExecutor.OutputToBelt(_planet, time); workerTimings.RecordTime(WorkType.OutputToBelt); _optimizedPlanet.AddMiningFlags(miningFlags); } public TypedObjectIndex GetAsGranularTypedObjectIndex(int index, PlanetFactory planet) { ref EntityData reference = ref planet.entityPool[index]; if (reference.beltId != 0) { return new TypedObjectIndex(EntityType.Belt, reference.beltId); } if (reference.assemblerId != 0) { if (_assemblerExecutor._assemblerIdToOptimizedIndex.TryGetValue(reference.assemblerId, out var value)) { return new TypedObjectIndex(EntityType.Assembler, value); } if (_assemblerExecutor._unOptimizedAssemblerIds.Contains(reference.assemblerId)) { return TypedObjectIndex.Invalid; } throw new InvalidOperationException("Failed to convert assembler id into optimized assembler id."); } if (reference.ejectorId != 0) { return new TypedObjectIndex(EntityType.Ejector, reference.ejectorId); } if (reference.siloId != 0) { return new TypedObjectIndex(EntityType.Silo, reference.siloId); } if (reference.labId != 0) { if (planet.factorySystem.labPool[reference.labId].researchMode) { if (_researchingLabIdToOptimizedIndex.TryGetValue(reference.labId, out var value2)) { return new TypedObjectIndex(EntityType.ResearchingLab, value2); } if (_researchingLabExecutor._unOptimizedLabIds.Contains(reference.labId)) { return TypedObjectIndex.Invalid; } throw new InvalidOperationException("Failed to convert researching lab id into optimized lab id."); } if (_producingLabIdToOptimizedIndex.TryGetValue(reference.labId, out var value3)) { return new TypedObjectIndex(EntityType.ProducingLab, value3); } if (_producingLabExecutor._unOptimizedLabIds.Contains(reference.labId)) { return TypedObjectIndex.Invalid; } throw new InvalidOperationException("Failed to convert producing lab id into optimized lab id."); } if (reference.storageId != 0) { return new TypedObjectIndex(EntityType.Storage, reference.storageId); } if (reference.stationId != 0) { return new TypedObjectIndex(EntityType.Station, reference.stationId); } if (reference.powerGenId != 0) { return new TypedObjectIndex(EntityType.PowerGenerator, reference.powerGenId); } if (reference.splitterId != 0) { return new TypedObjectIndex(EntityType.Splitter, reference.splitterId); } if (reference.inserterId != 0) { return new TypedObjectIndex(EntityType.Inserter, reference.inserterId); } throw new InvalidOperationException("Unknown entity type."); } public static int[]? GetEntityNeeds(PlanetFactory planet, int entityIndex) { ref EntityData reference = ref planet.entityPool[entityIndex]; if (reference.beltId != 0) { return null; } if (reference.assemblerId != 0) { return planet.factorySystem.assemblerPool[reference.assemblerId].needs ?? throw new InvalidOperationException("Need must not be null for assembler."); } if (reference.ejectorId != 0) { ref EjectorComponent reference2 = ref planet.factorySystem.ejectorPool[reference.ejectorId]; int[] needs = reference2.needs; if (needs == null) { reference2.needs = new int[6]; planet.entityNeeds[reference2.entityId] = reference2.needs; needs = reference2.needs; } return needs; } if (reference.siloId != 0) { ref SiloComponent reference3 = ref planet.factorySystem.siloPool[reference.siloId]; int[] needs2 = reference3.needs; if (needs2 == null) { reference3.needs = new int[6]; planet.entityNeeds[reference3.entityId] = reference3.needs; needs2 = reference3.needs; } return needs2; } if (reference.labId != 0) { return planet.factorySystem.labPool[reference.labId].needs ?? throw new InvalidOperationException("Need must not be null for lab."); } if (reference.storageId != 0) { return null; } if (reference.stationId != 0) { return planet.transport.stationPool[reference.stationId].needs ?? throw new InvalidOperationException("Need must not be null for station."); } if (reference.powerGenId != 0) { return null; } if (reference.splitterId != 0) { return null; } if (reference.inserterId != 0) { return null; } throw new InvalidOperationException("Unknown entity type."); } public bool InsertCargoIntoStorage(int entityId, ref OptimizedCargo cargo, bool useBan = true) { int storageId = _planet.entityPool[entityId].storageId; if (storageId > 0) { for (StorageComponent val = _planet.factoryStorage.storagePool[storageId]; val != null; val = val.nextStorage) { if (!useBan || val.lastFullItem != cargo.item) { if (AddWholeCargo(val, ref cargo, useBan)) { return true; } if (val.nextStorage == null) { return false; } } } } return false; } public int PickFromStorageFiltered(int entityId, ref int filter, int count, out int inc) { inc = 0; int num = count; int storageId = _planet.entityPool[entityId].storageId; if (storageId > 0) { StorageComponent val = _planet.factoryStorage.storagePool[storageId]; StorageComponent val2 = val; if (val != null) { int num4 = default(int); for (val = val.topStorage; val != null; val = val.previousStorage) { if (val.lastEmptyItem != 0 && val.lastEmptyItem != filter) { int num2 = filter; int num3 = count; val.TakeTailItemsFiltered(ref num2, ref num3, ref num4, _planet.entityPool[val.entityId].battleBaseId > 0); count -= num3; inc += num4; if (num2 > 0) { filter = num2; } if (count == 0) { val.lastEmptyItem = -1; return num; } if (filter >= 0) { val.lastEmptyItem = filter; } } if (val == val2) { break; } } } } return num - count; } private bool AddWholeCargo(StorageComponent storage, ref OptimizedCargo cargo, bool useBan = false) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Invalid comparison between Unknown and I4 //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Invalid comparison between Unknown and I4 //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Invalid comparison between Unknown and I4 //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Invalid comparison between Unknown and I4 //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Invalid comparison between Unknown and I4 //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Invalid comparison between Unknown and I4 if (cargo.item <= 0 || cargo.stack == 0 || cargo.item >= 12000) { return false; } bool flag = (int)storage.type > 0; if (flag) { if ((int)storage.type == 1 && !StorageComponent.itemIsFuel[cargo.item]) { return false; } if ((int)storage.type == 2 && (!StorageComponent.itemIsAmmo[cargo.item] || StorageComponent.itemIsBomb[cargo.item])) { return false; } if ((int)storage.type == 3 && !StorageComponent.itemIsBomb[cargo.item]) { return false; } if ((int)storage.type == 4 && !StorageComponent.itemIsFighter[cargo.item]) { return false; } } bool flag2 = false; int num = 0; int num2 = (useBan ? (storage.size - storage.bans) : storage.size); for (int i = 0; i < num2; i++) { if (storage.grids[i].itemId == 0) { if (flag && ((int)storage.type == 8 || storage.grids[i].filter > 0) && cargo.item != storage.grids[i].filter) { continue; } if (num == 0) { num = StorageComponent.itemStackCount[cargo.item]; } storage.grids[i].itemId = cargo.item; if (storage.grids[i].filter == 0) { storage.grids[i].stackSize = num; } } if (storage.grids[i].itemId == cargo.item) { if (num == 0) { num = storage.grids[i].stackSize; } int num3 = num - storage.grids[i].count; if (cargo.stack <= num3) { storage.grids[i].count += cargo.stack; storage.grids[i].inc += cargo.inc; flag2 = true; break; } } } if (flag2) { storage.searchStart = 0; storage.lastEmptyItem = -1; storage.NotifyStorageChange(); } return flag2; } } internal sealed class OptimizedTerrestrialPlanet : IOptimizedPlanet { private readonly PlanetFactory _planet; private readonly StarClusterResearchManager _starClusterResearchManager; private OptimizedSubFactory[] _subFactories; private OptimizedPowerSystem _optimizedPowerSystem; private TurretExecutor _turretExecutor; private WorkStep[] _workSteps; private int _workStepsParallelism; public OptimizedPlanetStatus Status { get; private set; } = OptimizedPlanetStatus.Stopped; public int OptimizeDelayInTicks { get; set; } public OptimizedTerrestrialPlanet(PlanetFactory planet, StarClusterResearchManager starClusterResearchManager) { _planet = planet; _starClusterResearchManager = starClusterResearchManager; } public void Save() { CargoContainer container = _planet.cargoTraffic.container; container.recycleBegin = 0; container.recycleEnd = 0; container.cursor = 0; OptimizedSubFactory[] subFactories = _subFactories; for (int i = 0; i < subFactories.Length; i++) { subFactories[i].Save(container); } _optimizedPowerSystem.Save(_planet); Status = OptimizedPlanetStatus.Stopped; _workSteps = null; _workStepsParallelism = -1; } public void Initialize() { List<Graph> list = Graphifier.ToGraphs(_planet); Graphifier.CombineSmallGraphs(list); OptimizedPowerSystemBuilder optimizedPowerSystemBuilder = new OptimizedPowerSystemBuilder(_planet); PlanetWideBeltExecutor planetWideBeltExecutor = new PlanetWideBeltExecutor(); TurretExecutorBuilder turretExecutorBuilder = new TurretExecutorBuilder(); _subFactories = new OptimizedSubFactory[list.Count]; for (int i = 0; i < _subFactories.Length; i++) { _subFactories[i] = new OptimizedSubFactory(_planet, this, _starClusterResearchManager); _subFactories[i].Initialize(list[i], optimizedPowerSystemBuilder, planetWideBeltExecutor, turretExecutorBuilder); } _optimizedPowerSystem = optimizedPowerSystemBuilder.Build(planetWideBeltExecutor); _turretExecutor = turretExecutorBuilder.Build(); Status = OptimizedPlanetStatus.Running; _workSteps = null; _workStepsParallelism = -1; } public void GameTickDefense(long time) { bool flag = GameMain.localPlanet == _planet.planet; if (Status == OptimizedPlanetStatus.Running) { DefenseGameTick(_planet.defenseSystem, time); } else { _planet.defenseSystem.GameTick(time, flag); } _planet.planetATField.GameTick(time, flag); } public WorkStep[] GetMultithreadedWork(int maxParallelism) { if (_workStepsParallelism != maxParallelism) { _workSteps = CreateMultithreadedWork(maxParallelism); _workStepsParallelism = maxParallelism; } return _workSteps; } private WorkStep[] CreateMultithreadedWork(int maxParallelism) { if (Status == OptimizedPlanetStatus.Stopped) { return CreateParallelWorkForNonRunningOptimizedPlanet(maxParallelism); } if (_subFactories.Length == 0) { return Array.Empty<WorkStep>(); } List<WorkStep> list = new List<WorkStep>(); List<IWorkChunk> list2 = new List<IWorkChunk>(); list2.Add(new PlanetWideBeforePower(this)); OptimizedSubFactory[] subFactories = _subFactories; foreach (OptimizedSubFactory subFactory in subFactories) { list2.Add(new SubFactoryBeforePower(_planet, _optimizedPowerSystem, subFactory)); } list.Add(new WorkStep(list2.ToArray())); list.Add(new WorkStep(new IWorkChunk[1] { new PlanetWidePower(this) })); List<IWorkChunk> list3 = new List<IWorkChunk>(); subFactories = _subFactories; foreach (OptimizedSubFactory subFactory2 in subFactories) { list3.Add(new SubFactoryGameTick(subFactory2)); } list.Add(new WorkStep(list3.ToArray())); list.Add(new WorkStep(new IWorkChunk[1] { new PlanetWideTransport(this) })); list.Add(new WorkStep(new IWorkChunk[1] { new PlanetWideDigitalSystem(this) })); return list.ToArray(); } public bool RequestDysonSpherePower() { if (Status == OptimizedPlanetStatus.Stopped) { return true; } _optimizedPowerSystem.RequestDysonSpherePower(_planet); return false; } public void BeforePowerStep(long time) { _planet.transport.GameTickBeforePower(time, false); _planet.defenseSystem.GameTickBeforePower(time, false); _planet.digitalSystem.GameTickBeforePower(time, false); } public void PowerStep(long time) { _optimizedPowerSystem.GameTick(_planet, time); } public void TransportGameTick(long time, Vector3 playerPos) { //IL_006a: 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_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_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) PlanetTransport transport = _planet.transport; DispenserGameTick_SandboxMode(transport); GameHistoryData history = GameMain.history; float[] networkServes = transport.powerSystem.networkServes; PowerConsumerComponent[] consumerPool = transport.powerSystem.consumerPool; double num = Math.Cos((double)history.dispenserDeliveryMaxAngle * Math.PI / 180.0); if (num < -0.999) { num = -1.0; } playerPos += ((Vector3)(ref playerPos)).normalized * 2.66666f; bool playerDeliveryEnabled = transport.playerDeliveryEnabled; transport.DeterminePlayerDeliveryEnabled(transport.factory); if (playerDeliveryEnabled != transport.playerDeliveryEnabled) { transport.RefreshDispenserTraffic(-10000); } for (int i = 1; i < transport.dispenserCursor; i++) { if (transport.dispenserPool[i] != null && transport.dispenserPool[i].id == i) { float num2 = networkServes[consumerPool[transport.dispenserPool[i].pcId].networkId]; transport.dispenserPool[i].InternalTick(transport.factory, transport.factory.entityPool, transport.dispenserPool, playerPos, time, num2, history.logisticCourierSpeedModified, history.logisticCourierCarries, num); } } } private static void DispenserGameTick_SandboxMode(PlanetTransport transport) { if (!GameMain.sandboxToolsEnabled) { return; } for (int i = 1; i < transport.dispenserCursor; i++) { if (transport.dispenserPool[i] != null && transport.dispenserPool[i].id == i) { transport.dispenserPool[i].UpdateKeepMode(); } } } public void DigitalSystemStep() { _planet.digitalSystem.GameTick(false); } private void DefenseGameTick(DefenseSystem defenseSystem, long tick) { //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) GameHistoryData history = GameMain.history; _ = GameMain.statistics.production.factoryStatPool[defenseSystem.factory.index].productRegister; PowerSystem powerSystem = defenseSystem.factory.powerSystem; float[] networkServes = powerSystem.networkServes; PowerConsumerComponent[] consumerPool = powerSystem.consumerPool; PowerNodeComponent[] nodePool = powerSystem.nodePool; EntityData[] entityPool = defenseSystem.factory.entityPool; AnimData[] entityAnimPool = defenseSystem.factory.entityAnimPool; ref CombatSettings combatSettings = ref defenseSystem.factory.gameData.history.combatSettings; CombatUpgradeData combatUpgradeData = default(CombatUpgradeData); history.GetCombatUpgradeData(ref combatUpgradeData); _ = defenseSystem.factory.gameData.relativePos; _ = defenseSystem.factory.gameData.relativeRot; _ = defenseSystem.factory.gameData.trashSystem.trashCount; defenseSystem.UpdateMatchSpaceEnemies(); EAggressiveLevel aggressiveLevel = ((CombatSettings)(ref combatSettings)).aggressiveLevel; int cursor = defenseSystem.beacons.cursor; BeaconComponent[] buffer = defenseSystem.beacons.buffer; for (int i = 1; i < cursor; i++) { ref BeaconComponent reference = ref buffer[i]; if (reference.id == i) { float num = networkServes[nodePool[reference.pnId].networkId]; PrefabDesc val = PlanetFactory.PrefabDescByModelIndex[entityPool[reference.entityId].modelIndex]; ((BeaconComponent)(ref reference)).GameTick(defenseSystem.factory, val, aggressiveLevel, num, tick); if (((BeaconComponent)(ref reference)).DeterminActiveEnemyUnits(false, tick)) { ((BeaconComponent)(ref reference)).ActiveEnemyUnits_Ground(defenseSystem.factory, val); } if (((BeaconComponent)(ref reference)).DeterminActiveEnemyUnits(true, tick)) { ((BeaconComponent)(ref reference)).ActiveEnemyUnits_Space(defenseSystem.factory, val); } } } bool flag = false; for (int num2 = defenseSystem.localGlobalTargetCursor - 1; num2 >= 0; num2--) { defenseSystem.globalTargets[num2].lifeTick--; if (defenseSystem.globalTargets[num2].lifeTick <= 0) { defenseSystem.RemoveGlobalTargets(num2); flag = true; } } if (flag) { defenseSystem.ArrangeGlobalTargets(); } defenseSystem.UpdateOtherGlobalTargets(); defenseSystem.engagingGaussCount = 0; defenseSystem.engagingLaserCount = 0; defenseSystem.engagingCannonCount = 0; defenseSystem.engagingMissileCount = 0; defenseSystem.engagingPlasmaCount = 0; defenseSystem.engagingLocalPlasmaCount = 0; defenseSystem.engagingTurretTotalCount = 0; defenseSystem.turretEnableDefenseSpace = false; int num3 = _turretExecutor.GameTick(defenseSystem, tick, ref combatUpgradeData); defenseSystem.engagingTurretTotalCount = defenseSystem.engagingGaussCount + defenseSystem.engagingLaserCount + defenseSystem.engagingCannonCount + defenseSystem.engagingPlasmaCount + defenseSystem.engagingMissileCount + defenseSystem.engagingLocalPlasmaCount; if (num3 < 300) { defenseSystem.incomingSupernovaTime = num3; } else { defenseSystem.incomingSupernovaTime = 0; } int cursor2 = defenseSystem.fieldGenerators.cursor; FieldGeneratorComponent[] buffer2 = defenseSystem.fieldGenerators.buffer; for (int j = 1; j < cursor2; j++) { ref FieldGeneratorComponent reference2 = ref buffer2[j]; if (reference2.id == j) { ref PowerConsumerComponent reference3 = ref consumerPool[reference2.pcId]; float num4 = networkServes[reference3.networkId]; ((FieldGeneratorComponent)(ref reference2)).InternalUpdate(defenseSystem.factory, (double)num4, ref reference3, ref entityAnimPool[reference2.entityId]); } } } public void DefenseGameTickUIThread(long tick) { //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) DefenseSystem defenseSystem = _planet.defenseSystem; int[] productRegister = GameMain.statistics.production.factoryStatPool[defenseSystem.factory.index].productRegister; PowerSystem powerSystem = defenseSystem.factory.powerSystem; float[] networkServes = powerSystem.networkServes; PowerConsumerComponent[] consumerPool = powerSystem.consumerPool; AnimData[] entityAnimPool = defenseSystem.factory.entityAnimPool; VectorLF3 relativePos = defenseSystem.factory.gameData.relativePos; Quaternion relativeRot = defenseSystem.factory.gameData.relativeRot; TrashSystem trashSystem = defenseSystem.factory.gameData.trashSystem; bool flag = trashSystem.trashCount > 0; float num = 1f / 60f; int num2 = (int)(tick % 4); BattleBaseComponent[] buffer = defenseSystem.battleBases.buffer; for (int i = 1; i < defenseSystem.battleBases.cursor; i++) { BattleBaseComponent val = buffer[i]; if (val != null && val.id == i) { float num3 = networkServes[consumerPool[val.pcId].networkId]; val.InternalUpdate(num, defenseSystem.factory, num3, ref entityAnimPool[val.entityId]); if (flag && val.autoPickEnabled && val.energy > 0 && (long)i % 4L == num2) { val.AutoPickTrash(defenseSystem.factory, trashSystem, tick, ref relativePos, ref relativeRot, productRegister); } } } } public void AddMiningFlags(MiningFlags miningFlags) { if (miningFlags.MiningFlag == 0 && miningFlags.VeinMiningFlag == 0) { return; } lock (this) { PlanetFactory planet = _planet; planet._miningFlag |= miningFlags.MiningFlag; PlanetFactory planet2 = _planet; planet2._veinMiningFlag |= miningFlags.VeinMiningFlag; } } private WorkStep[] CreateParallelWorkForNonRunningOptimizedPlanet(int maxParallelism) { List<WorkStep> list = new List<WorkStep>(); int minerCursor = _planet.factorySystem.minerCursor; int assemblerCursor = _planet.factorySystem.assemblerCursor; int fractionatorCursor = _planet.factorySystem.fractionatorCursor; int ejectorCursor = _planet.factorySystem.ejectorCursor; int siloCursor = _planet.factorySystem.siloCursor; int monitorCursor = _planet.cargoTraffic.monitorCursor; int spraycoaterCursor = _planet.cargoTraffic.spraycoaterCursor; int pilerCursor = _planet.cargoTraffic.pilerCursor; int splitterCursor = _planet.cargoTraffic.splitterCursor; int pathCursor = _planet.cargoTraffic.pathCursor; int stationCursor = _planet.transport.stationCursor; int dispenserCursor = _planet.transport.dispenserCursor; int num = stationCursor + dispenserCursor; int cursor = _planet.defenseSystem.turrets.cursor; int cursor2 = _planet.defenseSystem.fieldGenerators.cursor; int cursor3 = _planet.defenseSystem.battleBases.cursor; int cursor4 = _planet.digitalSystem.markers.cursor; int inserterCursor = _planet.factorySystem.inserterCursor; int labCursor = _planet.factorySystem.labCursor; int labCursor2 = _planet.factorySystem.labCursor; int labCursor3 = _planet.factorySystem.labCursor; int storageCursor = _planet.factoryStorage.storageCursor; int tankCursor = _planet.factoryStorage.tankCursor; int val = (minerCursor + assemblerCursor + fractionatorCursor + ejectorCursor + siloCursor + monitorCursor + spraycoaterCursor + pilerCursor + stationCursor + dispenserCursor + cursor + cursor2 + cursor3 + cursor4 + 4999) / 5000; val = Math.Min(val, maxParallelism); if (val > 0) { IWorkChunk[] workChunks = UnOptimizedPlanetWorkChunk.CreateDuplicateChunks(_planet, WorkType.BeforePower, val); list.Add(new WorkStep(workChunks)); } if (_planet.powerSystem.netCursor > 0) { IWorkChunk[] workChunks = UnOptimizedPlanetWorkChunk.CreateDuplicateChunks(_planet, WorkType.Power, 1); list.Add(new WorkStep(workChunks)); } int val2 = (minerCursor + assemblerCursor + fractionatorCursor + ejectorCursor + siloCursor + labCursor + 4999) / 5000; val2 = Math.Min(val2, maxParallelism); if (val2 > 0) { IWorkChunk[] workChunks = UnOptimizedPlanetWorkChunk.CreateDuplicateChunks(_planet, WorkType.Assembler, val2); list.Add(new WorkStep(workChunks)); } if (labCursor2 > 0) { IWorkChunk[] workChunks = UnOptimizedPlanetWorkChunk.CreateDuplicateChunks(_planet, WorkType.LabResearchMode, 1); list.Add(new WorkStep(workChunks)); } int val3 = (labCursor3 + 4999) / 5000; val3 = Math.Min(val3, maxParallelism); if (val3 > 0) { IWorkChunk[] workChunks = UnOptimizedPlanetWorkChunk.CreateDuplicateChunks(_planet, WorkType.LabOutput2NextData, val3); list.Add(new WorkStep(workChunks)); } if (num > 0) { IWorkChunk[] workChunks = UnOptimizedPlanetWorkChunk.CreateDuplicateChunks(_planet, WorkType.TransportData, 1); list.Add(new WorkStep(workChunks)); } if (stationCursor > 0) { IWorkChunk[] workChunks = UnOptimizedPlanetWorkChunk.CreateDuplicateChunks(_planet, WorkType.InputFromBelt, 1); list.Add(new WorkStep(workChunks)); } if (Math.Min((inserterCursor + 4999) / 5000, maxParallelism) > 0) { IWorkChunk[] workChunks = UnOptimizedPlanetWorkChunk.CreateDuplicateChunks(_planet, WorkType.InserterData, 1); list.Add(new WorkStep(workChunks)); } if (storageCursor + tankCursor > 0) { IWorkChunk[] workChunks = UnOptimizedPlanetWorkChunk.CreateDuplicateChunks(_planet, WorkType.Storage, 1); list.Add(new WorkStep(workChunks)); } int val4 = (pathCursor + 4999) / 5000; val4 = Math.Min(val4, maxParallelism); if (val4 > 0) { IWorkChunk[] workChunks = UnOptimizedPlanetWorkChunk.CreateDuplicateChunks(_planet, WorkType.CargoPathsData, val4); list.Add(new WorkStep(workChunks)); } if (splitterCursor > 0) { IWorkChunk[] workChunks = UnOptimizedPlanetWorkChunk.CreateDuplicateChunks(_planet, WorkType.Splitter, 1); list.Add(new WorkStep(workChunks)); } if (monitorCursor > 0) { IWorkChunk[] workChunks = UnOptimizedPlanetWorkChunk.CreateDuplicateChunks(_planet, WorkType.Monitor, 1); list.Add(new WorkStep(workChunks)); } if (spraycoaterCursor > 0) { IWorkChunk[] workChunks = UnOptimizedPlanetWorkChunk.CreateDuplicateChunks(_planet, WorkType.Spraycoater, 1); list.Add(new WorkStep(workChunks)); } if (pilerCursor > 0) { IWorkChunk[] workChunks = UnOptimizedPlanetWorkChunk.CreateDuplicateChunks(_planet, WorkType.Piler, 1); list.Add(new WorkStep(workChunks)); } if (stationCursor > 0) { IWorkChunk[] workChunks = UnOptimizedPlanetWorkChunk.CreateDuplicateChunks(_planet, WorkType.OutputToBelt, 1); list.Add(new WorkStep(workChunks)); } int val5 = (num + 4999) / 5000; val5 = Math.Min(val5, maxParallelism); if (GameMain.sandboxToolsEnabled && val5 > 0) { IWorkChunk[] workChunks = UnOptimizedPlanetWorkChunk.CreateDuplicateChunks(_planet, WorkType.SandboxMode, val5); list.Add(new WorkStep(workChunks)); } int val6 = (pathCursor + 4999) / 5000; val6 = Math.Min(val6, maxParallelism); if (val6 > 0) { IWorkChunk[] workChunks = UnOptimizedPlanetWorkChunk.CreateDuplicateChunks(_planet, WorkType.PresentCargoPathsData, val6); list.Add(new WorkStep(workChunks)); } if (cursor4 > 0) { IWorkChunk[] workChunks = UnOptimizedPlanetWorkChunk.CreateDuplicateChunks(_planet, WorkType.Digital, 1); list.Add(new WorkStep(workChunks)); } return list.ToArray(); } } internal readonly struct TypedObjectIndex { private const int IndexBitCount = 24; private const uint IndexBitMask = 16777215u; private const uint EntityTypeMask = 255u; private readonly uint _value; public static readonly TypedObjectIndex Invalid = new TypedObjectIndex(EntityType.None, 16777215); public EntityType EntityType => (EntityType)(_value >> 24); public int Index => (int)(0xFFFFFF & _value); public TypedObjectIndex(EntityType entityType, int index) { if (entityType < EntityType.None || entityType > (EntityType)255) { throw new ArgumentOutOfRangeException("index", $"{entityType} was outside the range {0} to {255u:N0}"); } if (index < 0 || (long)index > 16777215L) { throw new ArgumentOutOfRangeException("index", $"{index} was outside the range {0} to {16777215u:N0}"); } _value = ((uint)entityType << 24) | (0xFFFFFFu & (uint)index); } } } namespace Weaver.Optimizations.LinearDataAccess.WorkDistributors { internal sealed class PerformanceMonitorUpdater { private readonly double[] _sumWorkerWorkTypeTimings = new double[ArrayExtensions.GetEnumValuesEnumerable<WorkType>().Max((WorkType x) => (int)x) + 1]; private readonly HashSet<ECpuWorkEntry> _factoryWorkEntryChildren; private readonly Dictionary<WorkType, ECpuWorkEntry[]> _workTypeToCpuWorkEntry = new Dictionary<WorkType, ECpuWorkEntry[]> { { WorkType.BeforePower, (ECpuWorkEntry[])(object)new ECpuWorkEntry[1] { (ECpuWorkEntry)9 } }, { WorkType.Power, (ECpuWorkEntry[])(object)new ECpuWorkEntry[1] { (ECpuWorkEntry)9 } }, { WorkType.Construction, (ECpuWorkEntry[])(object)new ECpuWorkEntry[1] { (ECpuWorkEntry)21 } }, { WorkType.CheckBefore, (ECpuWorkEntry[])(object)new ECpuWorkEntry[1] }, { WorkType.Assembler, (ECpuWorkEntry[])(object)new ECpuWorkEntry[1] { (ECpuWorkEntry)13 } }, { WorkType.LabResearchMode, (ECpuWorkEntry[])(object)new ECpuWorkEntry[2] { (ECpuWorkEntry)13, (ECpuWorkEntry)18 } }, { WorkType.LabOutput2NextData, (ECpuWorkEntry[])(object)new ECpuWorkEntry[2] { (ECpuWorkEntry)13, (ECpuWorkEntry)18 } }, { WorkType.TransportData, (ECpuWorkEntry[])(object)new ECpuWorkEntry[1] { (ECpuWorkEntry)22 } }, { WorkType.InputFromBelt, (ECpuWorkEntry[])(object)new ECpuWorkEntry[1] { (ECpuWorkEntry)20 } }, { WorkType.InserterData, (ECpuWorkEntry[])(object)new ECpuWorkEntry[1] { (ECpuWorkEntry)11 } }, { WorkType.Storage, (ECpuWorkEntry[])(object)new ECpuWorkEntry[1] { (ECpuWorkEntry)20 } }, { WorkType.CargoPathsData, (ECpuWorkEntry[])(object)new ECpuWorkEntry[1] { (ECpuWorkEntry)10 } }, { WorkType.Splitter, (ECpuWorkEntry[])(object)new ECpuWorkEntry[1] { (ECpuWorkEntry)12 } }, { WorkType.Monitor, (ECpuWorkEntry[])(object)new ECpuWorkEntry[1] { (ECpuWorkEntry)10 } }, { WorkType.Spraycoater, (ECpuWorkEntry[])(object)new ECpuWorkEntry[1] { (ECpuWorkEntry)10 } }, { WorkType.Piler, (ECpuWorkEntry[])(object)new ECpuWorkEntry[1] { (ECpuWorkEntry)10 } }, { WorkType.OutputToBelt, (ECpuWorkEntry[])(object)new ECpuWorkEntry[1] { (ECpuWorkEntry)20 } }, { WorkType.SandboxMode, (ECpuWorkEntry[])(object)new ECpuWorkEntry[1] { (ECpuWorkEntry)20 } }, { WorkType.PresentCargoPathsData, (ECpuWorkEntry[])(object)new ECpuWorkEntry[1] { (ECpuWorkEntry)6 } }, { WorkType.Digital, (ECpuWorkEntry[])(object)new ECpuWorkEntry[1] { (ECpuWorkEntry)32 } } }; private PerformanceMonitorUpdater(HashSet<ECpuWorkEntry> factoryWorkEntryChildren) { _factoryWorkEntryChildren = factoryWorkEntryChildren; } public static PerformanceMonitorUpdater Create() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Invalid comparison between Unknown and I4 //IL_001e: Unknown result type (might be due to invalid IL or missing references) HashSet<ECpuWorkEntry> hashSet = new HashSet<ECpuWorkEntry>(); int count; do { count = hashSet.Count; for (int i = 0; i < PerformanceMonitor.cpuWorkParents.Length; i++) { ECpuWorkEntry val = PerformanceMonitor.cpuWorkParents[i]; if ((int)val == 5 || hashSet.Contains(val)) { hashSet.Add((ECpuWorkEntry)i); } } } while (count != hashSet.Count); return new PerformanceMonitorUpdater(hashSet); } public void UpdateTimings(double totalDuration, WorkExecutor[] workExecutors) { Array.Clear(_sumWorkerWorkTypeTimings, 0, _sumWorkerWorkTypeTimings.Length); for (int i = 0; i < workExecutors.Length; i++) { double[] workTypeTimings = workExecutors[i].GetWorkTypeTimings(); if (_sumWorkerWorkTypeTimings.Length != workTypeTimings.Length) { throw new InvalidOperationException($"Work type timing arrays were not the same size. Sum array size: {_sumWorkerWorkTypeTimings.Length}, worker array size: {workTypeTimings.Length}"); } for (int j = 0; j < _sumWorkerWorkTypeTimings.Length; j++) { _sumWorkerWorkTypeTimings[j] += workTypeTimings[j]; } } double num = _sumWorkerWorkTypeTimings.Sum(); double num2 = totalDuration / num; foreach (KeyValuePair<WorkType, ECpuWorkEntry[]> item in _workTypeToCpuWorkEntry) { for (int k = 0; k < item.Value.Length; k++) { if (item.Value[k]) { PerformanceMonitor.timeCostsFrame[(int)item.Value[k]] += _sumWorkerWorkTypeTimings[(int)item.Key] * num2; } } } } } internal sealed class PlanetWorkManager { private WorkStep[] _workSteps; private int _currentWorkStepIndex; public PlanetFactory Planet { get; } public IOptimizedPlanet OptimizedPlanet { get; } public PlanetWorkManager(PlanetFactory planet, IOptimizedPlanet optimizedPlanet) { Planet = planet; OptimizedPlanet = optimizedPlanet; } public void UpdatePlanetWork(int parallelism) { WorkStep[] multithreadedWork = OptimizedPlanet.GetMultithreadedWork(parallelism); if (_workSteps != multithreadedWork && _workSteps != null) { for (int i = 0; i < _workSteps.Length; i++) { _workSteps[i].Dispose(); } } _workSteps = multithreadedWork; } public IWorkChunk? TryGetWork(out bool canScheduleMoreWork) { int currentWorkStepIndex = _currentWorkStepIndex; if (currentWorkStepIndex == _workSteps.Length) { canScheduleMoreWork = false; return null; } bool canNoLongerProvideWork; IWorkChunk result = _workSteps[currentWorkStepIndex].TryGetWork(out canNoLongerProvideWork); if (currentWorkStepIndex == _workSteps.Length - 1 && canNoLongerProvideWork) { canScheduleMoreWork = false; } canScheduleMoreWork = true; return result; } public IWorkChunk? TryWaitForWork() { int currentWorkStepIndex = _currentWorkStepIndex; if (currentWorkStepIndex == _workSteps.Length) { return null; } int num = currentWorkStepIndex + 1; if (num >= _workSteps.Length) { return null; } WorkStep workStep = _workSteps[currentWorkStepIndex]; bool canNoLongerProvideWork; IWorkChunk workChunk = _workSteps[num].TryGetWork(out canNoLongerProvideWork); if (workChunk == null) { return workChunk; } workStep.WaitForCompletion(); return workChunk; } public void CompleteWork(IWorkChunk workChunk) { if (workChunk.Complete()) { Interlocked.Increment(ref _currentWorkStepIndex); workChunk.CompleteStep(); } } public void Reset() { for (int i = 0; i < _workSteps.Length; i++) { _workSteps[i].Reset(); } _currentWorkStepIndex = 0; } } internal record struct PlanetWorkPlan(PlanetWorkManager PlanetWorkManager, IWorkChunk WorkChunk); internal sealed class StarClusterWorkManager { private