Decompiled source of PlanetWormhole v2.0.2

PlanetWormhole.dll

Decompiled a day ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Threading;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using PlanetWormhole.Data;
using PlanetWormhole.Util;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.0.0")]
[module: UnverifiableCode]
namespace PlanetWormhole
{
	internal class Constants
	{
		public const int PROLIFERATOR_MK3 = 1143;

		public const int WARPER = 1210;

		public const int IONOSPHERIC_TECH = 1505;

		public const int SHIP_ENGINE_4 = 3404;

		public const int MAX_ITEM_COUNT = 12000;

		public const int BUFFER_SIZE = 1000;

		public const int PERIOD = 9;

		public static int INC_SPRAY_TIMES;

		public static int INC_ABILITY;

		public static int EXTRA_INC_SPRAY_TIMES;

		static Constants()
		{
			ItemProto obj = ((ProtoSet<ItemProto>)(object)LDB.items).Select(1143);
			INC_SPRAY_TIMES = obj.HpMax;
			INC_ABILITY = obj.Ability;
			EXTRA_INC_SPRAY_TIMES = (int)((double)INC_SPRAY_TIMES * ((double)Cargo.incTable[INC_ABILITY] * 0.001) + 0.1);
		}
	}
	[BepInPlugin("essium.DSP.PlanetWormhole", "PlanetWormhole", "2.0.2")]
	public class PlanetWormhole : BaseUnityPlugin
	{
		private const string package = "essium.DSP.PlanetWormhole";

		private const string plugin = "PlanetWormhole";

		private const string version = "2.0.2";

		private static List<LocalPlanet> planetWormhole;

		private static Cosmic globalWormhole;

		private static ManualLogSource logger;

		private static ConfigEntry<bool> enableInterstellar;

		private Harmony harmony;

		[HarmonyPostfix]
		[HarmonyPatch(typeof(GameLogic), "OnFactoryFrameEnd")]
		private static void _postfix_GameData_GameTick(GameLogic __instance)
		{
			if (!GameMain.instance.isMenuDemo)
			{
				DeepProfiler.BeginSample((DPEntry)28, -1, -1L);
				while (planetWormhole.Count < __instance.factoryCount)
				{
					planetWormhole.Add(new LocalPlanet());
				}
				globalWormhole.SetData(__instance.data);
				globalWormhole.BeforeLocal();
				for (int i = (int)(__instance.timei % 9); i < __instance.factoryCount; i += 9)
				{
					planetWormhole[i].SetFactory(__instance.factories[i]);
					planetWormhole[i].SetCosmic(globalWormhole);
					ThreadPool.QueueUserWorkItem(planetWormhole[i].PatchPlanet);
				}
				for (int j = (int)(__instance.timei % 9); j < __instance.factoryCount; j += 9)
				{
					planetWormhole[j].completeSignal.WaitOne();
				}
				globalWormhole.AfterLocal();
				DeepProfiler.EndSample(-1, -2L);
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(ProductionStatistics), "GameTick")]
		private static void _prefix_ProductionStatistics_GameTick(ProductionStatistics __instance)
		{
			for (int i = 0; i < __instance.gameData.factoryCount; i++)
			{
				if (i <= planetWormhole.Count && planetWormhole[i].consumedProliferator > 0)
				{
					__instance.factoryStatPool[i].consumeRegister[1143] += planetWormhole[i].consumedProliferator;
					planetWormhole[i].consumedProliferator = 0;
				}
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(ProductionStatistics), "GameTick_Parallel")]
		private static void _prefix_ProductionStatistics_GameTick_Parallel(ProductionStatistics __instance, int threadOrdinal, int threadCount)
		{
			for (int i = (threadOrdinal + 3) % threadCount; i < __instance.gameData.factoryCount; i += threadCount)
			{
				if (i <= planetWormhole.Count && planetWormhole[i].consumedProliferator > 0)
				{
					__instance.factoryStatPool[i].consumeRegister[1143] += planetWormhole[i].consumedProliferator;
					planetWormhole[i].consumedProliferator = 0;
				}
			}
		}

		public void Start()
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Expected O, but got Unknown
			BindConfig();
			harmony = new Harmony("essium.DSP.PlanetWormhole:2.0.2");
			harmony.PatchAll(typeof(PlanetWormhole));
		}

		public void OnDestroy()
		{
			harmony.UnpatchSelf();
			Logger.Sources.Remove((ILogSource)(object)logger);
		}

		private void BindConfig()
		{
			enableInterstellar = ((BaseUnityPlugin)this).Config.Bind<bool>("Config", "EnableInterstellar", false, "enable auto interstellar transportation");
		}

		public static bool EnableInterstellar()
		{
			return enableInterstellar.Value;
		}

		static PlanetWormhole()
		{
			logger = Logger.CreateLogSource("PlanetWormhole");
			planetWormhole = new List<LocalPlanet>();
			globalWormhole = new Cosmic();
		}

		public static void LogInfo(string msg)
		{
			logger.LogInfo((object)msg);
		}
	}
}
namespace PlanetWormhole.Util
{
	internal class Functions
	{
		public static int _split_inc(int inc, int count)
		{
			if (count > 0 && inc > 0)
			{
				return inc / count * count;
			}
			return 0;
		}

