Decompiled source of RateMonitor v0.2.0

RateMonitor.dll

Decompiled 5 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using CommonAPI;
using CommonAPI.Systems;
using CommonAPI.Systems.ModLocalization;
using HarmonyLib;
using RateMonitor.UI;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("RateMonitor")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.2.0.0")]
[module: UnverifiableCode]
namespace RateMonitor
{
	public static class CalDB
	{
		public const float WORKING_THRESHOLD = 1f;

		public static readonly int[] BeltSpeeds = new int[3] { 360, 720, 1800 };

		public static Action OnRefresh;

		public static int IncLevel { get; private set; } = 4;


		public static bool ForceInc { get; private set; }

		public static float IncToProliferatorRatio { get; private set; }

		public static int MaxBeltStack { get; private set; } = 4;


		public static bool IncludeFuelGenerator { get; private set; }

		public static bool ForceGammaCatalyst { get; private set; }

		public static bool CompatGB { get; set; } = false;


		public static void Refresh()
		{
			GameHistoryData history = GameMain.history;
			if (history == null)
			{
				return;
			}
			ForceInc = ModSettings.ForceInc.Value;
			IncLevel = ModSettings.IncLevel.Value;
			ForceGammaCatalyst = ModSettings.ForceLens.Value;
			if (IncLevel < 0 || IncLevel > 10)
			{
				IncLevel = 0;
				int[] array = ((ProtoSet<ItemProto>)(object)LDB.items).Select(2313)?.prefabDesc.incItemId;
				if (array != null)
				{
					for (int i = 0; i < array.Length; i++)
					{
						if (history.ItemUnlocked(array[i]))
						{
							ItemProto val = ((ProtoSet<ItemProto>)(object)LDB.items).Select(array[i]);
							if (val != null && val.Ability > IncLevel)
							{
								IncLevel = val.Ability;
							}
						}
					}
				}
				IncLevel = ((IncLevel <= 10) ? IncLevel : 10);
			}
			if (IncLevel == 0)
			{
				IncToProliferatorRatio = 0f;
			}
			else if (IncLevel == 1)
			{
				IncToProliferatorRatio = 1f / 13f;
			}
			else if (IncLevel == 2)
			{
				IncToProliferatorRatio = 1f / 28f;
			}
			else
			{
				IncToProliferatorRatio = 1f / 75f;
			}
			if (CompatGB)
			{
				OnRefresh_GB();
			}
			OnRefresh?.Invoke();
		}

		private static void OnRefresh_GB()
		{
			BeltSpeeds[0] = 720;
			BeltSpeeds[1] = 1800;
			BeltSpeeds[2] = 3600;
		}
	}
	public class EntityRecord
	{
		public enum EWorkState
		{
			Running,
			Inefficient,
			Idle,
			Removed,
			Full,
			Lack,
			LackInc,
			LackMatrix,
			MinerSlowMode,
			EjectorNoOrbit,
			EjectorBlocked,
			EjectorAngleLimit,
			SiloNoNode,
			GammaNoLens,
			GammaWarmUp,
			Error,
			Max
		}

		public const int MAX_WORKSTATE = 20;

		public static readonly string[] workStateTexts = new string[20];

		public int entityInfoIndex;

		public int entityId;

		public EWorkState worksate;

		public int itemId;

		public static void InitStrings(bool isZHCN)
		{
			workStateTexts[0] = Localization.Translate("正常运转");
			workStateTexts[1] = (isZHCN ? "低效" : Localization.Translate("Inefficient"));
			workStateTexts[2] = Localization.Translate("待机");
			workStateTexts[3] = Localization.Translate("无法监控");
			workStateTexts[4] = Localization.Translate("产物堆积");
			workStateTexts[5] = Localization.Translate("缺少原材料");
			workStateTexts[6] = (isZHCN ? "缺少增产剂" : Localization.Translate("Lack of proliferator"));
			workStateTexts[7] = Localization.Translate("矩阵不足");
			workStateTexts[8] = (isZHCN ? "减速模式" : Localization.Translate("Slow Mode"));
			workStateTexts[9] = Localization.Translate("轨道未设置");
			workStateTexts[10] = Localization.Translate("路径被遮挡");
			workStateTexts[11] = Localization.Translate("俯仰限制");
			workStateTexts[12] = Localization.Translate("待机无需求");
			workStateTexts[13] = (isZHCN ? "缺少透镜" : Localization.Translate("Lack of lens"));
			workStateTexts[14] = (isZHCN ? "热机中" : Localization.Translate("Warm Up"));
			workStateTexts[15] = "Error";
		}

		public override string ToString()
		{
			return workStateTexts[(int)worksate];
		}

		public EntityRecord(PlanetFactory factory, int entityId, int entityInfoIndex, float workingRatio)
		{
			this.entityInfoIndex = entityInfoIndex;
			this.entityId = entityId;
			worksate = ((!(workingRatio < float.Epsilon)) ? EWorkState.Inefficient : EWorkState.Idle);
			itemId = 0;
			if (entityId < 0 || entityId >= factory.entityPool.Length)
			{
				this.entityId = 0;
				worksate = EWorkState.Removed;
				return;
			}
			ref EntityData reference = ref factory.entityPool[entityId];
			if (reference.id != entityId)
			{
				this.entityId = 0;
				worksate = EWorkState.Removed;
				return;
			}
			try
			{
				if (reference.assemblerId > 0)
				{
					GetAssemblerState(in factory.factorySystem.assemblerPool[reference.assemblerId]);
				}
				else if (reference.labId > 0)
				{
					ref LabComponent reference2 = ref factory.factorySystem.labPool[reference.labId];
					if (((LabComponent)(ref reference2)).matrixMode)
					{
						GetLabStateMatrixMode(in reference2);
					}
					else
					{
						GetLabStateResearchMode(in reference2);
					}
				}
				else if (reference.minerId > 0)
				{
					GetMinerState(in factory.factorySystem.minerPool[reference.minerId]);
				}
				else if (reference.fractionatorId > 0)
				{
					GetFractionatorState(in factory.factorySystem.fractionatorPool[reference.fractionatorId]);
				}
				else if (reference.ejectorId > 0)
				{
					GetEjectorState(in factory.factorySystem.ejectorPool[reference.ejectorId]);
				}
				else if (reference.siloId > 0)
				{
					GetSiloState(in factory.factorySystem.siloPool[reference.siloId]);
				}
				else if (reference.powerGenId > 0)
				{
					GetPowerGeneratorState(in factory.powerSystem.genPool[reference.powerGenId]);
				}
				else if (reference.powerExcId > 0)
				{
					GetPowerExchangerState(in factory.powerSystem.excPool[reference.powerExcId]);
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogDebug((object)"EntityRecord error!");
				Plugin.Log.LogDebug((object)ex);
				worksate = EWorkState.Error;
			}
		}

		private void GetAssemblerState(in AssemblerComponent assemblerComponent)
		{
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Invalid comparison between Unknown and I4
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Invalid comparison between Unknown and I4
			if (assemblerComponent.replicating)
			{
				worksate = EWorkState.LackInc;
				int num = 1;
				for (int i = 0; i < assemblerComponent.requireCounts.Length; i++)
				{
					if (assemblerComponent.incServed[i] < assemblerComponent.served[i] * num)
					{
						itemId = assemblerComponent.requires[i];
						break;
					}
				}
				return;
			}
			if (assemblerComponent.time >= assemblerComponent.timeSpend)
			{
				worksate = EWorkState.Full;
				if (assemblerComponent.products.Length == 0)
				{
					return;
				}
				if (assemblerComponent.products.Length == 1)
				{
					itemId = assemblerComponent.products[0];
					return;
				}
				int num2 = assemblerComponent.products.Length;
				if ((int)assemblerComponent.recipeType == 4)
				{
					for (int j = 0; j < num2; j++)
					{
						if (assemblerComponent.produced[j] > assemblerComponent.productCounts[j] * 9)
						{
							itemId = assemblerComponent.products[j];
							return;
						}
					}
				}
				if ((int)assemblerComponent.recipeType == 1)
				{
					for (int k = 0; k < num2; k++)
					{
						if (assemblerComponent.produced[k] + assemblerComponent.productCounts[k] > 100)
						{
							itemId = assemblerComponent.products[k];
							return;
						}
					}
				}
				for (int l = 0; l < num2; l++)
				{
					if (assemblerComponent.produced[l] > assemblerComponent.productCounts[l] * 19)
					{
						itemId = assemblerComponent.products[l];
						break;
					}
				}
				return;
			}
			itemId = 0;
			for (int m = 0; m < assemblerComponent.requireCounts.Length; m++)
			{
				if (assemblerComponent.served[m] < assemblerComponent.requireCounts[m])
				{
					itemId = assemblerComponent.requires[m];
					break;
				}
			}
			if (itemId != 0)
			{
				worksate = EWorkState.Lack;
			}
		}

		private void GetLabStateMatrixMode(in LabComponent labComponent)
		{
			if (labComponent.replicating)
			{
				worksate = EWorkState.LackInc;
				int num = 1;
				for (int i = 0; i < labComponent.requireCounts.Length; i++)
				{
					if (labComponent.incServed[i] < labComponent.served[i] * num)
					{
						itemId = labComponent.requires[i];
						break;
					}
				}
				return;
			}
			if (labComponent.time >= labComponent.timeSpend)
			{
				worksate = EWorkState.Full;
				if (labComponent.products.Length == 0)
				{
					return;
				}
				if (labComponent.products.Length == 1)
				{
					itemId = labComponent.products[0];
					return;
				}
				int num2 = labComponent.products.Length;
				for (int j = 0; j < num2; j++)
				{
					if (labComponent.produced[j] > labComponent.productCounts[j] * 19)
					{
						itemId = labComponent.products[j];
						break;
					}
				}
				return;
			}
			itemId = 0;
			for (int k = 0; k < labComponent.requireCounts.Length; k++)
			{
				if (labComponent.served[k] < labComponent.requireCounts[k])
				{
					itemId = labComponent.requires[k];
					break;
				}
			}
			if (itemId != 0)
			{
				worksate = EWorkState.Lack;
			}
		}

		private void GetLabStateResearchMode(in LabComponent labComponent)
		{
			if (labComponent.replicating)
			{
				worksate = EWorkState.LackInc;
				int incLevel = CalDB.IncLevel;
				for (int i = 0; i < labComponent.matrixServed.Length; i++)
				{
					if (labComponent.matrixIncServed[i] < labComponent.matrixServed[i] * incLevel)
					{
						itemId = LabComponent.matrixIds[i];
						break;
					}
				}
				return;
			}
			itemId = 0;
			for (int j = 0; j < labComponent.matrixServed.Length; j++)
			{
				if (labComponent.matrixServed[j] < labComponent.matrixPoints[j])
				{
					itemId = LabComponent.matrixIds[j];
					break;
				}
			}
			if (itemId != 0)
			{
				worksate = EWorkState.LackMatrix;
			}
		}

		private void GetMinerState(in MinerComponent miner)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Invalid comparison between Unknown and I4
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			worksate = EWorkState.MinerSlowMode;
			if ((int)miner.workstate == -2)
			{
				worksate = EWorkState.Full;
			}
			else if ((int)miner.workstate == 0)
			{
				worksate = EWorkState.Idle;
			}
		}

		private void GetFractionatorState(in FractionatorComponent fractionator)
		{
			if (fractionator.isWorking)
			{
				itemId = fractionator.fluidId;
				worksate = EWorkState.LackInc;
			}
			else if (fractionator.productOutputCount >= fractionator.productOutputMax || fractionator.fluidOutputCount >= fractionator.fluidOutputMax)
			{
				itemId = fractionator.productId;
				worksate = EWorkState.Full;
			}
			else if (fractionator.fluidId > 0)
			{
				itemId = fractionator.fluidId;
				worksate = EWorkState.Lack;
			}
		}

