Decompiled source of Weaver v1.2.0

Weaver.dll

Decompiled a day 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 UnityEngine;
using Weaver.Extensions;
using Weaver.FatoryGraphs;
using Weaver.Optimizations.LinearDataAccess;
using Weaver.Optimizations.LinearDataAccess.Assemblers;
using Weaver.Optimizations.LinearDataAccess.Belts;
using Weaver.Optimizations.LinearDataAccess.Ejectors;
using Weaver.Optimizations.LinearDataAccess.Fractionators;
using Weaver.Optimizations.LinearDataAccess.Inserters;
using Weaver.Optimizations.LinearDataAccess.Inserters.Types;
using Weaver.Optimizations.LinearDataAccess.Labs;
using Weaver.Optimizations.LinearDataAccess.Labs.Producing;
using Weaver.Optimizations.LinearDataAccess.Labs.Researching;
using Weaver.Optimizations.LinearDataAccess.Miners;
using Weaver.Optimizations.LinearDataAccess.Monitors;
using Weaver.Optimizations.LinearDataAccess.Pilers;
using Weaver.Optimizations.LinearDataAccess.PowerSystems;
using Weaver.Optimizations.LinearDataAccess.Silos;
using Weaver.Optimizations.LinearDataAccess.Splitters;
using Weaver.Optimizations.LinearDataAccess.Spraycoaters;
using Weaver.Optimizations.LinearDataAccess.Stations;
using Weaver.Optimizations.LinearDataAccess.Tanks;
using Weaver.Optimizations.LinearDataAccess.Turrets;
using Weaver.Optimizations.LinearDataAccess.WorkDistributors;
using Weaver.Optimizations.LinearDataAccess.WorkDistributors.WorkChunks;
using Weaver.Optimizations.Statistics;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("Weaver")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.0.1.0")]
[assembly: AssemblyInformationalVersion("0.0.1+7ea0b25f30c9c790756600985b087a023faa9d2c")]
[assembly: AssemblyProduct("Weaver")]
[assembly: AssemblyTitle("Weaver")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.1.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class RequiresLocationAttribute : Attribute
	{
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

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

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

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace Weaver
{
	internal static class HarmonyConstants
	{
		public const bool EXECUTE_ORIGINAL_METHOD = true;

		public const bool SKIP_ORIGINAL_METHOD = false;
	}
	public struct HashCode
	{
		private static readonly uint s_seed = 5122634u;

		private const uint Prime1 = 2654435761u;

		private const uint Prime2 = 2246822519u;

		private const uint Prime3 = 3266489917u;

		private const uint Prime4 = 668265263u;

		private const uint Prime5 = 374761393u;

		private uint _v1;

		private uint _v2;

		private uint _v3;

		private uint _v4;

		private uint _queue1;

		private uint _queue2;

		private uint _queue3;

		private uint _length;

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private static void Initialize(out uint v1, out uint v2, out uint v3, out uint v4)
		{
			v1 = (uint)((int)s_seed + -1640531535 + -2048144777);
			v2 = s_seed + 2246822519u;
			v3 = s_seed;
			v4 = s_seed - 2654435761u;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private static uint Round(uint hash, uint input)
		{
			return RotateLeft(hash + (uint)((int)input * -2048144777), 13) * 2654435761u;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private static uint QueueRound(uint hash, uint queuedValue)
		{
			return RotateLeft(hash + (uint)((int)queuedValue * -1028477379), 17) * 668265263;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private static uint MixState(uint v1, uint v2, uint v3, uint v4)
		{
			return RotateLeft(v1, 1) + RotateLeft(v2, 7) + RotateLeft(v3, 12) + RotateLeft(v4, 18);
		}

		private static uint MixEmptyState()
		{
			return s_seed + 374761393;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private static uint MixFinal(uint hash)
		{
			hash ^= hash >> 15;
			hash *= 2246822519u;
			hash ^= hash >> 13;
			hash *= 3266489917u;
			hash ^= hash >> 16;
			return hash;
		}

		public void Add<T>(T value)
		{
			Add(value?.GetHashCode() ?? 0);
		}

		public void Add<T>(T value, IEqualityComparer<T> comparer)
		{
			Add((value != null) ? (comparer?.GetHashCode(value) ?? value.GetHashCode()) : 0);
		}

		private void Add(int value)
		{
			uint num = _length++;
			switch (num % 4)
			{
			case 0u:
				_queue1 = (uint)value;
				return;
			case 1u:
				_queue2 = (uint)value;
				return;
			case 2u:
				_queue3 = (uint)value;
				return;
			}
			if (num == 3)
			{
				Initialize(out _v1, out _v2, out _v3, out _v4);
			}
			_v1 = Round(_v1, _queue1);
			_v2 = Round(_v2, _queue2);
			_v3 = Round(_v3, _queue3);
			_v4 = Round(_v4, (uint)value);
		}

		public int ToHashCode()
		{
			uint length = _length;
			uint num = length % 4;
			uint num2 = ((length < 4) ? MixEmptyState() : MixState(_v1, _v2, _v3, _v4));
			num2 += length * 4;
			if (num != 0)
			{
				num2 = QueueRound(num2, _queue1);
				if (num > 1)
				{
					num2 = QueueRound(num2, _queue2);
					if (num > 2)
					{
						num2 = QueueRound(num2, _queue3);
					}
				}
			}
			return (int)MixFinal(num2);
		}

		public static uint RotateLeft(uint value, int offset)
		{
			return (value << offset) | (value >> 32 - offset);
		}
	}
	public static class ReflectionExtensions
	{
		public static void RaiseActionEvent<T>(this T instance, string eventName)
		{
			Delegate[] array = (typeof(T).GetField(eventName, BindingFlags.Instance | BindingFlags.NonPublic).GetValue(instance) as MulticastDelegate)?.GetInvocationList();
			if (array != null && array.Length != 0)
			{
				WeaverFixes.Logger.LogInfo((object)("Raised event " + eventName));
				Delegate[] array2 = array;
				for (int i = 0; i < array2.Length; i++)
				{
					array2[i].DynamicInvoke();
				}
			}
		}
	}
	internal static class ModInfo
	{
		public const string Guid = "Weaver";

		public const string Name = "Weaver";

		public const string Version = "1.2.0";
	}
	internal static class ModDependencies
	{
		public const string SampleAndHoldSimId = "starfi5h.plugin.SampleAndHoldSim";
	}
	[BepInPlugin("Weaver", "Weaver", "1.2.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class WeaverFixes : BaseUnityPlugin
	{
		internal static ManualLogSource Logger = Logger.CreateLogSource("Weaver");

		private void Awake()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Expected O, but got Unknown
			Harmony val = new Harmony("Weaver");
			val.PatchAll(typeof(ProductionStatisticsPatches));
			val.PatchAll(typeof(KillStatisticsPatches));
			val.PatchAll(typeof(TrafficStatisticsPatches));
			OptimizedStarCluster.EnableOptimization(val);
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "Weaver";

		public const string PLUGIN_NAME = "Weaver";

		public const string PLUGIN_VERSION = "0.0.1";
	}
}
namespace Weaver.Optimizations.Statistics
{
	public class CustomChartsPatches
	{
		[HarmonyPrefix]
		[HarmonyPatch(typeof(CustomCharts), "GameTick")]
		private static bool GameTick_Parallelize(CustomCharts __instance)
		{
			if (!GameMain.multithreadSystem.multithreadSystemEnable)
			{
				return true;
			}
			new ParallelOptions().MaxDegreeOfParallelism = GameMain.multithreadSystem.usedThreadCnt;
			StatPlan[] buffer = __instance.statPlans.buffer;
			int cursor = __instance.statPlans.cursor;
			Parallel.For(1, cursor, delegate(int i)
			{
				if (buffer[i] != null && buffer[i].id == i)
				{
					buffer[i].GameTick();
				}
			});
			return false;
		}
	}
	public class KillStatisticsPatches
	{
		[HarmonyPrefix]
		[HarmonyPatch(typeof(KillStatistics), "PrepareTick")]
		private static bool PrepareTick_Parallelize(KillStatistics __instance)
		{
			if (!GameMain.multithreadSystem.multithreadSystemEnable)
			{
				return true;
			}
			ParallelOptions parallelOptions = new ParallelOptions
			{
				MaxDegreeOfParallelism = GameMain.multithreadSystem.usedThreadCnt
			};
			Parallel.ForEach(__instance.starKillStatPool, parallelOptions, delegate(AstroKillStat x)
			{
				if (x != null)
				{
					x.PrepareTick();
				}
			});
			Parallel.ForEach(__instance.factoryKillStatPool, parallelOptions, delegate(AstroKillStat x)
			{
				if (x != null)
				{
					x.PrepareTick();
				}
			});
			AstroKillStat mechaKillStat = __instance.mechaKillStat;
			if (mechaKillStat != null)
			{
				mechaKillStat.PrepareTick();
			}
			return false;
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(KillStatistics), "GameTick")]
		private static bool GameTick_Parallelize(KillStatistics __instance, long time)
		{
			if (!GameMain.multithreadSystem.multithreadSystemEnable)
			{
				return true;
			}
			ParallelOptions parallelOptions = new ParallelOptions
			{
				MaxDegreeOfParallelism = GameMain.multithreadSystem.usedThreadCnt
			};
			Parallel.ForEach(__instance.starKillStatPool, parallelOptions, delegate(AstroKillStat x)
			{
				if (x != null)
				{
					x.GameTick(time);
				}
			});
			Parallel.ForEach(__instance.factoryKillStatPool, parallelOptions, delegate(AstroKillStat x)
			{
				if (x != null)
				{
					x.GameTick(time);
				}
			});
			AstroKillStat mechaKillStat = __instance.mechaKillStat;
			if (mechaKillStat != null)
			{
				mechaKillStat.GameTick(time);
			}
			return false;
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(KillStatistics), "AfterTick")]
		private static bool AfterTick_Parallelize(KillStatistics __instance)
		{
			if (!GameMain.multithreadSystem.multithreadSystemEnable)
			{
				return true;
			}
			ParallelOptions parallelOptions = new ParallelOptions
			{
				MaxDegreeOfParallelism = GameMain.multithreadSystem.usedThreadCnt
			};
			Parallel.ForEach(__instance.starKillStatPool, parallelOptions, delegate(AstroKillStat x)
			{
				if (x != null)
				{
					x.AfterTick();
				}
			});
			Parallel.ForEach(__instance.factoryKillStatPool, parallelOptions, delegate(AstroKillStat x)
			{
				if (x != null)
				{
					x.AfterTick();
				}
			});
			AstroKillStat mechaKillStat = __instance.mechaKillStat;
			if (mechaKillStat != null)
			{
				mechaKillStat.AfterTick();
			}
			return false;
		}
	}
	public class ProductionStatisticsPatches
	{
		[HarmonyPrefix]
		[HarmonyPatch(typeof(ProductionStatistics), "PrepareTick")]
		private static bool PrepareTick_Parallelize(ProductionStatistics __instance)
		{
			if (!GameMain.multithreadSystem.multithreadSystemEnable)
			{
				return true;
			}
			ParallelOptions parallelOptions = new ParallelOptions
			{
				MaxDegreeOfParallelism = GameMain.multithreadSystem.usedThreadCnt
			};
			Parallel.For(0, __instance.gameData.factoryCount, parallelOptions, delegate(int i)
			{
				PlanetFactory val = GameMain.data.factories[i];
				if (val.factorySystem == null || val.factorySystem.labCursor > 1 || val.factorySystem.assemblerCursor > 1 || val.factorySystem.minerCursor > 1 || val.factorySystem.fractionatorCursor > 1 || val.factorySystem.ejectorCursor > 1 || val.factorySystem.siloCursor > 1 || val.powerSystem.genCursor > 1 || val.powerSystem.excCursor > 1)
				{
					__instance.factoryStatPool[i].PrepareTick();
				}
			});
			return false;
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(ProductionStatistics), "GameTick")]
		private static bool GameTick_Parallelize(ProductionStatistics __instance, long time)
		{
			if (!GameMain.multithreadSystem.multithreadSystemEnable)
			{
				return true;
			}
			new ParallelOptions().MaxDegreeOfParallelism = GameMain.multithreadSystem.usedThreadCnt;
			Parallel.For(0, __instance.gameData.factoryCount, delegate(int i)
			{
				PlanetFactory val = GameMain.data.factories[i];
				if (val.factorySystem == null || val.factorySystem.labCursor > 1 || val.factorySystem.assemblerCursor > 1 || val.factorySystem.minerCursor > 1 || val.factorySystem.fractionatorCursor > 1 || val.factorySystem.ejectorCursor > 1 || val.factorySystem.siloCursor > 1 || val.powerSystem.genCursor > 1 || val.powerSystem.excCursor > 1)
				{
					__instance.factoryStatPool[i].GameTick(time);
					if (__instance.factoryStatPool[i].itemChanged)
					{
						try
						{
							__instance.RaiseActionEvent<ProductionStatistics>("onItemChange");
						}
						catch (Exception ex)
						{
							WeaverFixes.Logger.LogError((object)ex);
						}
					}
				}
			});
			__instance.extraInfoCalculator.GameTick();
			return false;
		}
	}
	public sealed class TrafficStatisticsPatches
	{
		private static bool[] _isStarUpdated;

		private static bool[] _isPlanetUpdated;

		[HarmonyPrefix]
		[HarmonyPatch(typeof(TrafficStatistics), "PrepareTick")]
		public static void PrepareTick(TrafficStatistics __instance, long time)
		{
			if (_isStarUpdated == null || __instance.starTrafficPool.Length != _isStarUpdated.Length)
			{
				_isStarUpdated = new bool[__instance.starTrafficPool.Length];
			}
			if (_isPlanetUpdated == null || __instance.factoryTrafficPool.Length != _isPlanetUpdated.Length)
			{
				_isPlanetUpdated = new bool[__instance.factoryTrafficPool.Length];
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(TrafficStatistics), "GameTick")]
		private static bool GameTick_Parallelize(TrafficStatistics __instance, long time)
		{
			if (!GameMain.multithreadSystem.multithreadSystemEnable)
			{
				return true;
			}
			ParallelOptions parallelOptions = new ParallelOptions
			{
				MaxDegreeOfParallelism = GameMain.multithreadSystem.usedThreadCnt
			};
			Parallel.For(0, __instance.starTrafficPool.Length, parallelOptions, delegate(int i)
			{
				AstroTrafficStat val2 = __instance.starTrafficPool[i];
				if (val2 != null)
				{
					val2.GameTick(time);
					if (val2.itemChanged)
					{
						try
						{
							__instance.RaiseActionEvent<TrafficStatistics>("onItemChange");
						}
						catch (Exception ex2)
						{
							WeaverFixes.Logger.LogError((object)ex2);
						}
					}
				}
			});
			Parallel.For(0, __instance.factoryTrafficPool.Length, parallelOptions, delegate(int i)
			{
				AstroTrafficStat val = __instance.factoryTrafficPool[i];
				if (val != null)
				{
					val.GameTick(time);
					if (val.itemChanged)
					{
						try
						{
							__instance.RaiseActionEvent<TrafficStatistics>("onItemChange");
						}
						catch (Exception ex)
						{
							WeaverFixes.Logger.LogError((object)ex);
						}
					}
				}
			});
			return false;
		}
	}
}
namespace Weaver.Optimizations.ObjectPools
{
	public class ShrinkPools
	{
		private delegate TReturn PassStructAsRefFunc<TArgument, TReturn>(ArrayStructRef<TArgument> item) where TArgument : struct;

		private struct ArrayStructRef<T> where T : struct
		{
			private readonly T[] _array;

			private readonly int _index;

			public readonly ref T Value => ref _array[_index];

			public ArrayStructRef(T[] array, int index)
			{
				_array = array;
				_index = index;
			}
		}

		private static int HasCalculatedData;

		private static bool HasOptimizedPools;

		[HarmonyPrefix]
		[HarmonyPatch(typeof(GameData), "GameTick")]
		private static void GameTick_DetectPoolHoles(GameData __instance)
		{
			if (DSPGame.IsMenuDemo || HasCalculatedData > 1)
			{
				return;
			}
			HasCalculatedData++;
			int totalSlots = 0;
			int usedSlots = 0;
			int unusedSlots = 0;
			int holes = 0;
			PlanetFactory[] factories = __instance.factories;
			foreach (PlanetFactory val in factories)
			{
				if (val == null)
				{
					continue;
				}
				if (val.factorySystem != null)
				{
					GatherPoolData<MinerComponent>(val.factorySystem.minerPool, (Func<MinerComponent, int>)((MinerComponent x) => x.id), ref totalSlots, ref usedSlots, ref unusedSlots, ref holes);
					GatherPoolData<InserterComponent>(val.factorySystem.inserterPool, (Func<InserterComponent, int>)((InserterComponent x) => x.id), ref totalSlots, ref usedSlots, ref unusedSlots, ref holes);
					GatherPoolData<AssemblerComponent>(val.factorySystem.assemblerPool, (Func<AssemblerComponent, int>)((AssemblerComponent x) => x.id), ref totalSlots, ref usedSlots, ref unusedSlots, ref holes);
					GatherPoolData<FractionatorComponent>(val.factorySystem.fractionatorPool, (Func<FractionatorComponent, int>)((FractionatorComponent x) => x.id), ref totalSlots, ref usedSlots, ref unusedSlots, ref holes);
					GatherPoolData<EjectorComponent>(val.factorySystem.ejectorPool, (Func<EjectorComponent, int>)((EjectorComponent x) => x.id), ref totalSlots, ref usedSlots, ref unusedSlots, ref holes);
					GatherPoolData<SiloComponent>(val.factorySystem.siloPool, (Func<SiloComponent, int>)((SiloComponent x) => x.id), ref totalSlots, ref usedSlots, ref unusedSlots, ref holes);
					GatherPoolData<LabComponent>(val.factorySystem.labPool, (Func<LabComponent, int>)((LabComponent x) => x.id), ref totalSlots, ref usedSlots, ref unusedSlots, ref holes);
				}
				if (val.factoryStorage != null)
				{
					GatherPoolDataForClass(val.factoryStorage.storagePool, (StorageComponent x) => x.id, ref totalSlots, ref usedSlots, ref unusedSlots, ref holes);
					GatherPoolData<TankComponent>(val.factoryStorage.tankPool, (Func<TankComponent, int>)((TankComponent x) => x.id), ref totalSlots, ref usedSlots, ref unusedSlots, ref holes);
				}
				if (val.cargoTraffic != null)
				{
					GatherPoolDataForClass(val.cargoTraffic.pathPool, (CargoPath x) => x.id, ref totalSlots, ref usedSlots, ref unusedSlots, ref holes);
					GatherPoolData<BeltComponent>(val.cargoTraffic.beltPool, (Func<BeltComponent, int>)((BeltComponent x) => x.id), ref totalSlots, ref usedSlots, ref unusedSlots, ref holes);
					GatherPoolData<SplitterComponent>(val.cargoTraffic.splitterPool, (Func<SplitterComponent, int>)((SplitterComponent x) => x.id), ref totalSlots, ref usedSlots, ref unusedSlots, ref holes);
					GatherPoolData<MonitorComponent>(val.cargoTraffic.monitorPool, (Func<MonitorComponent, int>)((MonitorComponent x) => x.id), ref totalSlots, ref usedSlots, ref unusedSlots, ref holes);
					GatherPoolData<SpraycoaterComponent>(val.cargoTraffic.spraycoaterPool, (Func<SpraycoaterComponent, int>)((SpraycoaterComponent x) => x.id), ref totalSlots, ref usedSlots, ref unusedSlots, ref holes);
					GatherPoolData<PilerComponent>(val.cargoTraffic.pilerPool, (Func<PilerComponent, int>)((PilerComponent x) => x.id), ref totalSlots, ref usedSlots, ref unusedSlots, ref holes);
				}
				if (val.transport != null)
				{
					GatherPoolDataForClass(val.transport.stationPool, (StationComponent x) => x.id, ref totalSlots, ref usedSlots, ref unusedSlots, ref holes);
					GatherPoolDataForClass(val.transport.dispenserPool, (DispenserComponent x) => x.id, ref totalSlots, ref usedSlots, ref unusedSlots, ref holes);
				}
				if (val.powerSystem != null)
				{
					GatherPoolData<PowerGeneratorComponent>(val.powerSystem.genPool, (Func<PowerGeneratorComponent, int>)((PowerGeneratorComponent x) => x.id), ref totalSlots, ref usedSlots, ref unusedSlots, ref holes);
					GatherPoolData<PowerNodeComponent>(val.powerSystem.nodePool, (Func<PowerNodeComponent, int>)((PowerNodeComponent x) => x.id), ref totalSlots, ref usedSlots, ref unusedSlots, ref holes);
					GatherPoolData<PowerConsumerComponent>(val.powerSystem.consumerPool, (Func<PowerConsumerComponent, int>)((PowerConsumerComponent x) => x.id), ref totalSlots, ref usedSlots, ref unusedSlots, ref holes);
					GatherPoolData<PowerAccumulatorComponent>(val.powerSystem.accPool, (Func<PowerAccumulatorComponent, int>)((PowerAccumulatorComponent x) => x.id), ref totalSlots, ref usedSlots, ref unusedSlots, ref holes);
					GatherPoolData<PowerExchangerComponent>(val.powerSystem.excPool, (Func<PowerExchangerComponent, int>)((PowerExchangerComponent x) => x.id), ref totalSlots, ref usedSlots, ref unusedSlots, ref holes);
					GatherPoolDataForClass(val.powerSystem.netPool, (PowerNetwork x) => x.id, ref totalSlots, ref usedSlots, ref unusedSlots, ref holes);
				}
			}
			WeaverFixes.Logger.LogInfo((object)$"Total:   {totalSlots:N0}");
			WeaverFixes.Logger.LogInfo((object)$"Used:    {usedSlots:N0}");
			WeaverFixes.Logger.LogInfo((object)$"Unused:  {unusedSlots:N0}");
			WeaverFixes.Logger.LogInfo((object)$"Holes:   {holes:N0}");
			WeaverFixes.Logger.LogInfo((object)$"Used Ratio: {(float)usedSlots / (float)totalSlots * 100f:N2}%");
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(GameData), "GameTick")]
		private static void GameTick_OptimizePools(GameData __instance)
		{
			if (DSPGame.IsMenuDemo || HasOptimizedPools)
			{
				return;
			}
			HasOptimizedPools = true;
			PlanetFactory[] factories = __instance.factories;
			foreach (PlanetFactory val in factories)
			{
				if (val == null)
				{
					continue;
				}
				if (val.factorySystem != null)
				{
					ResizePool<MinerComponent>(ref val.factorySystem.minerPool, (PassStructAsRefFunc<MinerComponent, int>)((ArrayStructRef<MinerComponent> x) => x.Value.id), (Action<int>)val.factorySystem.SetMinerCapacity, ref val.factorySystem.minerCursor, ref val.factorySystem.minerCapacity, ref val.factorySystem.minerRecycle, ref val.factorySystem.minerRecycleCursor);
					ResizePool<InserterComponent>(ref val.factorySystem.inserterPool, (PassStructAsRefFunc<InserterComponent, int>)((ArrayStructRef<InserterComponent> x) => x.Value.id), (Action<int>)val.factorySystem.SetInserterCapacity, ref val.factorySystem.inserterCursor, ref val.factorySystem.inserterCapacity, ref val.factorySystem.inserterRecycle, ref val.factorySystem.inserterRecycleCursor);
					ResizePool<AssemblerComponent>(ref val.factorySystem.assemblerPool, (PassStructAsRefFunc<AssemblerComponent, int>)((ArrayStructRef<AssemblerComponent> x) => x.Value.id), (Action<int>)val.factorySystem.SetAssemblerCapacity, ref val.factorySystem.assemblerCursor, ref val.factorySystem.assemblerCapacity, ref val.factorySystem.assemblerRecycle, ref val.factorySystem.assemblerRecycleCursor);
					ResizePool<FractionatorComponent>(ref val.factorySystem.fractionatorPool, (PassStructAsRefFunc<FractionatorComponent, int>)((ArrayStructRef<FractionatorComponent> x) => x.Value.id), (Action<int>)val.factorySystem.SetFractionatorCapacity, ref val.factorySystem.fractionatorCursor, ref val.factorySystem.fractionatorCapacity, ref val.factorySystem.fractionatorRecycle, ref val.factorySystem.fractionatorRecycleCursor);
					ResizePool<EjectorComponent>(ref val.factorySystem.ejectorPool, (PassStructAsRefFunc<EjectorComponent, int>)((ArrayStructRef<EjectorComponent> x) => x.Value.id), (Action<int>)val.factorySystem.SetEjectorCapacity, ref val.factorySystem.ejectorCursor, ref val.factorySystem.ejectorCapacity, ref val.factorySystem.ejectorRecycle, ref val.factorySystem.ejectorRecycleCursor);
					ResizePool<SiloComponent>(ref val.factorySystem.siloPool, (PassStructAsRefFunc<SiloComponent, int>)((ArrayStructRef<SiloComponent> x) => x.Value.id), (Action<int>)val.factorySystem.SetSiloCapacity, ref val.factorySystem.siloCursor, ref val.factorySystem.siloCapacity, ref val.factorySystem.siloRecycle, ref val.factorySystem.siloRecycleCursor);
					ResizePool<LabComponent>(ref val.factorySystem.labPool, (PassStructAsRefFunc<LabComponent, int>)((ArrayStructRef<LabComponent> x) => x.Value.id), (Action<int>)val.factorySystem.SetLabCapacity, ref val.factorySystem.labCursor, ref val.factorySystem.labCapacity, ref val.factorySystem.labRecycle, ref val.factorySystem.labRecycleCursor);
				}
				if (val.factoryStorage != null)
				{
					ResizePoolForClass(ref val.factoryStorage.storagePool, (Func<StorageComponent, int>)((StorageComponent x) => x.id), (Action<int>)val.factoryStorage.SetStorageCapacity, ref val.factoryStorage.storageCursor, ref val.factoryStorage.storageCapacity, ref val.factoryStorage.storageRecycle, ref val.factoryStorage.storageRecycleCursor);
					ResizePool<TankComponent>(ref val.factoryStorage.tankPool, (PassStructAsRefFunc<TankComponent, int>)((ArrayStructRef<TankComponent> x) => x.Value.id), (Action<int>)val.factoryStorage.SetTankCapacity, ref val.factoryStorage.tankCursor, ref val.factoryStorage.tankCapacity, ref val.factoryStorage.tankRecycle, ref val.factoryStorage.tankRecycleCursor);
				}
				if (val.cargoTraffic != null)
				{
					ResizePoolForClass(ref val.cargoTraffic.pathPool, (Func<CargoPath, int>)((CargoPath x) => x.id), (Action<int>)val.cargoTraffic.SetPathCapacity, ref val.cargoTraffic.pathCursor, ref val.cargoTraffic.pathCapacity, ref val.cargoTraffic.pathRecycle, ref val.cargoTraffic.pathRecycleCursor);
					ResizePool<BeltComponent>(ref val.cargoTraffic.beltPool, (PassStructAsRefFunc<BeltComponent, int>)((ArrayStructRef<BeltComponent> x) => x.Value.id), (Action<int>)val.cargoTraffic.SetBeltCapacity, ref val.cargoTraffic.beltCursor, ref val.cargoTraffic.beltCapacity, ref val.cargoTraffic.beltRecycle, ref val.cargoTraffic.beltRecycleCursor);
					ResizePool<SplitterComponent>(ref val.cargoTraffic.splitterPool, (PassStructAsRefFunc<SplitterComponent, int>)((ArrayStructRef<SplitterComponent> x) => x.Value.id), (Action<int>)val.cargoTraffic.SetSplitterCapacity, ref val.cargoTraffic.splitterCursor, ref val.cargoTraffic.splitterCapacity, ref val.cargoTraffic.splitterRecycle, ref val.cargoTraffic.splitterRecycleCursor);
					ResizePool<MonitorComponent>(ref val.cargoTraffic.monitorPool, (PassStructAsRefFunc<MonitorComponent, int>)((ArrayStructRef<MonitorComponent> x) => x.Value.id), (Action<int>)val.cargoTraffic.SetMonitorCapacity, ref val.cargoTraffic.monitorCursor, ref val.cargoTraffic.monitorCapacity, ref val.cargoTraffic.monitorRecycle, ref val.cargoTraffic.monitorRecycleCursor);
					ResizePool<SpraycoaterComponent>(ref val.cargoTraffic.spraycoaterPool, (PassStructAsRefFunc<SpraycoaterComponent, int>)((ArrayStructRef<SpraycoaterComponent> x) => x.Value.id), (Action<int>)val.cargoTraffic.SetSpraycoaterCapacity, ref val.cargoTraffic.spraycoaterCursor, ref val.cargoTraffic.spraycoaterCapacity, ref val.cargoTraffic.spraycoaterRecycle, ref val.cargoTraffic.spraycoaterRecycleCursor);
					ResizePool<PilerComponent>(ref val.cargoTraffic.pilerPool, (PassStructAsRefFunc<PilerComponent, int>)((ArrayStructRef<PilerComponent> x) => x.Value.id), (Action<int>)val.cargoTraffic.SetPilerCapacity, ref val.cargoTraffic.pilerCursor, ref val.cargoTraffic.pilerCapacity, ref val.cargoTraffic.pilerRecycle, ref val.cargoTraffic.pilerRecycleCursor);
				}
				if (val.transport != null)
				{
					ResizePoolForClass(ref val.transport.stationPool, (Func<StationComponent, int>)((StationComponent x) => x.id), (Action<int>)val.transport.SetStationCapacity, ref val.transport.stationCursor, ref val.transport.stationCapacity, ref val.transport.stationRecycle, ref val.transport.stationRecycleCursor);
					ResizePoolForClass(ref val.transport.dispenserPool, (Func<DispenserComponent, int>)((DispenserComponent x) => x.id), (Action<int>)val.transport.SetDispenserCapacity, ref val.transport.dispenserCursor, ref val.transport.dispenserCapacity, ref val.transport.dispenserRecycle, ref val.transport.dispenserRecycleCursor);
				}
				if (val.powerSystem != null)
				{
					ResizePool<PowerGeneratorComponent>(ref val.powerSystem.genPool, (PassStructAsRefFunc<PowerGeneratorComponent, int>)((ArrayStructRef<PowerGeneratorComponent> x) => x.Value.id), (Action<int>)val.powerSystem.SetGeneratorCapacity, ref val.powerSystem.genCursor, ref val.powerSystem.genCapacity, ref val.powerSystem.genRecycle, ref val.powerSystem.genRecycleCursor);
					ResizePool<PowerNodeComponent>(ref val.powerSystem.nodePool, (PassStructAsRefFunc<PowerNodeComponent, int>)((ArrayStructRef<PowerNodeComponent> x) => x.Value.id), (Action<int>)val.powerSystem.SetNodeCapacity, ref val.powerSystem.nodeCursor, ref val.powerSystem.nodeCapacity, ref val.powerSystem.nodeRecycle, ref val.powerSystem.nodeRecycleCursor);
					ResizePool<PowerConsumerComponent>(ref val.powerSystem.consumerPool, (PassStructAsRefFunc<PowerConsumerComponent, int>)((ArrayStructRef<PowerConsumerComponent> x) => x.Value.id), (Action<int>)val.powerSystem.SetConsumerCapacity, ref val.powerSystem.consumerCursor, ref val.powerSystem.consumerCapacity, ref val.powerSystem.consumerRecycle, ref val.powerSystem.consumerRecycleCursor);
					ResizePool<PowerAccumulatorComponent>(ref val.powerSystem.accPool, (PassStructAsRefFunc<PowerAccumulatorComponent, int>)((ArrayStructRef<PowerAccumulatorComponent> x) => x.Value.id), (Action<int>)val.powerSystem.SetAccumulatorCapacity, ref val.powerSystem.accCursor, ref val.powerSystem.accCapacity, ref val.powerSystem.accRecycle, ref val.powerSystem.accRecycleCursor);
					ResizePool<PowerExchangerComponent>(ref val.powerSystem.excPool, (PassStructAsRefFunc<PowerExchangerComponent, int>)((ArrayStructRef<PowerExchangerComponent> x) => x.Value.id), (Action<int>)val.powerSystem.SetExchangerCapacity, ref val.powerSystem.excCursor, ref val.powerSystem.excCapacity, ref val.powerSystem.excRecycle, ref val.powerSystem.excRecycleCursor);
					ResizePoolForClass(ref val.powerSystem.netPool, (Func<PowerNetwork, int>)((PowerNetwork x) => x.id), (Action<int>)val.powerSystem.SetNetworkCapacity, ref val.powerSystem.netCursor, ref val.powerSystem.netCapacity, ref val.powerSystem.netRecycle, ref val.powerSystem.netRecycleCursor);
				}
			}
			WeaverFixes.Logger.LogInfo((object)"Optimized pools");
		}

		private static void GatherPoolData<T>(T[] pool, Func<T, int> getId, ref int totalSlots, ref int usedSlots, ref int unusedSlots, ref int holes) where T : struct
		{
			totalSlots += pool.Length;
			int num = 0;
			for (int i = 1; i < pool.Length; i++)
			{
				if (getId(pool[i]) == i)
				{
					usedSlots++;
					num = i;
				}
				else
				{
					unusedSlots++;
				}
			}
			for (int j = 1; j <= num; j++)
			{
				if (getId(pool[j]) != j)
				{
					holes++;
				}
			}
		}

		private static void GatherPoolDataForClass<T>(T[] pool, Func<T, int> getId, ref int totalSlots, ref int usedSlots, ref int unusedSlots, ref int holes) where T : class
		{
			totalSlots += pool.Length;
			int num = 0;
			for (int i = 1; i < pool.Length; i++)
			{
				if (pool[i] != null && getId(pool[i]) == i)
				{
					usedSlots++;
					num = i;
				}
				else
				{
					unusedSlots++;
				}
			}
			for (int j = 1; j <= num; j++)
			{
				if (pool[j] == null || getId(pool[j]) != j)
				{
					holes++;
				}
			}
		}

		private static void ResizePool<T>(ref T[] pool, PassStructAsRefFunc<T, int> getId, Action<int> setCapacity, ref int cursor, ref int capacity, ref int[] recycle, ref int recycleCursor) where T : struct
		{
			int num = cursor - 1;
			while (num >= 1 && getId(new ArrayStructRef<T>(pool, num)) != num)
			{
				num--;
			}
			cursor = num + 1;
			setCapacity(cursor);
		}

		private static void ResizePoolForClass<T>(ref T[] pool, Func<T, int> getId, Action<int> setCapacity, ref int cursor, ref int capacity, ref int[] recycle, ref int recycleCursor) where T : class
		{
			int num = cursor - 1;
			while (num >= 1 && getId(pool[num]) != num)
			{
				num--;
			}
			cursor = num + 1;
			setCapacity(cursor);
		}
	}
}
namespace Weaver.Optimizations.LinearDataAccess
{
	internal static class HarmonyExtensions
	{
		public static void ReplaceCode(this CodeMatcher codeMatcher, CodeMatch[] start, bool replaceStart, CodeMatch[] end, bool replaceEnd, CodeInstruction[] replaceWith)
		{
			codeMatcher.MatchForward(!replaceStart, start).ThrowIfNotMatch("Failed to find start", Array.Empty<CodeMatch>());
			int pos = codeMatcher.Pos;
			codeMatcher.MatchForward(replaceEnd, end).ThrowIfNotMatch("Failed to find end", Array.Empty<CodeMatch>());
			int pos2 = codeMatcher.Pos;
			codeMatcher.Start().Advance(pos).RemoveInstructions(pos2 - pos + 1)
				.Insert(replaceWith);
		}

		public static void PrintRelativeRangeOfInstructions(this CodeMatcher codeMatcher, int startOffset, int length)
		{
			codeMatcher.Advance(startOffset);
			for (int i = 0; i < length; i++)
			{
				WeaverFixes.Logger.LogMessage((object)codeMatcher.Instruction);
				codeMatcher.Advance(1);
			}
		}
	}
	internal interface IOptimizedPlanet
	{
		OptimizedPlanetStatus Status { get; }

		int OptimizeDelayInTicks { get; set; }

		void Save();

		void Initialize();

		bool RequestDysonSpherePower();

		void TransportGameTick(long time, Vector3 playerPos);

		WorkStep[] GetMultithreadedWork(int maxParallelism);
	}
	internal struct NetworkIdAndState<T> where T : Enum
	{
		private const int IndexBitCount = 24;

		private const uint IndexBitMask = 16777215u;

		private const uint StateTypeMask = 255u;

		private uint _value;

		public int State
		{
			get
			{
				return (int)(_value >> 24);
			}
			set
			{
				_value = (_value & 0xFFFFFFu) | (uint)(value << 24);
			}
		}

		public readonly int Index => (int)(0xFFFFFF & _value);

		public NetworkIdAndState(int state, int index)
		{
			if ((uint)state < 0u || (uint)state > 255u)
			{
				throw new ArgumentOutOfRangeException("index", $"{state} was outside the range {0} to {255u:N0}");
			}
			if (index < 0 || (long)index > 16777215L)
			{
				throw new ArgumentOutOfRangeException("index", $"{index} was outside the range {0} to {16777215u:N0}");
			}
			_value = (uint)(state << 24) | (0xFFFFFFu & (uint)index);
		}
	}
	internal sealed class OptimizedGasPlanet : IOptimizedPlanet
	{
		private readonly PlanetFactory _planet;

		private GasPlanetWideStationExecutor _planetWideStationExecutor;

		private WorkStep[] _workSteps;

		private int _workStepsParallelism;

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


		public int OptimizeDelayInTicks { get; set; }

		public OptimizedGasPlanet(PlanetFactory planet)
		{
			_planet = planet;
		}

		public static bool IsGasPlanet(PlanetFactory planet)
		{
			for (int i = 1; i < planet.transport.stationCursor; i++)
			{
				StationComponent val = planet.transport.stationPool[i];
				if (val != null && val.id == i && val.isCollector)
				{
					return true;
				}
			}
			return false;
		}

		public void Initialize()
		{
			_planetWideStationExecutor = new GasPlanetWideStationExecutor();
			_planetWideStationExecutor.Initialize(_planet);
			Status = OptimizedPlanetStatus.Running;
			_workSteps = null;
			_workStepsParallelism = -1;
		}

		public void Save()
		{
			_workSteps = null;
			_workStepsParallelism = -1;
			Status = OptimizedPlanetStatus.Stopped;
		}

		public bool RequestDysonSpherePower()
		{
			return false;
		}

		public void TransportGameTick(long time, Vector3 playerPos)
		{
			MiningFlags miningFlags = new MiningFlags();
			_planetWideStationExecutor.StationGameTick(_planet, time, ref miningFlags);
			PlanetFactory planet = _planet;
			planet._miningFlag |= miningFlags.MiningFlag;
			PlanetFactory planet2 = _planet;
			planet2._veinMiningFlag |= miningFlags.VeinMiningFlag;
		}

		public WorkStep[] GetMultithreadedWork(int maxParallelism)
		{
			if (_workStepsParallelism != maxParallelism)
			{
				_workSteps = CreateMultithreadedWork(maxParallelism);
				_workStepsParallelism = maxParallelism;
			}
			return _workSteps;
		}

		private WorkStep[] CreateMultithreadedWork(int maxParallelism)
		{
			if (Status == OptimizedPlanetStatus.Stopped)
			{
				return CreateParallelWorkForNonRunningOptimizedPlanet(maxParallelism);
			}
			List<WorkStep> list = new List<WorkStep>();
			list.Add(new WorkStep(new IWorkChunk[1]
			{
				new PlanetWideTransport(this)
			}));
			return list.ToArray();
		}

		private WorkStep[] CreateParallelWorkForNonRunningOptimizedPlanet(int maxParallelism)
		{
			List<WorkStep> list = new List<WorkStep>();
			if (_planet.transport.stationCursor > 0)
			{
				IWorkChunk[] workChunks = UnOptimizedPlanetWorkChunk.CreateDuplicateChunks(_planet, WorkType.TransportData, 1);
				list.Add(new WorkStep(workChunks));
			}
			return list.ToArray();
		}
	}
	internal enum OptimizedPlanetStatus
	{
		Running,
		Stopped
	}
	internal static class OptimizedStarCluster
	{
		private static readonly Dictionary<PlanetFactory, IOptimizedPlanet> _planetToOptimizedPlanet = new Dictionary<PlanetFactory, IOptimizedPlanet>();

		private static readonly Queue<PlanetFactory> _newPlanets = new Queue<PlanetFactory>();

		private static readonly Queue<PlanetFactory> _planetsToReOptimize = new Queue<PlanetFactory>();

		public static readonly StarClusterResearchManager _starClusterResearchManager = new StarClusterResearchManager();

		private static readonly WorkStealingMultiThreadedFactorySimulation _workStealingMultiThreadedFactorySimulation = new WorkStealingMultiThreadedFactorySimulation(_starClusterResearchManager);

		private static bool _clearOptimizedPlanetsOnNextTick = false;

		private static readonly Random random = new Random();

		private static bool _debugEnableHeavyReOptimization = false;

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

		public static void DebugEnableHeavyReOptimization()
		{
			_debugEnableHeavyReOptimization = true;
		}

		public static IOptimizedPlanet GetOptimizedPlanet(PlanetFactory planet)
		{
			return _planetToOptimizedPlanet[planet];
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(GameMain), "End")]
		public static void End()
		{
			WeaverFixes.Logger.LogInfo((object)"Marking optimized planets to be cleared.");
			_clearOptimizedPlanetsOnNextTick = true;
		}

		[HarmonyPriority(1)]
		[HarmonyPostfix]
		[HarmonyPatch(typeof(GameSave), "LoadCurrentGame")]
		private static void LoadCurrentGame_Postfix()
		{
			WeaverFixes.Logger.LogInfo((object)"Initializing OptimizedStarCluster");
			_planetToOptimizedPlanet.Clear();
			_workStealingMultiThreadedFactorySimulation.Clear();
			_clearOptimizedPlanetsOnNextTick = false;
			for (int i = 0; i < GameMain.data.factoryCount; i++)
			{
				TryAddNewPlanet(GameMain.data.factories[i]);
			}
		}

		private static void TryAddNewPlanet(PlanetFactory planet)
		{
			if (planet.factorySystem != null)
			{
				if (OptimizedGasPlanet.IsGasPlanet(planet))
				{
					_planetToOptimizedPlanet.Add(planet, new OptimizedGasPlanet(planet));
				}
				else
				{
					_planetToOptimizedPlanet.Add(planet, new OptimizedTerrestrialPlanet(planet, _starClusterResearchManager));
				}
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(GameSave), "SaveCurrentGame")]
		private static void SaveCurrentGame_Prefix()
		{
			WeaverFixes.Logger.LogInfo((object)"Saving optimized planets");
			foreach (KeyValuePair<PlanetFactory, IOptimizedPlanet> item in _planetToOptimizedPlanet)
			{
				if (item.Value.Status == OptimizedPlanetStatus.Running)
				{
					WeaverFixes.Logger.LogInfo((object)("Saving planet: " + item.Key.planet.displayName));
					item.Value.Save();
				}
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(GameData), "GameTick")]
		public static void GameData_GameTick()
		{
			if (_clearOptimizedPlanetsOnNextTick)
			{
				_clearOptimizedPlanetsOnNextTick = false;
				_planetToOptimizedPlanet.Clear();
				_workStealingMultiThreadedFactorySimulation.Clear();
			}
			lock (_newPlanets)
			{
				while (_newPlanets.Count > 0)
				{
					PlanetFactory val = _newPlanets.Dequeue();
					WeaverFixes.Logger.LogInfo((object)("Adding planet: " + val.planet.displayName));
					TryAddNewPlanet(val);
				}
			}
			foreach (KeyValuePair<PlanetFactory, IOptimizedPlanet> item in _planetToOptimizedPlanet)
			{
				if (GameMain.localPlanet?.factory != item.Key)
				{
					if (item.Value.Status == OptimizedPlanetStatus.Stopped && (item.Value.OptimizeDelayInTicks <= 0 || item.Value.OptimizeDelayInTicks-- <= 0))
					{
						WeaverFixes.Logger.LogInfo((object)("Optimizing planet: " + item.Key.planet.displayName));
						item.Value.Initialize();
					}
				}
				else if (item.Value.Status != OptimizedPlanetStatus.Stopped)
				{
					WeaverFixes.Logger.LogInfo((object)("DeOptimizing planet: " + item.Key.planet.displayName));
					item.Value.Save();
				}
			}
			if (_planetsToReOptimize.Count > 0)
			{
				PlanetFactory val2 = _planetsToReOptimize.Dequeue();
				IOptimizedPlanet optimizedPlanet = _planetToOptimizedPlanet[val2];
				if (optimizedPlanet.Status == OptimizedPlanetStatus.Stopped)
				{
					return;
				}
				WeaverFixes.Logger.LogInfo((object)("DeOptimizing planet: " + val2.planet.displayName));
				optimizedPlanet.Save();
			}
			if (_debugEnableHeavyReOptimization && GameMain.gameTick % 10 == 0L)
			{
				PlanetFactory[] array = _planetToOptimizedPlanet.Keys.ToArray();
				int num = random.Next(0, array.Length);
				_planetsToReOptimize.Enqueue(array[num]);
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(PlanetFactory), "Init")]
		public static void PlanetFactory_Init(PlanetFactory __instance)
		{
			lock (_newPlanets)
			{
				_newPlanets.Enqueue(__instance);
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(PlanetFactory), "AddEntityDataWithComponents")]
		public static void PlanetFactory_AddEntityDataWithComponents(PlanetFactory __instance)
		{
			DeOptimizeDueToNonPlayerAction(__instance);
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(PlanetFactory), "RemoveEntityWithComponents")]
		public static void PlanetFactory_RemoveEntityWithComponents(PlanetFactory __instance)
		{
			DeOptimizeDueToNonPlayerAction(__instance);
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(PlanetFactory), "UpgradeEntityWithComponents")]
		public static void PlanetFactory_UpgradeEntityWithComponents(PlanetFactory __instance)
		{
			DeOptimizeDueToNonPlayerAction(__instance);
		}

		[HarmonyTranspiler]
		[HarmonyPatch(typeof(FactorySystem), "GameTickLabResearchMode")]
		private static IEnumerable<CodeInstruction> DeferResearchUnlockToStarClusterResearchManager(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Expected O, but got Unknown
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Expected O, but got Unknown
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Expected O, but got Unknown
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Expected O, but got Unknown
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Expected O, but got Unknown
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Expected O, but got Unknown
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Expected O, but got Unknown
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Expected O, but got Unknown
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Expected O, but got Unknown
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Expected O, but got Unknown
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Expected O, but got Unknown
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Expected O, but got Unknown
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: Expected O, but got Unknown
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a3: Expected O, but got Unknown
			//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c6: Expected O, but got Unknown
			CodeMatcher val = new CodeMatcher(instructions, generator);
			CodeMatch[] start = (CodeMatch[])(object)new CodeMatch[6]
			{
				new CodeMatch((OpCode?)OpCodes.Ldloc_1, (object)null, (string)null),
				new CodeMatch((OpCode?)OpCodes.Ldfld, (object)AccessTools.Field(typeof(GameHistoryData), "techStates"), (string)null),
				new CodeMatch((OpCode?)OpCodes.Ldarg_0, (object)null, (string)null),
				new CodeMatch((OpCode?)OpCodes.Ldfld, (object)AccessTools.Field(typeof(FactorySystem), "researchTechId"), (string)null),
				new CodeMatch((OpCode?)OpCodes.Ldloc_S, (object)null, (string)null),
				new CodeMatch((OpCode?)OpCodes.Callvirt, (object)AccessTools.PropertySetter(typeof(Dictionary<int, TechState>), "Item"), (string)null)
			};
			CodeMatch[] end = (CodeMatch[])(object)new CodeMatch[1]
			{
				new CodeMatch((OpCode?)OpCodes.Callvirt, (object)AccessTools.Method(typeof(GameHistoryData), "NotifyTechUnlock", (Type[])null, (Type[])null), (string)null)
			};
			CodeInstruction[] replaceWith = (CodeInstruction[])(object)new CodeInstruction[8]
			{
				new CodeInstruction(OpCodes.Callvirt, (object)AccessTools.PropertySetter(typeof(Dictionary<int, TechState>), "Item")),
				new CodeInstruction(OpCodes.Ldsfld, (object)AccessTools.Field(typeof(OptimizedStarCluster), "_starClusterResearchManager")),
				new CodeInstruction(OpCodes.Ldarg_0, (object)null),
				new CodeInstruction(OpCodes.Ldfld, (object)AccessTools.Field(typeof(FactorySystem), "researchTechId")),
				new CodeInstruction(OpCodes.Ldloc_S, (object)29),
				new CodeInstruction(OpCodes.Ldloc_S, (object)13),
				new CodeInstruction(OpCodes.Ldloc_S, (object)12),
				new CodeInstruction(OpCodes.Callvirt, (object)AccessTools.Method(typeof(StarClusterResearchManager), "AddResearchedTech", (Type[])null, (Type[])null))
			};
			val.ReplaceCode(start, replaceStart: false, end, replaceEnd: false, replaceWith);
			val.ReplaceCode(start, replaceStart: false, end, replaceEnd: false, replaceWith);
			return val.InstructionEnumeration();
		}

		[HarmonyTranspiler]
		[HarmonyPatch(typeof(GameData), "GameTick")]
		private static IEnumerable<CodeInstruction> ReplaceMultithreadedSimulationLogic(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Expected O, but got Unknown
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Expected O, but got Unknown
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Expected O, but got Unknown
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Expected O, but got Unknown
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Expected O, but got Unknown
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Expected O, but got Unknown
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Expected O, but got Unknown
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Expected O, but got Unknown
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Expected O, but got Unknown
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Expected O, but got Unknown
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Expected O, but got Unknown
			CodeMatcher val = new CodeMatcher(instructions, generator);
			CodeMatch[] array = (CodeMatch[])(object)new CodeMatch[1]
			{
				new CodeMatch((OpCode?)OpCodes.Ldfld, (object)AccessTools.Field(typeof(MultithreadSystem), "multithreadSystemEnable"), (string)null)
			};
			CodeMatch[] start = (CodeMatch[])(object)new CodeMatch[2]
			{
				new CodeMatch((OpCode?)OpCodes.Ldc_I4_S, (object)(sbyte)9, (string)null),
				new CodeMatch((OpCode?)OpCodes.Call, (object)AccessTools.Method(typeof(PerformanceMonitor), "BeginSample", (Type[])null, (Type[])null), (string)null)
			};
			CodeMatch[] end = (CodeMatch[])(object)new CodeMatch[2]
			{
				new CodeMatch((OpCode?)OpCodes.Ldc_I4_S, (object)(sbyte)32, (string)null),
				new CodeMatch((OpCode?)OpCodes.Call, (object)AccessTools.Method(typeof(PerformanceMonitor), "EndSample", (Type[])null, (Type[])null), (string)null)
			};
			PluginInfo value;
			CodeInstruction[] replaceWith = (CodeInstruction[])(object)((!Chainloader.PluginInfos.TryGetValue("starfi5h.plugin.SampleAndHoldSim", out value)) ? new CodeInstruction[3]
			{
				new CodeInstruction(OpCodes.Ldarg_0, (object)null),
				new CodeInstruction(OpCodes.Ldfld, (object)AccessTools.Field(typeof(GameData), "factories")),
				new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(OptimizedStarCluster), "ExecuteSimulation", (Type[])null, (Type[])null))
			} : new CodeInstruction[2]
			{
				new CodeInstruction(OpCodes.Ldsfld, (object)AccessTools.Field(AccessTools.TypeByName("SampleAndHoldSim.GameData_Patch"), "workFactories")),
				new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(OptimizedStarCluster), "ExecuteSimulation", (Type[])null, (Type[])null))
			});
			val.MatchForward(true, array).ThrowIfNotMatch("Failed to find multithreadedIfCondition", Array.Empty<CodeMatch>());
			val.ReplaceCode(start, replaceStart: true, end, replaceEnd: true, replaceWith);
			return val.InstructionEnumeration();
		}

		[HarmonyTranspiler]
		[HarmonyPatch(typeof(GameData), "GameTick")]
		private static IEnumerable<CodeInstruction> ReplaceDefenseSystemLogic(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Expected O, but got Unknown
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Expected O, but got Unknown
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Expected O, but got Unknown
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Expected O, but got Unknown
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Expected O, but got Unknown
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Expected O, but got Unknown
			CodeMatcher val = new CodeMatcher(instructions, generator);
			CodeMatch[] start = (CodeMatch[])(object)new CodeMatch[2]
			{
				new CodeMatch((OpCode?)OpCodes.Ldc_I4_S, (object)(sbyte)34, (string)null),
				new CodeMatch((OpCode?)OpCodes.Call, (object)AccessTools.Method(typeof(PerformanceMonitor), "BeginSample", (Type[])null, (Type[])null), (string)null)
			};
			CodeMatch[] end = (CodeMatch[])(object)new CodeMatch[2]
			{
				new CodeMatch((OpCode?)OpCodes.Ldc_I4_S, (object)(sbyte)34, (string)null),
				new CodeMatch((OpCode?)OpCodes.Call, (object)AccessTools.Method(typeof(PerformanceMonitor), "EndSample", (Type[])null, (Type[])null), (string)null)
			};
			CodeInstruction[] replaceWith = (CodeInstruction[])(object)new CodeInstruction[1]
			{
				new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(OptimizedStarCluster), "ExecuteParallelDefense", (Type[])null, (Type[])null))
			};
			val.ReplaceCode(start, replaceStart: true, end, replaceEnd: true, replaceWith);
			return val.InstructionEnumeration();
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(PowerSystem), "RequestDysonSpherePower")]
		public static bool PowerSystem_RequestDysonSpherePower(PowerSystem __instance)
		{
			return GetOptimizedPlanet(__instance.factory).RequestDysonSpherePower();
		}

		public static void ReOptimizeAllPlanets()
		{
			lock (_planetsToReOptimize)
			{
				foreach (PlanetFactory item in from x in _planetToOptimizedPlanet
					where x.Value.Status == OptimizedPlanetStatus.Running
					select x.Key)
				{
					_planetsToReOptimize.Enqueue(item);
				}
			}
		}

		private static void ExecuteSimulation(PlanetFactory?[] planets)
		{
			_workStealingMultiThreadedFactorySimulation.Simulate(planets);
		}

		private static void ExecuteParallelDefense()
		{
			PerformanceMonitor.BeginSample((ECpuWorkEntry)34);
			long gameTick = GameMain.gameTick;
			foreach (IOptimizedPlanet value in _planetToOptimizedPlanet.Values)
			{
				if (value is OptimizedTerrestrialPlanet optimizedTerrestrialPlanet)
				{
					optimizedTerrestrialPlanet.GameTickDefense(gameTick);
					optimizedTerrestrialPlanet.DefenseGameTickUIThread(gameTick);
				}
			}
			PerformanceMonitor.EndSample((ECpuWorkEntry)34);
		}

		private static void DeOptimizeDueToNonPlayerAction(PlanetFactory planet)
		{
			IOptimizedPlanet optimizedPlanet = _planetToOptimizedPlanet[planet];
			if (optimizedPlanet.Status == OptimizedPlanetStatus.Running)
			{
				WeaverFixes.Logger.LogInfo((object)("DeOptimizing planet: " + planet.planet.displayName));
				optimizedPlanet.Save();
			}
			optimizedPlanet.OptimizeDelayInTicks = 200;
		}
	}
	internal sealed class OptimizedSubFactory
	{
		private readonly PlanetFactory _planet;

		private readonly OptimizedTerrestrialPlanet _optimizedPlanet;

		private readonly StarClusterResearchManager _starClusterResearchManager;

		public InserterExecutor<OptimizedBiInserter> _optimizedBiInserterExecutor;

		public InserterExecutor<OptimizedInserter> _optimizedInserterExecutor;

		public AssemblerExecutor _assemblerExecutor;

		public VeinMinerExecutor<BeltMinerOutput> _beltVeinMinerExecutor;

		public VeinMinerExecutor<StationMinerOutput> _stationVeinMinerExecutor;

		public OilMinerExecutor _oilMinerExecutor;

		public WaterMinerExecutor _waterMinerExecutor;

		public EjectorExecutor _ejectorExecutor;

		public SiloExecutor _siloExecutor;

		public ProducingLabExecutor _producingLabExecutor;

		public NetworkIdAndState<LabState>[] _producingLabNetworkIdAndStates;

		public OptimizedProducingLab[] _optimizedProducingLabs;

		public ProducingLabRecipe[] _producingLabRecipes;

		public Dictionary<int, int> _producingLabIdToOptimizedIndex;

		public ResearchingLabExecutor _researchingLabExecutor;

		public NetworkIdAndState<LabState>[] _researchingLabNetworkIdAndStates;

		public OptimizedResearchingLab[] _optimizedResearchingLabs;

		public Dictionary<int, int> _researchingLabIdToOptimizedIndex;

		public MonitorExecutor _monitorExecutor;

		public SpraycoaterExecutor _spraycoaterExecutor;

		public PilerExecutor _pilerExecutor;

		public FractionatorExecutor _fractionatorExecutor;

		public StationExecutor _stationExecutor;

		public TankExecutor _tankExecutor;

		public BeltExecutor _beltExecutor;

		public SplitterExecutor _splitterExecutor;

		public OptimizedSubFactory(PlanetFactory planet, OptimizedTerrestrialPlanet optimizedTerrestrialPlanet, StarClusterResearchManager starClusterResearchManager)
		{
			_planet = planet;
			_optimizedPlanet = optimizedTerrestrialPlanet;
			_starClusterResearchManager = starClusterResearchManager;
		}

		public void Save(CargoContainer cargoContainer)
		{
			_beltExecutor.Save(cargoContainer);
			_beltVeinMinerExecutor.Save(_planet);
			_stationVeinMinerExecutor.Save(_planet);
			_oilMinerExecutor.Save(_planet);
			_waterMinerExecutor.Save(_planet);
			_optimizedBiInserterExecutor.Save(_planet);
			_optimizedInserterExecutor.Save(_planet);
			_assemblerExecutor.Save(_planet);
			_producingLabExecutor.Save(_planet);
			_researchingLabExecutor.Save(_planet);
			_spraycoaterExecutor.Save(_planet);
			_fractionatorExecutor.Save(_planet);
			_tankExecutor.Save(_planet);
		}

		public void Initialize(Graph subFactoryGraph, OptimizedPowerSystemBuilder optimizedPowerSystemBuilder, PlanetWideBeltExecutor planetWideBeltExecutor, TurretExecutorBuilder turretExecutorBuilder)
		{
			optimizedPowerSystemBuilder.AddSubFactory(this);
			InitializeBelts(subFactoryGraph, planetWideBeltExecutor);
			InitializeAssemblers(subFactoryGraph, optimizedPowerSystemBuilder);
			InitializeMiners(subFactoryGraph, optimizedPowerSystemBuilder, _beltExecutor);
			InitializeStations(subFactoryGraph, _beltExecutor, _stationVeinMinerExecutor);
			InitializeEjectors(subFactoryGraph);
			InitializeSilos(subFactoryGraph);
			InitializeLabAssemblers(subFactoryGraph, optimizedPowerSystemBuilder);
			InitializeResearchingLabs(subFactoryGraph, optimizedPowerSystemBuilder);
			InitializeInserters(subFactoryGraph, optimizedPowerSystemBuilder, _beltExecutor);
			InitializeMonitors(subFactoryGraph, optimizedPowerSystemBuilder, _beltExecutor);
			InitializeSpraycoaters(subFactoryGraph, optimizedPowerSystemBuilder, _beltExecutor);
			InitializePilers(subFactoryGraph, optimizedPowerSystemBuilder, _beltExecutor);
			InitializeFractionators(subFactoryGraph, optimizedPowerSystemBuilder, _beltExecutor);
			InitializeTanks(subFactoryGraph, _beltExecutor);
			InitializeSplitters(subFactoryGraph, _beltExecutor);
			turretExecutorBuilder.Initialize(_planet, subFactoryGraph, _beltExecutor);
		}

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

		private void InitializeAssemblers(Graph subFactoryGraph, OptimizedPowerSystemBuilder optimizedPowerSystemBuilder)
		{
			_assemblerExecutor = new AssemblerExecutor();
			_assemblerExecutor.InitializeAssemblers(_planet, subFactoryGraph, optimizedPowerSystemBuilder);
		}

		private void InitializeMiners(Graph subFactoryGraph, OptimizedPowerSystemBuilder optimizedPowerSystemBuilder, BeltExecutor beltExecutor)
		{
			_beltVeinMinerExecutor = new VeinMinerExecutor<BeltMinerOutput>();
			_beltVeinMinerExecutor.Initialize(_planet, subFactoryGraph, optimizedPowerSystemBuilder.CreateBeltVeinMinerBuilder(), beltExecutor);
			_stationVeinMinerExecutor = new VeinMinerExecutor<StationMinerOutput>();
			_stationVeinMinerExecutor.Initialize(_planet, subFactoryGraph, optimizedPowerSystemBuilder.CreateStationVeinMinerBuilder(), beltExecutor);
			_oilMinerExecutor = new OilMinerExecutor();
			_oilMinerExecutor.Initialize(_planet, subFactoryGraph, optimizedPowerSystemBuilder, beltExecutor);
			_waterMinerExecutor = new WaterMinerExecutor();
			_waterMinerExecutor.Initialize(_planet, subFactoryGraph, optimizedPowerSystemBuilder, beltExecutor);
		}

		private void InitializeEjectors(Graph subFactoryGraph)
		{
			_ejectorExecutor = new EjectorExecutor();
			_ejectorExecutor.Initialize(_planet, subFactoryGraph);
		}

		private void InitializeSilos(Graph subFactoryGraph)
		{
			_siloExecutor = new SiloExecutor();
			_siloExecutor.Initialize(_planet, subFactoryGraph);
		}

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

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

		private void InitializeMonitors(Graph subFactoryGraph, OptimizedPowerSystemBuilder optimizedPowerSystemBuilder, BeltExecutor beltExecutor)
		{
			_monitorExecutor = new MonitorExecutor();
			_monitorExecutor.Initialize(_planet, subFactoryGraph, optimizedPowerSystemBuilder, beltExecutor);
		}

		private void InitializeSpraycoaters(Graph subFactoryGraph, OptimizedPowerSystemBuilder optimizedPowerSystemBuilder, BeltExecutor beltExecutor)
		{
			_spraycoaterExecutor = new SpraycoaterExecutor();
			_spraycoaterExecutor.Initialize(_planet, this, subFactoryGraph, optimizedPowerSystemBuilder, beltExecutor);
		}

		private void InitializePilers(Graph subFactoryGraph, OptimizedPowerSystemBuilder optimizedPowerSystemBuilder, BeltExecutor beltExecutor)
		{
			_pilerExecutor = new PilerExecutor();
			_pilerExecutor.Initialize(_planet, subFactoryGraph, optimizedPowerSystemBuilder, beltExecutor);
		}

		private void InitializeFractionators(Graph subFactoryGraph, OptimizedPowerSystemBuilder optimizedPowerSystemBuilder, BeltExecutor beltExecutor)
		{
			_fractionatorExecutor = new FractionatorExecutor();
			_fractionatorExecutor.Initialize(_planet, subFactoryGraph, optimizedPowerSystemBuilder, beltExecutor);
		}

		private void InitializeStations(Graph subFactoryGraph, BeltExecutor beltExecutor, VeinMinerExecutor<StationMinerOutput> stationVeinMinerExecutor)
		{
			_stationExecutor = new StationExecutor();
			_stationExecutor.Initialize(_planet, subFactoryGraph, beltExecutor, stationVeinMinerExecutor);
		}

		private void InitializeTanks(Graph subFactoryGraph, BeltExecutor beltExecutor)
		{
			_tankExecutor = new TankExecutor();
			_tankExecutor.Initialize(_planet, subFactoryGraph, beltExecutor);
		}

		private void InitializeBelts(Graph subFactoryGraph, PlanetWideBeltExecutor planetWideBeltExecutor)
		{
			_beltExecutor = new BeltExecutor();
			_beltExecutor.Initialize(_planet, subFactoryGraph);
			planetWideBeltExecutor.AddBeltExecutor(_beltExecutor);
		}

		private void InitializeSplitters(Graph subFactoryGraph, BeltExecutor beltExecutor)
		{
			_splitterExecutor = new SplitterExecutor();
			_splitterExecutor.Initialize(_planet, subFactoryGraph, beltExecutor);
		}

		public void GameTick(WorkerTimings workerTimings, long time)
		{
			MiningFlags miningFlags = new MiningFlags();
			workerTimings.StartTimer();
			_beltVeinMinerExecutor.GameTick(_planet, ref miningFlags);
			_stationVeinMinerExecutor.GameTick(_planet, ref miningFlags);
			_oilMinerExecutor.GameTick(_planet);
			_waterMinerExecutor.GameTick(_planet);
			_assemblerExecutor.GameTick(_planet);
			_fractionatorExecutor.GameTick(_planet);
			_ejectorExecutor.GameTick(_planet, time);
			_siloExecutor.GameTick(_planet);
			_producingLabExecutor.GameTickLabProduceMode(_planet);
			_producingLabExecutor.GameTickLabOutputToNext();
			workerTimings.RecordTime(WorkType.Assembler);
			workerTimings.StartTimer();
			_researchingLabExecutor.GameTickLabResearchMode(_planet);
			_researchingLabExecutor.GameTickLabOutputToNext();
			workerTimings.RecordTime(WorkType.LabResearchMode);
			workerTimings.StartTimer();
			_stationExecutor.StationGameTick(_planet, time, _stationVeinMinerExecutor, ref miningFlags);
			workerTimings.RecordTime(WorkType.TransportData);
			workerTimings.StartTimer();
			_stationExecutor.InputFromBelt(_planet, time);
			workerTimings.RecordTime(WorkType.InputFromBelt);
			workerTimings.StartTimer();
			_optimizedBiInserterExecutor.GameTickInserters(_planet);
			_optimizedInserterExecutor.GameTickInserters(_planet);
			workerTimings.RecordTime(WorkType.InserterData);
			workerTimings.StartTimer();
			_tankExecutor.GameTick();
			workerTimings.RecordTime(WorkType.Storage);
			workerTimings.StartTimer();
			_beltExecutor.GameTick(_planet);
			workerTimings.RecordTime(WorkType.CargoPathsData);
			workerTimings.StartTimer();
			_splitterExecutor.GameTick(_planet, this, _beltExecutor, time);
			workerTimings.RecordTime(WorkType.Splitter);
			workerTimings.StartTimer();
			_monitorExecutor.GameTick(_planet);
			workerTimings.RecordTime(WorkType.Monitor);
			workerTimings.StartTimer();
			_spraycoaterExecutor.GameTick(_planet);
			workerTimings.RecordTime(WorkType.Spraycoater);
			workerTimings.StartTimer();
			_pilerExecutor.GameTick(_planet);
			workerTimings.RecordTime(WorkType.Piler);
			workerTimings.StartTimer();
			_stationExecutor.OutputToBelt(_planet, time);
			workerTimings.RecordTime(WorkType.OutputToBelt);
			_optimizedPlanet.AddMiningFlags(miningFlags);
		}

		public TypedObjectIndex GetAsGranularTypedObjectIndex(int index, PlanetFactory planet)
		{
			ref EntityData reference = ref planet.entityPool[index];
			if (reference.beltId != 0)
			{
				return new TypedObjectIndex(EntityType.Belt, reference.beltId);
			}
			if (reference.assemblerId != 0)
			{
				if (_assemblerExecutor._assemblerIdToOptimizedIndex.TryGetValue(reference.assemblerId, out var value))
				{
					return new TypedObjectIndex(EntityType.Assembler, value);
				}
				if (_assemblerExecutor._unOptimizedAssemblerIds.Contains(reference.assemblerId))
				{
					return TypedObjectIndex.Invalid;
				}
				throw new InvalidOperationException("Failed to convert assembler id into optimized assembler id.");
			}
			if (reference.ejectorId != 0)
			{
				return new TypedObjectIndex(EntityType.Ejector, reference.ejectorId);
			}
			if (reference.siloId != 0)
			{
				return new TypedObjectIndex(EntityType.Silo, reference.siloId);
			}
			if (reference.labId != 0)
			{
				if (planet.factorySystem.labPool[reference.labId].researchMode)
				{
					if (_researchingLabIdToOptimizedIndex.TryGetValue(reference.labId, out var value2))
					{
						return new TypedObjectIndex(EntityType.ResearchingLab, value2);
					}
					if (_researchingLabExecutor._unOptimizedLabIds.Contains(reference.labId))
					{
						return TypedObjectIndex.Invalid;
					}
					throw new InvalidOperationException("Failed to convert researching lab id into optimized lab id.");
				}
				if (_producingLabIdToOptimizedIndex.TryGetValue(reference.labId, out var value3))
				{
					return new TypedObjectIndex(EntityType.ProducingLab, value3);
				}
				if (_producingLabExecutor._unOptimizedLabIds.Contains(reference.labId))
				{
					return TypedObjectIndex.Invalid;
				}
				throw new InvalidOperationException("Failed to convert producing lab id into optimized lab id.");
			}
			if (reference.storageId != 0)
			{
				return new TypedObjectIndex(EntityType.Storage, reference.storageId);
			}
			if (reference.stationId != 0)
			{
				return new TypedObjectIndex(EntityType.Station, reference.stationId);
			}
			if (reference.powerGenId != 0)
			{
				return new TypedObjectIndex(EntityType.PowerGenerator, reference.powerGenId);
			}
			if (reference.splitterId != 0)
			{
				return new TypedObjectIndex(EntityType.Splitter, reference.splitterId);
			}
			if (reference.inserterId != 0)
			{
				return new TypedObjectIndex(EntityType.Inserter, reference.inserterId);
			}
			throw new InvalidOperationException("Unknown entity type.");
		}

		public static int[]? GetEntityNeeds(PlanetFactory planet, int entityIndex)
		{
			ref EntityData reference = ref planet.entityPool[entityIndex];
			if (reference.beltId != 0)
			{
				return null;
			}
			if (reference.assemblerId != 0)
			{
				return planet.factorySystem.assemblerPool[reference.assemblerId].needs ?? throw new InvalidOperationException("Need must not be null for assembler.");
			}
			if (reference.ejectorId != 0)
			{
				ref EjectorComponent reference2 = ref planet.factorySystem.ejectorPool[reference.ejectorId];
				int[] needs = reference2.needs;
				if (needs == null)
				{
					reference2.needs = new int[6];
					planet.entityNeeds[reference2.entityId] = reference2.needs;
					needs = reference2.needs;
				}
				return needs;
			}
			if (reference.siloId != 0)
			{
				ref SiloComponent reference3 = ref planet.factorySystem.siloPool[reference.siloId];
				int[] needs2 = reference3.needs;
				if (needs2 == null)
				{
					reference3.needs = new int[6];
					planet.entityNeeds[reference3.entityId] = reference3.needs;
					needs2 = reference3.needs;
				}
				return needs2;
			}
			if (reference.labId != 0)
			{
				return planet.factorySystem.labPool[reference.labId].needs ?? throw new InvalidOperationException("Need must not be null for lab.");
			}
			if (reference.storageId != 0)
			{
				return null;
			}
			if (reference.stationId != 0)
			{
				return planet.transport.stationPool[reference.stationId].needs ?? throw new InvalidOperationException("Need must not be null for station.");
			}
			if (reference.powerGenId != 0)
			{
				return null;
			}
			if (reference.splitterId != 0)
			{
				return null;
			}
			if (reference.inserterId != 0)
			{
				return null;
			}
			throw new InvalidOperationException("Unknown entity type.");
		}

		public bool InsertCargoIntoStorage(int entityId, ref OptimizedCargo cargo, bool useBan = true)
		{
			int storageId = _planet.entityPool[entityId].storageId;
			if (storageId > 0)
			{
				for (StorageComponent val = _planet.factoryStorage.storagePool[storageId]; val != null; val = val.nextStorage)
				{
					if (!useBan || val.lastFullItem != cargo.item)
					{
						if (AddWholeCargo(val, ref cargo, useBan))
						{
							return true;
						}
						if (val.nextStorage == null)
						{
							return false;
						}
					}
				}
			}
			return false;
		}

		public int PickFromStorageFiltered(int entityId, ref int filter, int count, out int inc)
		{
			inc = 0;
			int num = count;
			int storageId = _planet.entityPool[entityId].storageId;
			if (storageId > 0)
			{
				StorageComponent val = _planet.factoryStorage.storagePool[storageId];
				StorageComponent val2 = val;
				if (val != null)
				{
					int num4 = default(int);
					for (val = val.topStorage; val != null; val = val.previousStorage)
					{
						if (val.lastEmptyItem != 0 && val.lastEmptyItem != filter)
						{
							int num2 = filter;
							int num3 = count;
							val.TakeTailItemsFiltered(ref num2, ref num3, ref num4, _planet.entityPool[val.entityId].battleBaseId > 0);
							count -= num3;
							inc += num4;
							if (num2 > 0)
							{
								filter = num2;
							}
							if (count == 0)
							{
								val.lastEmptyItem = -1;
								return num;
							}
							if (filter >= 0)
							{
								val.lastEmptyItem = filter;
							}
						}
						if (val == val2)
						{
							break;
						}
					}
				}
			}
			return num - count;
		}

		private bool AddWholeCargo(StorageComponent storage, ref OptimizedCargo cargo, bool useBan = false)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Invalid comparison between Unknown and I4
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Invalid comparison between Unknown and I4
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Invalid comparison between Unknown and I4
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Invalid comparison between Unknown and I4
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Invalid comparison between Unknown and I4
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Invalid comparison between Unknown and I4
			if (cargo.item <= 0 || cargo.stack == 0 || cargo.item >= 12000)
			{
				return false;
			}
			bool flag = (int)storage.type > 0;
			if (flag)
			{
				if ((int)storage.type == 1 && !StorageComponent.itemIsFuel[cargo.item])
				{
					return false;
				}
				if ((int)storage.type == 2 && (!StorageComponent.itemIsAmmo[cargo.item] || StorageComponent.itemIsBomb[cargo.item]))
				{
					return false;
				}
				if ((int)storage.type == 3 && !StorageComponent.itemIsBomb[cargo.item])
				{
					return false;
				}
				if ((int)storage.type == 4 && !StorageComponent.itemIsFighter[cargo.item])
				{
					return false;
				}
			}
			bool flag2 = false;
			int num = 0;
			int num2 = (useBan ? (storage.size - storage.bans) : storage.size);
			for (int i = 0; i < num2; i++)
			{
				if (storage.grids[i].itemId == 0)
				{
					if (flag && ((int)storage.type == 8 || storage.grids[i].filter > 0) && cargo.item != storage.grids[i].filter)
					{
						continue;
					}
					if (num == 0)
					{
						num = StorageComponent.itemStackCount[cargo.item];
					}
					storage.grids[i].itemId = cargo.item;
					if (storage.grids[i].filter == 0)
					{
						storage.grids[i].stackSize = num;
					}
				}
				if (storage.grids[i].itemId == cargo.item)
				{
					if (num == 0)
					{
						num = storage.grids[i].stackSize;
					}
					int num3 = num - storage.grids[i].count;
					if (cargo.stack <= num3)
					{
						storage.grids[i].count += cargo.stack;
						storage.grids[i].inc += cargo.inc;
						flag2 = true;
						break;
					}
				}
			}
			if (flag2)
			{
				storage.searchStart = 0;
				storage.lastEmptyItem = -1;
				storage.NotifyStorageChange();
			}
			return flag2;
		}
	}
	internal sealed class OptimizedTerrestrialPlanet : IOptimizedPlanet
	{
		private readonly PlanetFactory _planet;

		private readonly StarClusterResearchManager _starClusterResearchManager;

		private OptimizedSubFactory[] _subFactories;

		private OptimizedPowerSystem _optimizedPowerSystem;

		private TurretExecutor _turretExecutor;

		private WorkStep[] _workSteps;

		private int _workStepsParallelism;

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


		public int OptimizeDelayInTicks { get; set; }

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

		public void Save()
		{
			CargoContainer container = _planet.cargoTraffic.container;
			container.recycleBegin = 0;
			container.recycleEnd = 0;
			container.cursor = 0;
			OptimizedSubFactory[] subFactories = _subFactories;
			for (int i = 0; i < subFactories.Length; i++)
			{
				subFactories[i].Save(container);
			}
			_optimizedPowerSystem.Save(_planet);
			Status = OptimizedPlanetStatus.Stopped;
			_workSteps = null;
			_workStepsParallelism = -1;
		}

		public void Initialize()
		{
			List<Graph> list = Graphifier.ToGraphs(_planet);
			Graphifier.CombineSmallGraphs(list);
			OptimizedPowerSystemBuilder optimizedPowerSystemBuilder = new OptimizedPowerSystemBuilder(_planet);
			PlanetWideBeltExecutor planetWideBeltExecutor = new PlanetWideBeltExecutor();
			TurretExecutorBuilder turretExecutorBuilder = new TurretExecutorBuilder();
			_subFactories = new OptimizedSubFactory[list.Count];
			for (int i = 0; i < _subFactories.Length; i++)
			{
				_subFactories[i] = new OptimizedSubFactory(_planet, this, _starClusterResearchManager);
				_subFactories[i].Initialize(list[i], optimizedPowerSystemBuilder, planetWideBeltExecutor, turretExecutorBuilder);
			}
			_optimizedPowerSystem = optimizedPowerSystemBuilder.Build(planetWideBeltExecutor);
			_turretExecutor = turretExecutorBuilder.Build();
			Status = OptimizedPlanetStatus.Running;
			_workSteps = null;
			_workStepsParallelism = -1;
		}

		public void GameTickDefense(long time)
		{
			bool flag = GameMain.localPlanet == _planet.planet;
			if (Status == OptimizedPlanetStatus.Running)
			{
				DefenseGameTick(_planet.defenseSystem, time);
			}
			else
			{
				_planet.defenseSystem.GameTick(time, flag);
			}
			_planet.planetATField.GameTick(time, flag);
		}

		public WorkStep[] GetMultithreadedWork(int maxParallelism)
		{
			if (_workStepsParallelism != maxParallelism)
			{
				_workSteps = CreateMultithreadedWork(maxParallelism);
				_workStepsParallelism = maxParallelism;
			}
			return _workSteps;
		}

		private WorkStep[] CreateMultithreadedWork(int maxParallelism)
		{
			if (Status == OptimizedPlanetStatus.Stopped)
			{
				return CreateParallelWorkForNonRunningOptimizedPlanet(maxParallelism);
			}
			if (_subFactories.Length == 0)
			{
				return Array.Empty<WorkStep>();
			}
			List<WorkStep> list = new List<WorkStep>();
			List<IWorkChunk> list2 = new List<IWorkChunk>();
			list2.Add(new PlanetWideBeforePower(this));
			OptimizedSubFactory[] subFactories = _subFactories;
			foreach (OptimizedSubFactory subFactory in subFactories)
			{
				list2.Add(new SubFactoryBeforePower(_planet, _optimizedPowerSystem, subFactory));
			}
			list.Add(new WorkStep(list2.ToArray()));
			list.Add(new WorkStep(new IWorkChunk[1]
			{
				new PlanetWidePower(this)
			}));
			List<IWorkChunk> list3 = new List<IWorkChunk>();
			subFactories = _subFactories;
			foreach (OptimizedSubFactory subFactory2 in subFactories)
			{
				list3.Add(new SubFactoryGameTick(subFactory2));
			}
			list.Add(new WorkStep(list3.ToArray()));
			list.Add(new WorkStep(new IWorkChunk[1]
			{
				new PlanetWideTransport(this)
			}));
			list.Add(new WorkStep(new IWorkChunk[1]
			{
				new PlanetWideDigitalSystem(this)
			}));
			return list.ToArray();
		}

		public bool RequestDysonSpherePower()
		{
			if (Status == OptimizedPlanetStatus.Stopped)
			{
				return true;
			}
			_optimizedPowerSystem.RequestDysonSpherePower(_planet);
			return false;
		}

		public void BeforePowerStep(long time)
		{
			_planet.transport.GameTickBeforePower(time, false);
			_planet.defenseSystem.GameTickBeforePower(time, false);
			_planet.digitalSystem.GameTickBeforePower(time, false);
		}

		public void PowerStep(long time)
		{
			_optimizedPowerSystem.GameTick(_planet, time);
		}

		public void TransportGameTick(long time, Vector3 playerPos)
		{
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			PlanetTransport transport = _planet.transport;
			DispenserGameTick_SandboxMode(transport);
			GameHistoryData history = GameMain.history;
			float[] networkServes = transport.powerSystem.networkServes;
			PowerConsumerComponent[] consumerPool = transport.powerSystem.consumerPool;
			double num = Math.Cos((double)history.dispenserDeliveryMaxAngle * Math.PI / 180.0);
			if (num < -0.999)
			{
				num = -1.0;
			}
			playerPos += ((Vector3)(ref playerPos)).normalized * 2.66666f;
			bool playerDeliveryEnabled = transport.playerDeliveryEnabled;
			transport.DeterminePlayerDeliveryEnabled(transport.factory);
			if (playerDeliveryEnabled != transport.playerDeliveryEnabled)
			{
				transport.RefreshDispenserTraffic(-10000);
			}
			for (int i = 1; i < transport.dispenserCursor; i++)
			{
				if (transport.dispenserPool[i] != null && transport.dispenserPool[i].id == i)
				{
					float num2 = networkServes[consumerPool[transport.dispenserPool[i].pcId].networkId];
					transport.dispenserPool[i].InternalTick(transport.factory, transport.factory.entityPool, transport.dispenserPool, playerPos, time, num2, history.logisticCourierSpeedModified, history.logisticCourierCarries, num);
				}
			}
		}

		private static void DispenserGameTick_SandboxMode(PlanetTransport transport)
		{
			if (!GameMain.sandboxToolsEnabled)
			{
				return;
			}
			for (int i = 1; i < transport.dispenserCursor; i++)
			{
				if (transport.dispenserPool[i] != null && transport.dispenserPool[i].id == i)
				{
					transport.dispenserPool[i].UpdateKeepMode();
				}
			}
		}

		public void DigitalSystemStep()
		{
			_planet.digitalSystem.GameTick(false);
		}

		private void DefenseGameTick(DefenseSystem defenseSystem, long tick)
		{
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			GameHistoryData history = GameMain.history;
			_ = GameMain.statistics.production.factoryStatPool[defenseSystem.factory.index].productRegister;
			PowerSystem powerSystem = defenseSystem.factory.powerSystem;
			float[] networkServes = powerSystem.networkServes;
			PowerConsumerComponent[] consumerPool = powerSystem.consumerPool;
			PowerNodeComponent[] nodePool = powerSystem.nodePool;
			EntityData[] entityPool = defenseSystem.factory.entityPool;
			AnimData[] entityAnimPool = defenseSystem.factory.entityAnimPool;
			ref CombatSettings combatSettings = ref defenseSystem.factory.gameData.history.combatSettings;
			CombatUpgradeData combatUpgradeData = default(CombatUpgradeData);
			history.GetCombatUpgradeData(ref combatUpgradeData);
			_ = defenseSystem.factory.gameData.relativePos;
			_ = defenseSystem.factory.gameData.relativeRot;
			_ = defenseSystem.factory.gameData.trashSystem.trashCount;
			defenseSystem.UpdateMatchSpaceEnemies();
			EAggressiveLevel aggressiveLevel = ((CombatSettings)(ref combatSettings)).aggressiveLevel;
			int cursor = defenseSystem.beacons.cursor;
			BeaconComponent[] buffer = defenseSystem.beacons.buffer;
			for (int i = 1; i < cursor; i++)
			{
				ref BeaconComponent reference = ref buffer[i];
				if (reference.id == i)
				{
					float num = networkServes[nodePool[reference.pnId].networkId];
					PrefabDesc val = PlanetFactory.PrefabDescByModelIndex[entityPool[reference.entityId].modelIndex];
					((BeaconComponent)(ref reference)).GameTick(defenseSystem.factory, val, aggressiveLevel, num, tick);
					if (((BeaconComponent)(ref reference)).DeterminActiveEnemyUnits(false, tick))
					{
						((BeaconComponent)(ref reference)).ActiveEnemyUnits_Ground(defenseSystem.factory, val);
					}
					if (((BeaconComponent)(ref reference)).DeterminActiveEnemyUnits(true, tick))
					{
						((BeaconComponent)(ref reference)).ActiveEnemyUnits_Space(defenseSystem.factory, val);
					}
				}
			}
			bool flag = false;
			for (int num2 = defenseSystem.localGlobalTargetCursor - 1; num2 >= 0; num2--)
			{
				defenseSystem.globalTargets[num2].lifeTick--;
				if (defenseSystem.globalTargets[num2].lifeTick <= 0)
				{
					defenseSystem.RemoveGlobalTargets(num2);
					flag = true;
				}
			}
			if (flag)
			{
				defenseSystem.ArrangeGlobalTargets();
			}
			defenseSystem.UpdateOtherGlobalTargets();
			defenseSystem.engagingGaussCount = 0;
			defenseSystem.engagingLaserCount = 0;
			defenseSystem.engagingCannonCount = 0;
			defenseSystem.engagingMissileCount = 0;
			defenseSystem.engagingPlasmaCount = 0;
			defenseSystem.engagingLocalPlasmaCount = 0;
			defenseSystem.engagingTurretTotalCount = 0;
			defenseSystem.turretEnableDefenseSpace = false;
			int num3 = _turretExecutor.GameTick(defenseSystem, tick, ref combatUpgradeData);
			defenseSystem.engagingTurretTotalCount = defenseSystem.engagingGaussCount + defenseSystem.engagingLaserCount + defenseSystem.engagingCannonCount + defenseSystem.engagingPlasmaCount + defenseSystem.engagingMissileCount + defenseSystem.engagingLocalPlasmaCount;
			if (num3 < 300)
			{
				defenseSystem.incomingSupernovaTime = num3;
			}
			else
			{
				defenseSystem.incomingSupernovaTime = 0;
			}
			int cursor2 = defenseSystem.fieldGenerators.cursor;
			FieldGeneratorComponent[] buffer2 = defenseSystem.fieldGenerators.buffer;
			for (int j = 1; j < cursor2; j++)
			{
				ref FieldGeneratorComponent reference2 = ref buffer2[j];
				if (reference2.id == j)
				{
					ref PowerConsumerComponent reference3 = ref consumerPool[reference2.pcId];
					float num4 = networkServes[reference3.networkId];
					((FieldGeneratorComponent)(ref reference2)).InternalUpdate(defenseSystem.factory, (double)num4, ref reference3, ref entityAnimPool[reference2.entityId]);
				}
			}
		}

		public void DefenseGameTickUIThread(long tick)
		{
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			DefenseSystem defenseSystem = _planet.defenseSystem;
			int[] productRegister = GameMain.statistics.production.factoryStatPool[defenseSystem.factory.index].productRegister;
			PowerSystem powerSystem = defenseSystem.factory.powerSystem;
			float[] networkServes = powerSystem.networkServes;
			PowerConsumerComponent[] consumerPool = powerSystem.consumerPool;
			AnimData[] entityAnimPool = defenseSystem.factory.entityAnimPool;
			VectorLF3 relativePos = defenseSystem.factory.gameData.relativePos;
			Quaternion relativeRot = defenseSystem.factory.gameData.relativeRot;
			TrashSystem trashSystem = defenseSystem.factory.gameData.trashSystem;
			bool flag = trashSystem.trashCount > 0;
			float num = 1f / 60f;
			int num2 = (int)(tick % 4);
			BattleBaseComponent[] buffer = defenseSystem.battleBases.buffer;
			for (int i = 1; i < defenseSystem.battleBases.cursor; i++)
			{
				BattleBaseComponent val = buffer[i];
				if (val != null && val.id == i)
				{
					float num3 = networkServes[consumerPool[val.pcId].networkId];
					val.InternalUpdate(num, defenseSystem.factory, num3, ref entityAnimPool[val.entityId]);
					if (flag && val.autoPickEnabled && val.energy > 0 && (long)i % 4L == num2)
					{
						val.AutoPickTrash(defenseSystem.factory, trashSystem, tick, ref relativePos, ref relativeRot, productRegister);
					}
				}
			}
		}

		public void AddMiningFlags(MiningFlags miningFlags)
		{
			if (miningFlags.MiningFlag == 0 && miningFlags.VeinMiningFlag == 0)
			{
				return;
			}
			lock (this)
			{
				PlanetFactory planet = _planet;
				planet._miningFlag |= miningFlags.MiningFlag;
				PlanetFactory planet2 = _planet;
				planet2._veinMiningFlag |= miningFlags.VeinMiningFlag;
			}
		}

		private WorkStep[] CreateParallelWorkForNonRunningOptimizedPlanet(int maxParallelism)
		{
			List<WorkStep> list = new List<WorkStep>();
			int minerCursor = _planet.factorySystem.minerCursor;
			int assemblerCursor = _planet.factorySystem.assemblerCursor;
			int fractionatorCursor = _planet.factorySystem.fractionatorCursor;
			int ejectorCursor = _planet.factorySystem.ejectorCursor;
			int siloCursor = _planet.factorySystem.siloCursor;
			int monitorCursor = _planet.cargoTraffic.monitorCursor;
			int spraycoaterCursor = _planet.cargoTraffic.spraycoaterCursor;
			int pilerCursor = _planet.cargoTraffic.pilerCursor;
			int splitterCursor = _planet.cargoTraffic.splitterCursor;
			int pathCursor = _planet.cargoTraffic.pathCursor;
			int stationCursor = _planet.transport.stationCursor;
			int dispenserCursor = _planet.transport.dispenserCursor;
			int num = stationCursor + dispenserCursor;
			int cursor = _planet.defenseSystem.turrets.cursor;
			int cursor2 = _planet.defenseSystem.fieldGenerators.cursor;
			int cursor3 = _planet.defenseSystem.battleBases.cursor;
			int cursor4 = _planet.digitalSystem.markers.cursor;
			int inserterCursor = _planet.factorySystem.inserterCursor;
			int labCursor = _planet.factorySystem.labCursor;
			int labCursor2 = _planet.factorySystem.labCursor;
			int labCursor3 = _planet.factorySystem.labCursor;
			int storageCursor = _planet.factoryStorage.storageCursor;
			int tankCursor = _planet.factoryStorage.tankCursor;
			int val = (minerCursor + assemblerCursor + fractionatorCursor + ejectorCursor + siloCursor + monitorCursor + spraycoaterCursor + pilerCursor + stationCursor + dispenserCursor + cursor + cursor2 + cursor3 + cursor4 + 4999) / 5000;
			val = Math.Min(val, maxParallelism);
			if (val > 0)
			{
				IWorkChunk[] workChunks = UnOptimizedPlanetWorkChunk.CreateDuplicateChunks(_planet, WorkType.BeforePower, val);
				list.Add(new WorkStep(workChunks));
			}
			if (_planet.powerSystem.netCursor > 0)
			{
				IWorkChunk[] workChunks = UnOptimizedPlanetWorkChunk.CreateDuplicateChunks(_planet, WorkType.Power, 1);
				list.Add(new WorkStep(workChunks));
			}
			int val2 = (minerCursor + assemblerCursor + fractionatorCursor + ejectorCursor + siloCursor + labCursor + 4999) / 5000;
			val2 = Math.Min(val2, maxParallelism);
			if (val2 > 0)
			{
				IWorkChunk[] workChunks = UnOptimizedPlanetWorkChunk.CreateDuplicateChunks(_planet, WorkType.Assembler, val2);
				list.Add(new WorkStep(workChunks));
			}
			if (labCursor2 > 0)
			{
				IWorkChunk[] workChunks = UnOptimizedPlanetWorkChunk.CreateDuplicateChunks(_planet, WorkType.LabResearchMode, 1);
				list.Add(new WorkStep(workChunks));
			}
			int val3 = (labCursor3 + 4999) / 5000;
			val3 = Math.Min(val3, maxParallelism);
			if (val3 > 0)
			{
				IWorkChunk[] workChunks = UnOptimizedPlanetWorkChunk.CreateDuplicateChunks(_planet, WorkType.LabOutput2NextData, val3);
				list.Add(new WorkStep(workChunks));
			}
			if (num > 0)
			{
				IWorkChunk[] workChunks = UnOptimizedPlanetWorkChunk.CreateDuplicateChunks(_planet, WorkType.TransportData, 1);
				list.Add(new WorkStep(workChunks));
			}
			if (stationCursor > 0)
			{
				IWorkChunk[] workChunks = UnOptimizedPlanetWorkChunk.CreateDuplicateChunks(_planet, WorkType.InputFromBelt, 1);
				list.Add(new WorkStep(workChunks));
			}
			if (Math.Min((inserterCursor + 4999) / 5000, maxParallelism) > 0)
			{
				IWorkChunk[] workChunks = UnOptimizedPlanetWorkChunk.CreateDuplicateChunks(_planet, WorkType.InserterData, 1);
				list.Add(new WorkStep(workChunks));
			}
			if (storageCursor + tankCursor > 0)
			{
				IWorkChunk[] workChunks = UnOptimizedPlanetWorkChunk.CreateDuplicateChunks(_planet, WorkType.Storage, 1);
				list.Add(new WorkStep(workChunks));
			}
			int val4 = (pathCursor + 4999) / 5000;
			val4 = Math.Min(val4, maxParallelism);
			if (val4 > 0)
			{
				IWorkChunk[] workChunks = UnOptimizedPlanetWorkChunk.CreateDuplicateChunks(_planet, WorkType.CargoPathsData, val4);
				list.Add(new WorkStep(workChunks));
			}
			if (splitterCursor > 0)
			{
				IWorkChunk[] workChunks = UnOptimizedPlanetWorkChunk.CreateDuplicateChunks(_planet, WorkType.Splitter, 1);
				list.Add(new WorkStep(workChunks));
			}
			if (monitorCursor > 0)
			{
				IWorkChunk[] workChunks = UnOptimizedPlanetWorkChunk.CreateDuplicateChunks(_planet, WorkType.Monitor, 1);
				list.Add(new WorkStep(workChunks));
			}
			if (spraycoaterCursor > 0)
			{
				IWorkChunk[] workChunks = UnOptimizedPlanetWorkChunk.CreateDuplicateChunks(_planet, WorkType.Spraycoater, 1);
				list.Add(new WorkStep(workChunks));
			}
			if (pilerCursor > 0)
			{
				IWorkChunk[] workChunks = UnOptimizedPlanetWorkChunk.CreateDuplicateChunks(_planet, WorkType.Piler, 1);
				list.Add(new WorkStep(workChunks));
			}
			if (stationCursor > 0)
			{
				IWorkChunk[] workChunks = UnOptimizedPlanetWorkChunk.CreateDuplicateChunks(_planet, WorkType.OutputToBelt, 1);
				list.Add(new WorkStep(workChunks));
			}
			int val5 = (num + 4999) / 5000;
			val5 = Math.Min(val5, maxParallelism);
			if (GameMain.sandboxToolsEnabled && val5 > 0)
			{
				IWorkChunk[] workChunks = UnOptimizedPlanetWorkChunk.CreateDuplicateChunks(_planet, WorkType.SandboxMode, val5);
				list.Add(new WorkStep(workChunks));
			}
			int val6 = (pathCursor + 4999) / 5000;
			val6 = Math.Min(val6, maxParallelism);
			if (val6 > 0)
			{
				IWorkChunk[] workChunks = UnOptimizedPlanetWorkChunk.CreateDuplicateChunks(_planet, WorkType.PresentCargoPathsData, val6);
				list.Add(new WorkStep(workChunks));
			}
			if (cursor4 > 0)
			{
				IWorkChunk[] workChunks = UnOptimizedPlanetWorkChunk.CreateDuplicateChunks(_planet, WorkType.Digital, 1);
				list.Add(new WorkStep(workChunks));
			}
			return list.ToArray();
		}
	}
	internal readonly struct TypedObjectIndex
	{
		private const int IndexBitCount = 24;

		private const uint IndexBitMask = 16777215u;

		private const uint EntityTypeMask = 255u;

		private readonly uint _value;

		public static readonly TypedObjectIndex Invalid = new TypedObjectIndex(EntityType.None, 16777215);

		public EntityType EntityType => (EntityType)(_value >> 24);

		public int Index => (int)(0xFFFFFF & _value);

		public TypedObjectIndex(EntityType entityType, int index)
		{
			if (entityType < EntityType.None || entityType > (EntityType)255)
			{
				throw new ArgumentOutOfRangeException("index", $"{entityType} was outside the range {0} to {255u:N0}");
			}
			if (index < 0 || (long)index > 16777215L)
			{
				throw new ArgumentOutOfRangeException("index", $"{index} was outside the range {0} to {16777215u:N0}");
			}
			_value = ((uint)entityType << 24) | (0xFFFFFFu & (uint)index);
		}
	}
}
namespace Weaver.Optimizations.LinearDataAccess.WorkDistributors
{
	internal sealed class PerformanceMonitorUpdater
	{
		private readonly double[] _sumWorkerWorkTypeTimings = new double[ArrayExtensions.GetEnumValuesEnumerable<WorkType>().Max((WorkType x) => (int)x) + 1];