		public static bool _float_equal(float x, float y)
		{
			return (double)Math.Abs(x - y) < 0.001;
		}

		public static int _positive(int x)
		{
			if (x >= 0)
			{
				return x;
			}
			return 0;
		}

		public static void _produce(int itemId, int[] served, ref int produce, ref int count)
		{
			if (served[itemId] > 0)
			{
				count = Math.Min(produce, served[itemId]);
				served[itemId] -= count;
				produce -= count;
			}
			else
			{
				count = 0;
			}
		}

		public static void _serve(int itemId, int[] produced, ref int serve, int max, ref int count)
		{
			if (produced[itemId] > 0)
			{
				count = _positive(Math.Min(max - serve, produced[itemId]));
				produced[itemId] -= count;
				serve += count;
			}
			else
			{
				count = 0;
			}
		}
	}
}
namespace PlanetWormhole.StateMachine
{
	public class StateMachine
	{
		private int n;

		private CodeInstruction[] circle;

		private Func<CodeInstruction, bool>[] conditions;

		private int state;

		private CodeInstruction[] replaced;

		public StateMachine(int n, CodeInstruction[] replaced, Func<CodeInstruction, bool>[] conditions)
		{
			this.n = n;
			this.replaced = replaced;
			this.conditions = conditions;
			circle = (CodeInstruction[])(object)new CodeInstruction[n];
		}

		public IEnumerable<CodeInstruction> Replace(IEnumerable<CodeInstruction> instructions)
		{
			state = 0;
			foreach (CodeInstruction instruction in instructions)
			{
				if (conditions[state](instruction))
				{
					state++;
					if (state == n)
					{
						CodeInstruction[] array = replaced;
						for (int i = 0; i < array.Length; i++)
						{
							yield return array[i];
						}
						state = 0;
					}
					else
					{
						circle[state - 1] = instruction;
					}
				}
				else
				{
					for (int i = 0; i < state; i++)
					{
						yield return circle[i];
					}
					yield return instruction;
					state = 0;
				}
			}
		}
	}
}
namespace PlanetWormhole.Data
{
	internal class Cosmic
	{
		public int[] trashProduced;

		public int[] trashServed;

		public int[] stationProduced;

		public int[] stationServed;

		public GameData data;

		private Random rng;

		public static Mutex mutex = new Mutex();

		public Cosmic()
		{
			trashProduced = new int[12000];
			trashServed = new int[12000];
			stationProduced = new int[12000];
			stationServed = new int[12000];
			rng = new Random();
		}

		public void BeforeLocal()
		{
			Reset();
			if (PlanetWormhole.EnableInterstellar())
			{
				RegisterStation();
				ConsumeStation();
			}
			RegisterTrash();
		}

		public void AfterLocal()
		{
			ConsumeTrash();
		}

		public void Reset()
		{
			Array.Clear(trashProduced, 0, 12000);
			Array.Clear(trashServed, 0, 12000);
			Array.Clear(stationProduced, 0, 12000);
			Array.Clear(stationServed, 0, 12000);
		}

		public void SetData(GameData data)
		{
			this.data = data;
		}

		public void RegisterTrash()
		{
			TrashContainer container = data.trashSystem.container;
			TrashObject[] trashObjPool = container.trashObjPool;
			for (int i = 0; i < container.trashCursor; i++)
			{
				if (trashObjPool[i].item > 0)
				{
					trashProduced[trashObjPool[i].item] += trashObjPool[i].count;
				}
			}
		}

		public void ConsumeTrash()
		{
			TrashContainer container = data.trashSystem.container;
			TrashObject[] trashObjPool = container.trashObjPool;
			for (int i = 0; i < container.trashCursor; i++)
			{
				if (trashObjPool[i].item <= 0)
				{
					continue;
				}
				int item = trashObjPool[i].item;
				if (trashServed[item] > 0)
				{
					int num = Math.Min(trashObjPool[i].count, trashServed[item]);
					trashServed[item] -= num;
					trashObjPool[i].count -= num;
					if (trashObjPool[i].count <= 0)
					{
						data.trashSystem.RemoveTrash(i);
					}
				}
			}
		}

		public void RegisterStation()
		{
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Invalid comparison between Unknown and I4
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Invalid comparison between Unknown and I4
			for (int i = 0; i < data.factoryCount; i++)
			{
				StationComponent[] stationPool = data.factories[i].transport.stationPool;
				for (int j = 1; j < data.factories[i].transport.stationCursor; j++)
				{
					if (stationPool[j] == null || stationPool[j].id != j || stationPool[j].storage == null)
					{
						continue;
					}
					StationStore[] storage = stationPool[j].storage;
					for (int k = 0; k < storage.Length; k++)
					{
						if (storage[k].itemId > 0)
						{
							if ((int)storage[k].remoteLogic == 1)
							{
								stationProduced[storage[k].itemId] += storage[k].count;
							}
							else if ((int)storage[k].remoteLogic == 2)
							{
								int num = Functions._positive(storage[k].max - storage[k].count);
								stationServed[storage[k].itemId] += num;
							}
						}
					}
				}
			}
		}

