Decompiled source of PlanetWormhole v2.0.0

PlanetWormhole.dll

Decompiled 11 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
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: AssemblyTitle("PlanetWormhole")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("PlanetWormhole")]
[assembly: AssemblyCopyright("MIT License")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("5cd3f34c-4823-48af-9910-53d010b5d8e9")]
[assembly: AssemblyFileVersion("2.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("2.0.0.0")]
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.0")]
	public class PlanetWormhole : BaseUnityPlugin
	{
		private const string package = "essium.DSP.PlanetWormhole";

		private const string plugin = "PlanetWormhole";

		private const string version = "2.0.0";

		private static List<LocalPlanet> planetWormhole;

		private static Cosmic globalWormhole;

		private static ManualLogSource logger;

		private static ConfigEntry<bool> enableInterstellar;

		private Harmony harmony;

		[HarmonyPostfix]
		[HarmonyPatch(typeof(GameData), "GameTick")]
		private static void _postfix_GameData_GameTick(GameData __instance, long time)
		{
			if (!GameMain.instance.isMenuDemo)
			{
				PerformanceMonitor.BeginSample((ECpuWorkEntry)9);
				while (planetWormhole.Count < __instance.factoryCount)
				{
					planetWormhole.Add(new LocalPlanet());
				}
				globalWormhole.SetData(__instance);
				globalWormhole.BeforeLocal();
				for (int i = (int)(time % 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)(time % 9); j < __instance.factoryCount; j += 9)
				{
					planetWormhole[j].completeSignal.WaitOne();
				}
				globalWormhole.AfterLocal();
				PerformanceMonitor.EndSample((ECpuWorkEntry)9);
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(ProductionStatistics), "GameTick")]
		private static void _postfix_ProductionStatistics_GameTick(ProductionStatistics __instance, long time)
		{
			if (GameMain.instance.isMenuDemo)
			{
				return;
			}
			for (int i = 0; i < __instance.gameData.factoryCount; i++)
			{
				if (planetWormhole.Count > i && 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.0");
			harmony.PatchAll(typeof(PlanetWormhole));
		}

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

		private void BindConfig()
		{
			enableInterstellar = ((BaseUnityPlugin)this).Config.Bind<bool>("Config", "EnableInterstellar", true, "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;
				}
				for (int j = 0; j < assemblerPool[i].produced.Length; j++)
				{
					if (assemblerPool[i].produced[j] > 0)
					{
						produced[assemblerPool[i].products[j]] += assemblerPool[i].produced[j];
					}
				}
				for (int k = 0; k < assemblerPool[i].requireCounts.Length; k++)
				{
					if (assemblerPool[i].needs[k] > 0)
					{
						int num = Functions._positive(3 * assemblerPool[i].requireCounts[k] - assemblerPool[i].served[k]);
						sumSpray += num;
						served[assemblerPool[i].needs[k]] += num;
					}
				}
			}
		}

		private void ConsumeAssembler()
		{
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Invalid comparison between Unknown and I4
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: 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;
				}
				for (int j = 0; j < assemblerPool[num].produced.Length; j++)
				{
					if (assemblerPool[num].produced[j] > 0)
					{
						Functions._produce(assemblerPool[num].products[j], served, ref assemblerPool[num].produced[j], ref count);
					}
				}
				if (assemblerPool[num].produced.Length > 1)
				{
					int num2 = assemblerPool[num].produced.Length;
					ERecipeType recipeType = assemblerPool[num].recipeType;
					if ((int)recipeType != 1)
					{
						if ((int)recipeType == 4)
						{
							for (int k = 0; k < num2; k++)
							{
								if (assemblerPool[num].produced[k] > assemblerPool[num].productCounts[k] * 9 && buffer[assemblerPool[num].products[k]] < 1000)
								{
									assemblerPool[num].produced[k] -= assemblerPool[num].productCounts[k];
									buffer[assemblerPool[num].products[k]] += assemblerPool[num].productCounts[k];
								}
							}
						}
						else
						{
							for (int l = 0; l < num2; l++)
							{
								if (assemblerPool[num].produced[l] > assemblerPool[num].productCounts[l] * 19 && buffer[assemblerPool[num].products[l]] < 1000)
								{
									assemblerPool[num].produced[l] -= assemblerPool[num].productCounts[l];
									buffer[assemblerPool[num].products[l]] += assemblerPool[num].productCounts[l];
								}
							}
						}
					}
					else
					{
						for (int m = 0; m < num2; m++)
						{
							if (assemblerPool[num].produced[m] + assemblerPool[num].productCounts[m] > 100 && buffer[assemblerPool[num].products[m]] < 1000)
							{
								assemblerPool[num].produced[m] -= assemblerPool[num].productCounts[m];
								buffer[assemblerPool[num].products[m]] += assemblerPool[num].productCounts[m];
							}
						}
					}
				}
				for (int n = 0; n < assemblerPool[num].requireCounts.Length; n++)
				{
					if (assemblerPool[num].needs[n] > 0)
					{
						Functions._serve(assemblerPool[num].needs[n], produced, ref assemblerPool[num].served[n], 3 * assemblerPool[num].requireCounts[n], ref count);
						if (spray)
						{
							inc -= count * Constants.INC_ABILITY;
							assemblerPool[num].incServed[n] += Constants.INC_ABILITY * count;
						}
					}
				}
			}
		}

		private void RegisterStation()
		{
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Invalid comparison between Unknown and I4
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Invalid comparison between Unknown and I4
			StationComponent[] stationPool = factory.transport.stationPool;
			for (int i = 1; i < factory.transport.stationCursor; i++)
			{
				if (stationPool[i] == null || stationPool[i].id != i || stationPool[i].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 (stationPool[i].needs[5] == 1210 && factory.gameData.history.TechUnlocked(3404))
				{
					served[1210] += Functions._positive(stationPool[i].warperMaxCount - stationPool[i].warperCount);
				}
			}
		}

		private void ConsumeStation()
		{
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Invalid comparison between Unknown and I4
			//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c1: 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;
				if (stationPool[num] != null && stationPool[num].id == num && stationPool[num].storage != null && stationPool[num].needs[5] == 1210 && factory.gameData.history.TechUnlocked(3404))
				{
					Functions._serve(1210, produced, ref stationPool[num].warperCount, stationPool[num].warperMaxCount, ref count);
				}
			}
			for (int j = 1; j < factory.transport.stationCursor; j++)
			{
				int num2 = (int)((r + j) % (factory.transport.stationCursor - 1)) + 1;
				if (stationPool[num2] == null || stationPool[num2].id != num2 || stationPool[num2].storage == null)
				{
					continue;
				}
				StationStore[] storage = stationPool[num2].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;
				}
				if (genPool[i].catalystId > 0 && factory.gameData.history.TechUnlocked(1505))
				{
					int num = Functions._positive((72000 - genPool[i].catalystPoint) / 3600);
					sumSpray += num;
					served[genPool[i].catalystId] += num;
					if (genPool[i].productId > 0)
					{
						produced[genPool[i].productId] += (int)genPool[i].productCount;
					}
				}
				int[] array = ItemProto.fuelNeeds[genPool[i].fuelMask];
				if (genPool[i].fuelId <= 0 && (array == null || array.Length == 0))
				{
					continue;
				}
				int num2;
				if (genPool[i].fuelId > 0)
				{
					num2 = genPool[i].fuelId;
				}
				else
				{
					if (array.Length == 0)
					{
						continue;
					}
					num2 = array[0];
					((PowerGeneratorComponent)(ref genPool[i])).SetNewFuel(num2, (short)0, (short)0);
				}
				int num3 = Functions._positive(10 - genPool[i].fuelCount);
				sumSpray += num3;
				served[num2] += num3;
			}
			PowerExchangerComponent[] excPool = factory.powerSystem.excPool;
			for (int j = 1; j < factory.powerSystem.excCursor; j++)
			{
				if (excPool[j].id == j && excPool[j].fullId > 0 && excPool[j].emptyId > 0)
				{
					if (Functions._float_equal(excPool[j].targetState, 1f))
					{
						produced[excPool[j].fullId] += excPool[j].fullCount;
						served[excPool[j].emptyId] += Functions._positive(20 - excPool[j].emptyCount);
					}
					else if (Functions._float_equal(excPool[j].targetState, -1f))
					{
						produced[excPool[j].emptyId] += excPool[j].emptyCount;
						served[excPool[j].fullId] += Functions._positive(20 - excPool[j].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;
				if (genPool[num2].id != num2)
				{
					continue;
				}
				if (genPool[num2].catalystId > 0 && factory.gameData.history.TechUnlocked(1505))
				{
					int catalystId = genPool[num2].catalystId;
					if (produced[catalystId] > 0)
					{
						num = Functions._positive(Math.Min((72000 - genPool[num2].catalystPoint) / 3600, produced[catalystId]));
						produced[catalystId] -= num;
						genPool[num2].catalystPoint += num * 3600;
						if (spray)
						{
							inc -= num * Constants.INC_ABILITY;
							genPool[num2].catalystIncPoint += num * 3600 * Constants.INC_ABILITY;
						}
					}
					if (genPool[num2].productId > 0)
					{
						catalystId = genPool[num2].productId;
						if (served[catalystId] > 0)
						{
							num = Math.Min((int)genPool[num2].productCount, served[catalystId]);
							served[catalystId] -= num;
							genPool[num2].productCount -= num;
						}
					}
				}
				if (genPool[num2].fuelId <= 0)
				{
					continue;
				}
				int fuelId = genPool[num2].fuelId;
				if (produced[fuelId] > 0)
				{
					num = Functions._positive(Math.Min(10 - genPool[num2].fuelCount, produced[fuelId]));
					produced[fuelId] -= num;
					genPool[num2].fuelCount += (short)num;
					if (spray)
					{
						inc -= num * Constants.INC_ABILITY;
						genPool[num2].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;
				if (excPool[num3].id != num3 || excPool[num3].fullId <= 0 || excPool[num3].emptyId <= 0)
				{
					continue;
				}
				int fullId = excPool[num3].fullId;
				int emptyId = excPool[num3].emptyId;
				if (Functions._float_equal(excPool[num3].targetState, 1f))
				{
					if (served[fullId] > 0)
					{
						num = Math.Min(excPool[num3].fullCount, served[fullId]);
						served[fullId] -= num;
						excPool[num3].fullCount -= (short)num;
					}
					if (produced[emptyId] > 0)
					{
						num = Functions._positive(Math.Min(20 - excPool[num3].emptyCount, produced[emptyId]));
						produced[emptyId] -= num;
						excPool[num3].emptyCount += (short)num;
					}
				}
				else if (Functions._float_equal(excPool[num3].targetState, -1f))
				{
					if (served[emptyId] > 0)
					{
						num = Math.Min(excPool[num3].emptyCount, served[emptyId]);
						served[emptyId] -= num;
						excPool[num3].emptyCount -= (short)num;
					}
					if (produced[fullId] > 0)
					{
						num = Functions._positive(Math.Min(20 - excPool[num3].fullCount, produced[fullId]));
						produced[fullId] -= num;
						excPool[num3].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 && minerPool[i].productId > 0)
				{
					produced[minerPool[i].productId] += minerPool[i].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 && minerPool[num].productId > 0)
				{
					Functions._produce(minerPool[num].productId, served, ref minerPool[num].productCount, ref count);
				}
			}
		}

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

		private void RegisterEjector()
		{
			EjectorComponent[] ejectorPool = factory.factorySystem.ejectorPool;
			for (int i = 1; i < factory.factorySystem.ejectorCursor; i++)
			{
				if (ejectorPool[i].id == i && ejectorPool[i].bulletId > 0)
				{
					int num = Functions._positive(20 - ejectorPool[i].bulletCount);
					sumSpray += num;
					served[ejectorPool[i].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;
				if (ejectorPool[num].id == num && ejectorPool[num].bulletId > 0)
				{
					Functions._serve(ejectorPool[num].bulletId, produced, ref ejectorPool[num].bulletCount, 20, ref count);
					if (spray)
					{
						inc -= count * Constants.INC_ABILITY;
						ejectorPool[num].bulletInc += Constants.INC_ABILITY * count;
					}
				}
			}
		}

		private void RegisterSilo()
		{
			SiloComponent[] siloPool = factory.factorySystem.siloPool;
			for (int i = 1; i < factory.factorySystem.siloCursor; i++)
			{
				if (siloPool[i].id == i && siloPool[i].bulletId > 0)
				{
					int num = Functions._positive(20 - siloPool[i].bulletCount);
					sumSpray += num;
					served[siloPool[i].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;
				if (siloPool[num].id == num && siloPool[num].bulletId > 0)
				{
					Functions._serve(siloPool[num].bulletId, produced, ref siloPool[num].bulletCount, 20, ref count);
					if (spray)
					{
						inc -= count * Constants.INC_ABILITY;
						siloPool[num].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;
				if (fractionatorPool[num].id != num)
				{
					continue;
				}
				if (fractionatorPool[num].fluidId > 0)
				{
					int fluidId = fractionatorPool[num].fluidId;
					Functions._serve(fluidId, produced, ref fractionatorPool[num].fluidInputCount, 4 * fractionatorPool[num].fluidInputMax, ref count);
					fractionatorPool[num].fluidInputCargoCount += 0.25f * (float)count;
					if (spray)
					{
						inc -= count * Constants.INC_ABILITY;
						fractionatorPool[num].fluidInputInc += count * Constants.INC_ABILITY;
					}
					if (buffer[fluidId] < 1000 && fractionatorPool[num].fluidOutputCount > fractionatorPool[num].fluidOutputMax / 2)
					{
						buffer[fluidId] += fractionatorPool[num].fluidOutputCount;
						fractionatorPool[num].fluidOutputCount = 0;
					}
					else
					{
						Functions._produce(fluidId, served, ref fractionatorPool[num].fluidOutputCount, ref count);
					}
					int num2 = Functions._split_inc(fractionatorPool[num].fluidOutputInc, count);
					inc += num2;
					fractionatorPool[num].fluidOutputInc -= num2;
				}
				if (fractionatorPool[num].productId > 1)
				{
					int productId = fractionatorPool[num].productId;
					fractionatorPool[num].productOutputCount--;
					Functions._produce(productId, served, ref fractionatorPool[num].productOutputCount, ref count);
					fractionatorPool[num].productOutputCount++;
				}
			}
		}

		private void RegisterTurret()
		{
			TurretComponent[] array = factory.defenseSystem.turrets.buffer;
			int num = 0;
			for (int i = 1; i < factory.defenseSystem.turrets.cursor; i++)
			{
				if (array[i].id == i && array[i].itemId > 0)
				{
					int itemId = array[i].itemId;
					num = Functions._positive(5 - array[i].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;
				if (array[num].id == num && array[num].itemId > 0)
				{
					short itemId = array[num].itemId;
					int serve = array[num].itemCount;
					Functions._serve(itemId, produced, ref serve, 5, ref count);
					array[num].itemCount = (short)serve;
					if (spray)
					{
						inc -= count * Constants.INC_ABILITY;
						array[num].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;
			}
		}
	}
}