		private readonly HashSet<ECpuWorkEntry> _factoryWorkEntryChildren;

		private readonly Dictionary<WorkType, ECpuWorkEntry[]> _workTypeToCpuWorkEntry = new Dictionary<WorkType, ECpuWorkEntry[]>
		{
			{
				WorkType.BeforePower,
				(ECpuWorkEntry[])(object)new ECpuWorkEntry[1] { (ECpuWorkEntry)9 }
			},
			{
				WorkType.Power,
				(ECpuWorkEntry[])(object)new ECpuWorkEntry[1] { (ECpuWorkEntry)9 }
			},
			{
				WorkType.Construction,
				(ECpuWorkEntry[])(object)new ECpuWorkEntry[1] { (ECpuWorkEntry)21 }
			},
			{
				WorkType.CheckBefore,
				(ECpuWorkEntry[])(object)new ECpuWorkEntry[1]
			},
			{
				WorkType.Assembler,
				(ECpuWorkEntry[])(object)new ECpuWorkEntry[1] { (ECpuWorkEntry)13 }
			},
			{
				WorkType.LabResearchMode,
				(ECpuWorkEntry[])(object)new ECpuWorkEntry[2]
				{
					(ECpuWorkEntry)13,
					(ECpuWorkEntry)18
				}
			},
			{
				WorkType.LabOutput2NextData,
				(ECpuWorkEntry[])(object)new ECpuWorkEntry[2]
				{
					(ECpuWorkEntry)13,
					(ECpuWorkEntry)18
				}
			},
			{
				WorkType.TransportData,
				(ECpuWorkEntry[])(object)new ECpuWorkEntry[1] { (ECpuWorkEntry)22 }
			},
			{
				WorkType.InputFromBelt,
				(ECpuWorkEntry[])(object)new ECpuWorkEntry[1] { (ECpuWorkEntry)20 }
			},
			{
				WorkType.InserterData,
				(ECpuWorkEntry[])(object)new ECpuWorkEntry[1] { (ECpuWorkEntry)11 }
			},
			{
				WorkType.Storage,
				(ECpuWorkEntry[])(object)new ECpuWorkEntry[1] { (ECpuWorkEntry)20 }
			},
			{
				WorkType.CargoPathsData,
				(ECpuWorkEntry[])(object)new ECpuWorkEntry[1] { (ECpuWorkEntry)10 }
			},
			{
				WorkType.Splitter,
				(ECpuWorkEntry[])(object)new ECpuWorkEntry[1] { (ECpuWorkEntry)12 }
			},
			{
				WorkType.Monitor,
				(ECpuWorkEntry[])(object)new ECpuWorkEntry[1] { (ECpuWorkEntry)10 }
			},
			{
				WorkType.Spraycoater,
				(ECpuWorkEntry[])(object)new ECpuWorkEntry[1] { (ECpuWorkEntry)10 }
			},
			{
				WorkType.Piler,
				(ECpuWorkEntry[])(object)new ECpuWorkEntry[1] { (ECpuWorkEntry)10 }
			},
			{
				WorkType.OutputToBelt,
				(ECpuWorkEntry[])(object)new ECpuWorkEntry[1] { (ECpuWorkEntry)20 }
			},
			{
				WorkType.SandboxMode,
				(ECpuWorkEntry[])(object)new ECpuWorkEntry[1] { (ECpuWorkEntry)20 }
			},
			{
				WorkType.PresentCargoPathsData,
				(ECpuWorkEntry[])(object)new ECpuWorkEntry[1] { (ECpuWorkEntry)6 }
			},
			{
				WorkType.Digital,
				(ECpuWorkEntry[])(object)new ECpuWorkEntry[1] { (ECpuWorkEntry)32 }
			}
		};