		private void GetEjectorState(in EjectorComponent ejector)
		{
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Invalid comparison between Unknown and I4
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Invalid comparison between Unknown and I4
			if ((float)ejector.direction != 0f)
			{
				itemId = ejector.bulletId;
				worksate = EWorkState.LackInc;
			}
			else if (ejector.runtimeOrbitId == 0)
			{
				worksate = EWorkState.EjectorNoOrbit;
			}
			else if (ejector.bulletCount == 0)
			{
				itemId = ejector.bulletId;
				worksate = EWorkState.Lack;
			}
			else if ((int)ejector.targetState == 2)
			{
				worksate = EWorkState.EjectorBlocked;
			}
			else if ((int)ejector.targetState == 3)
			{
				worksate = EWorkState.EjectorAngleLimit;
			}
		}

		private void GetSiloState(in SiloComponent silo)
		{
			if ((float)silo.direction != 0f)
			{
				itemId = silo.bulletId;
				worksate = EWorkState.LackInc;
			}
			else if (silo.hasNode)
			{
				worksate = EWorkState.SiloNoNode;
			}
			else if (silo.bulletCount == 0)
			{
				itemId = silo.bulletId;
				worksate = EWorkState.Lack;
			}
		}

		private void GetPowerGeneratorState(in PowerGeneratorComponent powerGenerator)
		{
			worksate = EWorkState.Inefficient;
			if (powerGenerator.gamma)
			{
				if (powerGenerator.productCount >= 20f)
				{
					worksate = EWorkState.Full;
					itemId = powerGenerator.productId;
				}
				else if (powerGenerator.catalystPoint == 0)
				{
					worksate = EWorkState.GammaNoLens;
					itemId = powerGenerator.catalystId;
				}
				else if (powerGenerator.warmup < 0.999f)
				{
					worksate = EWorkState.GammaNoLens;
				}
				else
				{
					worksate = EWorkState.Inefficient;
				}
			}
		}

		private void GetPowerExchangerState(in PowerExchangerComponent powerExchanger)
		{
			worksate = EWorkState.Idle;
			if (powerExchanger.state == 1f)
			{
				if (powerExchanger.fullCount >= 20)
				{
					worksate = EWorkState.Full;
					itemId = powerExchanger.fullId;
				}
				else if (powerExchanger.emptyCount == 0)
				{
					worksate = EWorkState.Lack;
					itemId = powerExchanger.emptyId;
				}
			}
			else if (powerExchanger.state == -1f)
			{
				if (powerExchanger.emptyCount >= 20)
				{
					worksate = EWorkState.Full;
					itemId = powerExchanger.emptyId;
				}
				else if (powerExchanger.fullCount == 0)
				{
					worksate = EWorkState.Lack;
					itemId = powerExchanger.fullId;
				}
			}
		}
	}
	public class ProductionProfile : IComparable
	{
		public int protoId;

		public int recipeId;

		public bool accMode;

		public bool incUsed;

		public int incLevel;

		public float workEnergyW;

		public float idleEnergyW;

		public readonly List<int> itemIds = new List<int>();

		public readonly List<float> itemRefSpeeds = new List<float>();

		public int productCount;

		public int materialCount;

		public float incCost;

		public int highestProductId;

		public readonly List<int> entityIds = new List<int>();

		public readonly List<EntityRecord> entityRecords = new List<EntityRecord>();

		private bool isEntityRecordsDirty = true;

		private string recordSummary = "";

		public int TotalMachineCount => entityIds.Count;

		public float WorkingMachineCount { get; set; }

		public static long GetHash(PlanetFactory factory, in EntityData entityData)
		{
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Invalid comparison between Unknown and I4
			long num = entityData.protoId;
			if (entityData.assemblerId > 0)
			{
				ref AssemblerComponent reference = ref factory.factorySystem.assemblerPool[entityData.assemblerId];
				num |= (long)reference.recipeId << 32;
				if (reference.productive && !reference.forceAccMode)
				{
					num = -num;
				}
			}
			else if (entityData.labId > 0)
			{
				ref LabComponent reference2 = ref factory.factorySystem.labPool[entityData.labId];
				num |= (long)reference2.recipeId << 32;
				if (reference2.productive && !reference2.forceAccMode)
				{
					num = -num;
				}
			}
			else if (entityData.minerId > 0)
			{
				if ((int)factory.factorySystem.minerPool[entityData.minerId].type != 1)
				{
					num |= (long)entityData.minerId << 32;
				}
			}
			else if (entityData.powerGenId > 0)
			{
				ref PowerGeneratorComponent reference3 = ref factory.powerSystem.genPool[entityData.powerGenId];
				if (reference3.gamma)
				{
					return num;
				}
				num |= (long)reference3.fuelId << 32;
			}
			else if (entityData.powerExcId > 0 && factory.powerSystem.excPool[entityData.powerExcId].state < 0f)
			{
				num = -num;
			}
			return num;
		}

		public ProductionProfile(PlanetFactory factory, in EntityData entityData, int globalIncLevel, bool forceInc)
		{
			protoId = entityData.protoId;
			PrefabDesc val = ((ProtoSet<ItemProto>)(object)LDB.items).Select(protoId)?.prefabDesc;
			if (val != null && val.isPowerConsumer)
			{
				workEnergyW = (float)val.workEnergyPerTick * 60f;
				idleEnergyW = (float)val.idleEnergyPerTick * 60f;
			}
			incLevel = globalIncLevel;
			if (entityData.assemblerId > 0)
			{
				ref AssemblerComponent reference = ref factory.factorySystem.assemblerPool[entityData.assemblerId];
				recipeId = reference.recipeId;
				accMode = !reference.productive || reference.forceAccMode;
				incUsed = reference.incUsed || forceInc;
				if (!incUsed)
				{
					incLevel = 0;
				}
				CalculateRefSpeed(in reference, incLevel);
				workEnergyW *= (float)Cargo.powerTableRatio[incLevel];
			}
			else if (entityData.labId > 0)
			{
				ref LabComponent reference2 = ref factory.factorySystem.labPool[entityData.labId];
				recipeId = reference2.recipeId;
				accMode = !reference2.productive || reference2.forceAccMode;
				incUsed = reference2.incUsed || forceInc;
				if (!incUsed)
				{
					incLevel = 0;
				}
				CalculateRefSpeed(in reference2, incLevel);
				workEnergyW *= (float)Cargo.powerTableRatio[incLevel];
			}
			else if (entityData.minerId > 0)
			{
				ref MinerComponent ptr = ref factory.factorySystem.minerPool[entityData.minerId];
				incUsed = false;
				incLevel = 0;
				CalculateRefSpeed(in ptr, factory);
				if (val != null && val.isVeinCollector)
				{
					workEnergyW *= 3f;
				}
			}
			else if (entityData.fractionatorId > 0)
			{
				ref FractionatorComponent reference3 = ref factory.factorySystem.fractionatorPool[entityData.fractionatorId];
				incUsed = reference3.incUsed || forceInc;
				if (!incUsed)
				{
					incLevel = 0;
				}
				CalculateRefSpeed(in reference3, incLevel);
				workEnergyW *= (float)Cargo.powerTableRatio[incLevel];
			}
			else if (entityData.ejectorId > 0)
			{
				ref EjectorComponent reference4 = ref factory.factorySystem.ejectorPool[entityData.ejectorId];
				accMode = true;
				incUsed = reference4.incUsed || forceInc;
				if (!incUsed)
				{
					incLevel = 0;
				}
				CalculateRefSpeed(in reference4, incLevel);
				workEnergyW *= (float)Cargo.powerTableRatio[incLevel];
			}
			else if (entityData.siloId > 0)
			{
				ref SiloComponent reference5 = ref factory.factorySystem.siloPool[entityData.siloId];
				accMode = true;
				incUsed = reference5.incUsed || forceInc;
				if (!incUsed)
				{
					incLevel = 0;
				}
				CalculateRefSpeed(in reference5, incLevel);
				workEnergyW *= (float)Cargo.powerTableRatio[incLevel];
			}
			else if (entityData.powerGenId > 0)
			{
				ref PowerGeneratorComponent reference6 = ref factory.powerSystem.genPool[entityData.powerGenId];
				bool flag = reference6.catalystPoint > 0 || CalDB.ForceGammaCatalyst;
				accMode = true;
				incUsed = ((PowerGeneratorComponent)(ref reference6)).catalystIncLevel > 0 || forceInc;
				if (!flag)
				{
					incLevel = 0;
				}
				CalculateRefSpeed(in reference6, incLevel, flag);
			}
			else if (entityData.powerExcId > 0)
			{
				ref PowerExchangerComponent reference7 = ref factory.powerSystem.excPool[entityData.powerExcId];
				accMode = true;
				int num = 0;
				if (reference7.fullCount > 0)
				{
					num = reference7.fullInc / reference7.fullCount;
				}
				if (reference7.emptyCount > 0)
				{
					num = reference7.emptyInc / reference7.emptyCount;
				}
				incUsed = num > 0 || forceInc;
				CalculateRefSpeed(in reference7, incLevel);
			}
		}

		public int CompareTo(object obj)
		{
			ProductionProfile productionProfile = obj as ProductionProfile;
			if (highestProductId != productionProfile.highestProductId)
			{
				return highestProductId - productionProfile.highestProductId;
			}
			if (recipeId != productionProfile.recipeId)
			{
				return recipeId - productionProfile.recipeId;
			}
			if (protoId != productionProfile.protoId)
			{
				return protoId - productionProfile.protoId;
			}
			if (accMode != productionProfile.accMode)
			{
				if (!accMode)
				{
					return 1;
				}
				return -1;
			}
			return 0;
		}

		public void Reset()
		{
			entityRecords.Clear();
			isEntityRecordsDirty = true;
		}

		public void AddEnittyRecord(EntityRecord entityRecord)
		{
			entityRecords.Add(entityRecord);
			isEntityRecordsDirty = true;
		}

		public string GetRecordSummary()
		{
			if (isEntityRecordsDirty)
			{
				isEntityRecordsDirty = false;
				int num = 0;
				int[] array = new int[20];
				foreach (EntityRecord entityRecord in entityRecords)
				{
					array[(int)entityRecord.worksate]++;
					num++;
				}
				array[0] = TotalMachineCount - num;
				recordSummary = "";
				for (int i = 0; i < 20; i++)
				{
					if (array[i] != 0)
					{
						recordSummary += $"{EntityRecord.workStateTexts[i]}[{array[i]}]  ";
					}
				}
			}
			return recordSummary;
		}

		private void AddRefSpeed(int itemId, float refSpeed)
		{
			if (refSpeed > 0f && itemId > highestProductId)
			{
				highestProductId = itemId;
			}
			if (refSpeed < 0f)
			{
				incCost += (float)incLevel * refSpeed;
			}
			for (int i = 0; i < itemIds.Count; i++)
			{
				if (itemIds[i] == itemId)
				{
					itemRefSpeeds[i] += refSpeed;
					return;
				}
			}
			itemIds.Add(itemId);
			itemRefSpeeds.Add(refSpeed);
			if (refSpeed >= 0f)
			{
				productCount++;
			}
			if (refSpeed <= 0f)
			{
				materialCount++;
			}
		}