		public void ConsumeStation()
		{
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Invalid comparison between Unknown and I4
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Invalid comparison between Unknown and I4
			uint num = (uint)rng.Next();
			int count = 0;
			for (int i = 0; i < data.factoryCount; i++)
			{
				int num2 = (int)((num + i) % data.factoryCount);
				StationComponent[] stationPool = data.factories[num2].transport.stationPool;
				for (int j = 1; j < data.factories[num2].transport.stationCursor; j++)
				{
					if (stationPool[j] == null || stationPool[j].id != j || stationPool[j].storage == null)
					{
						continue;
					}
					StationStore[] storage = stationPool[j].storage;
					for (int k = 0; k < storage.Length; k++)
					{
						if (storage[k].itemId > 0)
						{
							int itemId = storage[k].itemId;
							if ((int)storage[k].remoteLogic == 1)
							{
								Functions._produce(itemId, stationServed, ref storage[k].count, ref count);
							}
							else if ((int)storage[k].remoteLogic == 2)
							{
								Functions._serve(itemId, stationProduced, ref storage[k].count, storage[k].max, ref count);
							}
						}
					}
				}
			}
		}
	}
	internal class LocalPlanet
	{
		public int[] produced;

		public int[] served;

		public int[] buffer;

		public int inc;

		public int consumedProliferator;

		public int sumSpray;

		public bool spray;

		public PlanetFactory factory;

		public Cosmic cosmic;

		public AutoResetEvent completeSignal;

		private uint r;

		private static ThreadLocal<Random> rng = new ThreadLocal<Random>(() => new Random());

		public LocalPlanet()
		{
			produced = new int[12000];
			served = new int[12000];
			buffer = new int[12000];
			Init();
			completeSignal = new AutoResetEvent(initialState: false);
		}

		public void Init()
		{
			Array.Clear(buffer, 0, 12000);
			inc = 0;
		}

		public void SetFactory(PlanetFactory factory)
		{
			this.factory = factory;
		}

		public void SetCosmic(Cosmic cosmic)
		{
			this.cosmic = cosmic;
		}

		public void PatchPlanet(object stateInfo = null)
		{
			Reset();
			RegisterTrash();
			RegisterPowerSystem();
			RegisterTurret();
			RegisterMiner();
			RegisterAssembler();
			RegisterFractionator();
			RegisterLab();
			RegisterEjector();
			RegisterSilo();
			RegisterStorage();
			RegisterStation();
			Spray();
			ConsumeBuffer();
			ConsumeTrash();
			ConsumeStorage();
			ConsumePowerSystem();
			ConsumeTurret();
			ConsumeMiner();
			ConsumeFractionator();
			ConsumeAssembler();
			ConsumeLab();
			ConsumeEjector();
			ConsumeSilo();
			ConsumeStation();
			completeSignal.Set();
		}

		private void Reset()
		{
			Array.Clear(produced, 0, 12000);
			Array.Clear(served, 0, 12000);
			spray = true;
			sumSpray = 0;
			consumedProliferator = 0;
			r = (uint)rng.Value.Next();
		}

		private void RegisterAssembler()
		{
			AssemblerComponent[] assemblerPool = factory.factorySystem.assemblerPool;
			for (int i = 1; i < factory.factorySystem.assemblerCursor; i++)
			{
				if (assemblerPool[i].id != i || assemblerPool[i].recipeId <= 0)
				{
					continue;
				}
				ref AssemblerComponent reference = ref assemblerPool[i];
				for (int j = 0; j < reference.produced.Length; j++)
				{
					if (reference.produced[j] > 0)
					{
						produced[reference.recipeExecuteData.products[j]] += reference.produced[j];
					}
				}
				for (int k = 0; k < reference.recipeExecuteData.requireCounts.Length; k++)
				{
					if (reference.needs[k] > 0)
					{
						int num = Functions._positive(3 * reference.recipeExecuteData.requireCounts[k] - reference.served[k]);
						sumSpray += num;
						served[reference.needs[k]] += num;
					}
				}
			}
		}

