Decompiled source of Weaver v2.1.3
Weaver.dll
Decompiled 3 weeks ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Threading; using System.Threading.Tasks; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using PowerNetworkStructures; using UnityEngine; using UnityEngine.UI; using Weaver.Extensions; using Weaver.FatoryGraphs; using Weaver.Optimizations; using Weaver.Optimizations.Assemblers; using Weaver.Optimizations.Belts; using Weaver.Optimizations.Ejectors; using Weaver.Optimizations.Fractionators; using Weaver.Optimizations.Inserters; using Weaver.Optimizations.Inserters.Types; using Weaver.Optimizations.Labs; using Weaver.Optimizations.Labs.Producing; using Weaver.Optimizations.Labs.Researching; using Weaver.Optimizations.Miners; using Weaver.Optimizations.Monitors; using Weaver.Optimizations.NeedsSystem; using Weaver.Optimizations.Pilers; using Weaver.Optimizations.PowerSystems; using Weaver.Optimizations.PowerSystems.Generators; using Weaver.Optimizations.Silos; using Weaver.Optimizations.Splitters; using Weaver.Optimizations.Spraycoaters; using Weaver.Optimizations.Stations; using Weaver.Optimizations.Statistics; using Weaver.Optimizations.Storages; using Weaver.Optimizations.Tanks; using Weaver.Optimizations.Turrets; using Weaver.Optimizations.WorkDistributors; using Weaver.Optimizations.WorkDistributors.WorkChunks; [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+a2ef1322ca83d0c595f74ac7d406bec9ae5a211f")] [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 System.Diagnostics.CodeAnalysis { [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)] internal sealed class MemberNotNullWhenAttribute : Attribute { public bool ReturnValue { get; } public string[] Members { get; } public MemberNotNullWhenAttribute(bool returnValue, string member) { ReturnValue = returnValue; Members = new string[1] { member }; } public MemberNotNullWhenAttribute(bool returnValue, params string[] members) { ReturnValue = returnValue; Members = members; } } [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] internal sealed class NotNullWhenAttribute : Attribute { public bool ReturnValue { get; } public NotNullWhenAttribute(bool returnValue) { ReturnValue = returnValue; } } } 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; public static int Combine<T>(T value1) { HashCode hashCode = default(HashCode); hashCode.Add(value1); return hashCode.GetHashCode(); } public static int Combine<T1, T2>(T1 value1, T2 value2) { HashCode hashCode = default(HashCode); hashCode.Add(value1); hashCode.Add(value2); return hashCode.GetHashCode(); } public static int Combine<T1, T2, T3>(T1 value1, T2 value2, T3 value3) { HashCode hashCode = default(HashCode); hashCode.Add(value1); hashCode.Add(value2); hashCode.Add(value3); return hashCode.GetHashCode(); } public static int Combine<T1, T2, T3, T4>(T1 value1, T2 value2, T3 value3, T4 value4) { HashCode hashCode = default(HashCode); hashCode.Add(value1); hashCode.Add(value2); hashCode.Add(value3); hashCode.Add(value4); return hashCode.GetHashCode(); } public static int Combine<T1, T2, T3, T4, T5>(T1 value1, T2 value2, T3 value3, T4 value4, T5 value5) { HashCode hashCode = default(HashCode); hashCode.Add(value1); hashCode.Add(value2); hashCode.Add(value3); hashCode.Add(value4); hashCode.Add(value5); return hashCode.GetHashCode(); } public static int Combine<T1, T2, T3, T4, T5, T6>(T1 value1, T2 value2, T3 value3, T4 value4, T5 value5, T6 value6) { HashCode hashCode = default(HashCode); hashCode.Add(value1); hashCode.Add(value2); hashCode.Add(value3); hashCode.Add(value4); hashCode.Add(value5); hashCode.Add(value6); return hashCode.GetHashCode(); } public static int Combine<T1, T2, T3, T4, T5, T6, T7>(T1 value1, T2 value2, T3 value3, T4 value4, T5 value5, T6 value6, T7 value7) { HashCode hashCode = default(HashCode); hashCode.Add(value1); hashCode.Add(value2); hashCode.Add(value3); hashCode.Add(value4); hashCode.Add(value5); hashCode.Add(value6); hashCode.Add(value7); return hashCode.GetHashCode(); } [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 readonly 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 = "2.1.3"; } [BepInPlugin("Weaver", "Weaver", "2.1.3")] public class WeaverFixes : BaseUnityPlugin { private record struct ModIncompatibility(string ModName, string ModGuid, IncompatibilityDegree IncompatibilityDegree, string? IncompatibilityDescription, string TechnicalIncompatibilityDescription); private enum IncompatibilityDegree { PartiallyCompatible, CompletelyIncompatible } internal static ManualLogSource Logger = Logger.CreateLogSource("Weaver"); private const string _ModCompatibilityConfigName = "WarnAboutModIncompatibility"; private static readonly bool _enableDebugOptions = false; private bool _firstUpdate = true; private bool _warnAbountModIncompatibility; private static readonly ModIncompatibility[] _incompatibleMods = new ModIncompatibility[7] { new ModIncompatibility("GenesisBook", "org.LoShin.GenesisBook", IncompatibilityDegree.CompletelyIncompatible, null, "Patches base game code which Weaver never calls."), new ModIncompatibility("Multfuntion mod", "cn.blacksnipe.dsp.Multfuntion_mod", IncompatibilityDegree.PartiallyCompatible, "Some functionality may not work.", "Most patches are for logic that weaver never calls."), new ModIncompatibility("MoreMegaStructure", "Gnimaerd.DSP.plugin.MoreMegaStructure", IncompatibilityDegree.PartiallyCompatible, "Mega structures do not work unless player is present on planet.", "Patches base game code which Weaver never calls."), new ModIncompatibility("VeinityProject", "eirshy.dsp.VeinityProject", IncompatibilityDegree.CompletelyIncompatible, null, "Patches base game code which Weaver never calls."), new ModIncompatibility("PlanetMiner", "crecheng.PlanetMiner", IncompatibilityDegree.CompletelyIncompatible, null, "It depends on the research lab update which weaver never calls for optimized planets."), new ModIncompatibility("SmartTank", "GniMaerd.DSP.plugin.SmartTank", IncompatibilityDegree.PartiallyCompatible, "Well presumably most people will only use it on their first planet? If true then there is no issue.", "Patches base game code which Weaver never calls."), new ModIncompatibility("PlanetwideSpray", "starfi5h.plugin.PlanetwideSpray", IncompatibilityDegree.CompletelyIncompatible, null, "Patches base game code which Weaver never calls.") }; private void Awake() { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Expected O, but got Unknown _warnAbountModIncompatibility = ((BaseUnityPlugin)this).Config.Bind<bool>("Weaver", "WarnAboutModIncompatibility", true, "Displays incompatible mods, if any, on game launch.").Value; Harmony val = new Harmony("Weaver"); val.PatchAll(typeof(KillStatisticsPatches)); val.PatchAll(typeof(TrafficStatisticsPatches)); OptimizedStarCluster.EnableOptimization(val); } public void Update() { if (_firstUpdate) { _firstUpdate = false; if (_warnAbountModIncompatibility) { CheckForAndWarnAboutIncompatibleMods(); } } } private static void CheckForAndWarnAboutIncompatibleMods() { //IL_0178: Unknown result type (might be due to invalid IL or missing references) ModIncompatibility[] array = _incompatibleMods.Where((ModIncompatibility x) => Chainloader.PluginInfos.ContainsKey(x.ModGuid)).ToArray(); if (array.Length == 0) { return; } StringBuilder stringBuilder = new StringBuilder(); ModIncompatibility[] array2 = array.Where((ModIncompatibility x) => x.IncompatibilityDegree == IncompatibilityDegree.CompletelyIncompatible).ToArray(); if (array2.Length != 0) { stringBuilder.AppendLine("The following mods are not compatible with Weaver:"); ModIncompatibility[] array3 = array2; foreach (ModIncompatibility modIncompatibility in array3) { stringBuilder.AppendLine("\t" + modIncompatibility.ModName); } } ModIncompatibility[] array4 = array.Where((ModIncompatibility x) => x.IncompatibilityDegree == IncompatibilityDegree.PartiallyCompatible).ToArray(); if (array4.Length != 0) { if (array2.Length != 0) { stringBuilder.AppendLine(); } stringBuilder.AppendLine("The following mods are partially incompatible. Some functionality will not work with Weaver."); ModIncompatibility[] array3 = array4; foreach (ModIncompatibility modIncompatibility2 in array3) { stringBuilder.AppendLine("\t" + modIncompatibility2.ModName); } } stringBuilder.AppendLine(); stringBuilder.AppendLine("This warning can be disabled by setting the Weaver"); stringBuilder.AppendLine("config WarnAboutModIncompatibility to false."); ((Graphic)UIMessageBox.Show("Incompatible mods", stringBuilder.ToString(), "Close", 0).m_MessageText).rectTransform.sizeDelta = new Vector2((float)Screen.width, (float)Screen.height); } } 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 { internal sealed class DysonSphereManager { private readonly Queue<PlanetFactory> _createDysonSpheresFor = new Queue<PlanetFactory>(); public void AddDysonDysonSphere(PlanetFactory planet) { lock (_createDysonSpheresFor) { _createDysonSpheresFor.Enqueue(planet); } } public void UIThreadCreateDysonSpheres() { try { foreach (PlanetFactory item in _createDysonSpheresFor) { item.CheckOrCreateDysonSphere(); } } finally { _createDysonSpheresFor.Clear(); } } } internal sealed class DysonSphereStatisticsManager { private readonly HashSet<int[]> _dysonSphereProductionRegisters = new HashSet<int[]>(); private const int _sailItemId = 11901; private const int _structureNodeItemId = 11902; private const int _cellItemId = 11903; private static readonly int[] _dysonItemIds = new int[3] { 11901, 11902, 11903 }; public bool IsDysonSphereStatistics(FactoryProductionStat factoryStats) { return _dysonSphereProductionRegisters.Contains(factoryStats.productRegister); } public void FindAllDysonSphereProductRegisters() { for (int i = 0; i < GameMain.data.dysonSpheres.Length; i++) { DysonSphere val = GameMain.data.dysonSpheres[i]; if (val != null) { int[] productRegister = val.productRegister; if (productRegister != null) { _dysonSphereProductionRegisters.Add(productRegister); } } } } public void ClearDysonSphereProductRegisters() { _dysonSphereProductionRegisters.Clear(); } public static void DysonSphereGameTick(FactoryProductionStat factoryStats, long time) { ProductionHelper.PartialProductionStatisticsGameTick(factoryStats, time, _dysonItemIds); } public static void DysonSphereClearRegisters(FactoryProductionStat factoryStats) { int[] dysonItemIds = _dysonItemIds; for (int i = 0; i < dysonItemIds.Length; i++) { factoryStats.productRegister[dysonItemIds[i]] = 0; factoryStats.consumeRegister[dysonItemIds[i]] = 0; } } } 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(); void TransportGameTick(int workerIndex, long time, Vector3 playerPos); IWorkNode 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 { readonly 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); } public override string ToString() { return string.Format("NetworkIdAndState<{0}>\r\n\\t{1}: {2}\r\n\\t{3}: {4:N0}", typeof(T).Name, "State", Enum.GetName(typeof(T), State), "Index", Index); } } internal sealed class OptimizedDysonSphere { private static readonly Dictionary<DysonSphere, OptimizedDysonSphere> _dysonSphereToOptimizedDysonSphere = new Dictionary<DysonSphere, OptimizedDysonSphere>(); private static readonly Dictionary<DysonSwarm, OptimizedDysonSphere> _dysonSwarmToOptimizedDysonSphere = new Dictionary<DysonSwarm, OptimizedDysonSphere>(); private readonly DysonSphere _dysonSphere; private readonly long[] _dysonSphereLayersPowerGenerated; private bool _needToRecalculatePower; public OptimizedDysonSphere(DysonSphere dysonSphere) { _dysonSphere = dysonSphere; _dysonSphereLayersPowerGenerated = new long[dysonSphere.layersSorted.Length]; _needToRecalculatePower = true; } public static void Reset() { _dysonSphereToOptimizedDysonSphere.Clear(); _dysonSwarmToOptimizedDysonSphere.Clear(); if (GameMain.data.dysonSpheres == null) { return; } DysonSphere[] dysonSpheres = GameMain.data.dysonSpheres; foreach (DysonSphere val in dysonSpheres) { if (val != null) { OptimizedDysonSphere value = new OptimizedDysonSphere(val); _dysonSphereToOptimizedDysonSphere.Add(val, value); if (val.swarm != null) { _dysonSwarmToOptimizedDysonSphere.Add(val.swarm, value); } } } } [HarmonyPostfix] [HarmonyPatch(typeof(DysonSphere), "Init")] public static void DysonSphere_Init(DysonSphere __instance) { OptimizedDysonSphere value = new OptimizedDysonSphere(__instance); _dysonSphereToOptimizedDysonSphere.Add(__instance, value); _dysonSwarmToOptimizedDysonSphere.Add(__instance.swarm, value); } [HarmonyPrefix] [HarmonyPatch(typeof(DysonSphere), "ConstructSp")] public static bool DysonSphere_ConstructSp(DysonSphere __instance, DysonNode node) { OptimizedDysonSphere optimizedDysonSphere = GetOptimizedDysonSphere(__instance); object obj = node.ConstructSp(); if (obj == null) { return false; } DysonNode val = (DysonNode)((obj is DysonNode) ? obj : null); if (val != null) { __instance.UpdateProgress(val); optimizedDysonSphere.AddDysonNodeToPowerGenerated(val.layerId - 1); } else { DysonFrame val2 = (DysonFrame)((obj is DysonFrame) ? obj : null); if (val2 != null) { __instance.UpdateProgress(val2); optimizedDysonSphere.AddDysonFrameToPowerGenerated(val2.layerId - 1); } } int[] productRegister = __instance.productRegister; if (productRegister != null) { lock (productRegister) { productRegister[11902]++; } } return false; } [HarmonyPrefix] [HarmonyPatch(typeof(DysonShell), "Construct")] public static void DysonShell_Construct(DysonShell __instance) { GetOptimizedDysonSphere(__instance.dysonSphere).AddDysonShellToPowerGenerated(__instance.layerId - 1); } public static OptimizedDysonSphere GetOptimizedDysonSphere(DysonSphere dysonSphere) { return _dysonSphereToOptimizedDysonSphere[dysonSphere]; } public static OptimizedDysonSphere GetOptimizedDysonSphere(DysonSwarm dysonSwarm) { return _dysonSwarmToOptimizedDysonSphere[dysonSwarm]; } [HarmonyPrefix] [HarmonyPatch(typeof(DysonSphere), "BeforeGameTick")] public static bool DysonSphere_BeforeGameTick_Prefix(DysonSphere __instance) { OptimizedDysonSphere optimizedDysonSphere = GetOptimizedDysonSphere(__instance); if (optimizedDysonSphere.ShouldRecalculatePower()) { return true; } optimizedDysonSphere.OptimizedBeforeGameTick(); return false; } [HarmonyPostfix] [HarmonyPatch(typeof(DysonSphere), "BeforeGameTick")] public static void DysonSphere_BeforeGameTick_Postfix(DysonSphere __instance) { OptimizedDysonSphere optimizedDysonSphere = GetOptimizedDysonSphere(__instance); if (optimizedDysonSphere.ShouldRecalculatePower()) { optimizedDysonSphere.ResetPowerGenerated(); } } public void OptimizedBeforeGameTick() { _dysonSphere.energyReqCurrentTick = 0L; _dysonSphere.energyGenCurrentTick = 0L; _dysonSphere.energyGenOriginalCurrentTick = 0L; _dysonSphere.swarm.energyGenCurrentTick = _dysonSphere.swarm.sailCount * _dysonSphere.energyGenPerSail; DysonSphere dysonSphere = _dysonSphere; dysonSphere.energyGenCurrentTick += _dysonSphere.swarm.energyGenCurrentTick; _dysonSphere.grossRadius = _dysonSphere.swarm.grossRadius; DeepProfiler.BeginSample((DPEntry)55, -1, -1L); long[] dysonSphereLayersPowerGenerated = _dysonSphereLayersPowerGenerated; for (int i = 0; i < dysonSphereLayersPowerGenerated.Length; i++) { DysonSphereLayer val = _dysonSphere.layersSorted[i]; if (val != null) { if (val.grossRadius > _dysonSphere.grossRadius) { _dysonSphere.grossRadius = val.grossRadius; } val.energyGenCurrentTick = dysonSphereLayersPowerGenerated[i]; DysonSphere dysonSphere2 = _dysonSphere; dysonSphere2.energyGenCurrentTick += dysonSphereLayersPowerGenerated[i]; } } DeepProfiler.EndSample((DPEntry)55, -1); _dysonSphere.energyGenOriginalCurrentTick = _dysonSphere.energyGenCurrentTick; _dysonSphere.energyGenCurrentTick = (long)((double)_dysonSphere.energyGenCurrentTick * _dysonSphere.energyDFHivesDebuffCoef); } public void AddDysonNodeToPowerGenerated(int layerIndex) { Interlocked.Add(ref _dysonSphereLayersPowerGenerated[layerIndex], _dysonSphere.energyGenPerNode); } public void AddDysonFrameToPowerGenerated(int layerIndex) { Interlocked.Add(ref _dysonSphereLayersPowerGenerated[layerIndex], _dysonSphere.energyGenPerFrame); } public void AddDysonShellToPowerGenerated(int layerIndex) { Interlocked.Add(ref _dysonSphereLayersPowerGenerated[layerIndex], _dysonSphere.energyGenPerShell); } public void ResetPowerGenerated() { for (int i = 0; i < _dysonSphere.layersSorted.Length; i++) { DysonSphereLayer val = _dysonSphere.layersSorted[i]; if (val == null) { _dysonSphereLayersPowerGenerated[i] = 0L; } else { _dysonSphereLayersPowerGenerated[i] = val.energyGenCurrentTick; } } _needToRecalculatePower = false; } internal void MarkNeedToRecalculatePower() { if (!_needToRecalculatePower) { _needToRecalculatePower = true; } } internal bool ShouldRecalculatePower() { return _needToRecalculatePower; } [HarmonyPrefix] [HarmonyPatch(typeof(DysonSphere), "RemoveLayer", new Type[] { typeof(DysonSphereLayer) })] public static void DysonSphere_RemoveLayerDysonSphereLayer(DysonSphere __instance) { GetOptimizedDysonSphere(__instance).MarkNeedToRecalculatePower(); } [HarmonyPrefix] [HarmonyPatch(typeof(DysonSphere), "RemoveLayer", new Type[] { typeof(int) })] public static void DysonSphere_RemoveLayerId(DysonSphere __instance) { GetOptimizedDysonSphere(__instance).MarkNeedToRecalculatePower(); } [HarmonyPrefix] [HarmonyPatch(typeof(DysonSphere), "AddDysonNodeRData")] public static void DysonSphere_AddDysonNodeRData(DysonSphere __instance) { GetOptimizedDysonSphere(__instance).MarkNeedToRecalculatePower(); } [HarmonyPrefix] [HarmonyPatch(typeof(DysonSphere), "RemoveDysonNodeRData")] public static void DysonSphere_RemoveDysonNodeRData(DysonSphere __instance) { GetOptimizedDysonSphere(__instance).MarkNeedToRecalculatePower(); } [HarmonyPrefix] [HarmonyPatch(typeof(DysonSphere), "AutoConstruct")] public static void DysonSphere_AutoConstruct(DysonSphere __instance) { GetOptimizedDysonSphere(__instance).MarkNeedToRecalculatePower(); } [HarmonyPrefix] [HarmonyPatch(typeof(DysonSwarm), "AutoConstruct")] public static void DysonSwarm_AutoConstruct(DysonSwarm __instance) { GetOptimizedDysonSphere(__instance).MarkNeedToRecalculatePower(); } [HarmonyPrefix] [HarmonyPatch(typeof(DysonSwarm), "RemoveSailsByOrbit")] public static void DysonSwarm_RemoveSailsByOrbit(DysonSwarm __instance) { GetOptimizedDysonSphere(__instance).MarkNeedToRecalculatePower(); } } internal sealed class OptimizedGasPlanet : IOptimizedPlanet { private readonly PlanetFactory _planet; private GasPlanetWideStationExecutor _planetWideStationExecutor; private OptimizedPlanetWideProductionStatistics _optimizedPlanetWideProductionStatistics; private IWorkNode? _workNodes; 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) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Invalid comparison between Unknown and I4 return (int)planet.planet.type == 5; } public void Initialize() { _planetWideStationExecutor = new GasPlanetWideStationExecutor(); _planetWideStationExecutor.Initialize(_planet); PlanetWideProductionRegisterBuilder planetWideProductionRegisterBuilder = new PlanetWideProductionRegisterBuilder(_planet); for (int i = 0; i < _planet.planet.gasItems.Length; i++) { planetWideProductionRegisterBuilder.AdditionalProductItemsIdToWatch(_planet.planet.gasItems[i]); } _optimizedPlanetWideProductionStatistics = planetWideProductionRegisterBuilder.Build(); Status = OptimizedPlanetStatus.Running; _workNodes = null; _workStepsParallelism = -1; } public void Save() { _workNodes = null; _workStepsParallelism = -1; Status = OptimizedPlanetStatus.Stopped; } public void TransportGameTick(int workerIndex, long time, Vector3 playerPos) { MiningFlags miningFlags = new MiningFlags(); _planetWideStationExecutor.StationGameTick(_planet, time, ref miningFlags); if (_planetWideStationExecutor.Count > 0) { DeepProfiler.BeginSample((DPEntry)36, workerIndex, (long)_planet.planetId); DeepProfiler.BeginMajorSample((DPEntry)37, workerIndex, -1L); _planetWideStationExecutor.StationGameTick(_planet, time, ref miningFlags); DeepProfiler.EndMajorSample((DPEntry)37, workerIndex); DeepProfiler.EndSample((DPEntry)36, workerIndex); } PlanetFactory planet = _planet; planet._miningFlag |= miningFlags.MiningFlag; PlanetFactory planet2 = _planet; planet2._veinMiningFlag |= miningFlags.VeinMiningFlag; DeepProfiler.BeginSample((DPEntry)75, workerIndex, -1L); FactoryProductionStat obj = GameMain.statistics.production.factoryStatPool[_planet.index]; int[] productRegister = obj.productRegister; int[] consumeRegister = obj.consumeRegister; _optimizedPlanetWideProductionStatistics.UpdateStatistics(time, productRegister, consumeRegister); DeepProfiler.EndSample((DPEntry)75, workerIndex); } public IWorkNode GetMultithreadedWork(int maxParallelism) { if (_workNodes == null || _workStepsParallelism != maxParallelism) { _workNodes = CreateMultithreadedWork(maxParallelism); _workStepsParallelism = maxParallelism; } return _workNodes; } private IWorkNode CreateMultithreadedWork(int maxParallelism) { if (Status == OptimizedPlanetStatus.Stopped) { return CreateParallelWorkForNonRunningOptimizedPlanet(maxParallelism); } if (_planetWideStationExecutor.Count > 0) { return new WorkLeaf(new IWorkChunk[1] { new PlanetWideTransport(this) }); } return new NoWorkNode(); } private IWorkNode CreateParallelWorkForNonRunningOptimizedPlanet(int maxParallelism) { if (_planet.transport.stationCursor > 0) { IWorkChunk[] workNodes = UnOptimizedPlanetWorkChunk.CreateDuplicateChunks(_planet, WorkType.TransportData, 1); return new WorkLeaf(workNodes); } return new NoWorkNode(); } } internal enum OptimizedPlanetStatus { Running, Stopped } internal static class OptimizedStarCluster { private static readonly Dictionary<PlanetFactory, IOptimizedPlanet> _planetToOptimizedPlanet = new Dictionary<PlanetFactory, IOptimizedPlanet>(); private static readonly Dictionary<FactoryProductionStat, IOptimizedPlanet> _planetProductionStatisticsToOptimizedPlanet = new Dictionary<FactoryProductionStat, 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(); public static readonly DysonSphereManager _dysonSphereManager = new DysonSphereManager(); private static readonly DysonSphereStatisticsManager _dysonSphereStatisticsManager = new DysonSphereStatisticsManager(); private static readonly UniverseStaticDataBuilder _universeStaticDataBuilder = new UniverseStaticDataBuilder(); private static readonly WorkStealingMultiThreadedFactorySimulation _workStealingMultiThreadedFactorySimulation = new WorkStealingMultiThreadedFactorySimulation(_starClusterResearchManager, _dysonSphereManager, _universeStaticDataBuilder); private static bool _clearOptimizedPlanetsOnNextTick = false; private static bool _firstUpdate = true; private static bool _programShutdown = false; private static readonly Random random = new Random(); private static bool _debugEnableHeavyReOptimization = false; private static bool _enableStatistics = false; public static bool ForceOptimizeLocalPlanet { get; set; } = false; public static void EnableOptimization(Harmony harmony) { harmony.PatchAll(typeof(OptimizedStarCluster)); harmony.PatchAll(typeof(OptimizedDysonSphere)); } public static void DebugEnableHeavyReOptimization() { _debugEnableHeavyReOptimization = true; } public static void EnableStatistics() { _enableStatistics = true; } public static IOptimizedPlanet GetOptimizedPlanet(PlanetFactory planet) { return _planetToOptimizedPlanet[planet]; } public static bool TryGetOptimizedPlanet(FactoryProductionStat productionStatistics, [NotNullWhen(true)] out IOptimizedPlanet? optimizedPlanet) { return _planetProductionStatisticsToOptimizedPlanet.TryGetValue(productionStatistics, out optimizedPlanet); } public static IEnumerable<IOptimizedPlanet> GetAllOptimizedPlanets() { return _planetToOptimizedPlanet.Values; } [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"); PrepareOptimizedStarClusterForGame(); for (int i = 0; i < GameMain.data.factoryCount; i++) { TryAddNewPlanet(GameMain.data.factories[i]); } OptimizedDysonSphere.Reset(); _dysonSphereStatisticsManager.FindAllDysonSphereProductRegisters(); } [HarmonyPrefix] [HarmonyPatch(typeof(DSPGame), "ExitProgram")] private static void DSPGame_ExitProgram() { WeaverFixes.Logger.LogInfo((object)"Stopping simulation threads."); _workStealingMultiThreadedFactorySimulation.Dispose(); _programShutdown = true; } private static void PrepareOptimizedStarClusterForGame() { _clearOptimizedPlanetsOnNextTick = false; _firstUpdate = true; _planetToOptimizedPlanet.Clear(); _planetProductionStatisticsToOptimizedPlanet.Clear(); _dysonSphereStatisticsManager.ClearDysonSphereProductRegisters(); _universeStaticDataBuilder.Clear(); _workStealingMultiThreadedFactorySimulation.Clear(); KillStatisticsPatches.Clear(); TrafficStatisticsPatches.Clear(); } private static void TryAddNewPlanet(PlanetFactory planet) { if (planet.factorySystem != null) { if (OptimizedGasPlanet.IsGasPlanet(planet)) { OptimizedGasPlanet value = new OptimizedGasPlanet(planet); _planetToOptimizedPlanet.Add(planet, value); _planetProductionStatisticsToOptimizedPlanet.Add(GameMain.statistics.production.factoryStatPool[planet.index], value); } else { OptimizedTerrestrialPlanet value2 = new OptimizedTerrestrialPlanet(planet, _starClusterResearchManager, _dysonSphereManager, _universeStaticDataBuilder); _planetToOptimizedPlanet.Add(planet, value2); _planetProductionStatisticsToOptimizedPlanet.Add(GameMain.statistics.production.factoryStatPool[planet.index], value2); } } } [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(GameThreadController), "LogicFrame")] public static bool GameThreadController_LogicFrame(GameThreadController __instance) { if (_programShutdown) { return true; } if (_clearOptimizedPlanetsOnNextTick) { PrepareOptimizedStarClusterForGame(); } lock (_newPlanets) { if (_newPlanets.Count > 0) { while (_newPlanets.Count > 0) { PlanetFactory val = _newPlanets.Dequeue(); WeaverFixes.Logger.LogInfo((object)("Adding planet: " + val.planet.displayName)); TryAddNewPlanet(val); } _dysonSphereStatisticsManager.FindAllDysonSphereProductRegisters(); } } foreach (KeyValuePair<PlanetFactory, IOptimizedPlanet> item in _planetToOptimizedPlanet) { if (GameMain.localPlanet?.factory != item.Key || ForceOptimizeLocalPlanet) { 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 (_firstUpdate) { _firstUpdate = false; if (_enableStatistics) { _workStealingMultiThreadedFactorySimulation.PrintWorkStatistics(); } } if (_planetsToReOptimize.Count > 0) { PlanetFactory val2 = _planetsToReOptimize.Dequeue(); IOptimizedPlanet optimizedPlanet = _planetToOptimizedPlanet[val2]; if (optimizedPlanet.Status == OptimizedPlanetStatus.Stopped) { return false; } 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]); } DeepProfiler.BeginSample((DPEntry)82, -1, 2L); __instance.EnsureThreadCount(); __instance.threadManager.samplePerformanceCounters = DeepProfiler.watchEnabled; DeepProfiler.EndSample(-1, -2L); ExecuteSimulation(__instance.gameLogic, GameMain.data.factories); return false; } [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), "KillEntityFinally")] public static void PlanetFactory_KillEntityFinally(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(); } [HarmonyPrefix] [HarmonyPatch(typeof(ProductionStatistics), "RefreshPowerGenerationCapacitesWithFactory")] public static bool ProductionStatistics_RefreshPowerGenerationCapacitesWithFactory(ProductionStatistics __instance, PlanetFactory factory) { if (factory == null) { return true; } IOptimizedPlanet optimizedPlanet = GetOptimizedPlanet(factory); if (optimizedPlanet.Status == OptimizedPlanetStatus.Stopped) { return true; } if (!(optimizedPlanet is OptimizedTerrestrialPlanet optimizedTerrestrialPlanet)) { return true; } optimizedTerrestrialPlanet.RefreshPowerGenerationCapacites(__instance, factory); return false; } [HarmonyPrefix] [HarmonyPatch(typeof(ProductionStatistics), "RefreshPowerConsumptionDemandsWithFactory")] public static bool ProductionStatistics_RefreshPowerConsumptionDemandsWithFactory(ProductionStatistics __instance, PlanetFactory factory) { if (factory == null) { return true; } IOptimizedPlanet optimizedPlanet = GetOptimizedPlanet(factory); if (optimizedPlanet.Status == OptimizedPlanetStatus.Stopped) { return true; } if (!(optimizedPlanet is OptimizedTerrestrialPlanet optimizedTerrestrialPlanet)) { return true; } optimizedTerrestrialPlanet.RefreshPowerConsumptionDemands(__instance, factory); return false; } [HarmonyPrefix] [HarmonyPatch(typeof(FactoryProductionStat), "GameTick")] public static bool FactoryProductionStat_GameTick(FactoryProductionStat __instance, long time) { if (_dysonSphereStatisticsManager.IsDysonSphereStatistics(__instance)) { DysonSphereStatisticsManager.DysonSphereGameTick(__instance, time); } if (!TryGetOptimizedPlanet(__instance, out IOptimizedPlanet optimizedPlanet)) { return true; } if (optimizedPlanet.Status == OptimizedPlanetStatus.Stopped) { return true; } return false; } [HarmonyPrefix] [HarmonyPatch(typeof(FactoryProductionStat), "ClearRegisters")] public static bool FactoryProductionStat_ClearRegisters(FactoryProductionStat __instance) { if (_dysonSphereStatisticsManager.IsDysonSphereStatistics(__instance)) { DysonSphereStatisticsManager.DysonSphereClearRegisters(__instance); } if (!TryGetOptimizedPlanet(__instance, out IOptimizedPlanet optimizedPlanet)) { return true; } if (optimizedPlanet.Status == OptimizedPlanetStatus.Stopped) { return true; } __instance.powerGenRegister = 0L; __instance.powerConRegister = 0L; __instance.powerDisRegister = 0L; __instance.powerChaRegister = 0L; __instance.hashRegister = 0L; return false; } [HarmonyPrefix] [HarmonyPatch(typeof(DeepProfiler), "BeginSample")] public static void DeepProfiler_BeginSample(DPEntry entry, ref int thread, long detail) { UpdateThreadIndexIfRequired(ref thread); } [HarmonyPrefix] [HarmonyPatch(typeof(DeepProfiler), "EndSample", new Type[] { typeof(int), typeof(long) })] public static void DeepProfiler_EndSampleNonTyped(ref int thread, long detail) { UpdateThreadIndexIfRequired(ref thread); } [HarmonyPrefix] [HarmonyPatch(typeof(DeepProfiler), "EndSample", new Type[] { typeof(DPEntry), typeof(int) })] public static void DeepProfiler_EndSampleTyped(DPEntry entry, ref int thread) { UpdateThreadIndexIfRequired(ref thread); } 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(GameLogic gameLogic, PlanetFactory?[] planets) { _workStealingMultiThreadedFactorySimulation.Simulate(gameLogic, planets); } 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; } private static void UpdateThreadIndexIfRequired(ref int thread) { if (thread == -1) { int? value = ThreadLocalData.ThreadIndex.Value; if (value.HasValue) { thread = value.Value; } } } } internal sealed class OptimizedSubFactory { private readonly PlanetFactory _planet; private readonly OptimizedTerrestrialPlanet _optimizedPlanet; private readonly StarClusterResearchManager _starClusterResearchManager; private readonly UniverseStaticDataBuilder _universeStaticDataBuilder; private OptimizedProductionStatistics _optimizedProductionStatistics; private SubFactoryNeeds _subFactoryNeeds; public InserterExecutor<OptimizedBiInserter, BiInserterGrade> _optimizedBiInserterExecutor; public InserterExecutor<OptimizedInserter, InserterGrade> _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 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 bool HasCalculatedPowerConsumption; public OptimizedSubFactory(PlanetFactory planet, OptimizedTerrestrialPlanet optimizedTerrestrialPlanet, StarClusterResearchManager starClusterResearchManager, UniverseStaticDataBuilder universeStaticDataBuilder) { _planet = planet; _optimizedPlanet = optimizedTerrestrialPlanet; _starClusterResearchManager = starClusterResearchManager; _universeStaticDataBuilder = universeStaticDataBuilder; } 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, _subFactoryNeeds); _producingLabExecutor.Save(_planet, _subFactoryNeeds); _researchingLabExecutor.Save(_planet, _subFactoryNeeds); _spraycoaterExecutor.Save(_planet); _fractionatorExecutor.Save(_planet); _tankExecutor.Save(_planet); _siloExecutor.Save(_planet, _subFactoryNeeds); _ejectorExecutor.Save(_planet, _subFactoryNeeds); } public void Initialize(Graph subFactoryGraph, OptimizedPowerSystemBuilder optimizedPowerSystemBuilder, PlanetWideBeltExecutor planetWideBeltExecutor, TurretExecutorBuilder turretExecutorBuilder, PlanetWideProductionRegisterBuilder planetWideProductionRegisterBuilder, SubFactoryProductionRegisterBuilder subFactoryProductionRegisterBuilder, OptimizedItemId[]?[]? fuelNeeds) { SubFactoryPowerSystemBuilder subFactoryPowerSystemBuilder = optimizedPowerSystemBuilder.AddSubFactory(this); SubFactoryNeedsBuilder subFactoryNeedsBuilder = new SubFactoryNeedsBuilder(); InitializeBelts(subFactoryGraph, planetWideBeltExecutor); InitializeAssemblers(subFactoryGraph, subFactoryPowerSystemBuilder, subFactoryProductionRegisterBuilder, subFactoryNeedsBuilder); InitializeMiners(subFactoryGraph, subFactoryPowerSystemBuilder, subFactoryProductionRegisterBuilder, _beltExecutor); InitializeStations(subFactoryGraph, _beltExecutor, _stationVeinMinerExecutor); InitializeEjectors(subFactoryGraph, subFactoryPowerSystemBuilder, subFactoryProductionRegisterBuilder, subFactoryNeedsBuilder); InitializeSilos(subFactoryGraph, subFactoryPowerSystemBuilder, subFactoryProductionRegisterBuilder, subFactoryNeedsBuilder); InitializeLabAssemblers(subFactoryGraph, subFactoryPowerSystemBuilder, subFactoryProductionRegisterBuilder, subFactoryNeedsBuilder); InitializeResearchingLabs(subFactoryGraph, subFactoryPowerSystemBuilder, subFactoryProductionRegisterBuilder, subFactoryNeedsBuilder); _subFactoryNeeds = subFactoryNeedsBuilder.Build(); InitializeInserters(subFactoryGraph, subFactoryPowerSystemBuilder, _beltExecutor, fuelNeeds, _subFactoryNeeds); InitializeMonitors(subFactoryGraph, subFactoryPowerSystemBuilder, _beltExecutor); InitializeSpraycoaters(subFactoryGraph, subFactoryPowerSystemBuilder, subFactoryProductionRegisterBuilder, _beltExecutor); InitializePilers(subFactoryGraph, subFactoryPowerSystemBuilder, _beltExecutor); InitializeFractionators(subFactoryGraph, subFactoryPowerSystemBuilder, subFactoryProductionRegisterBuilder, _beltExecutor); InitializeTanks(subFactoryGraph, _beltExecutor); InitializeSplitters(subFactoryGraph, _beltExecutor); turretExecutorBuilder.Initialize(_planet, subFactoryGraph, planetWideProductionRegisterBuilder, _beltExecutor); _optimizedProductionStatistics = subFactoryProductionRegisterBuilder.Build(); HasCalculatedPowerConsumption = false; } private void InitializeInserters(Graph subFactoryGraph, SubFactoryPowerSystemBuilder subFactoryPowerSystemBuilder, BeltExecutor beltExecutor, OptimizedItemId[]?[]? fuelNeeds, SubFactoryNeeds subFactoryNeeds) { _optimizedBiInserterExecutor = new InserterExecutor<OptimizedBiInserter, BiInserterGrade>(_assemblerExecutor._assemblerNetworkIdAndStates, _producingLabNetworkIdAndStates, _researchingLabNetworkIdAndStates, subFactoryPowerSystemBuilder.FuelGeneratorSegments, fuelNeeds, subFactoryNeeds, _assemblerExecutor._producedSize, _assemblerExecutor._served, _assemblerExecutor._incServed, _assemblerExecutor._produced, _assemblerExecutor._assemblerRecipeIndexes, _assemblerExecutor._needToUpdateNeeds, _producingLabExecutor._producedSize, _producingLabExecutor._served, _producingLabExecutor._incServed, _producingLabExecutor._produced, _producingLabExecutor._labRecipeIndexes, _researchingLabExecutor._matrixServed, _researchingLabExecutor._matrixIncServed, _siloExecutor._siloIndexes, _ejectorExecutor._ejectorIndexes, _universeStaticDataBuilder.UniverseStaticData); _optimizedBiInserterExecutor.Initialize(_planet, this, subFactoryGraph, (InserterComponent x) => x.bidirectional, subFactoryPowerSystemBuilder.CreateBiInserterBuilder(), beltExecutor, _universeStaticDataBuilder.BiInserterGrades); _optimizedInserterExecutor = new InserterExecutor<OptimizedInserter, InserterGrade>(_assemblerExecutor._assemblerNetworkIdAndStates, _producingLabNetworkIdAndStates, _researchingLabNetworkIdAndStates, subFactoryPowerSystemBuilder.FuelGeneratorSegments, fuelNeeds, subFactoryNeeds, _assemblerExecutor._producedSize, _assemblerExecutor._served, _assemblerExecutor._incServed, _assemblerExecutor._produced, _assemblerExecutor._assemblerRecipeIndexes, _assemblerExecutor._needToUpdateNeeds, _producingLabExecutor._producedSize, _producingLabExecutor._served, _producingLabExecutor._incServed, _producingLabExecutor._produced, _producingLabExecutor._labRecipeIndexes, _researchingLabExecutor._matrixServed, _researchingLabExecutor._matrixIncServed, _siloExecutor._siloIndexes, _ejectorExecutor._ejectorIndexes, _universeStaticDataBuilder.UniverseStaticData); _optimizedInserterExecutor.Initialize(_planet, this, subFactoryGraph, (InserterComponent x) => !x.bidirectional, subFactoryPowerSystemBuilder.CreateInserterBuilder(), beltExecutor, _universeStaticDataBuilder.InserterGrades); } private void InitializeAssemblers(Graph subFactoryGraph, SubFactoryPowerSystemBuilder subFactoryPowerSystemBuilder, SubFactoryProductionRegisterBuilder subFactoryProductionRegisterBuilder, SubFactoryNeedsBuilder subFactoryNeedsBuilder) { _assemblerExecutor = new AssemblerExecutor(); _assemblerExecutor.InitializeAssemblers(_planet, subFactoryGraph, subFactoryPowerSystemBuilder, subFactoryProductionRegisterBuilder, subFactoryNeedsBuilder, _universeStaticDataBuilder); } private void InitializeMiners(Graph subFactoryGraph, SubFactoryPowerSystemBuilder subFactoryPowerSystemBuilder, SubFactoryProductionRegisterBuilder subFactoryProductionRegisterBuilder, BeltExecutor beltExecutor) { _beltVeinMinerExecutor = new VeinMinerExecutor<BeltMinerOutput>(); _beltVeinMinerExecutor.Initialize(_planet, subFactoryGraph, subFactoryPowerSystemBuilder.CreateBeltVeinMinerBuilder(), subFactoryProductionRegisterBuilder, beltExecutor); _stationVeinMinerExecutor = new VeinMinerExecutor<StationMinerOutput>(); _stationVeinMinerExecutor.Initialize(_planet, subFactoryGraph, subFactoryPowerSystemBuilder.CreateStationVeinMinerBuilder(), subFactoryProductionRegisterBuilder, beltExecutor); _oilMinerExecutor = new OilMinerExecutor(); _oilMinerExecutor.Initialize(_planet, subFactoryGraph, subFactoryPowerSystemBuilder, subFactoryProductionRegisterBuilder, beltExecutor); _waterMinerExecutor = new WaterMinerExecutor(); _waterMinerExecutor.Initialize(_planet, subFactoryGraph, subFactoryPowerSystemBuilder, subFactoryProductionRegisterBuilder, beltExecutor); } private void InitializeEjectors(Graph subFactoryGraph, SubFactoryPowerSystemBuilder subFactoryPowerSystemBuilder, SubFactoryProductionRegisterBuilder subFactoryProductionRegisterBuilder, SubFactoryNeedsBuilder subFactoryNeedsBuilder) { _ejectorExecutor = new EjectorExecutor(); _ejectorExecutor.Initialize(_planet, subFactoryGraph, subFactoryPowerSystemBuilder, subFactoryProductionRegisterBuilder, subFactoryNeedsBuilder); } private void InitializeSilos(Graph subFactoryGraph, SubFactoryPowerSystemBuilder subFactoryPowerSystemBuilder, SubFactoryProductionRegisterBuilder subFactoryProductionRegisterBuilder, SubFactoryNeedsBuilder subFactoryNeedsBuilder) { _siloExecutor = new SiloExecutor(); _siloExecutor.Initialize(_planet, subFactoryGraph, subFactoryPowerSystemBuilder, subFactoryProductionRegisterBuilder, subFactoryNeedsBuilder); } private void InitializeLabAssemblers(Graph subFactoryGraph, SubFactoryPowerSystemBuilder subFactoryPowerSystemBuilder, SubFactoryProductionRegisterBuilder subFactoryProductionRegisterBuilder, SubFactoryNeedsBuilder subFactoryNeedsBuilder) { _producingLabExecutor = new ProducingLabExecutor(); _producingLabExecutor.Initialize(_planet, subFactoryGraph, subFactoryPowerSystemBuilder, subFactoryProductionRegisterBuilder, subFactoryNeedsBuilder, _universeStaticDataBuilder); _producingLabNetworkIdAndStates = _producingLabExecutor._networkIdAndStates; _optimizedProducingLabs = _producingLabExecutor._optimizedLabs; _producingLabIdToOptimizedIndex = _producingLabExecutor._labIdToOptimizedLabIndex; } private void InitializeResearchingLabs(Graph subFactoryGraph, SubFactoryPowerSystemBuilder subFactoryPowerSystemBuilder, SubFactoryProductionRegisterBuilder subFactoryProductionRegisterBuilder, SubFactoryNeedsBuilder subFactoryNeedsBuilder) { _researchingLabExecutor = new ResearchingLabExecutor(_starClusterResearchManager); _researchingLabExecutor.Initialize(_planet, subFactoryGraph, subFactoryPowerSystemBuilder, subFactoryProductionRegisterBuilder, subFactoryNeedsBuilder); _researchingLabNetworkIdAndStates = _researchingLabExecutor._networkIdAndStates; _optimizedResearchingLabs = _researchingLabExecutor._optimizedLabs; _researchingLabIdToOptimizedIndex = _researchingLabExecutor._labIdToOptimizedLabIndex; } private void InitializeMonitors(Graph subFactoryGraph, SubFactoryPowerSystemBuilder subFactoryPowerSystemBuilder, BeltExecutor beltExecutor) { _monitorExecutor = new MonitorExecutor(); _monitorExecutor.Initialize(_planet, subFactoryGraph, subFactoryPowerSystemBuilder, beltExecutor); } private void InitializeSpraycoaters(Graph subFactoryGraph, SubFactoryPowerSystemBuilder subFactoryPowerSystemBuilder, SubFactoryProductionRegisterBuilder subFactoryProductionRegisterBuilder, BeltExecutor beltExecutor) { _spraycoaterExecutor = new SpraycoaterExecutor(); _spraycoaterExecutor.Initialize(_planet, subFactoryGraph, subFactoryPowerSystemBuilder, subFactoryProductionRegisterBuilder, beltExecutor); } private void InitializePilers(Graph subFactoryGraph, SubFactoryPowerSystemBuilder subFactoryPowerSystemBuilder, BeltExecutor beltExecutor) { _pilerExecutor = new PilerExecutor(); _pilerExecutor.Initialize(_planet, subFactoryGraph, subFactoryPowerSystemBuilder, beltExecutor); } private void InitializeFractionators(Graph subFactoryGraph, SubFactoryPowerSystemBuilder subFactoryPowerSystemBuilder, SubFactoryProductionRegisterBuilder subFactoryProductionRegisterBuilder, BeltExecutor beltExecutor) { _fractionatorExecutor = new FractionatorExecutor(); _fractionatorExecutor.Initialize(_planet, subFactoryGraph, subFactoryPowerSystemBuilder, subFactoryProductionRegisterBuilder, beltExecutor, _universeStaticDataBuilder); } 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(int workerIndex, long time, SubFactoryPowerConsumption powerSystem) { MiningFlags miningFlags = new MiningFlags(); long[] networksPowerConsumption = powerSystem.NetworksPowerConsumption; Array.Clear(networksPowerConsumption, 0, networksPowerConsumption.Length); int[] productRegister = _optimizedProductionStatistics.ProductRegister; int[] consumeRegister = _optimizedProductionStatistics.ConsumeRegister; if (_beltVeinMinerExecutor.Count + _stationVeinMinerExecutor.Count + _oilMinerExecutor.Count + _waterMinerExecutor.Count > 0) { DeepProfiler.BeginSample((DPEntry)19, workerIndex, -1L); _beltVeinMinerExecutor.GameTick(_planet, powerSystem.BeltVeinMinerPowerConsumerTypeIndexes, powerSystem.PowerConsumerTypes, networksPowerConsumption, productRegister, ref miningFlags, _beltExecutor.OptimizedCargoPaths); _stationVeinMinerExecutor.GameTick(_planet, powerSystem.StationVeinMinerPowerConsumerTypeIndexes, powerSystem.PowerConsumerTypes, networksPowerConsumption, productRegister, ref miningFlags, _beltExecutor.OptimizedCargoPaths); _oilMinerExecutor.GameTick(_planet, powerSystem.OilMinerPowerConsumerTypeIndexes, powerSystem.PowerConsumerTypes, networksPowerConsumption, productRegister, _beltExecutor.OptimizedCargoPaths); _waterMinerExecutor.GameTick(_planet, powerSystem.WaterMinerPowerConsumerTypeIndexes, powerSystem.PowerConsumerTypes, networksPowerConsumption, productRegister, _beltExecutor.OptimizedCargoPaths); DeepProfiler.EndSample((DPEntry)19, workerIndex); } if (_assemblerExecutor.Count > 0) { DeepProfiler.BeginSample((DPEntry)20, workerIndex, -1L); _assemblerExecutor.GameTick(_planet, powerSystem.AssemblerPowerConsumerTypeIndexes, powerSystem.PowerConsumerTypes, networksPowerConsumption, productRegister, consumeRegister, _subFactoryNeeds, _universeStaticDataBuilder.UniverseStaticData); DeepProfiler.EndSample((DPEntry)20, workerIndex); } if (_fractionatorExecutor.Count > 0) { DeepProfiler.BeginSample((DPEntry)21, workerIndex, -1L); _fractionatorExecutor.GameTick(_planet, powerSystem.FractionatorPowerConsumerTypeIndexes, powerSystem.PowerConsumerTypes, networksPowerConsumption, productRegister, consumeRegister, _beltExecutor.OptimizedCargoPaths, _universeStaticDataBuilder.UniverseStaticData); DeepProfiler.EndSample((DPEntry)21, workerIndex); } if (_ejectorExecutor.Count > 0) { DeepProfiler.BeginSample((DPEntry)22, workerIndex, -1L); _ejectorExecutor.GameTick(_planet, time, powerSystem.EjectorPowerConsumerTypeIndexes, powerSystem.PowerConsumerTypes, networksPowerConsumption, consumeRegister, _subFactoryNeeds); DeepProfiler.EndSample((DPEntry)22, workerIndex); } if (_siloExecutor.Count > 0) { DeepProfiler.BeginSample((DPEntry)23, workerIndex, -1L); _siloExecutor.GameTick(_planet, powerSystem.SiloPowerConsumerTypeIndexes, powerSystem.PowerConsumerTypes, networksPowerConsumption, consumeRegister, _subFactoryNeeds); DeepProfiler.EndSample((DPEntry)23, workerIndex); } if (_producingLabExecutor.Count + _researchingLabExecutor.Count > 0) { DeepProfiler.BeginMajorSample((DPEntry)24, workerIndex, -1L); if (_producingLabExecutor.Count > 0) { _producingLabExecutor.GameTickLabProduceMode(_planet, powerSystem.ProducingLabPowerConsumerTypeIndexes, powerSystem.PowerConsumerTypes, networksPowerConsumption, productRegister, consumeRegister, _subFactoryNeeds, _universeStaticDataBuilder.UniverseStaticData); _producingLabExecutor.GameTickLabOutputToNext(_subFactoryNeeds, _universeStaticDataBuilder.UniverseStaticData); } if (_researchingLabExecutor.Count > 0) { _researchingLabExecutor.GameTickLabResearchMode(_planet, powerSystem.ResearchingLabPowerConsumerTypeIndexes, powerSystem.PowerConsumerTypes, networksPowerConsumption, consumeRegister, _subFactoryNeeds); _researchingLabExecutor.GameTickLabOutputToNext(_subFactoryNeeds); } DeepProfiler.EndMajorSample((DPEntry)24, workerIndex); } if (_stationExecutor.Count > 0) { DeepProfiler.BeginSample((DPEntry)36, workerIndex, (long)_planet.planetId); DeepProfiler.BeginMajorSample((DPEntry)37, workerIndex, -1L); _stationExecutor.StationGameTick(_planet, time, _stationVeinMinerExecutor, ref miningFlags); DeepProfiler.EndMajorSample((DPEntry)37, workerIndex); DeepProfiler.EndSample((DPEntry)36, workerIndex); } if (_stationExecutor.Count > 0) { DeepProfiler.BeginMajorSample((DPEntry)37, workerIndex, -1L); _stationExecutor.InputFromBelt(_beltExecutor.OptimizedCargoPaths); DeepProfiler.EndMajorSample((DPEntry)37, workerIndex); } if (_optimizedBiInserterExecutor.Count + _optimizedInserterExecutor.Count > 0) { DeepProfiler.BeginMajorSample((DPEntry)25, workerIndex, -1L); _optimizedBiInserterExecutor.GameTickInserters(_planet, powerSystem.InserterBiPowerConsumerTypeIndexes, powerSystem.PowerConsumerTypes, networksPowerConsumption, _beltExecutor.OptimizedCargoPaths, _universeStaticDataBuilder.UniverseStaticData); _optimizedInserterExecutor.GameTickInserters(_planet, powerSystem.InserterPowerConsumerTypeIndexes, powerSystem.PowerConsumerTypes, networksPowerConsumption, _beltExecutor.OptimizedCargoPaths, _universeStaticDataBuilder.UniverseStaticData); DeepProfiler.EndMajorSample((DPEntry)25, workerIndex); } if (_tankExecutor.Count > 0) { DeepProfiler.BeginMajorSample((DPEntry)26, workerIndex, -1L); _tankExecutor.GameTick(_beltExecutor.OptimizedCargoPaths); DeepProfiler.EndMajorSample((DPEntry)26, workerIndex); } if (_beltExecutor.Count > 0) { DeepProfiler.BeginMajorSample((DPEntry)28, workerIndex, -1L); _beltExecutor.GameTick(); DeepProfiler.EndMajorSample((DPEntry)28, workerIndex); } if (_splitterExecutor.Count > 0) { DeepProfiler.BeginMajorSample((DPEntry)29, workerIndex, -1L); _splitterExecutor.GameTick(this, _beltExecutor.OptimizedCargoPaths); DeepProfiler.EndMajorSample((DPEntry)29, workerIndex); } if (_monitorExecutor.Count > 0) { DeepProfiler.BeginMajorSample((DPEntry)30, workerIndex, -1L); _monitorExecutor.GameTick(_planet, powerSystem.MonitorPowerConsumerTypeIndexes, powerSystem.PowerConsumerTypes, networksPowerConsumption, _beltExecutor.OptimizedCargoPaths); DeepProfiler.EndMajorSample((DPEntry)30, workerIndex); } if (_spraycoaterExecutor.Count > 0) { DeepProfiler.BeginMajorSample((DPEntry)31, workerIndex, -1L); _spraycoaterExecutor.GameTick(powerSystem.SpraycoaterPowerConsumerTypeIndexes, powerSystem.PowerConsumerTypes, networksPowerConsumption, consumeRegister, _beltExecutor.OptimizedCargoPaths); DeepProfiler.EndMajorSample((DPEntry)31, workerIndex); } if (_pilerExecutor.Count > 0) { DeepProfiler.BeginMajorSample((DPEntry)32, workerIndex, -1L); _pilerExecutor.GameTick(_planet, powerSystem.PilerPowerConsumerTypeIndexes, powerSystem.PowerConsumerTypes, networksPowerConsumption, _beltExecutor.OptimizedCargoPaths); DeepProfiler.EndMajorSample((DPEntry)32, workerIndex); } if (_stationExecutor.Count > 0) { DeepProfiler.BeginMajorSample((DPEntry)37, workerIndex, -1L); _stationExecutor.OutputToBelt(_beltExecutor.OptimizedCargoPaths); DeepProfiler.EndMajorSample((DPEntry)37, workerIndex); } _optimizedPlanet.AddMiningFlags(miningFlags); HasCalculatedPowerConsumption = true; } public void RefreshPowerConsumptionDemands(ProductionStatistics statistics, SubFactoryPowerConsumption powerSystem) { RefreshPowerConsumptionDemands(statistics, _beltVeinMinerExecutor.UpdatePowerConsumptionPerPrototype(powerSystem.BeltVeinMinerPowerConsumerTypeIndexes, powerSystem.PowerConsumerTypes)); RefreshPowerConsumptionDemands(statistics, _stationVeinMinerExecutor.UpdatePowerConsumptionPerPrototype(powerSystem.StationVeinMinerPowerConsumerTypeIndexes, powerSystem.PowerConsumerTypes)); RefreshPowerConsumptionDemands(statistics, _oilMinerExecutor.UpdatePowerConsumptionPerPrototype(powerSystem.OilMinerPowerConsumerTypeIndexes, powerSystem.PowerConsumerTypes)); RefreshPowerConsumptionDemands(statistics, _waterMinerExecutor.UpdatePowerConsumptionPerPrototype(powerSystem.WaterMinerPowerConsumerTypeIndexes, powerSystem.PowerConsumerTypes)); RefreshPowerConsumptionDemands(statistics, _assemblerExecutor.UpdatePowerConsumptionPerPrototype(powerSystem.AssemblerPowerConsumerTypeIndexes, powerSystem.PowerConsumerTypes)); RefreshPowerConsumptionDemands(statistics, _fractionatorExecutor.UpdatePowerConsumptionPerPrototype(powerSystem.FractionatorPowerConsumerTypeIndexes, powerSystem.PowerConsumerTypes)); RefreshPowerConsumptionDemands(statistics, _ejectorExecutor.UpdatePowerConsumptionPerPrototype(_planet, powerSystem.EjectorPowerConsumerTypeIndexes, powerSystem.PowerConsumerTypes)); RefreshPowerConsumptionDemands(statistics, _siloExecutor.UpdatePowerConsumptionPerPrototype(_planet, powerSystem.SiloPowerConsumerTypeIndexes, powerSystem.PowerConsumerTypes)); RefreshPowerConsumptionDemands(statistics, _producingLabExecutor.UpdatePowerConsumptionPerPrototype(powerSystem.ProducingLabPowerConsumerTypeIndexes, powerSystem.PowerConsumerTypes)); RefreshPowerConsumptionDemands(statistics, _researchingLabExecutor.UpdatePowerConsumptionPerPrototype(powerSystem.ResearchingLabPowerConsumerTypeIndexes, powerSystem.PowerConsumerTypes)); RefreshPowerConsumptionDemands(statistics, _optimizedBiInserterExecutor.UpdatePowerConsumptionPerPrototype(powerSystem.InserterBiPowerConsumerTypeIndexes, powerSystem.PowerConsumerTypes)); RefreshPowerConsumptionDemands(statistics, _optimizedInserterExecutor.UpdatePowerConsumptionPerPrototype(powerSystem.InserterPowerConsumerTypeIndexes, powerSystem.PowerConsumerTypes)); RefreshPowerConsumptionDemands(statistics, _monitorExecutor.UpdatePowerConsumptionPerPrototype(powerSystem.MonitorPowerConsumerTypeIndexes, powerSystem.PowerConsumerTypes)); RefreshPowerConsumptionDemands(statistics, _spraycoaterExecutor.UpdatePowerConsumptionPerPrototype(powerSystem.SpraycoaterPowerConsumerTypeIndexes, powerSystem.PowerConsumerTypes)); RefreshPowerConsumptionDemands(statistics, _pilerExecutor.UpdatePowerConsumptionPerPrototype(powerSystem.PilerPowerConsumerTypeIndexes, powerSystem.PowerConsumerTypes)); } 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, _ejectorExecutor.GetOptimizedEjectorIndex(reference.ejectorId)); } if (reference.siloId != 0) { return new TypedObjectIndex(EntityType.Silo, _siloExecutor.GetOptimizedSiloIndex(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) { ref PowerGeneratorComponent reference2 = ref planet.powerSystem.genPool[reference.powerGenId]; return new TypedObjectIndex((!reference2.wind && !reference2.photovoltaic && !reference2.gamma && !reference2.geothermal) ? EntityType.FuelPowerGenerator : 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); } if (reference.powerGenId != 0) { return new TypedObjectIndex(EntityType.FuelPowerGenerator, reference.powerGenId); } throw new InvalidOperationException("Unknown entity type."); } public bool InsertCargoIntoStorage(int entityId, 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 (AddCargo(val, 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 static bool AddCargo(StorageComponent storage, 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_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: 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 result = false; bool flag2 = false; int num = 0; int num2 = (useBan ? (storage.size - storage.bans) : storage.size); ref byte stack = ref cargo.Stack; 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 (stack <= num3) { storage.grids[i].count += stack; storage.grids[i].inc += cargo.Inc; result = true; flag2 = true; break; } storage.grids[i].count = num; storage.grids[i].inc += storage.split_inc(ref stack, ref cargo.Inc, (byte)num3); flag2 = true; } } if (flag2) { storage.searchStart = 0; storage.lastEmptyItem = -1; storage.NotifyStorageChange(); } return result; } private static void RefreshPowerConsumptionDemands(ProductionStatistics statistics, PrototypePowerConsumptions prototypePowerConsumptions) { int[] powerConId2Index = ItemProto.powerConId2Index; for (int i = 0; i < prototypePowerConsumptions.PrototypeIds.Length; i++) { int num = powerConId2Index[prototypePowerConsumptions.PrototypeIds[i]]; statistics.conDemands[num] += prototypePowerConsumptions.PrototypeIdPowerConsumption[i]; statistics.conCount[num] += prototypePowerConsumptions.PrototypeIdCounts[i]; statistics.totalConDemand += prototypePowerConsumptions.PrototypeIdPowerConsumption[i]; } } } internal sealed class OptimizedTerrestrialPlanet : IOptimizedPlanet { public static bool ViewBeltsOnLocalOptimizedPlanet; private readonly PlanetFactory _planet; private readonly StarClusterResearchManager _starClusterResearchManager; private readonly DysonSphereManager _dysonSphereManager; private readonly UniverseStaticDataBuilder _universeStaticDataBuilder; private OptimizedSubFactory[] _subFactories; private OptimizedPowerSystem _optimizedPowerSystem; private TurretExecutor _turretExecutor; private OptimizedPlanetWideProductionStatistics _optimizedPlanetWideProductionStatistics; private IWorkNode? _workNodes; private int _workStepsParallelism; public OptimizedPlanetStatus Status { get; private set; } = OptimizedPlanetStatus.Stopped; public int OptimizeDelayInTicks { get; set; } public OptimizedTerrestrialPlanet(PlanetFactory planet, StarClusterResearchManager starClusterResearchManager, DysonSphereManager dysonSphereManager, UniverseStaticDataBuilder universeStaticDataBuilder) { _planet = planet; _starClusterResearchManager = starClusterResearchManager; _dysonSphereManager = dysonSphereManager; _universeStaticDataBuilder = universeStaticDataBuilder; } 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); if (ViewBeltsOnLocalOptimizedPlanet) { _planet.cargoTraffic.PresentCargoPathsSync(); return; } Status = OptimizedPlanetStatus.Stopped; _workNodes = null; _workStepsParallelism = -1; } public void Initialize() { List<Graph> list = Graphifier.ToGraphs(_planet); Graphifier.CombineSmallGraphs(list); PlanetWideProductionRegisterBuilder planetWideProductionRegisterBuilder = new PlanetWideProductionRegisterBuilder(_planet); OptimizedItemId[][] fuelNeeds; OptimizedPowerSystemBuilder optimizedPowerSystemBuilder = OptimizedPowerSystemBuilder.Create(_planet, planetWideProductionRegisterBuilder.GetSubFactoryBuilder(), out fuelNeeds); 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, _universeStaticDataBuilder); _subFactories[i].Initialize(list[i], optimizedPowerSystemBuilder, planetWideBeltExecutor, turretExecutorBuilder, planetWideProductionRegisterBuilder, planetWideProductionRegisterBuilder.GetSubFactoryBuilder(), fuelNeeds); } _optimizedPowerSystem = optimizedPowerSystemBuilder.Build(_dysonSphereManager, planetWideBeltExecutor); _turretExecutor = turretExecutorBuilder.Build(); _optimizedPlanetWideProductionStatistics = planetWideProductionRegisterBuilder.Build(); Status = OptimizedPlanetStatus.Running; _workNodes = null; _workStepsParallelism = -1; } public void GameTickDefense(long time) { bool flag = GameMain.localPlanet == _planet.planet; _planet.spaceHashSystemDynamic.GameTick(); if (Status == OptimizedPlanetStatus.Running) { DefenseGameTick(_planet.defenseSystem, time); DefenseGameTickUIThread(time); } else { _planet.defenseSystem.GameTick(time, flag); } _planet.planetATField.GameTick(time, flag); } public IWorkNode GetMultithreadedWork(int maxParallelism) { if (_workNodes == null || _workStepsParallelism != maxParallelism) { _workNodes = CreateMultithreadedWork(maxParallelism); _workStepsParallelism = maxParallelism; } return _workNodes; } private IWorkNode CreateMultithreadedWork(int maxParallelism) { if (Status == OptimizedPlanetStatus.Stopped) { return CreateParallelWorkForNonRunningOptimizedPlanet(maxParallelism); } if (_subFactories.Length == 0) { return new NoWorkNode(); } if (_subFactories.Length == 1) { OptimizedSubFactory subFactory = _subFactories[0]; return new WorkLeaf(new IWorkChunk[1] { new EntirePlanet(this, subFactory, _optimizedPowerSystem.GetSubFactoryPowerConsumption(subFactory)) }); } List<IWorkNode[]> list = new List<IWorkNode[]>(); list.Add(new IWorkNode[1] { new WorkLeaf(new IWorkChunk[1] { new PlanetWidePower(this) }) }); List<IWorkChunk> list2 = new List<IWorkChunk>(); OptimizedSubFactory[] subFactories = _subFactories; foreach (OptimizedSubFactory subFactory2 in subFactories) { list2.Add(new SubFactoryGameTick(subFactory2, _optimizedPowerSystem.GetSubFactoryPowerConsumption(subFactory2))); } list.Add(new IWorkNode[1] { new WorkLeaf(list2.ToArray()) }); list.Add(new IWorkNode[1] { new WorkLeaf(new IWorkChunk[1] { new PostSubFactoryStep(this) }) }); return new WorkNode(list.ToArray()); } public void RequestDysonSpherePower(int workerIndex) { if (Status == OptimizedPlanetStatus.Running) { _optimizedPowerSystem.RequestDysonSpherePower(_planet, workerIndex); } else { UnoptimizedRequestDysonSpherePower(); } } public void BeforePowerStep(long time) { _planet.transport.GameTickBeforePower(time); _planet.defenseSystem.GameTickBeforePower(time); _planet.digitalSystem.GameTickBeforePower(time); } public void PowerStep(long time, int workerIndex) { _optimizedPowerSystem.GameTick(_planet, time, workerIndex); } public void TransportGameTick(int workerIndex, long time, Vector3 playerPos) { //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) PlanetTransport transport = _planet.transport; if (transport.dispenserCount == 0) { return; } DeepProfiler.BeginSample((DPEntry)36, workerIndex, (long)_planet.planetId); DeepProfiler.BeginSample((DPEntry)38, workerIndex, -1L); DispenserGameTick_SandboxMode(workerIndex, 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); } } DeepProfiler.EndSample((DPEntry)38, workerIndex); DeepProfiler.EndSample((DPEntry)36, workerIndex); } private static void DispenserGameTick_SandboxMode(int workerIndex, 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(int workerIndex) { DeepProfiler.BeginMajorSample((DPEntry)39, workerIndex, -1L); _planet.digitalSystem.GameTick(false); DeepProfiler.EndMajorSample((DPEntry)39, workerIndex); } public void AggregateSubFactoryDataStep(int workerIndex, long time) { DeepProfiler.BeginSample((DPEntry)75, workerIndex, -1L); FactoryProductionStat obj = GameMain.statistics.production.factoryStatPool[_planet.index]; int[] productRegister = obj.productRegister; int[] consumeRegister = obj.consumeRegister; _optimizedPlanetWideProductionStatistics.UpdateStatistics(time, productRegister, consumeRegister); DeepProfiler.EndSample((DPEntry)75, workerIndex); } private void DefenseGameTick(DefenseSystem defenseSystem, long tick) { //IL_0056: 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_0095: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) GameHistoryData history = GameMain.history; 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.UpdateMatchSpaceEnemies(); if (defenseSystem.beacons.count > 0) { DeepProfiler.BeginSample((DPEntry)44, -1, (long)defenseSystem.factory.planetId); 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); } } } DeepProfiler.EndSample((DPEntry)44, -1); } 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.UpdateSpaceUniqueGlobalTargets(); 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; } if (defenseSystem.fieldGenerators.count <= 0) { return; } DeepProfiler.BeginSample((DPEntry)46, -1, (long)defenseSystem.factory.planetId); 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]); } } DeepProfiler.EndSample((DPEntry)46, -1); } private void DefenseGameTickUIThread(long tick) { //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) DefenseSystem defenseSystem = _planet.defenseSystem; if (defenseSystem.battleBases.count <= 0) { return; } DeepProfiler.BeginSample((DPEntry)45, -1, (long)_planet.planetId); 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); } } } DeepProfiler.EndSample((DPEntry)45, -1); } 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; } } public void RefreshPowerGenerationCapacites(ProductionStatistics statistics, PlanetFactory planet) { _optimizedPowerSystem.RefreshPowerGenerationCapacites(statistics, planet); } public void RefreshPowerConsumptionDemands(ProductionStatistics statistics, PlanetFactory planet) { OptimizedSubFactory[] subFactories = _subFactories; foreach (OptimizedSubFactory optimizedSubFactory in subFactories) { optimizedSubFactory.RefreshPowerConsumptionDemands(statistics, _optimizedPowerSystem.GetSubFactoryPowerConsumption(optimizedSubFactory)); } _optimizedPowerSystem.RefreshPowerConsumptionDemands(statistics, planet); } private IWorkNode CreateParallelWorkForNonRunningOptimizedPlanet(int maxParallelism) { List<IWorkNode[]> list = new List<IWorkNode[]>(); 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) { IWorkNode[] array = new IWorkNode[1]; IWorkChunk[] workNodes = UnOptimizedPlanetWorkChunk.CreateDuplicateChunks(_planet, WorkType.BeforePower, val); array[0] = new WorkLeaf(workNodes); list.Add(array); } if (_planet.powerSystem.netCursor > 0) { IWorkNode[] array2 = new IWorkNode[1]; IWorkChunk[] workNodes = UnOptimizedPlanetWorkChunk.CreateDuplicateChunks(_planet, WorkType.Power, 1); array2[0] = new WorkLeaf(workNodes); list.Add(array2); } int val2 = (minerCursor + assemblerCursor + fractionatorCursor + ejectorCursor + siloCursor + labCursor + 4999) / 5000; val2 = Math.Min(val2, maxParallelism); if (val2 > 0) { val2 = 1; IWorkNode[] array3 = new IWorkNode[1]; IWorkChunk[] workNodes = UnOptimizedPlanetWorkChunk.CreateDuplicateChunks(_planet, WorkType.Assembler, val2); array3[0] = new WorkLeaf(workNodes); list.Add(array3); } if (labCursor2 > 0) { IWorkNode[] array4 = new IWorkNode[1]; IWorkChunk[] workNodes = UnOptimizedPlanetWorkChunk.CreateDuplicateChunks(_planet, WorkType.LabResearchMode, 1); array4[0] = new WorkLeaf(workNodes); list.Add(array4); } int val3 = (labCursor3 + 4999) / 5000; val3 = Math.Min(val3, maxParallelism); if (val3 > 0) { val3 = 1; IWorkNode[] array5 = new IWorkNode[1]; IWorkChunk[] workNodes = UnOptimizedPlanetWorkChunk.CreateDuplicateChunks(_planet, WorkType.LabOutput2NextData, val3); array5[0] = new WorkLeaf(workNodes); list.Add(array5); } if (num > 0) { IWorkNode[] array6 = new IWorkNode[1]; IWorkChunk[] workNodes = UnOptimizedPlanetWorkChunk.CreateDuplicateChunks(_planet, WorkType.TransportData, 1); array6[0] = new WorkLeaf(workNodes); list.Add(array6); } if (stationCursor > 0) { IWorkNode[] array7 = new IWorkNode[1]; IWorkChunk[] workNodes = UnOptimizedPlanetWorkChunk.CreateDuplicateChunks(_planet, WorkType.InputFromBelt, 1); array7[0] = new WorkLeaf(workNodes); list.Add(array7); } if (Math.Min((inserterCursor + 4999) / 5000, maxParallelism) > 0) { IWorkNode[] array8 = new IWorkNode[1]; IWorkChunk[] workNodes = UnOptimizedPlanetWorkChunk.CreateDuplicateChunks(_planet, WorkType.InserterData, 1); array8[0] = new WorkLeaf(workNodes); list.Add(array8); } if (storageCursor + tankCur