		private void CalculateRefSpeed(in AssemblerComponent ptr, int incLevel)
		{
			float num = 1f + (float)Cargo.incTableMilli[incLevel];
			float num2 = 1f + (float)Cargo.accTableMilli[incLevel];
			if (ptr.requires != null && ptr.products != null)
			{
				float num3 = 3600f * (float)ptr.speed / (float)ptr.timeSpend;
				float num4 = num3;
				if (incUsed)
				{
					num4 = ((ptr.productive && !ptr.forceAccMode) ? num4 : (num4 * num2));
				}
				for (int i = 0; i < ptr.requires.Length; i++)
				{
					AddRefSpeed(ptr.requires[i], (0f - num4) * (float)ptr.requireCounts[i]);
				}
				num4 = num3;
				if (incUsed)
				{
					num4 = ((ptr.productive && !ptr.forceAccMode) ? (num4 * num) : (num4 * num2));
				}
				for (int j = 0; j < ptr.products.Length; j++)
				{
					AddRefSpeed(ptr.products[j], num4 * (float)ptr.productCounts[j]);
				}
			}
		}

		private void CalculateRefSpeed(in LabComponent ptr, int incLevel)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			float num = 1f + (float)Cargo.incTableMilli[incLevel];
			float num2 = 1f + (float)Cargo.accTableMilli[incLevel];
			LabComponent val = ptr;
			if (((LabComponent)(ref val)).matrixMode)
			{
				float num3 = 3600f * (float)ptr.speed / (float)ptr.timeSpend;
				float num4 = num3;
				if (incUsed)
				{
					num4 = ((ptr.productive && !ptr.forceAccMode) ? num4 : (num4 * num2));
				}
				for (int i = 0; i < ptr.requires.Length; i++)
				{
					AddRefSpeed(ptr.requires[i], (0f - num4) * (float)ptr.requireCounts[i]);
				}
				num4 = num3;
				if (incUsed)
				{
					num4 = ((ptr.productive && !ptr.forceAccMode) ? (num4 * num) : (num4 * num2));
				}
				for (int j = 0; j < ptr.products.Length; j++)
				{
					AddRefSpeed(ptr.products[j], num4 * (float)ptr.productCounts[j]);
				}
			}
			else
			{
				if (!ptr.researchMode)
				{
					return;
				}
				for (int k = 0; k < ptr.matrixPoints.Length; k++)
				{
					if (ptr.techId > 0 && ptr.matrixPoints[k] > 0)
					{
						float num5 = (float)GameMain.data.history.techSpeed * (float)ptr.matrixPoints[k] * 60f * 60f;
						AddRefSpeed(LabComponent.matrixIds[k], (0f - num5) / 3600f);
					}
				}
			}
		}