		private void ConsumeAssembler()
		{
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Invalid comparison between Unknown and I4
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Invalid comparison between Unknown and I4
			AssemblerComponent[] assemblerPool = factory.factorySystem.assemblerPool;
			int count = 0;
			for (int i = 1; i < factory.factorySystem.assemblerCursor; i++)
			{
				int num = (int)((r + i) % (factory.factorySystem.assemblerCursor - 1)) + 1;
				if (assemblerPool[num].id != num || assemblerPool[num].recipeId <= 0)
				{
					continue;
				}
				ref AssemblerComponent reference = ref assemblerPool[num];
				for (int j = 0; j < reference.produced.Length; j++)
				{
					if (reference.produced[j] > 0)
					{
						Functions._produce(reference.recipeExecuteData.products[j], served, ref reference.produced[j], ref count);
					}
				}
				if (reference.produced.Length > 1)
				{
					int num2 = reference.produced.Length;
					ERecipeType recipeType = reference.recipeType;
					if ((int)recipeType != 1)
					{
						if ((int)recipeType == 4)
						{
							for (int k = 0; k < num2; k++)
							{
								if (reference.produced[k] > reference.recipeExecuteData.productCounts[k] * 9 && buffer[reference.recipeExecuteData.products[k]] < 1000)
								{
									reference.produced[k] -= reference.recipeExecuteData.productCounts[k];
									buffer[reference.recipeExecuteData.products[k]] += reference.recipeExecuteData.productCounts[k];
								}
							}
						}
						else
						{
							for (int l = 0; l < num2; l++)
							{
								if (reference.produced[l] > reference.recipeExecuteData.productCounts[l] * 19 && buffer[reference.recipeExecuteData.products[l]] < 1000)
								{
									reference.produced[l] -= reference.recipeExecuteData.productCounts[l];
									buffer[reference.recipeExecuteData.products[l]] += reference.recipeExecuteData.productCounts[l];
								}
							}
						}
					}
					else
					{
						for (int m = 0; m < num2; m++)
						{
							if (reference.produced[m] + reference.recipeExecuteData.productCounts[m] > 100 && buffer[reference.recipeExecuteData.products[m]] < 1000)
							{
								reference.produced[m] -= reference.recipeExecuteData.productCounts[m];
								buffer[reference.recipeExecuteData.products[m]] += reference.recipeExecuteData.productCounts[m];
							}
						}
					}
				}
				for (int n = 0; n < reference.recipeExecuteData.requireCounts.Length; n++)
				{
					if (reference.needs[n] > 0)
					{
						Functions._serve(reference.needs[n], produced, ref reference.served[n], 3 * reference.recipeExecuteData.requireCounts[n], ref count);
						if (spray)
						{
							inc -= count * Constants.INC_ABILITY;
							reference.incServed[n] += Constants.INC_ABILITY * count;
						}
					}
				}
			}
		}

		private void RegisterStation()
		{
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Invalid comparison between Unknown and I4
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Invalid comparison between Unknown and I4
			StationComponent[] stationPool = factory.transport.stationPool;
			for (int i = 1; i < factory.transport.stationCursor; i++)
			{
				StationComponent val = stationPool[i];
				if (val == null || val.id != i || val.storage == null)
				{
					continue;
				}
				StationStore[] storage = stationPool[i].storage;
				for (int j = 0; j < storage.Length; j++)
				{
					if (storage[j].itemId > 0)
					{
						if ((int)storage[j].localLogic == 1)
						{
							produced[storage[j].itemId] += storage[j].count;
						}
						else if ((int)storage[j].localLogic == 2)
						{
							int num = Functions._positive(storage[j].max - storage[j].count);
							served[storage[j].itemId] += num;
						}
					}
				}
				if (val.needs[5] == 1210 && factory.gameData.history.TechUnlocked(3404))
				{
					served[1210] += Functions._positive(val.warperMaxCount - val.warperCount);
				}
			}
		}

		private void ConsumeStation()
		{
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Invalid comparison between Unknown and I4
			//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01be: Invalid comparison between Unknown and I4
			StationComponent[] stationPool = factory.transport.stationPool;
			int count = 0;
			for (int i = 1; i < factory.transport.stationCursor; i++)
			{
				int num = (int)((r + i) % (factory.transport.stationCursor - 1)) + 1;
				StationComponent val = stationPool[num];
				if (val != null && val.id == num && val.storage != null && val.needs[5] == 1210 && factory.gameData.history.TechUnlocked(3404))
				{
					Functions._serve(1210, produced, ref val.warperCount, val.warperMaxCount, ref count);
				}
			}
			for (int j = 1; j < factory.transport.stationCursor; j++)
			{
				int num2 = (int)((r + j) % (factory.transport.stationCursor - 1)) + 1;
				StationComponent val2 = stationPool[num2];
				if (val2 == null || val2.id != num2 || val2.storage == null)
				{
					continue;
				}
				StationStore[] storage = val2.storage;
				for (int k = 0; k < storage.Length; k++)
				{
					if (storage[k].itemId > 0)
					{
						int itemId = storage[k].itemId;
						if ((int)storage[k].localLogic == 1)
						{
							Functions._produce(itemId, served, ref storage[k].count, ref count);
							int num3 = Functions._split_inc(storage[k].inc, count);
							storage[k].inc -= num3;
							inc += num3;
						}
						else if ((int)storage[k].localLogic == 2)
						{
							Functions._serve(itemId, produced, ref storage[k].count, storage[k].max, ref count);
						}
					}
				}
			}
		}

