Decompiled source of PlanetwideCollector v1.0.0

plugins\PlanetwideCollector.dll

Decompiled 2 days 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 BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("PlanetwideCollector")]
[assembly: AssemblyDescription("Dyson Sphere Program BepInEx mod.")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("PlanetwideCollector")]
[assembly: AssemblyCopyright("Copyright (c) 2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("00000000-0000-0000-0000-000000000000")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = "")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace PlanetwideCollector;

internal static class PlanetwideCollectorLog
{
	private const string Tag = "[PlanetwideCollector] ";

	private static ManualLogSource logger;

	private static ConfigEntry<bool> debugGate;

	public static void Init(ManualLogSource src, ConfigEntry<bool> debug)
	{
		logger = src;
		debugGate = debug;
	}

	public static bool IsDebugEnabled()
	{
		if (debugGate != null)
		{
			return debugGate.Value;
		}
		return false;
	}

	public static void Info(string msg)
	{
		if (logger != null && IsDebugEnabled())
		{
			logger.LogInfo((object)("[PlanetwideCollector] " + msg));
		}
	}

	public static void Warn(string msg)
	{
		if (logger != null)
		{
			logger.LogWarning((object)("[PlanetwideCollector] " + msg));
		}
	}

	public static void Error(string msg)
	{
		if (logger != null)
		{
			logger.LogError((object)("[PlanetwideCollector] " + msg));
		}
	}
}
internal static class MiningScan
{
	private struct ScanTotals
	{
		public int total;

		public int collected;

		public int movedItems;

		public int noSlot;

		public int skippedInserter;

		public int skippedClaimed;
	}

	private const long LogThrottleTicks = 300L;

	private static long _lastScannedTick = -1L;

	private static long _lastLogTick = long.MinValue;

	private static float _lastErrorLogRealtime = float.NegativeInfinity;

	private static bool[] _inserterIndex;

	private static bool[] _claimedMinerIndex;

	internal static void Tick()
	{
		try
		{
			if (!Plugin.MiningEnabled.Value || GameMain.data == null || GameMain.data.factories == null)
			{
				return;
			}
			long gameTick = GameMain.gameTick;
			int num = Plugin.MiningCollectIntervalTicks.Value;
			if (num < 1)
			{
				num = 1;
			}
			if (gameTick < _lastScannedTick)
			{
				_lastScannedTick = gameTick - num;
				_lastLogTick = gameTick - 300;
			}
			if (gameTick - _lastScannedTick < num)
			{
				return;
			}
			_lastScannedTick = gameTick;
			float value = Plugin.MiningCollectRadius.Value;
			ScanTotals totals = default(ScanTotals);
			PlanetFactory[] factories = GameMain.data.factories;
			foreach (PlanetFactory val in factories)
			{
				if (val != null && val.factorySystem != null)
				{
					ScanFactory(val, value, ref totals);
				}
			}
			if (PlanetwideCollectorLog.IsDebugEnabled())
			{
				bool value2 = Plugin.MiningVerboseScan.Value;
				bool flag = totals.movedItems > 0 || totals.noSlot > 0 || totals.skippedInserter > 0;
				if ((value2 || flag) && gameTick - _lastLogTick >= 300)
				{
					_lastLogTick = gameTick;
					PlanetwideCollectorLog.Info("[collect] mining{" + (value2 ? ("total=" + totals.total + " claimed=" + totals.skippedClaimed + " ") : "") + "collected=" + totals.collected + " items=" + totals.movedItems + ((totals.noSlot > 0) ? (" noSlot=" + totals.noSlot) : "") + ((totals.skippedInserter > 0) ? (" skippedInserter=" + totals.skippedInserter) : "") + "}");
				}
			}
		}
		catch (Exception ex)
		{
			float realtimeSinceStartup = Time.realtimeSinceStartup;
			if (realtimeSinceStartup - _lastErrorLogRealtime >= 5f)
			{
				_lastErrorLogRealtime = realtimeSinceStartup;
				PlanetwideCollectorLog.Error("[scan] MiningScan.Tick threw: " + ex);
			}
		}
	}

	private static void ScanFactory(PlanetFactory factory, float radius, ref ScanTotals totals)
	{
		//IL_010f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0114: Unknown result type (might be due to invalid IL or missing references)
		//IL_0139: Unknown result type (might be due to invalid IL or missing references)
		//IL_012d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0132: Unknown result type (might be due to invalid IL or missing references)
		FactorySystem factorySystem = factory.factorySystem;
		if (factorySystem.minerCursor <= 1)
		{
			return;
		}
		MinerComponent[] minerPool = factorySystem.minerPool;
		if (minerPool == null)
		{
			return;
		}
		MiningSourcing.BuildClaimedMinerIndex(factory, ref _claimedMinerIndex);
		bool value = Plugin.MiningSkipInserterFedMiners.Value;
		if (value)
		{
			ProductionSourcing.BuildInserterIndex(factory, ref _inserterIndex);
		}
		EntityData[] entityPool = factory.entityPool;
		int minerCursor = factorySystem.minerCursor;
		for (int i = 1; i < minerCursor; i++)
		{
			if (minerPool[i].id != i)
			{
				continue;
			}
			totals.total++;
			if (_claimedMinerIndex != null && i < _claimedMinerIndex.Length && _claimedMinerIndex[i])
			{
				totals.skippedClaimed++;
				continue;
			}
			int entityId = minerPool[i].entityId;
			if (value && _inserterIndex != null && entityId > 0 && entityId < _inserterIndex.Length && _inserterIndex[entityId])
			{
				totals.skippedInserter++;
				continue;
			}
			int productId = minerPool[i].productId;
			if (productId == 0)
			{
				continue;
			}
			int productCount = minerPool[i].productCount;
			if (productCount > 0)
			{
				Vector3 pos = Vector3.zero;
				if (entityPool != null && entityId > 0 && entityId < entityPool.Length)
				{
					pos = entityPool[entityId].pos;
				}
				int num = MiningSourcing.TryPushToPlanet(factory, productId, productCount, pos, radius);
				if (num <= 0)
				{
					totals.noSlot++;
					continue;
				}
				minerPool[i].productCount -= num;
				totals.collected++;
				totals.movedItems += num;
			}
		}
	}
}
internal static class MiningSourcing
{
	private struct StationDist
	{
		public int index;

		public float distSqr;
	}

	private static List<StationDist> _scratch;

	private static readonly Comparison<StationDist> _byDist = (StationDist a, StationDist b) => a.distSqr.CompareTo(b.distSqr);

	internal static int TryPushToPlanet(PlanetFactory factory, int itemId, int want, Vector3 pos, float radius)
	{
		//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00de: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
		if (factory == null || itemId <= 0 || want <= 0)
		{
			return 0;
		}
		PlanetTransport transport = factory.transport;
		if (transport == null || transport.stationPool == null)
		{
			return 0;
		}
		bool value = Plugin.MiningRequireStationDemandFlag.Value;
		bool value2 = Plugin.MiningNearestStationFirst.Value;
		float num = ((radius > 0f) ? (radius * radius) : 0f);
		EntityData[] entityPool = factory.entityPool;
		int stationCursor = transport.stationCursor;
		int moved = 0;
		Vector3 val2;
		if (value2)
		{
			if (_scratch == null)
			{
				_scratch = new List<StationDist>(64);
			}
			_scratch.Clear();
			for (int i = 1; i < stationCursor; i++)
			{
				StationComponent val = transport.stationPool[i];
				if (val == null || val.id != i || val.storage == null)
				{
					continue;
				}
				float num2 = 0f;
				if (entityPool != null)
				{
					int entityId = val.entityId;
					if (entityId > 0 && entityId < entityPool.Length)
					{
						val2 = entityPool[entityId].pos - pos;
						num2 = ((Vector3)(ref val2)).sqrMagnitude;
						if (num > 0f && num2 > num)
						{
							continue;
						}
					}
				}
				if (StationHasAssignedSlot(val, itemId, value))
				{
					_scratch.Add(new StationDist
					{
						index = i,
						distSqr = num2
					});
				}
			}
			_scratch.Sort(_byDist);
			for (int j = 0; j < _scratch.Count; j++)
			{
				if (moved >= want)
				{
					break;
				}
				CreditStation(transport.stationPool[_scratch[j].index], itemId, want, value, ref moved);
			}
		}
		else
		{
			for (int k = 1; k < stationCursor && moved < want; k++)
			{
				StationComponent val3 = transport.stationPool[k];
				if (val3 == null || val3.id != k || val3.storage == null)
				{
					continue;
				}
				if (num > 0f && entityPool != null)
				{
					int entityId2 = val3.entityId;
					if (entityId2 > 0 && entityId2 < entityPool.Length)
					{
						val2 = entityPool[entityId2].pos - pos;
						if (((Vector3)(ref val2)).sqrMagnitude > num)
						{
							continue;
						}
					}
				}
				CreditStation(val3, itemId, want, value, ref moved);
			}
		}
		return moved;
	}

	private static bool StationHasAssignedSlot(StationComponent station, int itemId, bool requireDemand)
	{
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		//IL_002a: Invalid comparison between Unknown and I4
		//IL_0033: Unknown result type (might be due to invalid IL or missing references)
		//IL_0039: Invalid comparison between Unknown and I4
		StationStore[] storage = station.storage;
		for (int i = 0; i < storage.Length; i++)
		{
			if (storage[i].itemId == itemId && (!requireDemand || (int)storage[i].localLogic == 2 || (int)storage[i].remoteLogic == 2))
			{
				return true;
			}
		}
		return false;
	}

	private static void CreditStation(StationComponent station, int itemId, int want, bool requireDemand, ref int moved)
	{
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		//IL_002a: Invalid comparison between Unknown and I4
		//IL_0033: Unknown result type (might be due to invalid IL or missing references)
		//IL_0039: Invalid comparison between Unknown and I4
		StationStore[] storage = station.storage;
		for (int i = 0; i < storage.Length; i++)
		{
			if (moved >= want)
			{
				break;
			}
			if (storage[i].itemId != itemId || (requireDemand && (int)storage[i].localLogic != 2 && (int)storage[i].remoteLogic != 2))
			{
				continue;
			}
			int num = storage[i].max - storage[i].count;
			if (num > 0)
			{
				int num2 = want - moved;
				if (num2 > num)
				{
					num2 = num;
				}
				storage[i].count += num2;
				moved += num2;
			}
		}
	}

	internal static void BuildClaimedMinerIndex(PlanetFactory factory, ref bool[] buffer)
	{
		int num = factory.factorySystem?.minerCursor ?? 0;
		if (buffer == null || buffer.Length < num)
		{
			buffer = new bool[num];
		}
		else
		{
			Array.Clear(buffer, 0, num);
		}
		PlanetTransport transport = factory.transport;
		if (transport == null || transport.stationPool == null)
		{
			return;
		}
		StationComponent[] stationPool = transport.stationPool;
		int stationCursor = transport.stationCursor;
		for (int i = 1; i < stationCursor; i++)
		{
			StationComponent val = stationPool[i];
			if (val != null && val.id == i && val.isVeinCollector)
			{
				int minerId = val.minerId;
				if (minerId > 0 && minerId < buffer.Length)
				{
					buffer[minerId] = true;
				}
			}
		}
	}
}
[BepInPlugin("com.zicarius.PlanetwideCollector", "PlanetwideCollector", "1.0.0")]
public sealed class Plugin : BaseUnityPlugin
{
	public const string PluginGuid = "com.zicarius.PlanetwideCollector";

	public const string PluginName = "PlanetwideCollector";

	public const string PluginVersion = "1.0.0";

	internal static ConfigEntry<bool> ProductionEnabled;

	internal static ConfigEntry<float> ProductionCollectRadius;

	internal static ConfigEntry<bool> ProductionNearestStationFirst;

	internal static ConfigEntry<int> ProductionCollectIntervalTicks;

	internal static ConfigEntry<bool> ProductionRequireStationDemandFlag;

	internal static ConfigEntry<bool> ProductionSkipInserterFedBuildings;

	internal static ConfigEntry<bool> ProductionVerboseScan;

	internal static ConfigEntry<bool> MiningEnabled;

	internal static ConfigEntry<float> MiningCollectRadius;

	internal static ConfigEntry<bool> MiningNearestStationFirst;

	internal static ConfigEntry<int> MiningCollectIntervalTicks;

	internal static ConfigEntry<bool> MiningRequireStationDemandFlag;

	internal static ConfigEntry<bool> MiningSkipInserterFedMiners;

	internal static ConfigEntry<bool> MiningVerboseScan;

	internal static ConfigEntry<bool> DebugLog;

	private Harmony harmony;

	private void Awake()
	{
		//IL_03c2: Unknown result type (might be due to invalid IL or missing references)
		//IL_03cc: Expected O, but got Unknown
		DebugLog = ((BaseUnityPlugin)this).Config.Bind<bool>("Diagnostics", "DebugLog", false, "Enable verbose diagnostic logging to the BepInEx console.");
		ProductionEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Production", "Enabled", true, "Master switch for crafting-building output collection (smelters, assemblers, chemical plants, refineries, produce-mode Matrix Labs). If false this module is fully inert.");
		ProductionCollectRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Production", "CollectRadius", 0f, "Max straight-line distance from a producer to an eligible station. 0 = planetwide.");
		ProductionNearestStationFirst = ((BaseUnityPlugin)this).Config.Bind<bool>("Production", "NearestStationFirst", true, "Credit the closest eligible station first (true) instead of station build order (false).");
		ProductionCollectIntervalTicks = ((BaseUnityPlugin)this).Config.Bind<int>("Production", "CollectIntervalTicks", 60, "Game ticks between collection scans. ~60 = 1s.");
		ProductionRequireStationDemandFlag = ((BaseUnityPlugin)this).Config.Bind<bool>("Production", "RequireStationDemandFlag", false, "If true, only credit station slots set to Demand.");
		ProductionSkipInserterFedBuildings = ((BaseUnityPlugin)this).Config.Bind<bool>("Production", "SkipInserterFedBuildings", true, "If true, never auto-collect from a producer whose output is already being picked up by a sorter/inserter - only collect from producers with no outbound inserter connection at all.");
		ProductionVerboseScan = ((BaseUnityPlugin)this).Config.Bind<bool>("Production", "VerboseScan", false, "Debug aid (needs DebugLog on): periodic scan heartbeat even when nothing moved.");
		MiningEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Mining", "Enabled", true, "Master switch for standalone-miner output collection (Mining Machines, Oil Extractors not already claimed by a station's own vein-collector mode). If false this module is fully inert.");
		MiningCollectRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Mining", "CollectRadius", 0f, "Max straight-line distance from a miner to an eligible station. 0 = planetwide.");
		MiningNearestStationFirst = ((BaseUnityPlugin)this).Config.Bind<bool>("Mining", "NearestStationFirst", true, "Credit the closest eligible station first (true) instead of station build order (false).");
		MiningCollectIntervalTicks = ((BaseUnityPlugin)this).Config.Bind<int>("Mining", "CollectIntervalTicks", 60, "Game ticks between collection scans. ~60 = 1s.");
		MiningRequireStationDemandFlag = ((BaseUnityPlugin)this).Config.Bind<bool>("Mining", "RequireStationDemandFlag", false, "If true, only credit station slots set to Demand.");
		MiningSkipInserterFedMiners = ((BaseUnityPlugin)this).Config.Bind<bool>("Mining", "SkipInserterFedMiners", true, "If true, never auto-collect from a miner whose output is already being picked up by a sorter/inserter.");
		MiningVerboseScan = ((BaseUnityPlugin)this).Config.Bind<bool>("Mining", "VerboseScan", false, "Debug aid (needs DebugLog on): periodic scan heartbeat even when nothing moved.");
		PlanetwideCollectorLog.Init(((BaseUnityPlugin)this).Logger, DebugLog);
		PlanetwideCollectorLog.Info("[config] Production.Enabled=" + ProductionEnabled.Value + " CollectRadius=" + ProductionCollectRadius.Value + " CollectIntervalTicks=" + ProductionCollectIntervalTicks.Value + " NearestStationFirst=" + ProductionNearestStationFirst.Value + " RequireStationDemandFlag=" + ProductionRequireStationDemandFlag.Value + " SkipInserterFedBuildings=" + ProductionSkipInserterFedBuildings.Value + " VerboseScan=" + ProductionVerboseScan.Value);
		PlanetwideCollectorLog.Info("[config] Mining.Enabled=" + MiningEnabled.Value + " CollectRadius=" + MiningCollectRadius.Value + " CollectIntervalTicks=" + MiningCollectIntervalTicks.Value + " NearestStationFirst=" + MiningNearestStationFirst.Value + " RequireStationDemandFlag=" + MiningRequireStationDemandFlag.Value + " SkipInserterFedMiners=" + MiningSkipInserterFedMiners.Value + " VerboseScan=" + MiningVerboseScan.Value);
		harmony = new Harmony("com.zicarius.PlanetwideCollector");
		try
		{
			harmony.PatchAll();
			PlanetwideCollectorLog.Info("[patch] PatchAll complete.");
		}
		catch (Exception ex)
		{
			PlanetwideCollectorLog.Error("[patch] PatchAll failed: " + ex);
		}
		if (DebugLog.Value)
		{
			DumpTargetMethodSignatures();
		}
		PlanetwideCollectorLog.Info("PlanetwideCollector 1.0.0 loaded.");
	}

	private void Update()
	{
		ProductionScan.Tick();
		MiningScan.Tick();
	}

	private void OnDestroy()
	{
		if (harmony != null)
		{
			harmony.UnpatchSelf();
			harmony = null;
		}
		PlanetwideCollectorLog.Info("PlanetwideCollector unloaded.");
	}

	private static void DumpTargetMethodSignatures()
	{
		string[][] array = new string[22][]
		{
			new string[2] { "PlanetFactory", "transport" },
			new string[2] { "PlanetTransport", "stationPool" },
			new string[2] { "StationComponent", "storage" },
			new string[2] { "FactorySystem", "assemblerPool" },
			new string[2] { "FactorySystem", "assemblerCursor" },
			new string[2] { "FactorySystem", "labPool" },
			new string[2] { "FactorySystem", "labCursor" },
			new string[2] { "AssemblerComponent", "produced" },
			new string[2] { "AssemblerComponent", "recipeExecuteData" },
			new string[2] { "LabComponent", "produced" },
			new string[2] { "LabComponent", "researchMode" },
			new string[2] { "FactorySystem", "inserterPool" },
			new string[2] { "FactorySystem", "inserterCursor" },
			new string[2] { "InserterComponent", "pickTarget" },
			new string[2] { "InserterComponent", "insertTarget" },
			new string[2] { "FactorySystem", "minerPool" },
			new string[2] { "FactorySystem", "minerCursor" },
			new string[2] { "MinerComponent", "productId" },
			new string[2] { "MinerComponent", "productCount" },
			new string[2] { "MinerComponent", "entityId" },
			new string[2] { "StationComponent", "minerId" },
			new string[2] { "StationComponent", "isVeinCollector" }
		};
		foreach (string[] array2 in array)
		{
			try
			{
				Type type = AccessTools.TypeByName(array2[0]);
				if (type == null)
				{
					PlanetwideCollectorLog.Warn("[diag] Type not found: " + array2[0]);
					continue;
				}
				FieldInfo fieldInfo = AccessTools.Field(type, array2[1]);
				if (fieldInfo == null)
				{
					PlanetwideCollectorLog.Warn("[diag] Field not found: " + array2[0] + "." + array2[1]);
					continue;
				}
				PlanetwideCollectorLog.Info("[diag] field " + array2[0] + "." + array2[1] + " : " + fieldInfo.FieldType.Name);
			}
			catch (Exception ex)
			{
				PlanetwideCollectorLog.Error("[diag] Failed to inspect field " + array2[0] + "." + array2[1] + ": " + ex.Message);
			}
		}
	}
}
internal static class ProductionScan
{
	private struct ScanTotals
	{
		public int total;

		public int collected;

		public int movedItems;

		public int noSlot;

		public int skippedInserter;
	}

	private const long LogThrottleTicks = 300L;

	private static long _lastScannedTick = -1L;

	private static long _lastLogTick = long.MinValue;

	private static float _lastErrorLogRealtime = float.NegativeInfinity;

	private static bool[] _inserterIndex;

	internal static void Tick()
	{
		try
		{
			if (!Plugin.ProductionEnabled.Value || GameMain.data == null || GameMain.data.factories == null)
			{
				return;
			}
			long gameTick = GameMain.gameTick;
			int num = Plugin.ProductionCollectIntervalTicks.Value;
			if (num < 1)
			{
				num = 1;
			}
			if (gameTick < _lastScannedTick)
			{
				_lastScannedTick = gameTick - num;
				_lastLogTick = gameTick - 300;
			}
			if (gameTick - _lastScannedTick < num)
			{
				return;
			}
			_lastScannedTick = gameTick;
			float value = Plugin.ProductionCollectRadius.Value;
			ScanTotals totals = default(ScanTotals);
			PlanetFactory[] factories = GameMain.data.factories;
			foreach (PlanetFactory val in factories)
			{
				if (val != null && val.factorySystem != null)
				{
					ScanFactory(val, value, ref totals);
				}
			}
			if (PlanetwideCollectorLog.IsDebugEnabled())
			{
				bool value2 = Plugin.ProductionVerboseScan.Value;
				bool flag = totals.movedItems > 0 || totals.noSlot > 0 || totals.skippedInserter > 0;
				if ((value2 || flag) && gameTick - _lastLogTick >= 300)
				{
					_lastLogTick = gameTick;
					PlanetwideCollectorLog.Info("[collect] production{" + (value2 ? ("total=" + totals.total + " ") : "") + "collected=" + totals.collected + " items=" + totals.movedItems + ((totals.noSlot > 0) ? (" noSlot=" + totals.noSlot) : "") + ((totals.skippedInserter > 0) ? (" skippedInserter=" + totals.skippedInserter) : "") + "}");
				}
			}
		}
		catch (Exception ex)
		{
			float realtimeSinceStartup = Time.realtimeSinceStartup;
			if (realtimeSinceStartup - _lastErrorLogRealtime >= 5f)
			{
				_lastErrorLogRealtime = realtimeSinceStartup;
				PlanetwideCollectorLog.Error("[scan] ProductionScan.Tick threw: " + ex);
			}
		}
	}

	private static void ScanFactory(PlanetFactory factory, float radius, ref ScanTotals totals)
	{
		FactorySystem factorySystem = factory.factorySystem;
		if (factorySystem.assemblerCursor <= 1 && factorySystem.labCursor <= 1)
		{
			return;
		}
		bool value = Plugin.ProductionSkipInserterFedBuildings.Value;
		if (value)
		{
			ProductionSourcing.BuildInserterIndex(factory, ref _inserterIndex);
		}
		EntityData[] entityPool = factory.entityPool;
		AssemblerComponent[] assemblerPool = factorySystem.assemblerPool;
		if (assemblerPool != null)
		{
			int assemblerCursor = factorySystem.assemblerCursor;
			for (int i = 1; i < assemblerCursor; i++)
			{
				if (assemblerPool[i].id == i && assemblerPool[i].recipeId != 0)
				{
					ScanProduced(factory, entityPool, assemblerPool[i].entityId, assemblerPool[i].recipeExecuteData, assemblerPool[i].produced, radius, value, ref totals);
				}
			}
		}
		LabComponent[] labPool = factorySystem.labPool;
		if (labPool == null)
		{
			return;
		}
		int labCursor = factorySystem.labCursor;
		for (int j = 1; j < labCursor; j++)
		{
			if (labPool[j].id == j && !labPool[j].researchMode && labPool[j].recipeId != 0)
			{
				ScanProduced(factory, entityPool, labPool[j].entityId, labPool[j].recipeExecuteData, labPool[j].produced, radius, value, ref totals);
			}
		}
	}

	private static void ScanProduced(PlanetFactory factory, EntityData[] entityPool, int entityId, RecipeExecuteData recipeExecuteData, int[] produced, float radius, bool skipInserterFed, ref ScanTotals totals)
	{
		//IL_004e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0053: Unknown result type (might be due to invalid IL or missing references)
		//IL_0068: Unknown result type (might be due to invalid IL or missing references)
		//IL_006d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0088: Unknown result type (might be due to invalid IL or missing references)
		if (recipeExecuteData == null || produced == null)
		{
			return;
		}
		totals.total++;
		if (skipInserterFed && _inserterIndex != null && entityId > 0 && entityId < _inserterIndex.Length && _inserterIndex[entityId])
		{
			totals.skippedInserter++;
			return;
		}
		int[] products = recipeExecuteData.products;
		if (products == null)
		{
			return;
		}
		Vector3 pos = Vector3.zero;
		if (entityPool != null && entityId > 0 && entityId < entityPool.Length)
		{
			pos = entityPool[entityId].pos;
		}
		for (int i = 0; i < products.Length && i < produced.Length; i++)
		{
			int num = products[i];
			if (num == 0)
			{
				continue;
			}
			int num2 = produced[i];
			if (num2 > 0)
			{
				int num3 = ProductionSourcing.TryPushToPlanet(factory, num, num2, pos, radius);
				if (num3 <= 0)
				{
					totals.noSlot++;
					continue;
				}
				produced[i] -= num3;
				totals.collected++;
				totals.movedItems += num3;
			}
		}
	}
}
internal static class ProductionSourcing
{
	private struct StationDist
	{
		public int index;

		public float distSqr;
	}

	private static List<StationDist> _scratch;

	private static readonly Comparison<StationDist> _byDist = (StationDist a, StationDist b) => a.distSqr.CompareTo(b.distSqr);

	internal static int TryPushToPlanet(PlanetFactory factory, int itemId, int want, Vector3 pos, float radius)
	{
		//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00de: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
		if (factory == null || itemId <= 0 || want <= 0)
		{
			return 0;
		}
		PlanetTransport transport = factory.transport;
		if (transport == null || transport.stationPool == null)
		{
			return 0;
		}
		bool value = Plugin.ProductionRequireStationDemandFlag.Value;
		bool value2 = Plugin.ProductionNearestStationFirst.Value;
		float num = ((radius > 0f) ? (radius * radius) : 0f);
		EntityData[] entityPool = factory.entityPool;
		int stationCursor = transport.stationCursor;
		int moved = 0;
		Vector3 val2;
		if (value2)
		{
			if (_scratch == null)
			{
				_scratch = new List<StationDist>(64);
			}
			_scratch.Clear();
			for (int i = 1; i < stationCursor; i++)
			{
				StationComponent val = transport.stationPool[i];
				if (val == null || val.id != i || val.storage == null)
				{
					continue;
				}
				float num2 = 0f;
				if (entityPool != null)
				{
					int entityId = val.entityId;
					if (entityId > 0 && entityId < entityPool.Length)
					{
						val2 = entityPool[entityId].pos - pos;
						num2 = ((Vector3)(ref val2)).sqrMagnitude;
						if (num > 0f && num2 > num)
						{
							continue;
						}
					}
				}
				if (StationHasAssignedSlot(val, itemId, value))
				{
					_scratch.Add(new StationDist
					{
						index = i,
						distSqr = num2
					});
				}
			}
			_scratch.Sort(_byDist);
			for (int j = 0; j < _scratch.Count; j++)
			{
				if (moved >= want)
				{
					break;
				}
				CreditStation(transport.stationPool[_scratch[j].index], itemId, want, value, ref moved);
			}
		}
		else
		{
			for (int k = 1; k < stationCursor && moved < want; k++)
			{
				StationComponent val3 = transport.stationPool[k];
				if (val3 == null || val3.id != k || val3.storage == null)
				{
					continue;
				}
				if (num > 0f && entityPool != null)
				{
					int entityId2 = val3.entityId;
					if (entityId2 > 0 && entityId2 < entityPool.Length)
					{
						val2 = entityPool[entityId2].pos - pos;
						if (((Vector3)(ref val2)).sqrMagnitude > num)
						{
							continue;
						}
					}
				}
				CreditStation(val3, itemId, want, value, ref moved);
			}
		}
		return moved;
	}

	private static bool StationHasAssignedSlot(StationComponent station, int itemId, bool requireDemand)
	{
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		//IL_002a: Invalid comparison between Unknown and I4
		//IL_0033: Unknown result type (might be due to invalid IL or missing references)
		//IL_0039: Invalid comparison between Unknown and I4
		StationStore[] storage = station.storage;
		for (int i = 0; i < storage.Length; i++)
		{
			if (storage[i].itemId == itemId && (!requireDemand || (int)storage[i].localLogic == 2 || (int)storage[i].remoteLogic == 2))
			{
				return true;
			}
		}
		return false;
	}

	private static void CreditStation(StationComponent station, int itemId, int want, bool requireDemand, ref int moved)
	{
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		//IL_002a: Invalid comparison between Unknown and I4
		//IL_0033: Unknown result type (might be due to invalid IL or missing references)
		//IL_0039: Invalid comparison between Unknown and I4
		StationStore[] storage = station.storage;
		for (int i = 0; i < storage.Length; i++)
		{
			if (moved >= want)
			{
				break;
			}
			if (storage[i].itemId != itemId || (requireDemand && (int)storage[i].localLogic != 2 && (int)storage[i].remoteLogic != 2))
			{
				continue;
			}
			int num = storage[i].max - storage[i].count;
			if (num > 0)
			{
				int num2 = want - moved;
				if (num2 > num)
				{
					num2 = num;
				}
				storage[i].count += num2;
				moved += num2;
			}
		}
	}

	internal static void BuildInserterIndex(PlanetFactory factory, ref bool[] buffer)
	{
		int entityCursor = factory.entityCursor;
		if (buffer == null || buffer.Length < entityCursor)
		{
			buffer = new bool[entityCursor];
		}
		else
		{
			Array.Clear(buffer, 0, entityCursor);
		}
		FactorySystem factorySystem = factory.factorySystem;
		if (factorySystem == null || factorySystem.inserterPool == null)
		{
			return;
		}
		InserterComponent[] inserterPool = factorySystem.inserterPool;
		int inserterCursor = factorySystem.inserterCursor;
		for (int i = 1; i < inserterCursor; i++)
		{
			if (inserterPool[i].id == i)
			{
				int pickTarget = inserterPool[i].pickTarget;
				if (pickTarget > 0 && pickTarget < buffer.Length)
				{
					buffer[pickTarget] = true;
				}
			}
		}
	}
}