		private void CalculateRefSpeed(in MinerComponent ptr, PlanetFactory factory)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Expected I4, but got Unknown
			double num = GameMain.data.history.miningSpeedScale;
			int waterItemId = factory.planet.waterItemId;
			VeinData[] veinPool = factory.veinPool;
			int num2 = 0;
			float refSpeed = 0f;
			EMinerType type = ptr.type;
			switch (type - 1)
			{
			case 0:
				num2 = waterItemId;
				refSpeed = (float)(3600.0 / (double)ptr.period * num * (double)ptr.speed);
				break;
			case 1:
				num2 = ((ptr.veinCount > 0) ? veinPool[ptr.veins[ptr.currentVeinIndex]].productId : 0);
				refSpeed = (float)(3600.0 / (double)ptr.period * num * (double)ptr.speed * (double)ptr.veinCount);
				break;
			case 2:
				num2 = veinPool[ptr.veins[0]].productId;
				refSpeed = (float)(3600.0 / (double)ptr.period * num * (double)ptr.speed * (double)veinPool[ptr.veins[0]].amount * (double)VeinData.oilSpeedMultiplier);
				break;
			}
			if (num2 > 0)
			{
				AddRefSpeed(num2, refSpeed);
			}
		}

		private void CalculateRefSpeed(in FractionatorComponent ptr, int incAbility)
		{
			float num = 1f + (float)Cargo.accTableMilli[incAbility];
			float num2 = (float)(CalDB.BeltSpeeds[2] * CalDB.MaxBeltStack) * (incUsed ? num : 1f) * ptr.produceProb;
			if (ptr.fluidId > 0)
			{
				AddRefSpeed(ptr.fluidId, 0f - num2);
			}
			if (ptr.productId > 0)
			{
				AddRefSpeed(ptr.productId, num2);
			}
		}

		private void CalculateRefSpeed(in EjectorComponent ptr, int incAbility)
		{
			float num = 1f + (float)Cargo.accTableMilli[incAbility];
			float num2 = 36000000f / (float)(ptr.chargeSpend + ptr.coldSpend);
			num2 = (incUsed ? (num2 * num) : num2);
			AddRefSpeed(ptr.bulletId, 0f - num2);
		}

		private void CalculateRefSpeed(in SiloComponent ptr, int incAbility)
		{
			float num = 1f + (float)Cargo.accTableMilli[incAbility];
			float num2 = 36000000f / (float)(ptr.chargeSpend + ptr.coldSpend);
			num2 = (incUsed ? (num2 * num) : num2);
			AddRefSpeed(ptr.bulletId, 0f - num2);
		}

		private void CalculateRefSpeed(in PowerGeneratorComponent ptr, int incAbility, bool useLen)
		{
			if (ptr.gamma)
			{
				if (ptr.productId == 1208 && ptr.productHeat != 0L)
				{
					if (useLen)
					{
						float num = 1f + (float)Cargo.accTableMilli[incAbility];
						float refSpeed = 12f * num;
						AddRefSpeed(1208, refSpeed);
					}
					else
					{
						AddRefSpeed(1208, 6f);
					}
				}
			}
			else if (ptr.fuelHeat > 0 && ptr.fuelId > 0)
			{
				float num2 = 3600f * (float)ptr.useFuelPerTick / (float)ptr.fuelHeat;
				AddRefSpeed(ptr.fuelId, 0f - num2);
			}
		}

		public void CalculateRefSpeed(in PowerExchangerComponent ptr, int incLevel)
		{
			float num = 1f + (float)Cargo.accTableMilli[incLevel];
			float num2 = num * ((float)ptr.energyPerTick * 3600f / (float)ptr.maxPoolEnergy);
			if (ptr.state == 1f)
			{
				AddRefSpeed(ptr.emptyId, 0f - num2);
				AddRefSpeed(ptr.fullId, num2);
				workEnergyW = (float)ptr.energyPerTick * num * 60f;
			}
			else if (ptr.state == -1f)
			{
				AddRefSpeed(ptr.fullId, 0f - num2);
				AddRefSpeed(ptr.emptyId, num2);
			}
		}
	}
	public class StatTable
	{
		private struct EntityInfo
		{
			public int entityId;

			public float utilization;

			public EntityRecord.EWorkState workState;

			public ProductionProfile profile;
		}

		private PlanetFactory factory;

		private EntityInfo[] entityInfos = new EntityInfo[0];

		public List<ProductionProfile> Profiles { get; private set; } = new List<ProductionProfile>();


		public Dictionary<int, float> ItemRefRates { get; private set; } = new Dictionary<int, float>();


		public List<int> ItemIdProduce { get; private set; } = new List<int>();


		public List<int> ItemIdConsume { get; private set; } = new List<int>();


		public List<int> ItemIdIntermediate { get; private set; } = new List<int>();


		public Dictionary<int, float> ItemEstRates { get; private set; } = new Dictionary<int, float>();


		public HashSet<int> WorkingItemIds { get; private set; } = new HashSet<int>();


		public int TotalTick { get; set; }

		public List<int> GetEntityIds(out PlanetFactory factory)
		{
			factory = this.factory;
			List<int> list = new List<int>();
			for (int i = 0; i < entityInfos.Length; i++)
			{
				list.Add(entityInfos[i].entityId);
			}
			return list;
		}

		public int GetEntityCount()
		{
			return entityInfos.Length;
		}

		public PlanetFactory GetFactory()
		{
			return factory;
		}

		public void Recalculate()
		{
			List<int> list = new List<int>();
			for (int i = 0; i < entityInfos.Length; i++)
			{
				list.Add(entityInfos[i].entityId);
			}
			Initialize(factory, list);
		}

		public void Initialize(PlanetFactory facotry, List<int> entityIds)
		{
			CalDB.Refresh();
			factory = facotry;
			Profiles.Clear();
			TotalTick = 0;
			if (facotry == null)
			{
				CalculateRefRate();
				return;
			}
			Dictionary<long, ProductionProfile> dictionary = new Dictionary<long, ProductionProfile>();
			List<EntityInfo> list = new List<EntityInfo>();
			foreach (int entityId in entityIds)
			{
				if (entityId > 0 && entityId < facotry.entityCursor)
				{
					ref EntityData entityData = ref facotry.entityPool[entityId];
					EntityInfo entityInfo = default(EntityInfo);
					entityInfo.entityId = entityId;
					EntityInfo item = entityInfo;
					long hash = ProductionProfile.GetHash(facotry, in entityData);
					if (dictionary.TryGetValue(hash, out var value))
					{
						item.profile = value;
						value.entityIds.Add(entityId);
					}
					else
					{
						item.profile = new ProductionProfile(facotry, in entityData, CalDB.IncLevel, CalDB.ForceInc);
						dictionary.Add(hash, item.profile);
						Profiles.Add(item.profile);
						item.profile.entityIds.Add(entityId);
					}
					list.Add(item);
				}
			}
			Profiles.Sort();
			Profiles.Reverse();
			entityInfos = list.ToArray();
			CalculateRefRate();
		}

		public void CalculateRefRate()
		{
			ItemRefRates.Clear();
			ItemEstRates.Clear();
			HashSet<int> hashSet = new HashSet<int>();
			HashSet<int> hashSet2 = new HashSet<int>();
			HashSet<int> hashSet3 = new HashSet<int>();
			foreach (ProductionProfile profile in Profiles)
			{
				int totalMachineCount = profile.TotalMachineCount;
				for (int i = 0; i < profile.itemIds.Count; i++)
				{
					int num = profile.itemIds[i];
					float num2 = (float)totalMachineCount * profile.itemRefSpeeds[i];
					ItemRefRates.TryGetValue(num, out var value);
					ItemRefRates[num] = value + num2;
					ItemEstRates.TryGetValue(num, out var value2);
					ItemEstRates[num] = value2 + num2;
					if (!hashSet3.Contains(num))
					{
						if (num2 > 0f)
						{
							hashSet.Add(num);
						}
						else if (num2 < 0f)
						{
							hashSet2.Add(num);
						}
						else
						{
							hashSet3.Add(num);
						}
					}
				}
			}
			foreach (int item in hashSet.Intersect(hashSet2).ToList())
			{
				hashSet.Remove(item);
				hashSet2.Remove(item);
				hashSet3.Add(item);
			}
			ItemIdProduce = hashSet.ToList();
			ItemIdConsume = hashSet2.ToList();
			ItemIdIntermediate = hashSet3.ToList();
			ItemIdProduce.Sort();
			ItemIdProduce.Reverse();
			ItemIdConsume.Sort();
			ItemIdConsume.Reverse();
			ItemIdIntermediate.Sort();
			ItemIdIntermediate.Reverse();
		}

		public void CalculateEstRate()
		{
			foreach (ProductionProfile profile in Profiles)
			{
				profile.WorkingMachineCount = 0f;
			}
			for (int i = 0; i < entityInfos.Length; i++)
			{
				entityInfos[i].profile.WorkingMachineCount += entityInfos[i].utilization;
			}
			foreach (int item in ItemIdProduce)
			{
				ItemEstRates[item] = 0f;
			}
			foreach (int item2 in ItemIdConsume)
			{
				ItemEstRates[item2] = 0f;
			}
			foreach (int item3 in ItemIdIntermediate)
			{
				ItemEstRates[item3] = 0f;
			}
			foreach (ProductionProfile profile2 in Profiles)
			{
				if (!(profile2.WorkingMachineCount < float.Epsilon))
				{
					for (int j = 0; j < profile2.itemIds.Count; j++)
					{
						int num = profile2.itemIds[j];
						WorkingItemIds.Add(num);
						float num2 = profile2.WorkingMachineCount * profile2.itemRefSpeeds[j];
						ItemEstRates[num] += num2;
					}
				}
			}
		}

		public void OnGameTick()
		{
			if (factory == null)
			{
				return;
			}
			if (++TotalTick >= 108000)
			{
				TotalTick -= 15;
			}
			for (int i = 0; i < entityInfos.Length; i++)
			{
				ref EntityInfo reference = ref entityInfos[i];
				reference.utilization *= (float)(TotalTick - 1) / (float)TotalTick;
				float entityWorkingRatio = GetEntityWorkingRatio(reference.entityId, reference.profile);
				reference.utilization += entityWorkingRatio / (float)TotalTick;
				if (entityWorkingRatio < 0.999f && reference.workState == EntityRecord.EWorkState.Running)
				{
					EntityRecord entityRecord = new EntityRecord(factory, reference.entityId, i, entityWorkingRatio);
					reference.workState = entityRecord.worksate;
					if (reference.workState == EntityRecord.EWorkState.Running)
					{
						reference.workState = EntityRecord.EWorkState.Idle;
					}
					reference.profile.AddEnittyRecord(entityRecord);
				}
			}
			if (TotalTick % 15 == 0)
			{
				CalculateEstRate();
			}
		}

		public void OnError()
		{
			factory = null;
		}

		public float GetEntityWorkingRatio(int entityId, ProductionProfile profile)
		{
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Invalid comparison between Unknown and I4
			if (entityId <= 0 || entityId >= factory.entityCursor)
			{
				return 0f;
			}
			ref EntityData reference = ref factory.entityPool[entityId];
			int incLevel = profile.incLevel;
			float result = 0f;
			if (reference.assemblerId > 0)
			{
				ref AssemblerComponent reference2 = ref factory.factorySystem.assemblerPool[reference.assemblerId];
				result = ((!reference2.replicating) ? 0f : ((reference2.extraPowerRatio >= Cargo.powerTable[incLevel]) ? 1f : 0.5f));
			}
			else if (reference.labId > 0)
			{
				ref LabComponent reference3 = ref factory.factorySystem.labPool[reference.labId];
				result = ((!reference3.replicating) ? 0f : ((reference3.extraPowerRatio >= Cargo.powerTable[incLevel]) ? 1f : 0.5f));
			}
			else if (reference.minerId > 0)
			{
				ref MinerComponent reference4 = ref factory.factorySystem.minerPool[reference.minerId];
				result = (((int)reference4.workstate > 0) ? (reference4.speedDamper * (float)reference4.speed * (float)reference4.speed / 100000000f) : 0f);
			}
			else if (reference.fractionatorId > 0)
			{
				ref FractionatorComponent reference5 = ref factory.factorySystem.fractionatorPool[reference.fractionatorId];
				result = ((!reference5.isWorking) ? 0f : ((((FractionatorComponent)(ref reference5)).incLevel >= incLevel) ? 1f : 0.5f));
			}
			else if (reference.ejectorId > 0)
			{
				ref EjectorComponent reference6 = ref factory.factorySystem.ejectorPool[reference.ejectorId];
				result = ((reference6.direction == 0) ? 0f : ((((EjectorComponent)(ref reference6)).incLevel >= incLevel) ? 1f : 0.5f));
			}
			else if (reference.siloId > 0)
			{
				ref SiloComponent reference7 = ref factory.factorySystem.siloPool[reference.siloId];
				result = ((reference7.direction == 0) ? 0f : ((((SiloComponent)(ref reference7)).incLevel >= incLevel) ? 1f : 0.5f));
			}
			else if (reference.powerGenId > 0)
			{
				ref PowerGeneratorComponent reference8 = ref factory.powerSystem.genPool[reference.powerGenId];
				result = 1f;
				if (reference8.gamma)
				{
					result = 0f;
					if ((float)reference8.productHeat > 0f && profile.itemRefSpeeds.Count > 0)
					{
						result = (float)reference8.capacityCurrentTick / (float)reference8.productHeat * 3600f / profile.itemRefSpeeds[0];
					}
				}
			}
			else if (reference.powerExcId > 0)
			{
				result = (((float)factory.powerSystem.excPool[reference.powerExcId].currEnergyPerTick == 0f) ? 0f : 1f);
			}
			return result;
		}

		public void PrintRefRates()
		{
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.AppendLine($"Settings: IncAbility={CalDB.IncLevel}, ForceInc={CalDB.ForceInc}");
			stringBuilder.AppendLine($"== Product [{ItemIdProduce.Count}] ==");
			foreach (int item in ItemIdProduce)
			{
				stringBuilder.AppendLine($"{LDB.ItemName(item)}: {ItemRefRates[item]:F2}/min");
			}
			stringBuilder.AppendLine($"== Ingredients [{ItemIdConsume.Count}] ==");
			foreach (int item2 in ItemIdConsume)
			{
				stringBuilder.AppendLine($"{LDB.ItemName(item2)}: {ItemRefRates[item2]:F2}/min");
			}
			stringBuilder.AppendLine($"== Intermediates [{ItemIdIntermediate.Count}] ==");
			foreach (int item3 in ItemIdIntermediate)
			{
				stringBuilder.AppendLine($"{LDB.ItemName(item3)}: {ItemRefRates[item3]:F2}/min");
			}
			Plugin.Log.LogDebug((object)stringBuilder.ToString());
		}

		public void PrintProifles(bool showWorkingCount = false)
		{
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.AppendLine($"Profile count = {Profiles.Count}. Total machine count = {entityInfos.Length}");
			Plugin.Log.LogDebug((object)stringBuilder.ToString());
		}
	}
	public static class ModSettings
	{
		public static ConfigEntry<KeyboardShortcut> SelectionToolKey;

		public static ConfigEntry<int> RateUnit;

		public static ConfigEntry<bool> ShowRealtimeRate;

		public static ConfigEntry<bool> ShowWorkingRateInPercentage;

		public static ConfigEntry<float> WindowWidth;

		public static ConfigEntry<float> WindowHeight;

		public static ConfigEntry<float> WindowRatePanelWidth;

		public static ConfigEntry<int> IncLevel;

		public static ConfigEntry<bool> ForceInc;

		public static ConfigEntry<bool> ForceLens;

		public static void LoadConfigs(ConfigFile config)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Expected O, but got Unknown
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Expected O, but got Unknown
			SelectionToolKey = config.Bind<KeyboardShortcut>("KeyBinds", "SelectToolKey", new KeyboardShortcut((KeyCode)120, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), "Hotkey to toggle area selection tool\n启用框选工具的热键");
			RateUnit = config.Bind<int>("UI", "Rate Unit", 1, new ConfigDescription("Timescale unit (x item per minute)\n速率单位(每分钟x个物品)", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 14400), Array.Empty<object>()));
			WindowWidth = config.Bind<float>("UI", "Window Width", 580f, (ConfigDescription)null);
			WindowHeight = config.Bind<float>("UI", "Window Height", 400f, (ConfigDescription)null);
			WindowRatePanelWidth = config.Bind<float>("UI", "Window Rate Panel Width", 190f, (ConfigDescription)null);
			ShowRealtimeRate = config.Bind<bool>("UI", "Show Realtime Rate", true, "Show Real-time Monitoring Rate\n显示即时监控速率");
			ShowWorkingRateInPercentage = config.Bind<bool>("UI", "Show Working Rate in percentage", true, "Show Real-time Working Rate in percentage\n以百分比显示工作效率");
			IncLevel = config.Bind<int>("General", "Proliferator Level", -1, new ConfigDescription("Level of proliferator [1,2,4]. Auto dectect: -1\n增产效果等级[1,2,4] 自动侦测:-1", (AcceptableValueBase)(object)new AcceptableValueRange<int>(-1, 10), Array.Empty<object>()));
			ForceInc = config.Bind<bool>("General", "Force Proliferator", false, "The theoretical max rate always apply proliferator, regardless the material.\n计算理论上限时是否强制套用增产设定(否=依照当下原料决定)");
			ForceLens = config.Bind<bool>("General", "Force Gravity Lens in Ray Receiver", false, "The theoretical max rate always apply gravity lens.\n计算射线接收站时总是套用透镜(否=依照当下决定)");
		}
	}
	[BepInPlugin("starfi5h.plugin.RateMonitor", "RateMonitor", "0.2.0")]
	public class Plugin : BaseUnityPlugin
	{
		public enum EOperation
		{
			Normal,
			Add,
			Sub
		}

		public const string GUID = "starfi5h.plugin.RateMonitor";

		public const string NAME = "RateMonitor";

		public const string VERSION = "0.2.0";

		public static ManualLogSource Log;

		public static Plugin instance;

		private static Harmony harmony;

		private static List<int> lastEntityIds = new List<int>();

		private static int lastPlanetId;

		public static StatTable MainTable { get; set; }

		public static EOperation Operation { get; set; }

		public static string LastStatInfo { get; private set; } = "";


		public void Awake()
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			instance = this;
			harmony = new Harmony("starfi5h.plugin.RateMonitor");
			harmony.PatchAll(typeof(SelectionTool_Patches));
			harmony.PatchAll(typeof(Plugin));
			ModSettings.LoadConfigs(((BaseUnityPlugin)this).Config);
			if (Chainloader.PluginInfos.TryGetValue("org.LoShin.GenesisBook", out var _))
			{
				Log.LogInfo((object)"Compat - GenesisBook");
				CalDB.CompatGB = true;
			}
			Utils.Init();
			UIWindow.LoadUIWindowConfig();
			Localization.OnLanguageChange += SP.Init;
		}

		public void OnGUI()
		{
			UIWindow.OnGUI();
		}

		public void Update()
		{
			if (GameMain.localPlanet == null && SelectionTool_Patches.IsHotKey() && MainTable == null && !LoadLastTable())
			{
				CreateMainTable(null, new List<int>(0));
			}
		}

		public static void OnSelectionFinish(PlanetFactory factory, HashSet<int> entityIdSet)
		{
			switch (Operation)
			{
			case EOperation.Add:
			{
				Operation = EOperation.Normal;
				if (MainTable == null)
				{
					break;
				}
				PlanetFactory factory3;
				List<int> entityIds2 = MainTable.GetEntityIds(out factory3);
				if (factory3 == factory)
				{
					entityIdSet.UnionWith(entityIds2);
					if (entityIdSet.Count() > 0)
					{
						SaveCurrentTable();
						CreateMainTable(factory, entityIdSet.ToList());
					}
				}
				break;
			}
			case EOperation.Sub:
			{
				Operation = EOperation.Normal;
				if (MainTable == null)
				{
					break;
				}
				PlanetFactory factory2;
				List<int> entityIds = MainTable.GetEntityIds(out factory2);
				if (factory2 != factory)
				{
					break;
				}
				IEnumerable<int> enumerable = entityIdSet.Intersect(entityIds);
				foreach (int item in enumerable)
				{
					entityIds.Remove(item);
				}
				if (enumerable.Count() > 0)
				{
					SaveCurrentTable();
					CreateMainTable(factory, entityIds.ToList());
				}
				break;
			}
			default:
				SaveCurrentTable();
				CreateMainTable(factory, entityIdSet.ToList());
				break;
			}
		}

		public static void CreateMainTable(PlanetFactory factory, List<int> entityIds)
		{
			if (!SP.IsInit)
			{
				SP.Init();
			}
			MainTable = new StatTable();
			MainTable.Initialize(factory, entityIds);
			MainTable.PrintRefRates();
			MainTable.PrintProifles();
			Log.LogDebug((object)("CreateMainTable: " + MainTable.GetEntityCount()));
		}

		public static bool SaveCurrentTable()
		{
			if (MainTable == null)
			{
				return false;
			}
			PlanetFactory factory;
			List<int> entityIds = MainTable.GetEntityIds(out factory);
			if (entityIds.Count == 0)
			{
				return false;
			}
			lastEntityIds = entityIds;
			lastPlanetId = factory.planetId;
			PlanetData obj = GameMain.galaxy.PlanetById(lastPlanetId);
			LastStatInfo = (((obj != null) ? obj.displayName : null) ?? " ") + ": " + lastEntityIds.Count;
			Log.LogDebug((object)("SaveCurrentTable: " + LastStatInfo));
			return true;
		}

		public static bool LoadLastTable()
		{
			PlanetFactory val = GameMain.galaxy.PlanetById(lastPlanetId)?.factory;
			if (val == null || lastEntityIds.Count == 0)
			{
				return false;
			}
			List<int> list = new List<int>();
			foreach (int lastEntityId in lastEntityIds)
			{
				if (SelectionTool.ShouldAddObject(val, lastEntityId))
				{
					list.Add(lastEntityId);
				}
			}
			if (list.Count == 0)
			{
				return false;
			}
			SaveCurrentTable();
			CreateMainTable(val, list);
			return true;
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(GameData), "GameTick")]
		private static void UpdateMonitor(bool __runOriginal)
		{
			if (MainTable != null && __runOriginal)
			{
				try
				{
					MainTable.OnGameTick();
				}
				catch (Exception ex)
				{
					Log.LogError((object)ex);
					MainTable.OnError();
				}
				if (UIWindow.InResizingArea)
				{
					UICursor.SetCursor((ECursor)13);
				}
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(GameMain), "End")]
		private static void OnGameEnd()
		{
			MainTable = null;
			UIWindow.SaveUIWindowConfig();
		}

		public void OnDestroy()
		{
			harmony.UnpatchSelf();
			harmony = null;
			Localization.OnLanguageChange -= SP.Init;
		}
	}
	[BepInPlugin("starfi5h.plugin.RateMonitor.CAPIcompat", "RateMonitorCAPIcompat", "1.0.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[CommonAPISubmoduleDependency(new string[] { "LocalizationModule", "CustomKeyBindSystem" })]
	public class PluginCAPIcompat : BaseUnityPlugin
	{
		public const string GUID = "starfi5h.plugin.RateMonitor.CAPIcompat";

		public const string NAME = "RateMonitorCAPIcompat";

		public const string VERSION = "1.0.0";

		public static bool IsRegisiter;

		public void Awake()
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			BuiltinKey val = default(BuiltinKey);
			val.key = new CombineKey(120, (byte)4, (ECombineKeyAction)0, false);
			val.conflictGroup = 2048;
			val.name = "RateMonitorSelectionToolKey";
			val.canOverride = true;
			CustomKeyBindSystem.RegisterKeyBind<PressKeyBind>(val);
			LocalizationModule.RegisterTranslation("RateMonitorSelection", "(Mod) RateMonitor Selection", "(Mod) RateMonitor框选计算", "(Mod) Rate Monitor Selection");
			IsRegisiter = true;
		}

		public static bool IsPressed()
		{
			return CustomKeyBindSystem.GetKeyBind("RateMonitorSelectionToolKey").keyValue;
		}
	}
	public class SelectionTool : BuildTool
	{
		public Action<PlanetFactory, HashSet<int>> OnSelectionFinish;

		private bool castTerrain;

		private bool castGround;

		private Vector3 castGroundPos = Vector3.zero;

		private Vector3 castGroundPosSnapped = Vector3.zero;

		private int castObjectId;

		private bool cursorValid;

		private Vector3 cursorTarget;

		private Vector3 startGroundPosSnapped = Vector3.zero;

		private Vector3 lastGroundPosSnapped = Vector3.zero;

		public BPGratBox selectGratBox = BPGratBox.zero;

		private BPGratBox lastSelectGratBox = BPGratBox.zero;

		private BPGratBox selectArcBox = BPGratBox.zero;

		private HashSet<int> selectObjIds;

		private BuildPreview[] bpPool;

		private AnimData[] animPool;

		private ComputeBuffer animBuffer;

		private int bpCursor = 1;

		private int bpPoolCapacity;

		private int[] bpRecycle;

		private int bpRecycleCursor;

		public bool IsEnable { get; set; }

		public bool IsSelecting { get; private set; }

		public void FinishSelectAction()
		{
			IsSelecting = false;
			OnSelectionFinish?.Invoke(base.factory, selectObjIds);
			ClearSelection();
		}

		public static bool ShouldAddObject(PlanetFactory factory, int objId)
		{
			if (objId <= 0 || objId >= factory.entityCursor)
			{
				return false;
			}
			ref EntityData reference = ref factory.entityPool[objId];
			if (reference.assemblerId > 0)
			{
				return factory.factorySystem.assemblerPool[reference.assemblerId].recipeId > 0;
			}
			if (reference.labId > 0)
			{
				ref LabComponent reference2 = ref factory.factorySystem.labPool[reference.labId];
				if (!((LabComponent)(ref reference2)).matrixMode || reference2.recipeId <= 0)
				{
					return reference2.researchMode;
				}
				return true;
			}
			if (reference.minerId > 0 || reference.fractionatorId > 0 || reference.ejectorId > 0 || reference.siloId > 0)
			{
				return true;
			}
			if (reference.powerGenId > 0)
			{
				ref PowerGeneratorComponent reference3 = ref factory.powerSystem.genPool[reference.powerGenId];
				if (reference3.gamma)
				{
					return reference3.productId > 0;
				}
				if (reference3.wind || reference3.photovoltaic || reference3.geothermal)
				{
					return false;
				}
				bool flag = reference3.fuelHeat > 0 && reference3.fuelId > 0;
				return CalDB.IncludeFuelGenerator && flag;
			}
			if (reference.powerExcId > 0)
			{
				ref PowerExchangerComponent reference4 = ref factory.powerSystem.excPool[reference.powerExcId];
				if (reference4.state != 1f)
				{
					return reference4.state == -1f;
				}
				return true;
			}
			return false;
		}

		public override void _OnInit()
		{
			selectObjIds = new HashSet<int>();
			SetDisplayPreviewCapacity(256);
		}

		public override void _OnFree()
		{
			selectObjIds = null;
			FreeBuildPreviews();
			IsEnable = false;
			IsSelecting = false;
		}

		public override void _OnOpen()
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: 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_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			ClearSelection();
			ResetBuildPreviews();
			castTerrain = false;
			castGround = false;
			castGroundPos = Vector3.zero;
			startGroundPosSnapped = (lastGroundPosSnapped = (castGroundPosSnapped = Vector3.zero));
			lastSelectGratBox = (selectGratBox = (selectArcBox = BPGratBox.zero));
			castObjectId = 0;
			cursorValid = false;
			cursorTarget = Vector3.zero;
			IsSelecting = false;
		}

		public override void _OnClose()
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			ClearSelection();
			ResetBuildPreviews();
			startGroundPosSnapped = (lastGroundPosSnapped = (castGroundPosSnapped = Vector3.zero));
			lastSelectGratBox = (selectGratBox = (selectArcBox = BPGratBox.zero));
			castObjectId = 0;
			cursorValid = false;
			cursorTarget = Vector3.zero;
			IsEnable = false;
			IsSelecting = false;
		}

		public override void _OnTick(long time)
		{
			UpdateRaycast();
			Operating();
			if (((BuildTool)this).active)
			{
				((BuildTool)this).UpdatePreviewModels(((BuildTool)this).actionBuild.model);
			}
		}

		public override bool DetermineActive()
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			if (IsEnable && (int)((BuildTool)this).actionBuild.blueprintMode == 0)
			{
				return ((BuildTool)this).controller.cmd.mode == 0;
			}
			return false;
		}

		public override void EscLogic()
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			bool flag = !VFInput.onGUI && VFInput.inScreen && !VFInput.inputing;
			bool flag2 = VFInput.escKey.onDown || VFInput.escape;
			bool num = !VFInput._godModeMechaMove && VFInput.rtsCancel.onDown && flag;
			if (num || flag2)
			{
				((BuildTool)this).player.SetHandItems(0, 0, 0);
				((BuildTool)this)._Close();
				((BuildTool)this).actionBuild.Close();
			}
			if (flag2)
			{
				VFInput.UseEscape();
			}
			if (num)
			{
				VFInput.UseMouseRight();
			}
		}

		public override void UpdatePreviewModels(BuildModel model)
		{
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			for (int i = 1; i < bpCursor; i++)
			{
				BuildPreview val = bpPool[i];
				if (val == null || val.bpgpuiModelId <= 0 || !val.isConnNode)
				{
					continue;
				}
				if (val.objId > 0)
				{
					base.factory.cargoTraffic.SetBeltSelected(base.factory.entityPool[val.objId].beltId);
					continue;
				}
				uint beltSpeed = (uint)val.desc.beltSpeed;
				if (val.outputObjId == 0 || val.inputObjId == 0 || val.coverbp != null)
				{
					model.connRenderer.AddBlueprintBeltMajorPoint(val.lpos, val.lrot, beltSpeed);
				}
				else
				{
					model.connRenderer.AddBlueprintBeltPoint(val.lpos, val.lrot, beltSpeed);
				}
			}
		}

		public void UpdateRaycast()
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: 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_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Invalid comparison between Unknown and I4
			//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Invalid comparison between Unknown and I4
			//IL_01d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: 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_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_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			castTerrain = false;
			castGround = false;
			castGroundPos = Vector3.zero;
			castGroundPosSnapped = Vector3.zero;
			castObjectId = 0;
			cursorValid = false;
			cursorTarget = Vector3.zero;
			if (!VFInput.onGUI && VFInput.inScreen)
			{
				RaycastHit val = default(RaycastHit);
				castGround = Physics.Raycast(base.mouseRay, ref val, 800f, 8720, (QueryTriggerInteraction)2);
				if (castGround)
				{
					Layer val2 = (Layer)((Component)((RaycastHit)(ref val)).collider).gameObject.layer;
					castTerrain = (int)val2 == 9 || (int)val2 == 4;
					castGroundPos = (((BuildTool)this).controller.cmd.test = (((BuildTool)this).controller.cmd.target = ((RaycastHit)(ref val)).point));
					castGroundPosSnapped = ((BuildTool)this).actionBuild.planetAux.Snap(castGroundPos, castTerrain);
					castGroundPosSnapped = ((Vector3)(ref castGroundPosSnapped)).normalized * (base.planet.realRadius + 0.2f);
					((BuildTool)this).controller.cmd.test = castGroundPosSnapped;
					Vector3 normalized = ((Vector3)(ref castGroundPosSnapped)).normalized;
					if (Physics.Raycast(new Ray(castGroundPosSnapped + normalized * 10f, -normalized), ref val, 20f, 8720, (QueryTriggerInteraction)2))
					{
						((BuildTool)this).controller.cmd.test = ((RaycastHit)(ref val)).point;
					}
					cursorTarget = castGroundPosSnapped;
					cursorValid = true;
				}
			}
			((BuildTool)this).controller.cmd.state = (cursorValid ? 1 : 0);
			((BuildTool)this).controller.cmd.target = (cursorValid ? cursorTarget : Vector3.zero);
		}

		public void Operating()
		{
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: 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_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			if (!IsSelecting && VFInput.blueprintCopyOperate0.onDown && cursorValid)
			{
				IsSelecting = true;
				startGroundPosSnapped = castGroundPosSnapped;
				lastGroundPosSnapped = startGroundPosSnapped;
				InitSelectGratBox();
				VFInput.UseMouseLeft();
			}
			Vector3 val = castGroundPosSnapped - startGroundPosSnapped;
			bool num = ((Vector3)(ref val)).sqrMagnitude > 0.01f;
			bool flag = VFInput.blueprintCopyOperate0.onDown || VFInput.blueprintCopyOperate1.onDown;
			if (IsSelecting && flag && cursorValid)
			{
				FinishSelectAction();
				ResetBuildPreviews();
				IsSelecting = false;
				VFInput.UseMouseLeft();
				VFInput.UseEnterConfirm();
				((BuildTool)this)._Close();
			}
			else if (IsSelecting && VFInput.rtsCancel.onUp)
			{
				IsSelecting = false;
				startGroundPosSnapped = castGroundPosSnapped;
				lastGroundPosSnapped = startGroundPosSnapped;
				ClearSelection();
				ResetBuildPreviews();
			}
			if (IsSelecting)
			{
				UICursor.SetCursor((ECursor)2);
				DetermineSelectGratBox();
				if (lastSelectGratBox != selectGratBox)
				{
					DetermineAddSelection();
					lastSelectGratBox = selectGratBox;
				}
			}
			else
			{
				startGroundPosSnapped = castGroundPosSnapped;
				ReDeterminePreviews();
			}
			if (num)
			{
				ReDeterminePreviews();
			}
			string text = "[RateMonitor]";
			if (Plugin.Operation != 0)
			{
				text = text + ": " + Plugin.Operation;
			}
			((BuildTool)this).actionBuild.model.cursorText = text + "\r\nselected count:" + selectObjIds.Count;
		}

		private void InitSelectGratBox()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			BlueprintUtils.GetMinimumGratBox(((Vector3)(ref startGroundPosSnapped)).normalized, ref selectGratBox);
			selectArcBox = selectGratBox;
			if (selectArcBox.y >= 1.5707864f)
			{
				selectArcBox.y = (selectArcBox.w = (float)Math.PI / 2f);
				selectArcBox.z = selectArcBox.x + (float)Math.PI * 200f;
			}
			else if (selectArcBox.y <= -1.5707864f)
			{
				selectArcBox.y = (selectArcBox.w = -(float)Math.PI / 2f);
				selectArcBox.z = selectArcBox.x + (float)Math.PI * 200f;
			}
			lastSelectGratBox = selectGratBox;
		}

		public void DetermineSelectGratBox()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02df: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_030c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0311: Unknown result type (might be due to invalid IL or missing references)
			if (!cursorValid)
			{
				return;
			}
			float longitudeRad = BlueprintUtils.GetLongitudeRad(((Vector3)(ref castGroundPosSnapped)).normalized);
			float longitudeRad2 = BlueprintUtils.GetLongitudeRad(((Vector3)(ref lastGroundPosSnapped)).normalized);
			float latitudeRad = BlueprintUtils.GetLatitudeRad(((Vector3)(ref castGroundPosSnapped)).normalized);
			int num;
			float num2;
			if (!(latitudeRad >= 1.5707864f))
			{
				num = ((latitudeRad <= -1.5707864f) ? 1 : 0);
				if (num == 0)
				{
					num2 = longitudeRad - longitudeRad2;
					goto IL_0061;
				}
			}
			else
			{
				num = 1;
			}
			num2 = 0f;
			goto IL_0061;
			IL_0061:
			float num3 = num2;
			num3 = Mathf.Repeat(num3 + (float)Math.PI, (float)Math.PI * 2f) - (float)Math.PI;
			ref BPGratBox reference = ref selectArcBox;
			((BPGratBox)(ref reference)).endLongitudeRad = ((BPGratBox)(ref reference)).endLongitudeRad + num3;
			((BPGratBox)(ref selectArcBox)).endLatitudeRad = latitudeRad;
			selectGratBox = selectArcBox;
			selectGratBox.x = ((selectArcBox.x < selectArcBox.z) ? selectArcBox.x : selectArcBox.z);
			selectGratBox.z = ((selectArcBox.x > selectArcBox.z) ? selectArcBox.x : selectArcBox.z);
			if (selectArcBox.x < selectArcBox.z)
			{
				if (selectGratBox.z > selectGratBox.x + (float)Math.PI * 2f - 1E-05f - 4E-06f)
				{
					selectGratBox.z = selectGratBox.x + (float)Math.PI * 2f - 1E-05f - 4E-06f;
				}
				selectGratBox.z = Mathf.Repeat(selectGratBox.z + (float)Math.PI, (float)Math.PI * 2f) - (float)Math.PI;
			}
			else
			{
				if (selectGratBox.x < selectGratBox.z - (float)Math.PI * 2f + 1E-05f + 4E-06f)
				{
					selectGratBox.x = selectGratBox.z - (float)Math.PI * 2f + 1E-05f + 4E-06f;
				}
				selectGratBox.x = Mathf.Repeat(selectGratBox.x + (float)Math.PI, (float)Math.PI * 2f) - (float)Math.PI;
			}
			selectGratBox.y = ((selectArcBox.y < selectArcBox.w) ? selectArcBox.y : selectArcBox.w);
			selectGratBox.w = ((selectArcBox.y > selectArcBox.w) ? selectArcBox.y : selectArcBox.w);
			float num4 = BlueprintUtils.GetLongitudeRadPerGrid((Mathf.Abs(castGroundPosSnapped.y) < Mathf.Abs(startGroundPosSnapped.y)) ? ((Vector3)(ref castGroundPosSnapped)).normalized : ((Vector3)(ref startGroundPosSnapped)).normalized, 200) * 0.33f;
			((BPGratBox)(ref selectGratBox)).Extend(num4, 0.002f);
			if (num == 0)
			{
				lastGroundPosSnapped = castGroundPosSnapped;
			}
		}

		public void DetermineAddSelection()
		{
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			selectObjIds.Clear();
			if (Mathf.Abs(selectArcBox.x - selectArcBox.z) < 0.01f && Mathf.Abs(selectArcBox.y - selectArcBox.w) < 0.01f && castObjectId != 0)
			{
				if (ShouldAddObject(base.factory, castObjectId))
				{
					selectObjIds.Add(castObjectId);
				}
			}
			else
			{
				EntityData[] entityPool = base.factory.entityPool;
				int entityCursor = base.factory.entityCursor;
				for (int i = 1; i < entityCursor; i++)
				{
					ref EntityData reference = ref entityPool[i];
					if (reference.id == i && ((BPGratBox)(ref selectGratBox)).InGratBox(reference.pos) && ShouldAddObject(base.factory, i))
					{
						selectObjIds.Add(i);
					}
				}
			}
			DeterminePreviews();
		}

		public void ClearSelection()
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			selectObjIds.Clear();
			lastSelectGratBox = (selectGratBox = (selectArcBox = BPGratBox.zero));
		}

		public void ReDeterminePreviews()
		{
			ResetBuildPreviews();
			foreach (int selectObjId in selectObjIds)
			{
				BuildPreview buildPreview = GetBuildPreview(selectObjId);
				AddBPGPUIModel(buildPreview);
			}
			SyncAnimBuffer();
			base.planet.factoryModel.bpgpuiManager.animBuffer = animBuffer;
			base.planet.factoryModel.bpgpuiManager.SyncAllGPUBuffer();
		}

		public void DeterminePreviews()
		{
			HashSet<int> hashSet = new HashSet<int>(selectObjIds);
			for (int i = 1; i < bpCursor; i++)
			{
				BuildPreview val = bpPool[i];
				if (val == null || val.bpgpuiModelId <= 0)
				{
					continue;
				}
				if (!selectObjIds.Contains(val.objId))
				{
					if (val.bpgpuiModelInstIndex >= 0)
					{
						base.planet.factoryModel.bpgpuiManager.RemoveBuildPreviewModel(val.desc.modelIndex, val.bpgpuiModelInstIndex, false);
					}
					RemoveBuildPreview(i);
				}
				else
				{
					hashSet.Remove(val.objId);
				}
			}
			foreach (int item in hashSet)
			{
				BuildPreview buildPreview = GetBuildPreview(item);
				AddBPGPUIModel(buildPreview);
			}
			if (castObjectId != 0)
			{
				BuildPreview buildPreview2 = GetBuildPreview(castObjectId);
				AddBPGPUIModel(buildPreview2);
			}
			SyncAnimBuffer();
			base.planet.factoryModel.bpgpuiManager.animBuffer = animBuffer;
			base.planet.factoryModel.bpgpuiManager.SyncAllGPUBuffer();
		}

		public void AddBPGPUIModel(BuildPreview preview)
		{
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: 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_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: 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)
			//IL_022b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0234: Unknown result type (might be due to invalid IL or missing references)
			//IL_023e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0247: Unknown result type (might be due to invalid IL or missing references)
			//IL_0210: Unknown result type (might be due to invalid IL or missing references)
			//IL_0215: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e7: Unknown result type (might be due to invalid IL or missing references)
			if (preview == null || preview.bpgpuiModelId <= 0 || !preview.needModel)
			{
				return;
			}
			ModelProto val = ((ProtoSet<ModelProto>)(object)LDB.models).Select(preview.desc.modelIndex);
			Color32 val2 = default(Color32);
			((Color32)(ref val2))..ctor((byte)44, (byte)123, (byte)250, byte.MaxValue);
			if (val.RendererType == 2)
			{
				bool flag = default(bool);
				bool flag2 = default(bool);
				((BuildTool)this).GetInserterT1T2(preview.objId, ref flag, ref flag2);
				if (preview.objId > 0)
				{
					animPool[preview.bpgpuiModelId] = base.factory.entityAnimPool[preview.objId];
				}
				animPool[preview.bpgpuiModelId].state = (uint)((val2.r << 24) + (val2.g << 16) + (val2.b << 8) + val2.a);
				base.planet.factoryModel.bpgpuiManager.AddBuildPreviewModel(preview.desc.modelIndex, ref preview.bpgpuiModelInstIndex, preview.bpgpuiModelId, preview.lpos, preview.lrot, preview.lpos2, preview.lrot2, flag ? 1 : 0, flag2 ? 1 : 0, false);
				return;
			}
			if (val.RendererType == 3)
			{
				bool flag3 = default(bool);
				int num = default(int);
				int num2 = default(int);
				base.factory.ReadObjectConn(preview.objId, 14, ref flag3, ref num, ref num2);
				if (preview.objId > 0)
				{
					animPool[preview.bpgpuiModelId] = base.factory.entityAnimPool[preview.objId];
				}
				animPool[preview.bpgpuiModelId].state = (uint)((val2.r << 24) + (val2.g << 16) + (val2.b << 8) + val2.a);
				base.planet.factoryModel.bpgpuiManager.AddBuildPreviewModel(preview.desc.modelIndex, ref preview.bpgpuiModelInstIndex, preview.bpgpuiModelId, preview.lpos, preview.lrot, (num != 0) ? 1u : 0u, false);
				return;
			}
			if (preview.objId > 0)
			{
				animPool[preview.bpgpuiModelId] = base.factory.entityAnimPool[preview.objId];
			}
			animPool[preview.bpgpuiModelId].state = (uint)((val2.r << 24) + (val2.g << 16) + (val2.b << 8) + val2.a);
			if (preview.objId > 0 && preview.desc.isEjector)
			{
				animPool[preview.bpgpuiModelId].power = base.factory.factorySystem.ejectorPool[base.factory.entityPool[preview.objId].ejectorId].localDir.z;
			}
			base.planet.factoryModel.bpgpuiManager.AddBuildPreviewModel(preview.desc.modelIndex, ref preview.bpgpuiModelInstIndex, preview.bpgpuiModelId, preview.lpos, preview.lrot, false);
		}

		public void GeneratePreviewByObjId(BuildPreview preview, int objId)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: 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_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			ItemProto itemProto = ((BuildTool)this).GetItemProto(objId);
			PrefabDesc prefabDesc = ((BuildTool)this).GetPrefabDesc(objId);
			if (prefabDesc == null || itemProto == null)
			{
				preview.ResetAll();
				return;
			}
			Pose objectPose = ((BuildTool)this).GetObjectPose(objId);
			Pose val = (prefabDesc.isInserter ? ((BuildTool)this).GetObjectPose2(objId) : objectPose);
			preview.item = itemProto;
			preview.desc = prefabDesc;
			preview.lpos = objectPose.position;
			preview.lrot = objectPose.rotation;
			preview.lpos2 = objectPose.position;
			preview.lrot2 = objectPose.rotation;
			preview.objId = objId;
			preview.genNearColliderArea2 = 0f;
			if (preview.desc.lodCount > 0 && preview.desc.lodMeshes != null && (Object)(object)preview.desc.lodMeshes[0] != (Object)null)
			{
				preview.needModel = true;
			}
			else
			{
				preview.needModel = false;
			}
			preview.isConnNode = prefabDesc.isBelt;
			if (prefabDesc.isBelt)
			{
				bool flag = default(bool);
				int num = default(int);
				int num2 = default(int);
				for (int i = 0; i < 4; i++)
				{
					base.factory.ReadObjectConn(objId, i, ref flag, ref num, ref num2);
					if (num != 0)
					{
						if (flag)
						{
							preview.outputObjId = num;
						}
						else if (preview.inputObjId == 0)
						{
							preview.inputObjId = num;
						}
						else
						{
							preview.coverbp = preview;
						}
					}
				}
			}
			if (prefabDesc.isInserter)
			{
				preview.lpos2 = val.position;
				preview.lrot2 = val.rotation;
			}
		}

		public void ResetBuildPreviews()
		{
			if (base.planet != null && (Object)(object)base.planet.factoryModel != (Object)null && base.planet.factoryModel.bpgpuiManager != null)
			{
				base.planet.factoryModel.bpgpuiManager.Reset();
			}
			for (int i = 0; i < bpPool.Length; i++)
			{
				if (bpPool[i] != null)
				{
					bpPool[i].ResetAll();
				}
			}
			Array.Clear(animPool, 0, bpPoolCapacity);
			Array.Clear(bpRecycle, 0, bpPoolCapacity);
			bpCursor = 1;
			bpRecycleCursor = 0;
			animBuffer.SetData((Array)animPool);
		}

		public void FreeBuildPreviews()
		{
			if (base.planet != null && (Object)(object)base.planet.factoryModel != (Object)null && base.planet.factoryModel.bpgpuiManager != null)
			{
				base.planet.factoryModel.bpgpuiManager.Reset();
			}
			for (int i = 0; i < bpPool.Length; i++)
			{
				if (bpPool[i] != null)
				{
					bpPool[i].Free();
					bpPool[i] = null;
				}
			}
			animPool = null;
			bpPool = null;
			bpCursor = 1;
			bpPoolCapacity = 0;
			bpRecycle = null;
			bpRecycleCursor = 0;
			if (animBuffer != null)
			{
				animBuffer.Release();
				animBuffer = null;
			}
		}

		private void SetDisplayPreviewCapacity(int newCapacity)
		{
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Expected O, but got Unknown
			BuildPreview[] array = bpPool;
			AnimData[] sourceArray = animPool;
			bpPool = (BuildPreview[])(object)new BuildPreview[newCapacity];
			animPool = (AnimData[])(object)new AnimData[newCapacity];
			bpRecycle = new int[newCapacity];
			if (array != null)
			{
				Array.Copy(array, bpPool, (newCapacity > bpPoolCapacity) ? bpPoolCapacity : newCapacity);
				Array.Copy(sourceArray, animPool, (newCapacity > bpPoolCapacity) ? bpPoolCapacity : newCapacity);
			}
			bpPoolCapacity = newCapacity;
			ComputeBuffer obj = animBuffer;
			if (obj != null)
			{
				obj.Release();
			}
			animBuffer = new ComputeBuffer(newCapacity, 20, (ComputeBufferType)0);
		}

		public void RemoveBuildPreview(int id)
		{
			if (bpPool[id] != null && bpPool[id].bpgpuiModelInstIndex >= 0)
			{
				animPool[id].time = 0f;
				animPool[id].prepare_length = 0f;
				animPool[id].working_length = 0f;
				animPool[id].state = 0u;
				animPool[id].power = 0f;
				bpPool[id].ResetAll();
				bpRecycle[bpRecycleCursor++] = id;
			}
		}

		public BuildPreview GetBuildPreview(int objId)
		{
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Expected O, but got Unknown
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Expected O, but got Unknown
			if (bpRecycleCursor > 0)
			{
				int num = bpRecycle[--bpRecycleCursor];
				BuildPreview val = bpPool[num];
				if (val == null)
				{
					val = new BuildPreview();
					bpPool[num] = val;
				}
				GeneratePreviewByObjId(val, objId);
				animPool[num] = default(AnimData);
				val.previewIndex = num;
				val.bpgpuiModelId = num;
				return val;
			}
			int num2 = bpCursor++;
			if (num2 == bpPoolCapacity)
			{
				SetDisplayPreviewCapacity(bpPoolCapacity * 2);
			}
			BuildPreview val2 = bpPool[num2];
			if (val2 == null)
			{
				val2 = new BuildPreview();
				bpPool[num2] = val2;
			}
			GeneratePreviewByObjId(val2, objId);
			animPool[num2] = default(AnimData);
			val2.previewIndex = num2;
			val2.bpgpuiModelId = num2;
			return val2;
		}

		public void SyncAnimBuffer()
		{
			ComputeBuffer obj = animBuffer;
			if (obj != null)
			{
				obj.SetData((Array)animPool);
			}
		}
	}
	public class SelectionTool_Patches
	{
		public static SelectionTool tool;

		[HarmonyPostfix]
		[HarmonyAfter(new string[] { "org.kremnev8.plugin.BlueprintTweaks" })]
		[HarmonyPatch(typeof(PlayerAction_Build), "Init")]
		public static void InitTool(PlayerAction_Build __instance)
		{
			BuildTool[] tools = __instance.tools;
			if (tools != null)
			{
				BuildTool[] array = (BuildTool[])(object)new BuildTool[tools.Length + 1];
				tools.CopyTo(array, 0);
				tool = new SelectionTool();
				SelectionTool selectionTool = tool;
				selectionTool.OnSelectionFinish = (Action<PlanetFactory, HashSet<int>>)Delegate.Combine(selectionTool.OnSelectionFinish, new Action<PlanetFactory, HashSet<int>>(Plugin.OnSelectionFinish));
				array[^1] = (BuildTool)(object)tool;
				__instance.tools = array;
				Plugin.Log.LogDebug((object)("Add SelectionTool. Total tools count: " + array.Length));
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(PlayerAction_Build), "DetermineActive")]
		public static void UpdateCommandState(PlayerAction_Build __instance, ref bool __result)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			if (tool.IsEnable && __instance.activeTool == tool)
			{
				__result = true;
			}
			else if (VFInput.readyToBuild && VFInput.inScreen && IsHotKey() && (int)__instance.blueprintMode == 0)
			{
				Plugin.Log.LogDebug((object)"Enable selection tool");
				((CommandState)(ref ((PlayerAction)__instance).player.controller.cmd)).SetNoneCommand();
				tool.IsEnable = true;
				__result = true;
			}
		}

		public static bool IsHotKey()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			if (PluginCAPIcompat.IsRegisiter)
			{
				return PluginCAPIcompat.IsPressed();
			}
			KeyboardShortcut value = ModSettings.SelectionToolKey.Value;
			return ((KeyboardShortcut)(ref value)).IsPressed();
		}

		[HarmonyPostfix]
		[HarmonyPriority(200)]
		[HarmonyPatch(typeof(UIBuildingGrid), "Update")]
		public static void UpdateGrid(UIBuildingGrid __instance)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Invalid comparison between Unknown and I4
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Invalid comparison between Unknown and I4
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			Player mainPlayer = GameMain.mainPlayer;
			if (GameMain.localPlanet?.factory == null || (int)GameMain.localPlanet.type == 5 || tool == null || !((BuildTool)tool).active)
			{
				return;
			}
			PlayerAction_Build val = ((mainPlayer == null) ? null : mainPlayer.controller?.actionBuild);
			if (val == null || (int)val.blueprintMode != 0)
			{
				return;
			}
			PlanetGrid val2 = null;
			if (GameMain.localPlanet != null && GameMain.localPlanet.aux != null && GameMain.localPlanet.aux.activeGridIndex < GameMain.localPlanet.aux.customGrids.Count)
			{
				val2 = GameMain.localPlanet.aux.customGrids[GameMain.localPlanet.aux.activeGridIndex];
			}
			if (val2 != null)
			{
				Vector4 val3 = Vector4.zero;
				if (tool.IsSelecting)
				{
					__instance.gridRnd.enabled = (int)val.blueprintMode == 0;
					((Component)__instance.gridRnd).transform.localScale = new Vector3(__instance.displayScale, __instance.displayScale, __instance.displayScale);
					((Component)__instance.gridRnd).transform.rotation = val2.rotation;
					__instance.material.SetColor("_TintColor", new Color(0.5f, 0.6f, 0f));
					__instance.material.SetFloat("_ReformMode", 0f);
					__instance.material.SetFloat("_ZMin", -0.5f);
					val3 = (Vector4)tool.selectGratBox;
				}
				__instance.material.SetVector("_CursorGratBox", val3);
			}
		}
	}
	public static class SP
	{
		public static string uiSettingsText;

		public static string showRealTimeRateText;

		public static string showInPercentageText;

		public static string rateUnitText;

		public static string perMinuteText;

		public static string perSecondText;

		public static string[] perBeltTexts = new string[3];

		public static string calculateSettingsText;

		public static string incLevelText;

		public static string forceIncText;

		public static string forceText;

		public static string forceLens;

		public static string settingButtonText;

		public static string operationButtonText;

		public static string backButtonText;

		public static string entityCountText;

		public static string addActionText;

		public static string subActionText;

		public static string planetSelectDescriptionText;

		public static string wholeLocalPlanetText;

		public static string wholeRemotePlanetText;

		public static string loadLastText;

		public static string resetTimerText;

		public static string itemIdProduceText;

		public static string itemIdConsumeText;

		public static string itemIdIntermediateText;

		public static string workingOnlyText;

		public static string expandedOnlyText;

		public static string proliferatorCostText;

		public static string powerCostText;

		public static string totalProductionText;

		public static string totalConsumptionText;

		public static string netMachineText;

		public static string expandRecordText;

		public static string recordTooltipText;

		public static bool IsInit { get; private set; }

		public static void Init()
		{
			bool isZHCN = Localization.isZHCN;
			uiSettingsText = (isZHCN ? "UI设定" : Localization.Translate("UI Settings"));
			showRealTimeRateText = (isZHCN ? "显示即时监控速率" : Localization.Translate("Show Real-time Monitoring Rate"));
			showInPercentageText = (isZHCN ? "以百分比显示" : Localization.Translate("Show In Percentage"));
			rateUnitText = (isZHCN ? "速率单位: " : Localization.Translate("RateUnit: "));
			perMinuteText = (isZHCN ? "每分钟" : Localization.Translate("Per Minute"));
			perSecondText = (isZHCN ? "每秒钟" : Localization.Translate("Per Second"));
			perBeltTexts[0] = (isZHCN ? "黄带" : Localization.Translate("Mk1 Belt"));
			perBeltTexts[1] = (isZHCN ? "绿带" : Localization.Translate("Mk2 Belt"));
			perBeltTexts[2] = (isZHCN ? "蓝带" : Localization.Translate("Mk3 Belt"));
			calculateSettingsText = (isZHCN ? "計算设定" : Localization.Translate("Calculate Settings"));
			incLevelText = (isZHCN ? "增产等级: " : Localization.Translate("ProliferatorLevel: "));
			forceIncText = (isZHCN ? "强制增产" : Localization.Translate("ForceProliferator"));
			forceLens = (isZHCN ? "强制透镜" : Localization.Translate("ForceGravitonLens"));
			forceText = (isZHCN ? "强制" : Localization.Translate("Force"));
			settingButtonText = (isZHCN ? "设置" : Localization.Translate("Config"));
			operationButtonText = (isZHCN ? "操作" : Localization.Translate("Operate"));
			backButtonText = (isZHCN ? "返回" : Localization.Translate("Back"));
			entityCountText = (isZHCN ? "建筑数量: " : Localization.Translate("EntityCount: "));
			addActionText = (isZHCN ? "添增选取" : Localization.Translate("Add Selection"));
			subActionText = (isZHCN ? "移除选取" : Localization.Translate("Sub Selection"));
			planetSelectDescriptionText = (isZHCN ? "可以在统计面板或总控面板选择星球来框选全建筑" : Localization.Translate("Select a planet in the statistics panel or control panel to select all buildings on it"));
			wholeLocalPlanetText = (isZHCN ? "选取本地全球机器" : Localization.Translate("Select Whole Local Planet"));
			wholeRemotePlanetText = (isZHCN ? "选取远端全球机器" : Localization.Translate("Select Whole Remote Planet"));
			loadLastText = (isZHCN ? "载入上一个选取" : Localization.Translate("Load Last Selection"));
			resetTimerText = (isZHCN ? "重置计时器" : Localization.Translate("Reset Timer"));
			itemIdProduceText = (isZHCN ? "产物" : Localization.Translate("Product "));
			itemIdConsumeText = (isZHCN ? "原料" : Localization.Translate("Material"));
			itemIdIntermediateText = (isZHCN ? "中间产物" : Localization.Translate("Intermediate"));
			workingOnlyText = (isZHCN ? "工作中" : Localization.Translate("Working"));
			expandedOnlyText = (isZHCN ? "已展开" : Localization.Translate("Expanded"));
			proliferatorCostText = (isZHCN ? "增产剂需求: " : Localization.Translate("Proliferator Cost: "));
			powerCostText = (isZHCN ? "电力需求: " : Localization.Translate("Power Cost: "));
			totalProductionText = (isZHCN ? "总生产: " : Localization.Translate("Total Produce:   "));
			totalConsumptionText = (isZHCN ? "总消耗: " : Localization.Translate("Total Consume: "));
			netMachineText = (isZHCN ? "净机器: " : Localization.Translate("Net Machine: "));
			expandRecordText = (isZHCN ? "检视详情" : Localization.Translate("Detail"));
			recordTooltipText = (isZHCN ? "导航至机器" : Localization.Translate("Navigate to the machine"));
			EntityRecord.InitStrings(isZHCN);
			IsInit = true;
		}
	}
}
namespace RateMonitor.UI
{
	public class OperactionPanel
	{
		private readonly StatTable statTable;