		private void RegisterPowerSystem()
		{
			PowerGeneratorComponent[] genPool = factory.powerSystem.genPool;
			for (int i = 1; i < factory.powerSystem.genCursor; i++)
			{
				if (genPool[i].id != i)
				{
					continue;
				}
				ref PowerGeneratorComponent reference = ref genPool[i];
				if (reference.catalystId > 0 && factory.gameData.history.TechUnlocked(1505))
				{
					int num = Functions._positive((72000 - reference.catalystPoint) / 3600);
					sumSpray += num;
					served[reference.catalystId] += num;
					if (reference.productId > 0)
					{
						produced[reference.productId] += (int)reference.productCount;
					}
				}
				int[] array = ItemProto.fuelNeeds[reference.fuelMask];
				if (reference.fuelId <= 0 && (array == null || array.Length == 0))
				{
					continue;
				}
				int num2;
				if (reference.fuelId > 0)
				{
					num2 = reference.fuelId;
				}
				else if (reference.curFuelId > 0)
				{
					num2 = reference.curFuelId;
				}
				else
				{
					if (array.Length == 0)
					{
						continue;
					}
					num2 = array[0];
					((PowerGeneratorComponent)(ref reference)).SetNewFuel(num2, (short)0, (short)0);
				}
				int num3 = Functions._positive(10 - reference.fuelCount);
				sumSpray += num3;
				served[num2] += num3;
			}
			PowerExchangerComponent[] excPool = factory.powerSystem.excPool;
			for (int j = 1; j < factory.powerSystem.excCursor; j++)
			{
				ref PowerExchangerComponent reference2 = ref excPool[j];
				if (reference2.id == j && reference2.fullId > 0 && reference2.emptyId > 0)
				{
					if (Functions._float_equal(reference2.targetState, 1f))
					{
						produced[reference2.fullId] += reference2.fullCount;
						served[reference2.emptyId] += Functions._positive(20 - reference2.emptyCount);
					}
					else if (Functions._float_equal(reference2.targetState, -1f))
					{
						produced[reference2.emptyId] += reference2.emptyCount;
						served[reference2.fullId] += Functions._positive(20 - reference2.fullCount);
					}
				}
			}
		}

		private void ConsumePowerSystem()
		{
			PowerGeneratorComponent[] genPool = factory.powerSystem.genPool;
			int num = 0;
			for (int i = 1; i < factory.powerSystem.genCursor; i++)
			{
				int num2 = (int)((r + i) % (factory.powerSystem.genCursor - 1)) + 1;
				ref PowerGeneratorComponent reference = ref genPool[num2];
				if (reference.id != num2)
				{
					continue;
				}
				if (reference.catalystId > 0 && factory.gameData.history.TechUnlocked(1505))
				{
					int catalystId = reference.catalystId;
					if (produced[catalystId] > 0)
					{
						num = Functions._positive(Math.Min((72000 - reference.catalystPoint) / 3600, produced[catalystId]));
						produced[catalystId] -= num;
						reference.catalystPoint += num * 3600;
						if (spray)
						{
							inc -= num * Constants.INC_ABILITY;
							reference.catalystIncPoint += num * 3600 * Constants.INC_ABILITY;
						}
					}
					if (reference.productId > 0)
					{
						catalystId = reference.productId;
						if (served[catalystId] > 0)
						{
							num = Math.Min((int)reference.productCount, served[catalystId]);
							served[catalystId] -= num;
							reference.productCount -= num;
						}
					}
				}
				if (reference.fuelId <= 0)
				{
					continue;
				}
				int fuelId = reference.fuelId;
				if (produced[fuelId] > 0)
				{
					num = Functions._positive(Math.Min(10 - reference.fuelCount, produced[fuelId]));
					produced[fuelId] -= num;
					reference.fuelCount += (short)num;
					if (spray)
					{
						inc -= num * Constants.INC_ABILITY;
						reference.fuelInc += (short)(Constants.INC_ABILITY * num);
					}
				}
			}
			PowerExchangerComponent[] excPool = factory.powerSystem.excPool;
			for (int j = 1; j < factory.powerSystem.excCursor; j++)
			{
				int num3 = (int)((r + j) % (factory.powerSystem.excCursor - 1)) + 1;
				ref PowerExchangerComponent reference2 = ref excPool[num3];
				if (reference2.id != num3 || reference2.fullId <= 0 || reference2.emptyId <= 0)
				{
					continue;
				}
				int fullId = reference2.fullId;
				int emptyId = reference2.emptyId;
				if (Functions._float_equal(reference2.targetState, 1f))
				{
					if (served[fullId] > 0)
					{
						num = Math.Min(reference2.fullCount, served[fullId]);
						served[fullId] -= num;
						reference2.fullCount -= (short)num;
					}
					if (produced[emptyId] > 0)
					{
						num = Functions._positive(Math.Min(20 - reference2.emptyCount, produced[emptyId]));
						produced[emptyId] -= num;
						reference2.emptyCount += (short)num;
					}
				}
				else if (Functions._float_equal(reference2.targetState, -1f))
				{
					if (served[emptyId] > 0)
					{
						num = Math.Min(reference2.emptyCount, served[emptyId]);
						served[emptyId] -= num;
						reference2.emptyCount -= (short)num;
					}
					if (produced[fullId] > 0)
					{
						num = Functions._positive(Math.Min(20 - reference2.fullCount, produced[fullId]));
						produced[fullId] -= num;
						reference2.fullCount += (short)num;
					}
				}
			}
		}