		private PerformanceMonitorUpdater(HashSet<ECpuWorkEntry> factoryWorkEntryChildren)
		{
			_factoryWorkEntryChildren = factoryWorkEntryChildren;
		}

		public static PerformanceMonitorUpdater Create()
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Invalid comparison between Unknown and I4
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			HashSet<ECpuWorkEntry> hashSet = new HashSet<ECpuWorkEntry>();
			int count;
			do
			{
				count = hashSet.Count;
				for (int i = 0; i < PerformanceMonitor.cpuWorkParents.Length; i++)
				{
					ECpuWorkEntry val = PerformanceMonitor.cpuWorkParents[i];
					if ((int)val == 5 || hashSet.Contains(val))
					{
						hashSet.Add((ECpuWorkEntry)i);
					}
				}
			}
			while (count != hashSet.Count);
			return new PerformanceMonitorUpdater(hashSet);
		}

		public void UpdateTimings(double totalDuration, WorkExecutor[] workExecutors)
		{
			Array.Clear(_sumWorkerWorkTypeTimings, 0, _sumWorkerWorkTypeTimings.Length);
			for (int i = 0; i < workExecutors.Length; i++)
			{
				double[] workTypeTimings = workExecutors[i].GetWorkTypeTimings();
				if (_sumWorkerWorkTypeTimings.Length != workTypeTimings.Length)
				{
					throw new InvalidOperationException($"Work type timing arrays were not the same size. Sum array size: {_sumWorkerWorkTypeTimings.Length}, worker array size: {workTypeTimings.Length}");
				}
				for (int j = 0; j < _sumWorkerWorkTypeTimings.Length; j++)
				{
					_sumWorkerWorkTypeTimings[j] += workTypeTimings[j];
				}
			}
			double num = _sumWorkerWorkTypeTimings.Sum();
			double num2 = totalDuration / num;
			foreach (KeyValuePair<WorkType, ECpuWorkEntry[]> item in _workTypeToCpuWorkEntry)
			{
				for (int k = 0; k < item.Value.Length; k++)
				{
					if (item.Value[k])
					{
						PerformanceMonitor.timeCostsFrame[(int)item.Value[k]] += _sumWorkerWorkTypeTimings[(int)item.Key] * num2;
					}
				}
			}
		}
	}
	internal sealed class PlanetWorkManager
	{
		private WorkStep[] _workSteps;

		private int _currentWorkStepIndex;

		public PlanetFactory Planet { get; }

		public IOptimizedPlanet OptimizedPlanet { get; }

		public PlanetWorkManager(PlanetFactory planet, IOptimizedPlanet optimizedPlanet)
		{
			Planet = planet;
			OptimizedPlanet = optimizedPlanet;
		}

		public void UpdatePlanetWork(int parallelism)
		{
			WorkStep[] multithreadedWork = OptimizedPlanet.GetMultithreadedWork(parallelism);
			if (_workSteps != multithreadedWork && _workSteps != null)
			{
				for (int i = 0; i < _workSteps.Length; i++)
				{
					_workSteps[i].Dispose();
				}
			}
			_workSteps = multithreadedWork;
		}

		public IWorkChunk? TryGetWork(out bool canScheduleMoreWork)
		{
			int currentWorkStepIndex = _currentWorkStepIndex;
			if (currentWorkStepIndex == _workSteps.Length)
			{
				canScheduleMoreWork = false;
				return null;
			}
			bool canNoLongerProvideWork;
			IWorkChunk result = _workSteps[currentWorkStepIndex].TryGetWork(out canNoLongerProvideWork);
			if (currentWorkStepIndex == _workSteps.Length - 1 && canNoLongerProvideWork)
			{
				canScheduleMoreWork = false;
			}
			canScheduleMoreWork = true;
			return result;
		}

		public IWorkChunk? TryWaitForWork()
		{
			int currentWorkStepIndex = _currentWorkStepIndex;
			if (currentWorkStepIndex == _workSteps.Length)
			{
				return null;
			}
			int num = currentWorkStepIndex + 1;
			if (num >= _workSteps.Length)
			{
				return null;
			}
			WorkStep workStep = _workSteps[currentWorkStepIndex];
			bool canNoLongerProvideWork;
			IWorkChunk workChunk = _workSteps[num].TryGetWork(out canNoLongerProvideWork);
			if (workChunk == null)
			{
				return workChunk;
			}
			workStep.WaitForCompletion();
			return workChunk;
		}

		public void CompleteWork(IWorkChunk workChunk)
		{
			if (workChunk.Complete())
			{
				Interlocked.Increment(ref _currentWorkStepIndex);
				workChunk.CompleteStep();
			}
		}

		public void Reset()
		{
			for (int i = 0; i < _workSteps.Length; i++)
			{
				_workSteps[i].Reset();
			}
			_currentWorkStepIndex = 0;
		}
	}
	internal record struct PlanetWorkPlan(PlanetWorkManager PlanetWorkManager, IWorkChunk WorkChunk);
	internal sealed class StarClusterWorkManager
	{
		private