		private Vector2 scrollPosition;

		public bool IsActive { get; set; }

		public OperactionPanel(StatTable statTable)
		{
			this.statTable = statTable;
		}

		public void DrawPanel()
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			GUILayout.BeginVertical(GUI.skin.box, Array.Empty<GUILayoutOption>());
			scrollPosition = GUILayout.BeginScrollView(scrollPosition, Array.Empty<GUILayoutOption>());
			GUILayout.BeginVertical(GUI.skin.box, Array.Empty<GUILayoutOption>());
			GUILayout.Label(SP.planetSelectDescriptionText, Array.Empty<GUILayoutOption>());
			if (GameMain.localPlanet != null)
			{
				PlanetFactory factory = GameMain.localPlanet.factory;
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				if (GUILayout.Button(SP.wholeLocalPlanetText, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.MaxWidth(Utils.LargeButtonWidth) }))
				{
					List<int> list = new List<int>();
					for (int i = 1; i < factory.entityCursor; i++)
					{
						if (SelectionTool.ShouldAddObject(factory, i))
						{
							list.Add(i);
						}
					}
					if (list.Count > 0)
					{
						Plugin.SaveCurrentTable();
						Plugin.CreateMainTable(factory, list);
					}
				}
				GUILayout.Label("entity count: " + (factory.entityCursor - factory.enemyRecycleCursor), Array.Empty<GUILayoutOption>());
				GUILayout.EndHorizontal();
			}
			int num = 0;
			if (((ManualBehaviour)UIRoot.instance.uiGame.statWindow).active)
			{
				num = UIRoot.instance.uiGame.statWindow.astroFilter;
			}
			if (((ManualBehaviour)UIRoot.instance.uiGame.controlPanelWindow).active)
			{
				num = UIRoot.instance.uiGame.controlPanelWindow.filter.astroFilter;
			}
			PlanetData val = GameMain.galaxy.PlanetById(num);
			if (val != null && val.factory != null)
			{
				PlanetFactory factory2 = val.factory;
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				if (GUILayout.Button(SP.wholeRemotePlanetText, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.MaxWidth(Utils.LargeButtonWidth) }))
				{
					List<int> list2 = new List<int>();
					for (int j = 1; j < factory2.entityCursor; j++)
					{
						if (SelectionTool.ShouldAddObject(factory2, j))
						{
							list2.Add(j);
						}
					}
					if (list2.Count > 0)
					{
						Plugin.SaveCurrentTable();
						Plugin.CreateMainTable(factory2, list2);
					}
				}
				GUILayout.Label(val.displayName + ": " + (factory2.entityCursor - factory2.enemyRecycleCursor), Array.Empty<GUILayoutOption>());
				GUILayout.EndHorizontal();
			}
			GUILayout.EndVertical();
			GUILayout.BeginHorizontal(GUI.skin.box, Array.Empty<GUILayoutOption>());
			if (GUILayout.Button(SP.loadLastText, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.MaxWidth(Utils.LargeButtonWidth) }))
			{
				Plugin.LoadLastTable();
			}
			GUILayout.Label(Plugin.LastStatInfo, Array.Empty<GUILayoutOption>());
			GUILayout.EndHorizontal();
			GUILayout.BeginVertical(GUI.skin.box, Array.Empty<GUILayoutOption>());
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			if (GUILayout.Button(SP.resetTimerText, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.MaxWidth(Utils.LargeButtonWidth) }))
			{
				statTable.TotalTick = 0;
				foreach (ProductionProfile profile in statTable.Profiles)
				{
					profile.Reset();
				}
			}
			GUILayout.Label(((float)statTable.TotalTick / 60f).ToString("F2") + "s", Array.Empty<GUILayoutOption>());
			GUILayout.EndHorizontal();
			GUILayout.EndVertical();
			GUILayout.EndScrollView();
			GUILayout.EndVertical();
		}
	}
	public class ProfileEntry
	{
		public readonly ProductionProfile Profile;

		public bool IsExpand { get; set; }

		public bool IsExpandRecords { get; set; }

		public ProfileEntry(ProductionProfile profile)
		{
			Profile = profile;
		}

		public void DrawProfileItem(int index)
		{
			GUILayout.BeginVertical(GUI.skin.box, Array.Empty<GUILayoutOption>());
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			float num = UIWindow.Instance.ProfilePanelWidth - Utils.ShortButtonWidth;
			float num2 = Profile.TotalMachineCount;
			Utils.FocusItemIconButton(Profile.itemIds[index]);
			string text = Utils.RateKMG(Profile.itemRefSpeeds[index] * num2);
			float num3 = Profile.WorkingMachineCount / num2;
			if (ModSettings.ShowRealtimeRate.Value)
			{
				text = ((!ModSettings.ShowWorkingRateInPercentage.Value) ? (text + " (" + Utils.RateKMG(Profile.itemRefSpeeds[index] * Profile.WorkingMachineCount) + ")") : (text + ((num3 > 1f) ? " (100%)" : (" (" + (int)(num3 * 100f) + "%)"))));
			}
			GUILayout.Label(text, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(num / 3f) });
			if (Utils.RecipeExpandButton(Profile.protoId))
			{
				IsExpand = !IsExpand;
			}
			string text2 = "  " + num2;
			if (ModSettings.ShowRealtimeRate.Value)
			{
				text2 = text2 + " (" + Utils.KMG(Profile.WorkingMachineCount) + ")";
			}
			GUILayout.Label(text2, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(num / 3f - 10f) });
			string text3 = Utils.RateKMG(Profile.itemRefSpeeds[index]);
			if (Profile.incUsed)
			{
				text3 += "*";
			}
			GUILayout.Label(" x " + text3, Array.Empty<GUILayoutOption>());
			GUILayout.EndHorizontal();
			if (IsExpand)
			{
				DrawProfileItemDetail(Profile, index);
			}
			GUILayout.EndVertical();
		}

		private void DrawProfileItemDetail(ProductionProfile profile, int index)
		{
			GUILayout.BeginVertical(GUI.skin.box, Array.Empty<GUILayoutOption>());
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			int num = profile.itemIds[index];
			RecipeProto val = ((ProtoSet<RecipeProto>)(object)LDB.recipes).Select(profile.recipeId);
			if (val != null)
			{
				GUILayout.Label(((Proto)val).name, Array.Empty<GUILayoutOption>());
			}
			if (profile.incLevel > 0)
			{
				GUILayout.Label("(" + (profile.accMode ? Localization.Translate("加速生产") : Localization.Translate("额外产出")) + ")", Array.Empty<GUILayoutOption>());
			}
			GUILayout.FlexibleSpace();
			if (ProfilePanel.FocusItmeId != 0 && ProfilePanel.FocusItmeId == num)
			{
				StatTable table = UIWindow.Instance.Table;
				float num2 = table.ItemRefRates[num] / profile.itemRefSpeeds[index];
				float num3 = table.ItemEstRates[num] / profile.itemRefSpeeds[index];
				string text = SP.netMachineText + num2.ToString("0.##");
				if (ModSettings.ShowRealtimeRate.Value)
				{
					text = text + " (" + num3.ToString("0.00") + ")";
				}
				GUILayout.Label(text, Array.Empty<GUILayoutOption>());
			}
			GUILayout.EndHorizontal();
			if (profile.entityRecords.Count > 0)
			{
				GUILayout.BeginVertical(GUI.skin.box, Array.Empty<GUILayoutOption>());
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				GUILayout.Label(profile.GetRecordSummary(), Array.Empty<GUILayoutOption>());
				IsExpandRecords = GUILayout.Toggle(IsExpandRecords, SP.expandRecordText, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(Utils.ShortButtonWidth) });
				GUILayout.EndHorizontal();
				if (IsExpandRecords)
				{
					foreach (EntityRecord entityRecord in profile.entityRecords)
					{
						if (entityRecord.worksate != EntityRecord.EWorkState.Inefficient)
						{
							Utils.EntityRecordButton(entityRecord);
						}
					}
				}
				GUILayout.EndVertical();
			}
			if (profile.materialCount > 0)
			{
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				GUILayout.Label(SP.itemIdConsumeText, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(Utils.RateWidth) });
				for (int i = 0; i < profile.itemRefSpeeds.Count; i++)
				{
					float num4 = profile.itemRefSpeeds[i];
					if (num4 <= 0f)
					{
						Utils.FocusItemIconButton(profile.itemIds[i]);
						string text2 = " " + Utils.RateKMG(num4 * (floa