Decompiled source of Weaver v1.1.5

Weaver.dll

Decompiled a week ago
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 PowerNetworkStructures;
using UnityEngine;
using Weaver.Benchmarking;
using Weaver.Extensions;
using Weaver.FatoryGraphs;
using Weaver.Optimizations.LinearDataAccess;
using Weaver.Optimizations.LinearDataAccess.Assemblers;
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.PowerSystems;
using Weaver.Optimizations.LinearDataAccess.Spraycoaters;
using Weaver.Optimizations.LinearDataAccess.WorkDistributors;
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+0f3c743f92fcb1f820dc47586166d95aa67bbe2e")]
[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.1.5";
	}
	internal static class ModDependencies
	{
		public const string SampleAndHoldSimId = "starfi5h.plugin.SampleAndHoldSim";
	}
	[BepInPlugin("Weaver", "Weaver", "1.1.5")]
	[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)
			{
				FactorySystem factorySystem = GameMain.data.factories[i].factorySystem;
				if (factorySystem == null || factorySystem.labCursor > 1 || factorySystem.assemblerCursor > 1 || factorySystem.minerCursor > 1 || factorySystem.fractionatorCursor > 1 || factorySystem.ejectorCursor > 1 || factorySystem.siloCursor > 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)
			{
				FactorySystem factorySystem = GameMain.data.factories[i].factorySystem;
				if (factorySystem == null || factorySystem.labCursor > 1 || factorySystem.assemblerCursor > 1 || factorySystem.minerCursor > 1 || factorySystem.fractionatorCursor > 1 || factorySystem.ejectorCursor > 1 || factorySystem.siloCursor > 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.LoadBalance
{
	[StructLayout(LayoutKind.Sequential, Size = 1)]
	internal struct InserterExecutableGraphAction : IExecutableGraphAction
	{
		public void Execute(long time, PlanetFactory factory, int[] indexes)
		{
			bool flag = factory.planet == GameMain.localPlanet;
			InserterComponent[] inserterPool = factory.factorySystem.inserterPool;
			CargoTraffic traffic = factory.factorySystem.traffic;
			PowerSystem powerSystem = factory.powerSystem;
			float[] networkServes = powerSystem.networkServes;
			AnimData[] entityAnimPool = factory.entityAnimPool;
			int[][] entityNeeds = factory.entityNeeds;
			PowerConsumerComponent[] consumerPool = powerSystem.consumerPool;
			EntityData[] entityPool = factory.entityPool;
			BeltComponent[] beltPool = factory.cargoTraffic.beltPool;
			byte b = (byte)GameMain.history.inserterStackCountObsolete;
			byte b2 = (byte)GameMain.history.inserterStackInput;
			byte stackOutput = (byte)GameMain.history.inserterStackOutput;
			bool inserterBidirectional = GameMain.history.inserterBidirectional;
			int delay = ((b > 1) ? 110000 : 0);
			int delay2 = ((b2 > 1) ? 40000 : 0);
			bool flag2 = time % 60 == 0;
			int[] array;
			if (flag)
			{
				array = indexes;
				foreach (int num in array)
				{
					ref InserterComponent reference = ref inserterPool[num];
					if (flag2)
					{
						((InserterComponent)(ref reference)).InternalOffsetCorrection(entityPool, traffic, beltPool);
						if (reference.grade == 3)
						{
							reference.delay = delay;
							reference.stackInput = b;
							reference.stackOutput = 1;
							reference.bidirectional = false;
						}
						else if (reference.grade == 4)
						{
							reference.delay = delay2;
							reference.stackInput = b2;
							reference.stackOutput = stackOutput;
							reference.bidirectional = inserterBidirectional;
						}
						else
						{
							reference.delay = 0;
							reference.stackInput = 1;
							reference.stackOutput = 1;
							reference.bidirectional = false;
						}
					}
					float num2 = networkServes[consumerPool[reference.pcId].networkId];
					if (reference.bidirectional)
					{
						((InserterComponent)(ref reference)).InternalUpdate_Bidirectional(factory, entityNeeds, entityAnimPool, num2, flag);
					}
					else
					{
						((InserterComponent)(ref reference)).InternalUpdate(factory, entityNeeds, entityAnimPool, num2);
					}
				}
				return;
			}
			array = indexes;
			foreach (int num3 in array)
			{
				ref InserterComponent reference2 = ref inserterPool[num3];
				if (flag2)
				{
					if (reference2.grade == 3)
					{
						reference2.delay = delay;
						reference2.stackInput = b;
						reference2.stackOutput = 1;
						reference2.bidirectional = false;
					}
					else if (reference2.grade == 4)
					{
						reference2.delay = delay2;
						reference2.stackInput = b2;
						reference2.stackOutput = stackOutput;
						reference2.bidirectional = inserterBidirectional;
					}
					else
					{
						reference2.delay = 0;
						reference2.stackInput = 1;
						reference2.stackOutput = 1;
						reference2.bidirectional = false;
					}
				}
				float num4 = networkServes[consumerPool[reference2.pcId].networkId];
				if (reference2.bidirectional)
				{
					((InserterComponent)(ref reference2)).InternalUpdate_Bidirectional(factory, entityNeeds, entityAnimPool, num4, flag);
				}
				else
				{
					((InserterComponent)(ref reference2)).InternalUpdateNoAnim(factory, entityNeeds, num4);
				}
			}
		}
	}
	public class InserterMultithreadingOptimization
	{
		private static readonly TimeIndexedCollectionStatistic _inserterTickTimes = new TimeIndexedCollectionStatistic(200);

		private static readonly List<ExecutableGraph<InserterExecutableGraphAction>> _inserterExecutables = new List<ExecutableGraph<InserterExecutableGraphAction>>();

		private static long? _gameTime;

		public static void EnableOptimization(Harmony harmony)
		{
			harmony.PatchAll(typeof(InserterMultithreadingOptimization));
		}

		[HarmonyPriority(1)]
		[HarmonyPostfix]
		[HarmonyPatch(typeof(GameSave), "LoadCurrentGame")]
		private static void LoadCurrentGame_Postfix()
		{
			WeaverFixes.Logger.LogInfo((object)"Initializing InserterMultithreadingOptimization");
			_inserterTickTimes.Clear();
			_inserterExecutables.Clear();
			for (int i = 0; i < GameMain.data.factoryCount; i++)
			{
				PlanetFactory val = GameMain.data.factories[i];
				FactorySystem factorySystem = val.factorySystem;
				if (factorySystem == null)
				{
					continue;
				}
				List<Graph> list = Graphifier.ToInserterGraphs(factorySystem);
				Graphifier.SplitLargeGraphs(list);
				Graphifier.CombineSmallGraphs(list);
				foreach (Graph item2 in list)
				{
					ExecutableGraph<InserterExecutableGraphAction> item = new ExecutableGraph<InserterExecutableGraphAction>(val, item2, EntityType.Inserter, default(InserterExecutableGraphAction));
					_inserterExecutables.Add(item);
				}
			}
			WeaverFixes.Logger.LogInfo((object)$"Created {_inserterExecutables.Count} executable graphs");
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(MultithreadSystem), "PrepareInserterData")]
		private static bool PrepareInserterData_Prefix(MultithreadSystem __instance, long _time)
		{
			_gameTime = _time;
			__instance.missionOrders |= 2u;
			foreach (ExecutableGraph<InserterExecutableGraphAction> inserterExecutable in _inserterExecutables)
			{
				inserterExecutable.Prepare();
			}
			return false;
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(MultithreadSystem), "Schedule")]
		private static bool Schedule_Prefix(MultithreadSystem __instance)
		{
			return __instance.missionOrders != 2;
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(MultithreadSystem), "Complete")]
		private static bool Complete_Prefix(MultithreadSystem __instance)
		{
			if (__instance.missionOrders != 2)
			{
				return true;
			}
			if (!_gameTime.HasValue)
			{
				throw new InvalidOperationException("_gameTime is null.");
			}
			ParallelOptions parallelOptions = new ParallelOptions
			{
				MaxDegreeOfParallelism = GameMain.multithreadSystem.usedThreadCnt
			};
			_inserterTickTimes.EnsureCapacity(1);
			_inserterTickTimes.StartSampling(0);
			Parallel.ForEach(_inserterExecutables, parallelOptions, delegate(ExecutableGraph<InserterExecutableGraphAction> executableGraph)
			{
				executableGraph.Execute(_gameTime.Value);
			});
			_inserterTickTimes.EndSampling(0);
			if (_gameTime.Value % 60 == 0L)
			{
				WeaverFixes.Logger.LogInfo((object)$"Inserter tick {_inserterTickTimes.GetAverageTimeInMilliseconds(0):N2}");
			}
			__instance.isRevAllThreadCompleteSignal = true;
			__instance.missionOrders = 0u;
			return false;
		}
	}
	public class InserterThreadLoadBalance
	{
		private static uint _updateCounter;

		internal static int[]? _inserterPerThreadItemCount;

		internal static bool enableStatisticsLoadBalancing;

		public static void EnableOptimization(Harmony harmony)
		{
			harmony.PatchAll(typeof(WorkerThreadExecutorBenchmarkPatches));
			harmony.PatchAll(typeof(MultithreadSystemBenchmarkDisplayPatches));
			MultithreadSystemBenchmarkDisplayPatches._logResults = false;
			harmony.PatchAll(typeof(InserterThreadLoadBalance));
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(GameSave), "LoadCurrentGame")]
		private static void LoadCurrentGame_Postfix()
		{
			_updateCounter = 0u;
			_inserterPerThreadItemCount = null;
			enableStatisticsLoadBalancing = false;
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(MultithreadSystem), "Schedule")]
		private static void Schedule_Prefix(MultithreadSystem __instance, out bool __state)
		{
			if (__instance.missionOrders != 2)
			{
				__state = false;
				return;
			}
			__state = true;
			_updateCounter++;
			if (_inserterPerThreadItemCount == null || _inserterPerThreadItemCount.Length != GameMain.multithreadSystem.usedThreadCnt)
			{
				_inserterPerThreadItemCount = new int[GameMain.multithreadSystem.usedThreadCnt];
				enableStatisticsLoadBalancing = false;
				return;
			}
			if (_updateCounter % 60 == 0)
			{
				StringBuilder stringBuilder = new StringBuilder();
				for (int i = 0; i < _inserterPerThreadItemCount.Length; i++)
				{
					stringBuilder.Append($" {_inserterPerThreadItemCount[i],7:N0}");
				}
				WeaverFixes.Logger.LogInfo((object)string.Format("{0} Sum: {1} Thread item counts: {2}", "MultithreadSystem", _inserterPerThreadItemCount.Sum(), stringBuilder));
				MultithreadSystemBenchmarkDisplayPatches.LogComputeTimes((MissionOrderType)2, WorkerThreadExecutorBenchmarkPatches._missionComputeTimes[2u]);
				RebalanceInsertersPerThread(__instance);
			}
			RescaleToCurrentInserterCount(__instance);
		}

		private static void RebalanceInsertersPerThread(MultithreadSystem __instance)
		{
			TimeIndexedCollectionStatistic timeIndexedCollectionStatistic = WorkerThreadExecutorBenchmarkPatches._missionComputeTimes[2u];
			if (!timeIndexedCollectionStatistic.IsFilledWithData(_inserterPerThreadItemCount.Length))
			{
				return;
			}
			float num = 0f;
			for (int i = 0; i < _inserterPerThreadItemCount.Length; i++)
			{
				num += timeIndexedCollectionStatistic.GetAverageTimeInMilliseconds(i);
			}
			float num2 = num / (float)_inserterPerThreadItemCount.Length;
			int num3 = 0;
			for (int j = 0; j < _inserterPerThreadItemCount.Length; j++)
			{
				if (!(timeIndexedCollectionStatistic.GetAverageTimeInMilliseconds(j) > num2))
				{
					num3++;
				}
			}
			int num4 = -1;
			float num5 = float.MinValue;
			for (int k = 0; k < _inserterPerThreadItemCount.Length; k++)
			{
				if (!(num5 >= timeIndexedCollectionStatistic.GetAverageTimeInMilliseconds(k)))
				{
					num4 = k;
					num5 = timeIndexedCollectionStatistic.GetAverageTimeInMilliseconds(k);
				}
			}
			if (num4 == -1)
			{
				return;
			}
			int num6 = -1;
			float num7 = float.MaxValue;
			for (int l = 0; l < _inserterPerThreadItemCount.Length; l++)
			{
				if (!(num7 < timeIndexedCollectionStatistic.GetAverageTimeInMilliseconds(l)))
				{
					num6 = l;
					num7 = timeIndexedCollectionStatistic.GetAverageTimeInMilliseconds(l);
				}
			}
			if (num6 != -1 && !(num5 < num2 * 1.05f))
			{
				float averageTimeInMilliseconds = timeIndexedCollectionStatistic.GetAverageTimeInMilliseconds(num4);
				int num8 = (int)((float)_inserterPerThreadItemCount[num4] * ((1f - 1f / (averageTimeInMilliseconds / num2)) * 0.5f));
				_inserterPerThreadItemCount[num4] -= num8;
				_inserterPerThreadItemCount[num6] += num8;
			}
		}

		private static void RescaleToCurrentInserterCount(MultithreadSystem __instance)
		{
			PlanetFactory[] inserterFactories = __instance.workerThreadExecutors[0].inserterFactories;
			int inserterFactoryCnt = __instance.workerThreadExecutors[0].inserterFactoryCnt;
			int num = 0;
			for (int i = 0; i < inserterFactoryCnt; i++)
			{
				num += inserterFactories[i].factorySystem.inserterCursor;
			}
			int num2 = _inserterPerThreadItemCount.Sum();
			int num3 = (num - num2 + (_inserterPerThreadItemCount.Length - 1)) / _inserterPerThreadItemCount.Length;
			for (int j = 0; j < _inserterPerThreadItemCount.Length; j++)
			{
				_inserterPerThreadItemCount[j] += num3;
			}
			int num4 = _inserterPerThreadItemCount.Sum();
			if (num4 < num)
			{
				throw new InvalidOperationException($"Rescaled inserter count is less than the total inserter count.\r\nRescaled count: {num4}\r\nExpected count: {num}");
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(MultithreadSystem), "Schedule")]
		private static void Schedule_Postfix(MultithreadSystem __instance, bool __state)
		{
			if (__state)
			{
				enableStatisticsLoadBalancing = true;
				MultithreadSystemBenchmarkDisplayPatches._logResults = false;
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(MultithreadSystem), "PrepareInserterData")]
		private static void PrepareInserterData_Loadbalance(MultithreadSystem __instance)
		{
		}

		[HarmonyPrefix]
		[HarmonyPatch(/*Could not decode attribute arguments.*/)]
		private static bool CalculateMissionIndex_Loadbalance_Prefix(WorkerThreadExecutor __instance, ref bool __result, int _curThreadIdx, ref int _start, ref int _end)
		{
			if (!enableStatisticsLoadBalancing)
			{
				return true;
			}
			__result = _inserterPerThreadItemCount[_curThreadIdx] > 0;
			for (int i = 0; i < _curThreadIdx; i++)
			{
				_start += _inserterPerThreadItemCount[i];
			}
			_end = _start + _inserterPerThreadItemCount[_curThreadIdx];
			return false;
		}

		[HarmonyPostfix]
		[HarmonyPatch(/*Could not decode attribute arguments.*/)]
		private static void CalculateMissionIndex_Loadbalance_Postfix(WorkerThreadExecutor __instance, int _curThreadIdx, int _start, int _end)
		{
			if (!enableStatisticsLoadBalancing && _inserterPerThreadItemCount != null)
			{
				_inserterPerThreadItemCount[_curThreadIdx] = _end - _start;
			}
		}
	}
	public class MultithreadSystemLoadBalance
	{
	}
}
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);
			}
		}
	}
	[Flags]
	internal enum LabState
	{
		Active = 0,
		Inactive = 8,
		InactiveNoAssembler = 9,
		InactiveNoRecipeSet = 0xA,
		InactiveOutputFull = 0xB,
		InactiveInputMissing = 0xC,
		ResearchMode = 0x10
	}
	public class LinearInserterDataAccessOptimization
	{
		private record struct EntityIndexAndPowerIndex(EntityType EntityType, int EntityIndex, int PowerConsumerIndex);

		public static void EnableOptimization(Harmony harmony)
		{
			harmony.PatchAll(typeof(LinearInserterDataAccessOptimization));
		}

		[HarmonyPriority(2)]
		[HarmonyPostfix]
		[HarmonyPatch(typeof(GameSave), "LoadCurrentGame")]
		private static void LoadCurrentGame_Postfix()
		{
			WeaverFixes.Logger.LogInfo((object)"Initializing LinearInserterDataAccessOptimization");
			for (int i = 0; i < GameMain.data.factoryCount; i++)
			{
				PlanetFactory val = GameMain.data.factories[i];
				FactorySystem factorySystem = val.factorySystem;
				PowerSystem powerSystem = val.powerSystem;
				CargoTraffic cargoTraffic = val.cargoTraffic;
				PlanetTransport transport = val.transport;
				DefenseSystem defenseSystem = val.defenseSystem;
				DigitalSystem digitalSystem = val.digitalSystem;
				HashSystem hashSystemStatic = val.hashSystemStatic;
				if (factorySystem != null && powerSystem != null && cargoTraffic != null && transport != null && defenseSystem != null && digitalSystem != null && hashSystemStatic != null)
				{
					CompactInserters(val, factorySystem);
					InserterLinearAccessToAssemblers(val, factorySystem);
				}
			}
		}

		private static void CompactInserters(PlanetFactory planet, FactorySystem factory)
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			List<Graph> list = Graphifier.ToInserterGraphs(factory);
			if (list.Count == 0)
			{
				return;
			}
			Graphifier.CombineSmallGraphs(list);
			InserterComponent[] inserterPool = factory.inserterPool;
			List<InserterComponent> list2 = new List<InserterComponent>();
			list2.Add(new InserterComponent
			{
				id = 0
			});
			foreach (Graph item in list)
			{
				foreach (Node item2 in from x in item.GetAllNodes()
					where x.EntityTypeIndex.EntityType == EntityType.Inserter
					orderby (int)x.EntityTypeIndex.EntityType, x.EntityId
					select x)
				{
					InserterComponent val = inserterPool[item2.EntityTypeIndex.Index];
					val.id = list2.Count;
					planet.entityPool[val.entityId].inserterId = val.id;
					list2.Add(val);
				}
			}
			factory.SetInserterCapacity(list2.Count);
			list2.CopyTo(factory.inserterPool);
			factory.inserterCursor = factory.inserterPool.Length;
			factory.inserterRecycleCursor = 0;
		}

		private static void InserterLinearAccessToAssemblers(PlanetFactory planet, FactorySystem factory)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: 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)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_019a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0205: Unknown result type (might be due to invalid IL or missing references)
			//IL_0211: Unknown result type (might be due to invalid IL or missing references)
			//IL_021e: Unknown result type (might be due to invalid IL or missing references)
			List<Graph> source = Graphifier.ToInserterGraphs(factory);
			AssemblerComponent[] assemblerPool = factory.assemblerPool;
			List<AssemblerComponent> list = new List<AssemblerComponent>
			{
				new AssemblerComponent
				{
					id = 0
				}
			};
			HashSet<int> hashSet = new HashSet<int>();
			foreach (Node item in from x in source.SelectMany((Graph x) => x.GetAllNodes())
				where x.EntityTypeIndex.EntityType == EntityType.Inserter
				orderby x.EntityTypeIndex.Index
				select x)
			{
				ref InserterComponent reference = ref factory.inserterPool[item.EntityTypeIndex.Index];
				if (reference.pickTarget != 0)
				{
					int assemblerId = planet.entityPool[reference.pickTarget].assemblerId;
					if (assemblerId != 0 && hashSet.Add(reference.pickTarget))
					{
						AssemblerComponent val = assemblerPool[assemblerId];
						val.id = list.Count;
						planet.entityPool[reference.pickTarget].assemblerId = val.id;
						list.Add(val);
					}
				}
				if (reference.insertTarget != 0)
				{
					int assemblerId2 = planet.entityPool[reference.insertTarget].assemblerId;
					if (assemblerId2 != 0 && hashSet.Add(reference.insertTarget))
					{
						AssemblerComponent val2 = assemblerPool[assemblerId2];
						val2.id = list.Count;
						planet.entityPool[reference.insertTarget].assemblerId = val2.id;
						list.Add(val2);
					}
				}
			}
			for (int i = 1; i < factory.assemblerCursor; i++)
			{
				if (!hashSet.Contains(i) && assemblerPool[i].id == i)
				{
					AssemblerComponent val3 = assemblerPool[i];
					val3.id = list.Count;
					planet.entityPool[val3.entityId].assemblerId = val3.id;
					list.Add(val3);
				}
			}
			factory.SetAssemblerCapacity(list.Count);
			list.CopyTo(factory.assemblerPool);
			factory.assemblerCursor = factory.assemblerPool.Length;
			factory.assemblerRecycleCursor = 0;
		}

		private static void InserterLinearAccessToAssemblerEntities(PlanetFactory planet, FactorySystem factory, PowerSystem power, HashSystem hashSystem)
		{
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_020d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0212: Unknown result type (might be due to invalid IL or missing references)
			//IL_0225: Unknown result type (might be due to invalid IL or missing references)
			//IL_022e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0230: Unknown result type (might be due to invalid IL or missing references)
			//IL_0244: Unknown result type (might be due to invalid IL or missing references)
			//IL_0252: Unknown result type (might be due to invalid IL or missing references)
			//IL_025e: Unknown result type (might be due to invalid IL or missing references)
			//IL_026d: Unknown result type (might be due to invalid IL or missing references)
			EntityData[] entityPool = planet.entityPool;
			AnimData[] entityAnimPool = planet.entityAnimPool;
			SignData[] entitySignPool = planet.entitySignPool;
			int[] oldEntityConnPool = planet.entityConnPool;
			Mutex[] entityMutexs = planet.entityMutexs;
			int[][] entityNeeds = planet.entityNeeds;
			List<EntityData> list = new List<EntityData>();
			List<AnimData> list2 = new List<AnimData>();
			List<SignData> list3 = new List<SignData>();
			List<int> list4 = new List<int>();
			List<Mutex> list5 = new List<Mutex>();
			List<int[]> list6 = new List<int[]>();
			list.Add(default(EntityData));
			list2.Add(default(AnimData));
			list3.Add(default(SignData));
			list4.AddRange(Enumerable.Repeat(0, 16));
			list5.Add(null);
			list6.Add(null);
			HashSet<int> hashSet = new HashSet<int>();
			for (int i = 1; i < factory.assemblerCursor; i++)
			{
				ref AssemblerComponent reference = ref factory.assemblerPool[i];
				if (reference.id == i)
				{
					hashSet.Add(reference.entityId);
				}
			}
			for (int j = 1; j < planet.entityCursor; j++)
			{
				if (hashSet.Contains(j))
				{
					list.Add(default(EntityData));
					list2.Add(default(AnimData));
					list3.Add(default(SignData));
					list4.AddRange(Enumerable.Repeat(0, 16));
					list5.Add(null);
					list6.Add(null);
					continue;
				}
				list.Add(entityPool[j]);
				list2.Add(entityAnimPool[j]);
				list3.Add(entitySignPool[j]);
				list4.AddRange(from x in Enumerable.Range(j, 16)
					select oldEntityConnPool[x]);
				list5.Add(entityMutexs[j]);
				list6.Add(entityNeeds[j]);
			}
			Dictionary<int, int> dictionary = new Dictionary<int, int>();
			for (int k = 1; k < planet.entityCursor; k++)
			{
				if (hashSet.Contains(k))
				{
					EntityData val = entityPool[k];
					val.id = list.Count;
					val.hashAddress = hashSystem.UpdateObjectHashAddress(val.hashAddress, k, val.pos, (EObjectType)0);
					dictionary.Add(k, val.id);
					list.Add(val);
					list2.Add(entityAnimPool[k]);
					list3.Add(entitySignPool[k]);
					list4.AddRange(from x in Enumerable.Range(k, 16)
						select oldEntityConnPool[x]);
					list5.Add(entityMutexs[k]);
					list6.Add(entityNeeds[k]);
				}
			}
			for (int l = 1; l < factory.assemblerCursor; l++)
			{
				ref AssemblerComponent reference2 = ref factory.assemblerPool[l];
				if (reference2.id == l)
				{
					reference2.entityId = dictionary[reference2.entityId];
					list6[reference2.entityId] = reference2.needs;
				}
			}
			for (int m = 1; m < factory.inserterCursor; m++)
			{
				ref InserterComponent reference3 = ref factory.inserterPool[m];
				if (reference3.id != m)
				{
					continue;
				}
				if (reference3.pickTarget != 0)
				{
					if (planet.entityPool[reference3.pickTarget].assemblerId == 0)
					{
						continue;
					}
					reference3.pickTarget = dictionary[reference3.pickTarget];
				}
				if (reference3.insertTarget != 0 && planet.entityPool[reference3.insertTarget].assemblerId != 0)
				{
					reference3.insertTarget = dictionary[reference3.insertTarget];
				}
			}
			for (int n = 1; n < factory.minerCursor; n++)
			{
				ref MinerComponent reference4 = ref factory.minerPool[n];
				if (reference4.id == n && dictionary.TryGetValue(reference4.insertTarget, out var value))
				{
					reference4.insertTarget = value;
				}
			}
			int entityCapacity = Math.Max(planet.entityCapacity, list.Count);
			int count = list.Count;
			planet.SetEntityCapacity(entityCapacity);
			list.CopyTo(planet.entityPool);
			list2.CopyTo(planet.entityAnimPool);
			list3.CopyTo(planet.entitySignPool);
			list4.CopyTo(planet.entityConnPool);
			list5.CopyTo(planet.entityMutexs);
			list6.CopyTo(planet.entityNeeds);
			planet.entityCursor = count;
			planet.entityRecycleCursor = 0;
			foreach (KeyValuePair<int, int> item in dictionary)
			{
				planet.HandleObjectConnChangeWhenBuild(item.Key, item.Value);
			}
		}

		private static void InserterLinearAccessToPowerConsumers(PlanetFactory planet, FactorySystem factory, PowerSystem power, CargoTraffic cargoTraffic, PlanetTransport transport, DefenseSystem defenseSystem, DigitalSystem digitalSystem)
		{
			//IL_05f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0605: Unknown result type (might be due to invalid IL or missing references)
			//IL_069a: Unknown result type (might be due to invalid IL or missing references)
			//IL_069f: Unknown result type (might be due to invalid IL or missing references)
			//IL_06b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_06c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_06cd: Unknown result type (might be due to invalid IL or missing references)
			List<EntityIndexAndPowerIndex> list = new List<EntityIndexAndPowerIndex>();
			for (int i = 1; i < cargoTraffic.monitorCursor; i++)
			{
				ref MonitorComponent reference = ref cargoTraffic.monitorPool[i];
				if (reference.id == i && reference.pcId != 0)
				{
					list.Add(new EntityIndexAndPowerIndex(EntityType.Monitor, i, reference.pcId));
				}
			}
			for (int j = 1; j < cargoTraffic.spraycoaterCursor; j++)
			{
				ref SpraycoaterComponent reference2 = ref cargoTraffic.spraycoaterPool[j];
				if (reference2.id == j && reference2.pcId != 0)
				{
					list.Add(new EntityIndexAndPowerIndex(EntityType.SprayCoater, j, reference2.pcId));
				}
			}
			for (int k = 1; k < cargoTraffic.pilerCursor; k++)
			{
				ref PilerComponent reference3 = ref cargoTraffic.pilerPool[k];
				if (reference3.id == k && reference3.pcId != 0)
				{
					list.Add(new EntityIndexAndPowerIndex(EntityType.Piler, k, reference3.pcId));
				}
			}
			for (int l = 1; l < factory.minerCursor; l++)
			{
				ref MinerComponent reference4 = ref factory.minerPool[l];
				if (reference4.id == l && reference4.pcId != 0)
				{
					list.Add(new EntityIndexAndPowerIndex(EntityType.Miner, l, reference4.pcId));
				}
			}
			for (int m = 1; m < factory.inserterCursor; m++)
			{
				ref InserterComponent reference5 = ref factory.inserterPool[m];
				if (reference5.id == m && reference5.pcId != 0)
				{
					list.Add(new EntityIndexAndPowerIndex(EntityType.Inserter, m, reference5.pcId));
				}
			}
			for (int n = 1; n < factory.assemblerCursor; n++)
			{
				ref AssemblerComponent reference6 = ref factory.assemblerPool[n];
				if (reference6.id == n && reference6.pcId != 0)
				{
					list.Add(new EntityIndexAndPowerIndex(EntityType.Assembler, n, reference6.pcId));
				}
			}
			for (int num = 1; num < factory.fractionatorCursor; num++)
			{
				ref FractionatorComponent reference7 = ref factory.fractionatorPool[num];
				if (reference7.id == num && reference7.pcId != 0)
				{
					list.Add(new EntityIndexAndPowerIndex(EntityType.Fractionator, num, reference7.pcId));
				}
			}
			for (int num2 = 1; num2 < factory.ejectorCursor; num2++)
			{
				ref EjectorComponent reference8 = ref factory.ejectorPool[num2];
				if (reference8.id == num2 && reference8.pcId != 0)
				{
					list.Add(new EntityIndexAndPowerIndex(EntityType.Ejector, num2, reference8.pcId));
				}
			}
			for (int num3 = 1; num3 < factory.siloCursor; num3++)
			{
				ref SiloComponent reference9 = ref factory.siloPool[num3];
				if (reference9.id == num3 && reference9.pcId != 0)
				{
					list.Add(new EntityIndexAndPowerIndex(EntityType.Silo, num3, reference9.pcId));
				}
			}
			for (int num4 = 1; num4 < factory.labCursor; num4++)
			{
				ref LabComponent reference10 = ref factory.labPool[num4];
				if (reference10.id == num4 && reference10.pcId != 0)
				{
					list.Add(new EntityIndexAndPowerIndex(reference10.researchMode ? EntityType.ResearchingLab : EntityType.ProducingLab, num4, reference10.pcId));
				}
			}
			for (int num5 = 1; num5 < transport.stationCursor; num5++)
			{
				StationComponent val = transport.stationPool[num5];
				if (val != null && val.id == num5 && val.pcId != 0)
				{
					list.Add(new EntityIndexAndPowerIndex(EntityType.Station, num5, val.pcId));
				}
			}
			for (int num6 = 1; num6 < transport.dispenserCursor; num6++)
			{
				DispenserComponent val2 = transport.dispenserPool[num6];
				if (val2 != null && val2.id == num6 && val2.pcId != 0)
				{
					list.Add(new EntityIndexAndPowerIndex(EntityType.Dispenser, num6, val2.pcId));
				}
			}
			for (int num7 = 1; num7 < digitalSystem.markers.cursor; num7++)
			{
				MarkerComponent val3 = digitalSystem.markers.buffer[num7];
				if (val3 != null && val3.id == num7 && val3.pcId != 0)
				{
					list.Add(new EntityIndexAndPowerIndex(EntityType.Marker, num7, val3.pcId));
				}
			}
			for (int num8 = 1; num8 < defenseSystem.turrets.cursor; num8++)
			{
				ref TurretComponent reference11 = ref defenseSystem.turrets.buffer[num8];
				if (reference11.id == num8 && reference11.pcId != 0)
				{
					list.Add(new EntityIndexAndPowerIndex(EntityType.Turret, num8, reference11.pcId));
				}
			}
			for (int num9 = 1; num9 < defenseSystem.fieldGenerators.cursor; num9++)
			{
				ref FieldGeneratorComponent reference12 = ref defenseSystem.fieldGenerators.buffer[num9];
				if (reference12.id == num9 && reference12.pcId != 0)
				{
					list.Add(new EntityIndexAndPowerIndex(EntityType.FieldGenerator, num9, reference12.pcId));
				}
			}
			for (int num10 = 1; num10 < defenseSystem.battleBases.cursor; num10++)
			{
				BattleBaseComponent val4 = defenseSystem.battleBases.buffer[num10];
				if (val4 != null && val4.id == num10 && val4.pcId != 0)
				{
					list.Add(new EntityIndexAndPowerIndex(EntityType.BattleBase, num10, val4.pcId));
				}
			}
			HashSet<int> hashSet = new HashSet<int>();
			for (int num11 = 1; num11 < power.consumerCursor; num11++)
			{
				if (power.consumerPool[num11].id == num11)
				{
					hashSet.Add(num11);
				}
			}
			if (!hashSet.SetEquals(new HashSet<int>(list.Select((EntityIndexAndPowerIndex x) => x.PowerConsumerIndex))))
			{
				throw new InvalidOperationException($"Failed to gather all power consuming entities.\r\nExpected: {hashSet.Count:N0}\r\nActual: {new HashSet<int>(list.Select((EntityIndexAndPowerIndex x) => x.PowerConsumerIndex)).Count:N0}\r\n{list.First()}");
			}
			PowerConsumerComponent[] consumerPool = power.consumerPool;
			List<PowerConsumerComponent> list2 = new List<PowerConsumerComponent>();
			list2.Add(new PowerConsumerComponent
			{
				id = 0
			});
			Dictionary<int, int> dictionary = new Dictionary<int, int>();
			foreach (EntityIndexAndPowerIndex item in (from x in list
				group x by x.EntityType).SelectMany((IGrouping<EntityType, EntityIndexAndPowerIndex> x) => x.OrderBy((EntityIndexAndPowerIndex y) => y.EntityIndex)))
			{
				if (!dictionary.ContainsKey(item.PowerConsumerIndex))
				{
					dictionary.Add(item.PowerConsumerIndex, list2.Count);
					PowerConsumerComponent val5 = consumerPool[item.PowerConsumerIndex];
					val5.id = list2.Count;
					planet.entityPool[val5.entityId].powerConId = val5.id;
					list2.Add(val5);
				}
			}
			power.SetConsumerCapacity(list2.Count);
			list2.CopyTo(power.consumerPool);
			power.consumerCursor = power.consumerPool.Length;
			power.consumerRecycleCursor = 0;
			for (int num12 = 1; num12 < cargoTraffic.monitorCursor; num12++)
			{
				ref MonitorComponent reference13 = ref cargoTraffic.monitorPool[num12];
				if (reference13.id == num12 && reference13.pcId != 0)
				{
					reference13.pcId = dictionary[reference13.pcId];
				}
			}
			for (int num13 = 1; num13 < cargoTraffic.spraycoaterCursor; num13++)
			{
				ref SpraycoaterComponent reference14 = ref cargoTraffic.spraycoaterPool[num13];
				if (reference14.id == num13 && reference14.pcId != 0)
				{
					reference14.pcId = dictionary[reference14.pcId];
				}
			}
			for (int num14 = 1; num14 < cargoTraffic.pilerCursor; num14++)
			{
				ref PilerComponent reference15 = ref cargoTraffic.pilerPool[num14];
				if (reference15.id == num14 && reference15.pcId != 0)
				{
					reference15.pcId = dictionary[reference15.pcId];
				}
			}
			for (int num15 = 1; num15 < cargoTraffic.pilerCursor; num15++)
			{
				ref PilerComponent reference16 = ref cargoTraffic.pilerPool[num15];
				if (reference16.id == num15 && reference16.pcId != 0)
				{
					reference16.pcId = dictionary[reference16.pcId];
				}
			}
			for (int num16 = 1; num16 < factory.minerCursor; num16++)
			{
				ref MinerComponent reference17 = ref factory.minerPool[num16];
				if (reference17.id == num16 && reference17.pcId != 0)
				{
					reference17.pcId = dictionary[reference17.pcId];
				}
			}
			for (int num17 = 1; num17 < factory.inserterCursor; num17++)
			{
				ref InserterComponent reference18 = ref factory.inserterPool[num17];
				if (reference18.id == num17 && reference18.pcId != 0)
				{
					reference18.pcId = dictionary[reference18.pcId];
				}
			}
			for (int num18 = 1; num18 < factory.assemblerCursor; num18++)
			{
				ref AssemblerComponent reference19 = ref factory.assemblerPool[num18];
				if (reference19.id == num18 && reference19.pcId != 0)
				{
					reference19.pcId = dictionary[reference19.pcId];
				}
			}
			for (int num19 = 1; num19 < factory.fractionatorCursor; num19++)
			{
				ref FractionatorComponent reference20 = ref factory.fractionatorPool[num19];
				if (reference20.id == num19 && reference20.pcId != 0)
				{
					reference20.pcId = dictionary[reference20.pcId];
				}
			}
			for (int num20 = 1; num20 < factory.ejectorCursor; num20++)
			{
				ref EjectorComponent reference21 = ref factory.ejectorPool[num20];
				if (reference21.id == num20 && reference21.pcId != 0)
				{
					reference21.pcId = dictionary[reference21.pcId];
				}
			}
			for (int num21 = 1; num21 < factory.siloCursor; num21++)
			{
				ref SiloComponent reference22 = ref factory.siloPool[num21];
				if (reference22.id == num21 && reference22.pcId != 0)
				{
					reference22.pcId = dictionary[reference22.pcId];
				}
			}
			for (int num22 = 1; num22 < factory.labCursor; num22++)
			{
				ref LabComponent reference23 = ref factory.labPool[num22];
				if (reference23.id == num22 && reference23.pcId != 0)
				{
					reference23.pcId = dictionary[reference23.pcId];
				}
			}
			for (int num23 = 1; num23 < transport.stationCursor; num23++)
			{
				StationComponent val6 = transport.stationPool[num23];
				if (val6 != null && val6.id == num23 && val6.pcId != 0)
				{
					val6.pcId = dictionary[val6.pcId];
				}
			}
			for (int num24 = 1; num24 < transport.dispenserCursor; num24++)
			{
				DispenserComponent val7 = transport.dispenserPool[num24];
				if (val7 != null && val7.id == num24 && val7.pcId != 0)
				{
					val7.pcId = dictionary[val7.pcId];
				}
			}
			for (int num25 = 1; num25 < digitalSystem.markers.cursor; num25++)
			{
				MarkerComponent val8 = digitalSystem.markers.buffer[num25];
				if (val8 != null && val8.id == num25 && val8.pcId != 0)
				{
					val8.pcId = dictionary[val8.pcId];
				}
			}
			for (int num26 = 1; num26 < defenseSystem.turrets.cursor; num26++)
			{
				ref TurretComponent reference24 = ref defenseSystem.turrets.buffer[num26];
				if (reference24.id == num26 && reference24.pcId != 0)
				{
					reference24.pcId = dictionary[reference24.pcId];
				}
			}
			for (int num27 = 1; num27 < defenseSystem.fieldGenerators.cursor; num27++)
			{
				ref FieldGeneratorComponent reference25 = ref defenseSystem.fieldGenerators.buffer[num27];
				if (reference25.id == num27 && reference25.pcId != 0)
				{
					reference25.pcId = dictionary[reference25.pcId];
				}
			}
			for (int num28 = 1; num28 < defenseSystem.battleBases.cursor; num28++)
			{
				BattleBaseComponent val9 = defenseSystem.battleBases.buffer[num28];
				if (val9 != null && val9.id == num28 && val9.pcId != 0)
				{
					val9.pcId = dictionary[val9.pcId];
				}
			}
			for (int num29 = 1; num29 < power.netCursor; num29++)
			{
				if (power.netPool[num29] == null || power.netPool[num29].id == 0)
				{
					continue;
				}
				PowerNetwork val10 = power.netPool[num29];
				foreach (Node node in val10.nodes)
				{
					for (int num30 = 0; num30 < node.consumers.Count; num30++)
					{
						if (dictionary.TryGetValue(node.consumers[num30], out var value))
						{
							node.consumers[num30] = value;
						}
					}
					node.consumers.Sort();
				}
				for (int num31 = 0; num31 < val10.consumers.Count; num31++)
				{
					if (dictionary.TryGetValue(val10.consumers[num31], out var value2))
					{
						val10.consumers[num31] = value2;
					}
				}
				val10.consumers.Sort();
			}
		}
	}
	internal struct NetworkIdAndState<T> where T : Enum
	{
		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)
		{
			_value = (uint)((state << 24) | index);
		}
	}
	internal sealed class OptimizedPlanet
	{
		private readonly PlanetFactory _planet;

		private readonly StarClusterResearchManager _starClusterResearchManager;

		public InserterExecutor<OptimizedBiInserter> _optimizedBiInserterExecutor;

		public InserterExecutor<OptimizedInserter> _optimizedInserterExecutor;

		public AssemblerExecutor _assemblerExecutor;

		private int[] _minerNetworkIds;

		private int[] _ejectorNetworkIds;

		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 SpraycoaterExecutor _spraycoaterExecutor;

		public FractionatorExecutor _fractionatorExecutor;

		public OptimizedPowerSystem _optimizedPowerSystem;

		private WorkTracker[] _workTrackers;

		private int _workTrackersParallelism;

		public OptimizedPlanetStatus Status { get; private set; } = OptimizedPlanetStatus.Stopped;


		public int OptimizeDelayInTicks { get; set; }

		public OptimizedPlanet(PlanetFactory planet, StarClusterResearchManager starClusterResearchManager)
		{
			_planet = planet;
			_starClusterResearchManager = starClusterResearchManager;
		}

		public void Save()
		{
			_optimizedBiInserterExecutor.Save(_planet);
			_optimizedInserterExecutor.Save(_planet);
			_assemblerExecutor.Save(_planet);
			_producingLabExecutor.Save(_planet);
			_researchingLabExecutor.Save(_planet);
			_spraycoaterExecutor.Save(_planet);
			_fractionatorExecutor.Save(_planet);
			Status = OptimizedPlanetStatus.Stopped;
			_workTrackers = null;
			_workTrackersParallelism = -1;
		}

		public void Initialize()
		{
			OptimizedPowerSystemBuilder optimizedPowerSystemBuilder = new OptimizedPowerSystemBuilder(_planet.powerSystem);
			InitializeAssemblers(_planet, optimizedPowerSystemBuilder);
			InitializeMiners(_planet);
			InitializeEjectors(_planet);
			InitializeLabAssemblers(_planet, optimizedPowerSystemBuilder);
			InitializeResearchingLabs(_planet, optimizedPowerSystemBuilder);
			InitializeInserters(_planet, optimizedPowerSystemBuilder);
			InitializeSpraycoaters(_planet, optimizedPowerSystemBuilder);
			InitializeFractionators(_planet, optimizedPowerSystemBuilder);
			_optimizedPowerSystem = optimizedPowerSystemBuilder.Build();
			Status = OptimizedPlanetStatus.Running;
			_workTrackers = null;
			_workTrackersParallelism = -1;
		}

		private void InitializeInserters(PlanetFactory planet, OptimizedPowerSystemBuilder optimizedPowerSystemBuilder)
		{
			_optimizedBiInserterExecutor = new InserterExecutor<OptimizedBiInserter>(_assemblerExecutor._assemblerNetworkIdAndStates, _producingLabNetworkIdAndStates, _researchingLabNetworkIdAndStates);
			_optimizedBiInserterExecutor.Initialize(planet, this, (InserterComponent x) => x.bidirectional, optimizedPowerSystemBuilder.CreateBiInserterBuilder());
			_optimizedInserterExecutor = new InserterExecutor<OptimizedInserter>(_assemblerExecutor._assemblerNetworkIdAndStates, _producingLabNetworkIdAndStates, _researchingLabNetworkIdAndStates);
			_optimizedInserterExecutor.Initialize(planet, this, (InserterComponent x) => !x.bidirectional, optimizedPowerSystemBuilder.CreateInserterBuilder());
		}

		private void InitializeAssemblers(PlanetFactory planet, OptimizedPowerSystemBuilder optimizedPowerSystemBuilder)
		{
			_assemblerExecutor = new AssemblerExecutor();
			_assemblerExecutor.InitializeAssemblers(planet, optimizedPowerSystemBuilder);
		}

		private void InitializeMiners(PlanetFactory planet)
		{
			int[] array = new int[planet.factorySystem.minerCursor];
			for (int i = 0; i < planet.factorySystem.minerCursor; i++)
			{
				ref MinerComponent reference = ref planet.factorySystem.minerPool[i];
				if (reference.id == i)
				{
					array[i] = planet.powerSystem.consumerPool[reference.pcId].networkId;
				}
			}
			_minerNetworkIds = array;
		}

		private void InitializeEjectors(PlanetFactory planet)
		{
			int[] array = new int[planet.factorySystem.ejectorCursor];
			for (int i = 0; i < planet.factorySystem.ejectorCursor; i++)
			{
				ref EjectorComponent reference = ref planet.factorySystem.ejectorPool[i];
				if (reference.id == i)
				{
					array[i] = planet.powerSystem.consumerPool[reference.pcId].networkId;
					ref int[] needs = ref reference.needs;
					if (needs == null)
					{
						needs = new int[6];
					}
					planet.entityNeeds[reference.entityId] = reference.needs;
				}
			}
			_ejectorNetworkIds = array;
		}

		private void InitializeLabAssemblers(PlanetFactory planet, OptimizedPowerSystemBuilder optimizedPowerSystemBuilder)
		{
			_producingLabExecutor = new ProducingLabExecutor();
			_producingLabExecutor.Initialize(planet, optimizedPowerSystemBuilder);
			_producingLabNetworkIdAndStates = _producingLabExecutor._networkIdAndStates;
			_optimizedProducingLabs = _producingLabExecutor._optimizedLabs;
			_producingLabRecipes = _producingLabExecutor._producingLabRecipes;
			_producingLabIdToOptimizedIndex = _producingLabExecutor._labIdToOptimizedLabIndex;
		}

		private void InitializeResearchingLabs(PlanetFactory planet, OptimizedPowerSystemBuilder optimizedPowerSystemBuilder)
		{
			_researchingLabExecutor = new ResearchingLabExecutor(_starClusterResearchManager);
			_researchingLabExecutor.Initialize(planet, optimizedPowerSystemBuilder);
			_researchingLabNetworkIdAndStates = _researchingLabExecutor._networkIdAndStates;
			_optimizedResearchingLabs = _researchingLabExecutor._optimizedLabs;
			_researchingLabIdToOptimizedIndex = _researchingLabExecutor._labIdToOptimizedLabIndex;
		}

		private void InitializeSpraycoaters(PlanetFactory planet, OptimizedPowerSystemBuilder optimizedPowerSystemBuilder)
		{
			_spraycoaterExecutor = new SpraycoaterExecutor();
			_spraycoaterExecutor.Initialize(planet, optimizedPowerSystemBuilder);
		}

		private void InitializeFractionators(PlanetFactory planet, OptimizedPowerSystemBuilder optimizedPowerSystemBuilder)
		{
			_fractionatorExecutor = new FractionatorExecutor();
			_fractionatorExecutor.Initialize(planet, optimizedPowerSystemBuilder);
		}

		public void GameTick(PlanetFactory planet, long time, int _usedThreadCnt, int _curThreadIdx, int _minimumMissionCnt)
		{
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Invalid comparison between Unknown and I4
			GameHistoryData history = GameMain.history;
			FactoryProductionStat obj = GameMain.statistics.production.factoryStatPool[planet.index];
			int[] productRegister = obj.productRegister;
			int[] consumeRegister = obj.consumeRegister;
			PowerSystem powerSystem = planet.powerSystem;
			float[] networkServes = powerSystem.networkServes;
			_ = planet.entityPool;
			VeinData[] veinPool = planet.veinPool;
			AnimData[] entityAnimPool = planet.entityAnimPool;
			SignData[] entitySignPool = planet.entitySignPool;
			int[][] entityNeeds = planet.entityNeeds;
			FactorySystem factorySystem = planet.factorySystem;
			PowerConsumerComponent[] consumerPool = powerSystem.consumerPool;
			AstroData[] array = null;
			int num = default(int);
			int num2 = default(int);
			if (WorkerThreadExecutor.CalculateMissionIndex(1, factorySystem.minerCursor - 1, _usedThreadCnt, _curThreadIdx, _minimumMissionCnt, ref num, ref num2))
			{
				float num3;
				float num4 = (num3 = planet.gameData.gameDesc.resourceMultiplier);
				if (num3 < 5f / 12f)
				{
					num3 = 5f / 12f;
				}
				float num5 = history.miningCostRate;
				float miningSpeedScale = history.miningSpeedScale;
				float num6 = history.miningCostRate * 0.40111667f / num3;
				if (num4 > 99.5f)
				{
					num5 = 0f;
					num6 = 0f;
				}
				int[] minerNetworkIds = _minerNetworkIds;
				MinerComponent.InsufficientWarningThresAmount(num4, num5);
				for (int i = num; i < num2; i++)
				{
					if (factorySystem.minerPool[i].id == i)
					{
						float num7 = networkServes[minerNetworkIds[i]];
						((MinerComponent)(ref factorySystem.minerPool[i])).InternalUpdate(planet, veinPool, num7, ((int)factorySystem.minerPool[i].type == 3) ? num6 : num5, miningSpeedScale, productRegister);
					}
				}
			}
			_assemblerExecutor.GameTick(planet, time, _usedThreadCnt, _curThreadIdx, _minimumMissionCnt);
			_fractionatorExecutor.GameTick(planet, time, _usedThreadCnt, _curThreadIdx, _minimumMissionCnt);
			lock (factorySystem.ejectorPool)
			{
				if (factorySystem.ejectorCursor - factorySystem.ejectorRecycleCursor > 1)
				{
					array = factorySystem.planet.galaxy.astrosData;
				}
			}
			DysonSwarm val = null;
			if (factorySystem.factory.dysonSphere != null)
			{
				val = factorySystem.factory.dysonSphere.swarm;
			}
			if (WorkerThreadExecutor.CalculateMissionIndex(1, factorySystem.ejectorCursor - 1, _usedThreadCnt, _curThreadIdx, _minimumMissionCnt, ref num, ref num2))
			{
				int[] ejectorNetworkIds = _ejectorNetworkIds;
				for (int j = num; j < num2; j++)
				{
					if (factorySystem.ejectorPool[j].id == j)
					{
						float num8 = networkServes[ejectorNetworkIds[j]];
						((EjectorComponent)(ref factorySystem.ejectorPool[j])).InternalUpdate(num8, time, val, array, entityAnimPool, consumeRegister);
					}
				}
			}
			lock (factorySystem.siloPool)
			{
				if (factorySystem.siloCursor - factorySystem.siloRecycleCursor > 1)
				{
					array = factorySystem.planet.galaxy.astrosData;
				}
			}
			DysonSphere dysonSphere = factorySystem.factory.dysonSphere;
			bool flag = dysonSphere != null && dysonSphere.autoNodeCount > 0;
			if (!WorkerThreadExecutor.CalculateMissionIndex(1, factorySystem.siloCursor - 1, _usedThreadCnt, _curThreadIdx, _minimumMissionCnt, ref num, ref num2))
			{
				return;
			}
			for (int k = num; k < num2; k++)
			{
				if (factorySystem.siloPool[k].id == k)
				{
					int entityId = factorySystem.siloPool[k].entityId;
					uint num9 = 0u;
					float num10 = networkServes[consumerPool[factorySystem.siloPool[k].pcId].networkId];
					num9 = ((SiloComponent)(ref factorySystem.siloPool[k])).InternalUpdate(num10, dysonSphere, entityAnimPool, consumeRegister);
					entityAnimPool[entityId].state = num9;
					entityNeeds[entityId] = factorySystem.siloPool[k].needs;
					if (entitySignPool[entityId].signType == 0 || entitySignPool[entityId].signType > 3)
					{
						entitySignPool[entityId].signType = ((!flag) ? 9u : 0u);
					}
				}
			}
		}

		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 WorkTracker[] GetMultithreadedWork(int maxParallelism)
		{
			if (_workTrackersParallelism != maxParallelism)
			{
				_workTrackers = CreateMultithreadedWork(maxParallelism);
				_workTrackersParallelism = maxParallelism;
			}
			return _workTrackers;
		}

		private WorkTracker[] CreateMultithreadedWork(int maxParallelism)
		{
			List<WorkTracker> list = new List<WorkTracker>();
			int minerCursor = _planet.factorySystem.minerCursor;
			int num = ((Status == OptimizedPlanetStatus.Running) ? _assemblerExecutor.AssemblerCount : _planet.factorySystem.assemblerCursor);
			int num2 = ((Status == OptimizedPlanetStatus.Running) ? _fractionatorExecutor.FractionatorCount : _planet.factorySystem.fractionatorCursor);
			int ejectorCursor = _planet.factorySystem.ejectorCursor;
			int siloCursor = _planet.factorySystem.siloCursor;
			int monitorCursor = _planet.cargoTraffic.monitorCursor;
			int num3 = ((Status == OptimizedPlanetStatus.Running) ? _spraycoaterExecutor.SpraycoaterCount : _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 num4 = 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 num5 = ((Status == OptimizedPlanetStatus.Running) ? (_optimizedBiInserterExecutor.InserterCount + _optimizedInserterExecutor.InserterCount) : _planet.factorySystem.inserterCursor);
			int num6 = ((Status == OptimizedPlanetStatus.Running) ? _producingLabExecutor.ProducingLabCount : _planet.factorySystem.labCursor);
			int num7 = ((Status == OptimizedPlanetStatus.Running) ? _researchingLabExecutor.ResearchingLabCount : _planet.factorySystem.labCursor);
			int num8 = ((Status == OptimizedPlanetStatus.Running) ? (num6 + num7) : _planet.factorySystem.labCursor);
			int storageCursor = _planet.factoryStorage.storageCursor;
			int tankCursor = _planet.factoryStorage.tankCursor;
			int val = (minerCursor + num + num2 + ejectorCursor + siloCursor + monitorCursor + num3 + pilerCursor + stationCursor + dispenserCursor + cursor + cursor2 + cursor3 + cursor4 + 4999) / 5000;
			val = Math.Min(val, maxParallelism);
			if (val > 0)
			{
				list.Add(new WorkTracker(WorkType.BeforePower, val));
			}
			if (_planet.powerSystem.netCursor > 0)
			{
				list.Add(new WorkTracker(WorkType.Power, 1));
			}
			list.Add(new WorkTracker(WorkType.Construction, 1));
			list.Add(new WorkTracker(WorkType.CheckBefore, 1));
			int val2 = (minerCursor + num + num2 + ejectorCursor + siloCursor + num6 + 4999) / 5000;
			val2 = Math.Min(val2, maxParallelism);
			if (val2 > 0)
			{
				list.Add(new WorkTracker(WorkType.Assembler, val2));
			}
			if (num7 > 0)
			{
				list.Add(new WorkTracker(WorkType.LabResearchMode, 1));
			}
			int val3 = (num8 + 4999) / 5000;
			val3 = Math.Min(val3, maxParallelism);
			if (val3 > 0)
			{
				list.Add(new WorkTracker(WorkType.LabOutput2NextData, val3));
			}
			if (num4 > 0)
			{
				list.Add(new WorkTracker(WorkType.TransportData, 1));
			}
			if (stationCursor > 0)
			{
				list.Add(new WorkTracker(WorkType.InputFromBelt, 1));
			}
			int val4 = (num5 + 4999) / 5000;
			val4 = Math.Min(val4, maxParallelism);
			if (val4 > 0)
			{
				list.Add(new WorkTracker(WorkType.InserterData, val4));
			}
			if (storageCursor + tankCursor > 0)
			{
				list.Add(new WorkTracker(WorkType.Storage, 1));
			}
			int val5 = (pathCursor + 4999) / 5000;
			val5 = Math.Min(val5, maxParallelism);
			if (val5 > 0)
			{
				list.Add(new WorkTracker(WorkType.CargoPathsData, val5));
			}
			if (splitterCursor > 0)
			{
				list.Add(new WorkTracker(WorkType.Splitter, 1));
			}
			if (monitorCursor > 0)
			{
				list.Add(new WorkTracker(WorkType.Monitor, 1));
			}
			if (num3 > 0)
			{
				list.Add(new WorkTracker(WorkType.Spraycoater, 1));
			}
			if (pilerCursor > 0)
			{
				list.Add(new WorkTracker(WorkType.Piler, 1));
			}
			if (stationCursor > 0)
			{
				list.Add(new WorkTracker(WorkType.OutputToBelt, 1));
			}
			int val6 = (num4 + 4999) / 5000;
			val6 = Math.Min(val6, maxParallelism);
			if (GameMain.sandboxToolsEnabled && val6 > 0)
			{
				list.Add(new WorkTracker(WorkType.SandboxMode, val6));
			}
			int val7 = (pathCursor + 4999) / 5000;
			val7 = Math.Min(val7, maxParallelism);
			if (Status == OptimizedPlanetStatus.Stopped && val7 > 0)
			{
				list.Add(new WorkTracker(WorkType.PresentCargoPathsData, val7));
			}
			if (cursor4 > 0)
			{
				list.Add(new WorkTracker(WorkType.Digital, 1));
			}
			return list.ToArray();
		}
	}
	internal enum OptimizedPlanetStatus
	{
		Running,
		Stopped
	}
	internal static class OptimizedStarCluster
	{
		private static readonly Dictionary<PlanetFactory, OptimizedPlanet> _planetToOptimizedPlanet = new Dictionary<PlanetFactory, OptimizedPlanet>();

		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;

		public static void EnableOptimization(Harmony harmony)
		{
			harmony.PatchAll(typeof(OptimizedStarCluster));
		}

		public static OptimizedPlanet 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 OptimizedPlanet");
			_planetToOptimizedPlanet.Clear();
			_workStealingMultiThreadedFactorySimulation.Clear();
			_clearOptimizedPlanetsOnNextTick = false;
			for (int i = 0; i < GameMain.data.factoryCount; i++)
			{
				PlanetFactory val = GameMain.data.factories[i];
				if (val.factorySystem != null)
				{
					_planetToOptimizedPlanet.Add(val, new OptimizedPlanet(val, _starClusterResearchManager));
				}
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(GameSave), "SaveCurrentGame")]
		private static void SaveCurrentGame_Prefix()
		{
			WeaverFixes.Logger.LogInfo((object)"Saving optimized planets");
			foreach (KeyValuePair<PlanetFactory, OptimizedPlanet> 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));
					_planetToOptimizedPlanet.Add(val, new OptimizedPlanet(val, _starClusterResearchManager));
				}
			}
			foreach (KeyValuePair<PlanetFactory, OptimizedPlanet> 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();
				OptimizedPlanet optimizedPlanet = _planetToOptimizedPlanet[val2];
				if (optimizedPlanet.Status != OptimizedPlanetStatus.Stopped)
				{
					WeaverFixes.Logger.LogInfo((object)("DeOptimizing planet: " + val2.planet.displayName));
					optimizedPlanet.Save();
				}
			}
		}

		[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);
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(PlanetFactory), "GameTick", new Type[] { typeof(long) })]
		public static void PlanetFactory_SingleThreadedGameTick()
		{
			_starClusterResearchManager.UIThreadUnlockResearchedTechnologies(GameMain.history);
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(FactorySystem), "GameTick", new Type[]
		{
			typeof(long),
			typeof(bool),
			typeof(int),
			typeof(int),
			typeof(int)
		})]
		public static bool FactorySystem_ParallelGameTick(FactorySystem __instance, long time, bool isActive, int _usedThreadCnt, int _curThreadIdx, int _minimumMissionCnt)
		{
			OptimizedPlanet optimizedPlanet = _planetToOptimizedPlanet[__instance.factory];
			if (optimizedPlanet.Status != 0)
			{
				return true;
			}
			optimizedPlanet.GameTick(__instance.factory, time, _usedThreadCnt, _curThreadIdx, _minimumMissionCnt);
			return false;
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(FactorySystem), "GameTickLabProduceMode", new Type[]
		{
			typeof(long),
			typeof(bool),
			typeof(int),
			typeof(int),
			typeof(int)
		})]
		public static bool FactorySystem_GameTickLabProduceMode(FactorySystem __instance, long time, bool isActive, int _usedThreadCnt, int _curThreadIdx, int _minimumMissionCnt)
		{
			OptimizedPlanet optimizedPlanet = _planetToOptimizedPlanet[__instance.factory];
			if (optimizedPlanet.Status != 0)
			{
				return true;
			}
			optimizedPlanet._producingLabExecutor.GameTickLabProduceMode(__instance.factory, time, _usedThreadCnt, _curThreadIdx, _minimumMissionCnt);
			return false;
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(FactorySystem), "GameTickBeforePower")]
		public static bool FactorySystem_SingleThreadedGameTickBeforePower(FactorySystem __instance, long time, bool isActive)
		{
			return FactorySystem_ParallelGameTickBeforePower(__instance, time, isActive, 1, 0, 4);
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(FactorySystem), "ParallelGameTickBeforePower")]
		public static bool FactorySystem_ParallelGameTickBeforePower(FactorySystem __instance, long time, bool isActive, int _usedThreadCnt, int _curThreadIdx, int _minimumMissionCnt)
		{
			OptimizedPlanet optimizedPlanet = _planetToOptimizedPlanet[__instance.factory];
			if (optimizedPlanet.Status != 0)
			{
				return true;
			}
			optimizedPlanet._optimizedPowerSystem.FactorySystem_ParallelGameTickBeforePower(__instance.factory, optimizedPlanet, time, isActive, _usedThreadCnt, _curThreadIdx, _minimumMissionCnt);
			return false;
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(CargoTraffic), "GameTickBeforePower")]
		public static bool CargoTraffic_SingleThreadedGameTickBeforePower(CargoTraffic __instance, long time, bool isActive)
		{
			return CargoTraffic_ParallelGameTickBeforePower(__instance, time, isActive, 1, 0, 4);
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(CargoTraffic), "ParallelGameTickBeforePower")]
		public static bool CargoTraffic_ParallelGameTickBeforePower(CargoTraffic __instance, long time, bool isActive, int _usedThreadCnt, int _curThreadIdx, int _minimumMissionCnt)
		{
			OptimizedPlanet optimizedPlanet = _planetToOptimizedPlanet[__instance.factory];
			if (optimizedPlanet.Status != 0)
			{
				return true;
			}
			optimizedPlanet._optimizedPowerSystem.CargoTraffic_ParallelGameTickBeforePower(__instance.factory, optimizedPlanet, time, isActive, _usedThreadCnt, _curThreadIdx, _minimumMissionCnt);
			return false;
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(PowerSystem), "GameTick")]
		public static bool GameTick(PowerSystem __instance, long time, bool isActive, bool isMultithreadMode = false)
		{
			OptimizedPlanet optimizedPlanet = _planetToOptimizedPlanet[__instance.factory];
			if (optimizedPlanet.Status != 0)
			{
				return true;
			}
			optimizedPlanet._optimizedPowerSystem.GameTick(__instance.factory, time, isActive, isMultithreadMode);
			return false;
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(FactorySystem), "GameTickLabResearchMode")]
		public static bool GameTickLabResearchMode(FactorySystem __instance, long time, bool isActive)
		{
			OptimizedPlanet optimizedPlanet = _planetToOptimizedPlanet[__instance.factory];
			if (optimizedPlanet.Status != 0)
			{
				return true;
			}
			optimizedPlanet._researchingLabExecutor.GameTickLabResearchMode(__instance.factory, time);
			return false;
		}

		[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 re