		private void RegisterMiner()
		{
			MinerComponent[] minerPool = factory.factorySystem.minerPool;
			for (int i = 1; i < factory.factorySystem.minerCursor; i++)
			{
				if (minerPool[i].id == i)
				{
					ref MinerComponent reference = ref minerPool[i];
					if (reference.productId > 0)
					{
						produced[reference.productId] += reference.productCount;
					}
				}
			}
		}

		private void ConsumeMiner()
		{
			MinerComponent[] minerPool = factory.factorySystem.minerPool;
			int count = 0;
			for (int i = 1; i < factory.factorySystem.minerCursor; i++)
			{
				int num = (int)((r + i) % (factory.factorySystem.minerCursor - 1)) + 1;
				if (minerPool[num].id == num)
				{
					ref MinerComponent reference = ref minerPool[num];
					if (reference.productId > 0)
					{
						Functions._produce(reference.productId, served, ref reference.productCount, ref count);
					}
				}
			}
		}

		private void RegisterLab()
		{
			LabComponent[] labPool = factory.factorySystem.labPool;
			for (int i = 1; i < factory.factorySystem.labCursor; i++)
			{
				ref LabComponent reference = ref labPool[i];
				if (reference.id == i && !reference.researchMode && reference.recipeId > 0)
				{
					if (reference.recipeExecuteData.productCounts != null && reference.recipeExecuteData.productCounts.Length != 0)
					{
						for (int j = 0; j < reference.recipeExecuteData.productCounts.Length; j++)
						{
							produced[reference.recipeExecuteData.products[j]] += reference.produced[j];
						}
					}
					for (int k = 0; k < reference.needs.Length; k++)
					{
						if (reference.needs[k] > 0)
						{
							int num = Functions._positive(4 - reference.served[k]);
							sumSpray += num;
							served[reference.needs[k]] += num;
						}
					}
				}
				if (reference.id != i || !reference.researchMode)
				{
					continue;
				}
				for (int l = 0; l < reference.needs.Length; l++)
				{
					if (reference.needs[l] > 0)
					{
						int num2 = Functions._positive((36000 - reference.matrixServed[l]) / 3600);
						sumSpray += num2;
						served[reference.needs[l]] += num2;
					}
				}
			}
		}

		private void ConsumeLab()
		{
			LabComponent[] labPool = factory.factorySystem.labPool;
			int count = 0;
			for (int i = 1; i < factory.factorySystem.labCursor; i++)
			{
				int num = (int)((r + i) % (factory.factorySystem.labCursor - 1)) + 1;
				ref LabComponent reference = ref labPool[num];
				if (reference.id == num && !reference.researchMode && reference.recipeId > 0)
				{
					if (reference.recipeExecuteData.productCounts != null && reference.recipeExecuteData.productCounts.Length != 0)
					{
						for (int j = 0; j < reference.recipeExecuteData.productCounts.Length; j++)
						{
							Functions._produce(reference.recipeExecuteData.products[j], served, ref reference.produced[j], ref count);
						}
					}
					for (int k = 0; k < reference.needs.Length; k++)
					{
						if (reference.needs[k] > 0)
						{
							Functions._serve(reference.needs[k], produced, ref reference.served[k], 4, ref count);
							if (spray)
							{
								inc -= count * Constants.INC_ABILITY;
								reference.incServed[k] += Constants.INC_ABILITY * count;
							}
						}
					}
				}
				if (reference.id != num || !reference.researchMode)
				{
					continue;
				}
				for (int l = 0; l < reference.needs.Length; l++)
				{
					if (reference.needs[l] <= 0)
					{
						continue;
					}
					int num2 = reference.needs[l];
					if (produced[num2] > 0)
					{
						count = Functions._positive(Math.Min((36000 - reference.matrixServed[l]) / 3600, produced[num2]));
						produced[num2] -= count;
						reference.matrixServed[l] += count * 3600;
						if (spray)
						{
							inc -= count * Constants.INC_ABILITY;
							reference.matrixIncServed[l] += Constants.INC_ABILITY * count * 3600;
						}
					}
				}
			}
		}

		private void RegisterEjector()
		{
			EjectorComponent[] ejectorPool = factory.factorySystem.ejectorPool;
			for (int i = 1; i < factory.factorySystem.ejectorCursor; i++)
			{
				ref EjectorComponent reference = ref ejectorPool[i];
				if (reference.id == i && reference.bulletId > 0)
				{
					int num = Functions._positive(20 - reference.bulletCount);
					sumSpray += num;
					served[reference.bulletId] += num;
				}
			}
		}

		private void ConsumeEjector()
		{
			EjectorComponent[] ejectorPool = factory.factorySystem.ejectorPool;
			int count = 0;
			for (int i = 1; i < factory.factorySystem.ejectorCursor; i++)
			{
				int num = (int)((r + i) % (factory.factorySystem.ejectorCursor - 1)) + 1;
				ref EjectorComponent reference = ref ejectorPool[num];
				if (reference.id == num && reference.bulletId > 0)
				{
					Functions._serve(reference.bulletId, produced, ref reference.bulletCount, 20, ref count);
					if (spray)
					{
						inc -= count * Constants.INC_ABILITY;
						reference.bulletInc += Constants.INC_ABILITY * count;
					}
				}
			}
		}

		private void RegisterSilo()
		{
			SiloComponent[] siloPool = factory.factorySystem.siloPool;
			for (int i = 1; i < factory.factorySystem.siloCursor; i++)
			{
				ref SiloComponent reference = ref siloPool[i];
				if (reference.id == i && reference.bulletId > 0)
				{
					int num = Functions._positive(20 - reference.bulletCount);
					sumSpray += num;
					served[reference.bulletId] += num;
				}
			}
		}

		private void ConsumeSilo()
		{
			SiloComponent[] siloPool = factory.factorySystem.siloPool;
			int count = 0;
			for (int i = 1; i < factory.factorySystem.siloCursor; i++)
			{
				int num = (int)((r + i) % (factory.factorySystem.siloCursor - 1)) + 1;
				ref SiloComponent reference = ref siloPool[num];
				if (reference.id == num && reference.bulletId > 0)
				{
					Functions._serve(reference.bulletId, produced, ref reference.bulletCount, 20, ref count);
					if (spray)
					{
						inc -= count * Constants.INC_ABILITY;
						reference.bulletInc += Constants.INC_ABILITY * count;
					}
				}
			}
		}

		private void RegisterStorage()
		{
			StorageComponent[] storagePool = factory.factoryStorage.storagePool;
			for (int i = 1; i < factory.factoryStorage.storageCursor; i++)
			{
				if (storagePool[i] == null || storagePool[i].id != i || storagePool[i].grids == null)
				{
					continue;
				}
				for (int j = 0; j < storagePool[i].grids.Length; j++)
				{
					if (storagePool[i].grids[j].itemId > 0)
					{
						produced[storagePool[i].grids[j].itemId] += storagePool[i].grids[j].count;
					}
				}
			}
			TankComponent[] tankPool = factory.factoryStorage.tankPool;
			for (int k = 1; k < factory.factoryStorage.tankCursor; k++)
			{
				if (tankPool[k].id == k && tankPool[k].fluidId > 0)
				{
					produced[tankPool[k].fluidId] += tankPool[k].fluidCount;
				}
			}
		}

		private void ConsumeStorage()
		{
			StorageComponent[] storagePool = factory.factoryStorage.storagePool;
			int count = 0;
			for (int i = 1; i < factory.factoryStorage.storageCursor; i++)
			{
				int num = (int)((r + i) % (factory.factoryStorage.storageCursor - 1)) + 1;
				if (storagePool[num] == null || storagePool[num].id != num || storagePool[num].grids == null)
				{
					continue;
				}
				bool flag = false;
				for (int j = 0; j < storagePool[num].grids.Length; j++)
				{
					if (storagePool[num].grids[j].itemId > 0)
					{
						Functions._produce(storagePool[num].grids[j].itemId, served, ref storagePool[num].grids[j].count, ref count);
						int num2 = Functions._split_inc(storagePool[num].grids[j].inc, count);
						inc += num2;
						storagePool[num].grids[j].inc -= num2;
						if (storagePool[num].grids[j].count <= 0)
						{
							storagePool[num].grids[j].itemId = 0;
							storagePool[num].grids[j].count = 0;
							storagePool[num].grids[j].inc = 0;
						}
						if (count > 0)
						{
							flag = true;
						}
					}
				}
				if (flag)
				{
					storagePool[num].Sort(true);
				}
			}
			TankComponent[] tankPool = factory.factoryStorage.tankPool;
			for (int k = 1; k < factory.factoryStorage.tankCursor; k++)
			{
				int num3 = (int)((r + k) % (factory.factoryStorage.tankCursor - 1)) + 1;
				if (tankPool[num3].id != num3 || tankPool[num3].fluidId <= 0)
				{
					continue;
				}
				int fluidId = tankPool[num3].fluidId;
				if (buffer[fluidId] > 0)
				{
					if (tankPool[num3].fluidCount < tankPool[num3].fluidCapacity)
					{
						count = Math.Min(buffer[fluidId], tankPool[num3].fluidCapacity - tankPool[num3].fluidCount);
						buffer[fluidId] -= count;
						tankPool[num3].fluidCount += count;
					}
					else if (tankPool[num3].nextTankId > 0)
					{
						tankPool[tankPool[num3].nextTankId].fluidId = fluidId;
					}
				}
				Functions._produce(fluidId, served, ref tankPool[num3].fluidCount, ref count);
				int num4 = Functions._split_inc(tankPool[num3].fluidInc, count);
				inc += num4;
				tankPool[num3].fluidInc -= num4;
				if (tankPool[num3].fluidCount <= 0)
				{
					tankPool[num3].fluidId = 0;
					tankPool[num3].fluidCount = 0;
					tankPool[num3].fluidInc = 0;
				}
			}
		}

		private void RegisterTrash()
		{
			Cosmic.mutex.WaitOne();
			for (int i = 0; i < 12000; i++)
			{
				produced[i] += cosmic.trashProduced[i];
			}
			Cosmic.mutex.ReleaseMutex();
		}

		private void ConsumeTrash()
		{
			int num = 0;
			Cosmic.mutex.WaitOne();
			for (int i = 0; i < 12000; i++)
			{
				if (served[i] > 0)
				{
					num = Functions._positive(Math.Min(cosmic.trashProduced[i] - cosmic.trashServed[i], served[i]));
					served[i] -= num;
					cosmic.trashServed[i] += num;
				}
			}
			Cosmic.mutex.ReleaseMutex();
		}

		private void ConsumeBuffer()
		{
			for (int i = 0; i < 12000; i++)
			{
				if (served[i] > 0 && buffer[i] > 0)
				{
					int num = Math.Min(buffer[i], served[i]);
					served[i] -= num;
					buffer[i] -= num;
				}
			}
		}

		private void RegisterFractionator()
		{
			FractionatorComponent[] fractionatorPool = factory.factorySystem.fractionatorPool;
			for (int i = 1; i < factory.factorySystem.fractionatorCursor; i++)
			{
				if (fractionatorPool[i].id == i)
				{
					if (fractionatorPool[i].fluidId > 0)
					{
						int num = Functions._positive(fractionatorPool[i].fluidInputMax * 4 - fractionatorPool[i].fluidInputCount);
						served[fractionatorPool[i].fluidId] += num;
						sumSpray += num;
						num = Functions._positive(fractionatorPool[i].fluidOutputCount);
						produced[fractionatorPool[i].fluidId] += num;
					}
					if (fractionatorPool[i].productId > 0)
					{
						produced[fractionatorPool[i].productId] += Functions._positive(fractionatorPool[i].productOutputCount - 1);
					}
				}
			}
		}

		private void ConsumeFractionator()
		{
			FractionatorComponent[] fractionatorPool = factory.factorySystem.fractionatorPool;
			int count = 0;
			for (int i = 1; i < factory.factorySystem.fractionatorCursor; i++)
			{
				int num = (int)((r + i) % (factory.factorySystem.fractionatorCursor - 1)) + 1;
				ref FractionatorComponent reference = ref fractionatorPool[num];
				if (reference.id != num)
				{
					continue;
				}
				if (reference.fluidId > 0)
				{
					int fluidId = reference.fluidId;
					Functions._serve(fluidId, produced, ref reference.fluidInputCount, 4 * reference.fluidInputMax, ref count);
					reference.fluidInputCargoCount += 0.25f * (float)count;
					if (spray)
					{
						inc -= count * Constants.INC_ABILITY;
						reference.fluidInputInc += count * Constants.INC_ABILITY;
					}
					if (buffer[fluidId] < 1000 && reference.fluidOutputCount > reference.fluidOutputMax / 2)
					{
						buffer[fluidId] += reference.fluidOutputCount;
						reference.fluidOutputCount = 0;
					}
					else
					{
						Functions._produce(fluidId, served, ref reference.fluidOutputCount, ref count);
					}
					int num2 = Functions._split_inc(reference.fluidOutputInc, count);
					inc += num2;
					reference.fluidOutputInc -= num2;
				}
				if (reference.productId > 1)
				{
					int productId = reference.productId;
					reference.productOutputCount--;
					Functions._produce(productId, served, ref reference.productOutputCount, ref count);
					reference.productOutputCount++;
				}
			}
		}

		private void RegisterTurret()
		{
			TurretComponent[] array = factory.defenseSystem.turrets.buffer;
			int num = 0;
			for (int i = 1; i < factory.defenseSystem.turrets.cursor; i++)
			{
				ref TurretComponent reference = ref array[i];
				if (reference.id == i && reference.itemId > 0)
				{
					int itemId = reference.itemId;
					num = Functions._positive(5 - reference.itemCount);
					served[itemId] += num;
					sumSpray += num;
				}
			}
		}

		private void ConsumeTurret()
		{
			TurretComponent[] array = factory.defenseSystem.turrets.buffer;
			int count = 0;
			for (int i = 1; i < factory.defenseSystem.turrets.cursor; i++)
			{
				int num = (int)((r + i) % (factory.defenseSystem.turrets.cursor - 1)) + 1;
				ref TurretComponent reference = ref array[num];
				if (reference.id == num && reference.itemId > 0)
				{
					short itemId = reference.itemId;
					int serve = reference.itemCount;
					Functions._serve(itemId, produced, ref serve, 5, ref count);
					reference.itemCount = (short)serve;
					if (spray)
					{
						inc -= count * Constants.INC_ABILITY;
						reference.itemInc += (short)(count * Constants.INC_ABILITY);
					}
				}
			}
		}

		private void Spray()
		{
			if (inc < sumSpray * Constants.INC_ABILITY && produced[1143] > 0)
			{
				int num = Math.Min((sumSpray * Constants.INC_ABILITY - inc - 1) / (Constants.INC_SPRAY_TIMES + Constants.EXTRA_INC_SPRAY_TIMES - 1) / Constants.INC_ABILITY + 1, produced[1143]);
				inc += num * (Constants.INC_SPRAY_TIMES + Constants.EXTRA_INC_SPRAY_TIMES - 1) * Constants.INC_ABILITY;
				produced[1143] -= num;
				served[1143] += num;
				consumedProliferator += num;
			}
			if (inc < 1)
			{
				spray = false;
			}
		}
	}
}