Decompiled source of VeinityProject v0.2.6

VeinityProject.dll

Decompiled 2 months ago
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text.RegularExpressions;
using System.Threading;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using Eirshy.DSP.VeinityProject.Enums;
using Eirshy.DSP.VeinityProject.Helpers;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("VeinityProject")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("My first plugin")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+0ca40dc22036dab7d8c168fab77e1da3a4afb416")]
[assembly: AssemblyProduct("VeinityProject")]
[assembly: AssemblyTitle("VeinityProject")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace Eirshy.DSP.VeinityProject
{
	internal static class Config
	{
		public const ESourceType OceanSourceType = ESourceType.Infinite;

		public static int Buffer { get; set; }

		public static int WaterPumpVeinCount { get; set; }

		public static bool DisableDampers { get; set; }

		public static ESourceType VeinSourceType { get; set; }

		public static ESourceType OilSourceType { get; set; }

		public static EFiniteSourceConsumptionTarget FiniteSourceTargeting { get; set; }

		public static int DiminishLimit { get; set; }

		public static void Load(ConfigFile cf)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Expected O, but got Unknown
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Expected O, but got Unknown
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Expected O, but got Unknown
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Expected O, but got Unknown
			//IL_019a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: Expected O, but got Unknown
			//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f0: Expected O, but got Unknown
			//IL_0286: Unknown result type (might be due to invalid IL or missing references)
			//IL_0290: Expected O, but got Unknown
			//IL_02dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e7: Expected O, but got Unknown
			Buffer = cf.Bind<int>("VeinityProject", "Buffer", 50, new ConfigDescription("Internal buffer size for Miners, Oil Pumps, and Water Pumps.\nValues below 1 will be treated as 1.", (AcceptableValueBase)null, Array.Empty<object>())).Value;
			if (Buffer < 1)
			{
				Buffer = 1;
			}
			WaterPumpVeinCount = cf.Bind<int>("VeinityProject", "WaterPumpVeinCount", 1, new ConfigDescription("Number of \"veins\" to pretend Water Pumps are harvesting from.\nValues below 1 will be treated as 1.", (AcceptableValueBase)null, Array.Empty<object>())).Value;
			if (WaterPumpVeinCount < 1)
			{
				WaterPumpVeinCount = 1;
			}
			DisableDampers = cf.Bind<bool>("VeinityProject", "DisableDampers", false, new ConfigDescription("If true, we'll ignore the 'output is getting kinda full' damper values.", (AcceptableValueBase)null, Array.Empty<object>())).Value;
			string[] array = (from s in Enum.GetNames(typeof(ESourceType))
				where s != $"{ESourceType._UNSET}"
				select s).ToArray();
			cf.Bind<bool>("VeinityProject.SourceModes", "_OPTIONS", false, new ConfigDescription("Acceptable values for options in this group are one of the following values:\n" + string.Join(", ", array), (AcceptableValueBase)null, Array.Empty<object>()));
			if (Enum.TryParse<ESourceType>(cf.Bind<string>("VeinityProject.SourceModes", "VeinSourceType", $"{ESourceType.FiniteDepleting}", new ConfigDescription("The source depletion type for Ore Veins. Default is the same as Vanilla:\nHarvested at a rate scaled to vein count until fully depleted.", (AcceptableValueBase)(object)new AcceptableValueList<string>(array), Array.Empty<object>())).Value, out var result))
			{
				VeinSourceType = result;
			}
			else
			{
				VeinSourceType = ESourceType.FiniteDepleting;
			}
			if (Enum.TryParse<ESourceType>(cf.Bind<string>("VeinityProject.SourceModes", "OilSourceType", $"{ESourceType.Diminishing}", new ConfigDescription("The source depletion type for Oil Seeps. Default is the same as Vanilla:\nHarvest at a rate scaled to vein richness, reducing it to a limit.\nSee the DiminishLimit setting for more details." + $" Use {ESourceType.InfiniteDiminished} if you want this rate, but without reduction.", (AcceptableValueBase)(object)new AcceptableValueList<string>(array), Array.Empty<object>())).Value, out var result2))
			{
				OilSourceType = result2;
			}
			else
			{
				OilSourceType = ESourceType.Diminishing;
			}
			cf.Bind<string>("VeinityProject.SourceModes", "OceanSourceType", $"{ESourceType.Infinite}", new ConfigDescription("The source depletion type for Oceans. Default is the same as Vanilla:\nHarvest at a rate scaled to the source count (default: 1).\nThis value is currently completely ignored, as there is no tracked 'remaining ocean'.", (AcceptableValueBase)null, Array.Empty<object>()));
			string[] names = Enum.GetNames(typeof(EFiniteSourceConsumptionTarget));
			if (Enum.TryParse<EFiniteSourceConsumptionTarget>(cf.Bind<string>("VeinityProject.SourceModes.Config", "FiniteSourceTargeting", $"{EFiniteSourceConsumptionTarget.Cyclic}", new ConfigDescription($"How {ESourceType.FiniteDepleting} picks the vein to deplete." + $" Default ({EFiniteSourceConsumptionTarget.Cyclic}) is the same as Vanilla:" + "\nIterate over the whole list of veins each tick, depleting whichver is currently selected." + $"\nOther Options: \"{EFiniteSourceConsumptionTarget.Fullest}\" depletes the fullest first," + $" \"{EFiniteSourceConsumptionTarget.Lowest}\" depletes the most empty first.", (AcceptableValueBase)(object)new AcceptableValueList<string>(names), Array.Empty<object>())).Value, out var result3))
			{
				FiniteSourceTargeting = result3;
			}
			else
			{
				FiniteSourceTargeting = EFiniteSourceConsumptionTarget.Cyclic;
			}
			DiminishLimit = cf.Bind<int>("VeinityProject.SourceModes.Config", "DiminishLimit", 2500, new ConfigDescription($"For any {ESourceType.Diminishing}-mode miners, controls how low a vein is allowed to get." + "\n2500 is roughly 0.1/s, with 25000 being roughly 1/s. Keep in mind this is per vein.\nValues below 1 will be treated as 1.", (AcceptableValueBase)null, Array.Empty<object>())).Value;
			if (DiminishLimit < 1)
			{
				DiminishLimit = 1;
			}
		}
	}
	internal static class SmelterMinerCompat
	{
		private const int MapABase = 9446;

		private const int MapBBase = 9447;

		private const int MapCBase = 9448;

		private const int SplitOffset = 20;

		private const int MapOBuilding = 9469;

		public static void SetUpAwake()
		{
			Chainloader.PluginInfos.TryGetValue("Gnimaerd.DSP.plugin.SmelterMiner", out var value);
			if (value != null)
			{
				Type type = ((object)value.Instance).GetType();
				MethodInfo method = typeof(MinerComponent).GetMethod("InternalUpdate");
				MethodInfo method2 = typeof(StationComponent).GetMethod("UpdateVeinCollection");
				if ((object)method != null)
				{
					VeinityProject.Harmony.Unpatch((MethodBase)method, type.GetMethod("InternalUpdatePatch", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic));
				}
				if ((object)method2 != null)
				{
					VeinityProject.Harmony.Unpatch((MethodBase)method2, type.GetMethod("UpdateVeinCollectionPatch", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic));
				}
			}
		}

		public static void SetUpLate()
		{
			//IL_03dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e3: Invalid comparison between Unknown and I4
			//IL_02da: Unknown result type (might be due to invalid IL or missing references)
			Dictionary<EVeinType, int> oreMap = new Dictionary<EVeinType, int>
			{
				{
					(EVeinType)1,
					1001
				},
				{
					(EVeinType)2,
					1002
				},
				{
					(EVeinType)3,
					1003
				},
				{
					(EVeinType)4,
					1004
				},
				{
					(EVeinType)5,
					1005
				},
				{
					(EVeinType)6,
					1006
				},
				{
					(EVeinType)7,
					1007
				},
				{
					(EVeinType)8,
					1011
				},
				{
					(EVeinType)9,
					1012
				},
				{
					(EVeinType)10,
					1013
				},
				{
					(EVeinType)11,
					1117
				},
				{
					(EVeinType)12,
					1014
				},
				{
					(EVeinType)13,
					1015
				},
				{
					(EVeinType)14,
					1016
				}
			};
			Dictionary<EVeinType, int[]> dictionary = new Dictionary<EVeinType, int[]>();
			dictionary.Add((EVeinType)1, new int[3] { 1101, 1102, 0 });
			dictionary.Add((EVeinType)2, new int[3] { 1104, 1104, 0 });
			dictionary.Add((EVeinType)3, new int[3] { 1105, 1105, 0 });
			dictionary.Add((EVeinType)4, new int[3] { 1106, 1106, 0 });
			dictionary.Add((EVeinType)5, new int[3] { 1108, 1110, 0 });
			dictionary.Add((EVeinType)6, new int[3] { 1109, 1109, 0 });
			dictionary.Add((EVeinType)7, new int[3] { 0, 0, 1114 });
			dictionary.Add((EVeinType)8, new int[3] { 0, 0, 1123 });
			dictionary.Add((EVeinType)9, new int[3] { 1112, 1112, 0 });
			dictionary.Add((EVeinType)10, new int[3] { 0, 0, 1113 });
			dictionary.Add((EVeinType)11, new int[3]);
			dictionary.Add((EVeinType)12, new int[3]);
			dictionary.Add((EVeinType)13, new int[3] { 0, 0, 1124 });
			dictionary.Add((EVeinType)14, new int[3]);
			Dictionary<EVeinType, int[]> source = dictionary;
			int[] baseIDMap = new int[3] { 9446, 9447, 9448 };
			IEnumerable<(EVeinType, int, int, int)> enumerable = from vmop in source.SelectMany((KeyValuePair<EVeinType, int[]> kvp) => kvp.Value.Select((int prod, int i) => (kvp.Key, baseIDMap[i], oreMap[kvp.Key], prod)))
				where vmop.prod != 0
				select vmop;
			bool flag = false;
			foreach (var vmop2 in enumerable)
			{
				RecipeProto rec2 = ((IEnumerable<RecipeProto>)((ProtoSet<RecipeProto>)(object)LDB.recipes).dataArray).FirstOrDefault((Func<RecipeProto, bool>)((RecipeProto rec) => rec.Items.Contains(vmop2.Item3) && rec.Results.Contains(vmop2.Item4)));
				if (rec2 == null)
				{
					VeinityProject.Logs.LogWarning((object)$"Missing recipe for vein {vmop2.Item1} => {vmop2.Item4}");
					continue;
				}
				int qtyOre = rec2.ItemCounts.Where((int _, int i) => rec2.Items[i] == vmop2.Item3).First();
				int qtyProduct = rec2.ResultCounts.Where((int _, int i) => rec2.Results[i] == vmop2.Item4).First();
				int per = OreRemap.CalcOre2Product(qtyOre, qtyProduct);
				OreRemap.Register(vmop2.Item2, vmop2.Item3, per, vmop2.Item4);
				OreRemap.Register(vmop2.Item2 + 20, vmop2.Item3, per, vmop2.Item4);
				if ((int)vmop2.Item1 == 7 && vmop2.Item4 == 1114 && !flag)
				{
					OreRemap.Register(9469, vmop2.Item3, per, vmop2.Item4);
					flag = true;
				}
			}
		}

		private static IEnumerable<CodeInstruction> DisableIL_retTrue()
		{
			yield return new CodeInstruction(OpCodes.Ldc_I4_1, (object)null);
			yield return new CodeInstruction(OpCodes.Ret, (object)null);
		}
	}
	internal class VeinityPatcher
	{
		private const int ARBITRARY_LARGE_NUMBER = 500000;

		private static float DiminishingMiningRateModifier { get; set; }

		private static void _transcludedDependencies()
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			PlanetFactory val = null;
			MinerComponent val2 = default(MinerComponent);
			val.AddMiningFlagUnsafe((EVeinType)0);
			val.AddVeinMiningFlagUnsafe((EVeinType)0);
			((MinerComponent)(ref val2)).DetermineState();
			val.factorySystem.GameTickBeforePower(0L, false);
			val.factorySystem.ParallelGameTickBeforePower(0L, false, 0, 0, 0);
			((MinerComponent)(ref val2)).RemoveVeinFromArray(0);
			((MinerComponent)(ref val2)).GetMinimumVeinAmount(val, (VeinData[])null);
		}

		public static void SetUp()
		{
			VeinityProject.Harmony.PatchAll(typeof(VeinityPatcher));
		}

		[HarmonyTranspiler]
		[HarmonyPatch(typeof(StationComponent), "UpdateVeinCollection")]
		private static IEnumerable<CodeInstruction> DisableIL()
		{
			yield return new CodeInstruction(OpCodes.Ret, (object)null);
		}

		private static bool DisableRO()
		{
			return false;
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(GameSave), "LoadCurrentGame", new Type[] { typeof(string) })]
		public static void Precalc()
		{
			DiminishingMiningRateModifier = GameMain.data.gameDesc.resourceMultiplier * 0.40111667f;
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(MinerComponent), "SetPCState")]
		public static void SetPCState(PowerConsumerComponent[] pcPool, ref MinerComponent __instance, ref bool __runOriginal)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Invalid comparison between Unknown and I4
			if (__runOriginal)
			{
				__runOriginal = false;
				_DetermineState_inline(ref __instance);
				((PowerConsumerComponent)(ref pcPool[__instance.pcId])).SetRequiredEnergy(((int)__instance.workstate > 0) ? ((double)(_getupdDamper(ref __instance) * (float)__instance.speed * (float)__instance.speed) / 100000000.0) : 0.0);
			}
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static void _DetermineState_inline(ref MinerComponent __instance)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Expected I4, but got Unknown
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: 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_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			EMinerType type = __instance.type;
			switch ((int)type)
			{
			case 0:
				break;
			case 2:
			case 3:
				if (__instance.veinCount == 0)
				{
					__instance.time = 0;
					__instance.workstate = (EWorkState)0;
				}
				else if (__instance.productCount < Config.Buffer)
				{
					__instance.workstate = (EWorkState)1;
				}
				else
				{
					__instance.workstate = (EWorkState)(-2);
				}
				break;
			case 1:
				if (__instance.productCount < Config.Buffer)
				{
					__instance.workstate = (EWorkState)1;
				}
				else
				{
					__instance.workstate = (EWorkState)(-2);
				}
				break;
			default:
				((MinerComponent)(ref __instance)).DetermineState();
				break;
			}
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static float _getupdDamper(ref MinerComponent __instance)
		{
			if (__instance.productCount >= Config.Buffer)
			{
				__instance.speedDamper = 0f;
			}
			else if (Config.DisableDampers)
			{
				__instance.speedDamper = 1f;
			}
			else if (__instance.productCount > 0)
			{
				float num = 2.47f - 2.45f * ((float)__instance.productCount / 50f);
				num = ((num > 1f) ? 1f : ((num < 0f) ? 0f : num));
				if (__instance.speedDamper == num)
				{
					float num2 = 2.47f - 2.45f * ((float)__instance.productCount / (float)Config.Buffer);
					__instance.speedDamper = ((num2 > 1f) ? 1f : num2);
				}
			}
			return __instance.speedDamper;
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(MinerComponent), "InternalUpdate")]
		public static void InternalUpdate(PlanetFactory factory, VeinData[] veinPool, float power, float miningRate, float miningSpeed, int[] productRegister, ref MinerComponent __instance, ref bool __runOriginal, ref uint __result)
		{
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: 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_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Expected I4, but got Unknown
			//IL_0223: Unknown result type (might be due to invalid IL or missing references)
			//IL_0229: Invalid comparison between Unknown and I4
			//IL_0201: Unknown result type (might be due to invalid IL or missing references)
			//IL_0205: Unknown result type (might be due to invalid IL or missing references)
			//IL_0208: Invalid comparison between Unknown and I4
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: 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_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01db: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_054b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0552: Expected I4, but got Unknown
			//IL_0554: Unknown result type (might be due to invalid IL or missing references)
			//IL_0559: Unknown result type (might be due to invalid IL or missing references)
			//IL_056e: Unknown result type (might be due to invalid IL or missing references)
			if (!__runOriginal)
			{
				return;
			}
			__runOriginal = false;
			__result = 0u;
			if (power < 0.1f)
			{
				return;
			}
			int veinCount = -1;
			if (__instance.productCount < Config.Buffer || __instance.time < __instance.period)
			{
				veinCount = 0;
				int veinAmountTotal = 0;
				int num = int.MaxValue;
				int num2 = int.MinValue;
				int num3 = -1;
				int num4 = -1;
				EVeinType addVeinType = (EVeinType)0;
				ESourceType source = ESourceType._UNSET;
				int num5 = 0;
				EMinerType type = __instance.type;
				switch ((int)type)
				{
				default:
					__runOriginal = true;
					return;
				case 0:
					return;
				case 1:
					veinCount = ((__instance.veinCount == 0) ? Config.WaterPumpVeinCount : __instance.veinCount);
					source = ESourceType.Infinite;
					num5 = factory.planet.waterItemId;
					break;
				case 3:
					source = Config.OilSourceType;
					goto case 2;
				case 2:
				{
					int veinCount2 = __instance.veinCount;
					if (veinCount2 >= 0)
					{
						switch (veinCount2)
						{
						case 1:
						{
							int num6 = __instance.veins[0];
							if (num6 > 0)
							{
								int amount2 = veinPool[num6].amount;
								EVeinType type3 = veinPool[num6].type;
								int productId2 = veinPool[num6].productId;
								if (veinPool[num6].id == num6 && amount2 > 0)
								{
									veinCount = 1;
									veinAmountTotal = amount2;
									num = amount2;
									num2 = amount2;
									num3 = num6;
									num4 = num6;
									addVeinType = type3;
									num5 = productId2;
								}
								else
								{
									__instance.veins[0] = 0;
								}
							}
							break;
						}
						default:
						{
							int veinCount3 = __instance.veinCount;
							while (veinCount3-- > 0)
							{
								int num6 = __instance.veins[veinCount3];
								if (num6 <= 0)
								{
									continue;
								}
								int amount = veinPool[num6].amount;
								EVeinType type2 = veinPool[num6].type;
								int productId = veinPool[num6].productId;
								if (veinPool[num6].id == num6 && amount > 0)
								{
									veinCount++;
									veinAmountTotal += amount;
									if (amount < num)
									{
										num3 = num6;
										num = amount;
									}
									if (amount > num2)
									{
										num4 = num6;
										num2 = amount;
									}
									addVeinType = type2;
									num5 = productId;
								}
								else
								{
									__instance.veins[veinCount3] = 0;
								}
							}
							break;
						}
						case 0:
							break;
						}
					}
					if (source == ESourceType._UNSET)
					{
						source = (((int)addVeinType == 0) ? ESourceType.Infinite : (((int)addVeinType != 7) ? Config.VeinSourceType : Config.OilSourceType));
					}
					if ((int)__instance.type != 2)
					{
						break;
					}
					switch (source)
					{
					case ESourceType.FiniteDepleting:
						if (Config.FiniteSourceTargeting == EFiniteSourceConsumptionTarget.Fullest)
						{
							__instance.minimumVeinAmount = ((num4 != -1) ? num2 : 0);
						}
						else
						{
							__instance.minimumVeinAmount = ((num3 != -1) ? num : 0);
						}
						break;
					case ESourceType.Diminishing:
						__instance.minimumVeinAmount = ((veinCount > 0) ? (veinAmountTotal / veinCount) : 0);
						break;
					case ESourceType.Infinite:
						__instance.minimumVeinAmount = ((__instance.veinCount > 0) ? 500000 : 0);
						break;
					default:
						__instance.minimumVeinAmount = ((num3 != -1) ? num : 0);
						break;
					}
					break;
				}
				}
				if (veinCount > 0)
				{
					if (__instance.time <= __instance.period)
					{
						__instance.time += (int)GetSingleTickTime_inline(in source, in veinCount, in veinAmountTotal, in __instance.speed, in miningSpeed, in power, in __instance.speedDamper);
						__result = 1u;
					}
					if (__instance.time >= __instance.period && __instance.productCount < Config.Buffer && num5 > 0)
					{
						int num7 = __instance.time / __instance.period;
						__instance.productId = num5;
						switch (source)
						{
						case ESourceType.Infinite:
						case ESourceType.InfiniteDiminished:
							__instance.productCount += num7;
							Interlocked.Add(ref productRegister[num5], num7);
							__instance.time -= __instance.period * num7;
							break;
						case ESourceType.FiniteDepleting:
						{
							int num6;
							switch (Config.FiniteSourceTargeting)
							{
							default:
								throw new NotImplementedException();
							case EFiniteSourceConsumptionTarget.Cyclic:
							{
								int num10 = __instance.currentVeinIndex % __instance.veinCount;
								num6 = __instance.veins[num10];
								int veinCount4 = __instance.veinCount;
								while (veinCount4-- > 0)
								{
									num10 = (num10 + 1) % __instance.veinCount;
									if (num6 > 0)
									{
										break;
									}
									num6 = __instance.veins[num10];
								}
								__instance.currentVeinIndex = num10;
								break;
							}
							case EFiniteSourceConsumptionTarget.Lowest:
								__instance.currentVeinIndex = 0;
								num6 = num3;
								break;
							case EFiniteSourceConsumptionTarget.Fullest:
								__instance.currentVeinIndex = 0;
								num6 = num4;
								break;
							}
							ref VeinData reference2 = ref veinPool[num6];
							if (reference2.amount <= 0)
							{
								break;
							}
							int realized = 0;
							if (miningRate <= 0f)
							{
								realized = num7;
							}
							else
							{
								int consume = 0;
								if (miningRate < 0.99999f)
								{
									uint curSeed2 = __instance.seed;
									int num11 = num7;
									while (num11-- > 0)
									{
										if (_iu_cycleSeed_inline(ref curSeed2, in miningRate))
										{
											if (_iu_tryConsume_inline(ref reference2, ref realized, ref consume))
											{
												break;
											}
										}
										else
										{
											realized++;
										}
									}
									__instance.seed = curSeed2;
								}
								else
								{
									int num12 = num7;
									while (num12-- > 0 && !_iu_tryConsume_inline(ref reference2, ref realized, ref consume))
									{
									}
								}
								if (consume > 0)
								{
									int groupIndex = reference2.groupIndex;
									long num13 = Interlocked.Add(ref factory.veinGroups[groupIndex].amount, -consume);
									ref AnimData anim2 = ref factory.veinAnimPool[num6];
									float newTime = ((reference2.amount >= 20000) ? 0f : (1f - (float)reference2.amount * 5E-05f));
									_safeVeinAnim_largest_inline(ref anim2, in newTime);
									if (num13 <= 0)
									{
										lock (veinPool)
										{
											if (reference2.id == num6)
											{
												int num14 = (int)reference2.type;
												Vector3 pos = reference2.pos;
												factory.RemoveVeinWithComponents(num6);
												factory.RecalculateVeinGroup(groupIndex);
												factory.NotifyVeinExhausted(num14, pos);
											}
										}
									}
								}
							}
							__instance.productCount += realized;
							Interlocked.Add(ref productRegister[__instance.productId], realized);
							_safeAddFlagsToFactory_inline(ref factory, in addVeinType);
							__instance.time -= __instance.period * realized;
							break;
						}
						case ESourceType.Diminishing:
						{
							float miningRate2 = miningRate * DiminishingMiningRateModifier;
							if (miningRate2 > 0f && num2 > Config.DiminishLimit)
							{
								int reduceBy = 0;
								uint curSeed = __instance.seed;
								int num8 = num7;
								while (num8-- > 0)
								{
									if (_iu_cycleSeed_inline(ref curSeed, in miningRate2))
									{
										reduceBy++;
									}
								}
								__instance.seed = curSeed;
								if (reduceBy > 0)
								{
									int num6 = num4;
									ref VeinData reference = ref veinPool[num6];
									int veinCount2 = Config.DiminishLimit;
									int num9 = _iu_tryConsumeBulk_inline(ref reference, in reduceBy, in veinCount2);
									if (num9 > 0)
									{
										_ = ref factory.veinGroups[reference.groupIndex];
										Interlocked.Add(ref factory.veinGroups[reference.groupIndex].amount, -num9);
									}
									int amount3 = reference.amount;
									ref AnimData anim = ref factory.veinAnimPool[num6];
									float newTime = ((amount3 >= 25000) ? 0f : (1f - (float)amount3 * VeinData.oilSpeedMultiplier));
									_safeVeinAnim_largest_inline(ref anim, in newTime);
								}
							}
							__instance.productCount += num7;
							Interlocked.Add(ref productRegister[num5], num7);
							__instance.time -= __instance.period * num7;
							break;
						}
						}
					}
				}
			}
			_iu_export_inline(ref __instance, ref factory, ref productRegister);
			_iu_prune_inline(ref __instance, in veinCount);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static float GetSingleTickTime_inline(in ESourceType source, in int veinCount, in int veinAmountTotal, in int speed, in float miningSpeed, in float power, in float speedDamper)
		{
			switch (source)
			{
			default:
				throw new NotImplementedException();
			case ESourceType.Infinite:
			case ESourceType.FiniteDepleting:
				return power * (float)speed * speedDamper * miningSpeed * (float)veinCount;
			case ESourceType.InfiniteDiminished:
			case ESourceType.Diminishing:
				return power * (float)speed * speedDamper * miningSpeed * (float)veinAmountTotal * VeinData.oilSpeedMultiplier + (float)veinCount * 0.5f;
			}
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private static bool _iu_cycleSeed_inline(ref uint curSeed, in float miningRate)
		{
			curSeed = (uint)((int)((ulong)((long)(curSeed % 2147483646 + 1) * 48271L) % 2147483647uL) - 1);
			return (double)curSeed / 2147483646.0 < (double)miningRate;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private static bool _iu_tryConsume_inline(ref VeinData vtarg, ref int realized, ref int consume)
		{
			int num = Interlocked.Decrement(ref vtarg.amount);
			if (num >= 0)
			{
				if (num == 0)
				{
					realized++;
					consume++;
					return true;
				}
				realized++;
				consume++;
				return false;
			}
			return true;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private static int _iu_tryConsumeBulk_inline(ref VeinData vd, in int reduceBy, in int minRemaining)
		{
			int amount;
			int num;
			do
			{
				amount = vd.amount;
				if (amount <= minRemaining)
				{
					return 0;
				}
				num = amount - reduceBy;
				if (num < minRemaining)
				{
					num = minRemaining;
				}
			}
			while (Interlocked.CompareExchange(ref vd.amount, num, amount) != amount);
			return amount - num;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private static void _iu_export_inline(ref MinerComponent mc, ref PlanetFactory factory, ref int[] prodReg)
		{
			if (mc.productCount <= 0)
			{
				return;
			}
			if (mc.insertTarget > 0)
			{
				byte b2 = default(byte);
				if (OreRemap.HasRemap)
				{
					OreRemap oreRemap = OreRemap.Get(factory.entityPool[mc.entityId].protoId, mc.productId);
					byte b;
					if (oreRemap.IsDefault)
					{
						b = (byte)((mc.productCount < 4) ? ((uint)mc.productCount) : 4u);
						int num = factory.InsertInto(mc.insertTarget, 0, mc.productId, b, (byte)0, ref b2);
						mc.productCount -= num;
						return;
					}
					int num2 = oreRemap.Ore2Prod(mc.productCount);
					b = (byte)((num2 < 4) ? ((uint)num2) : 4u);
					if (b > 0)
					{
						int[] consumeRegister = GameMain.statistics.production.factoryStatPool[factory.index].consumeRegister;
						int num = factory.InsertInto(mc.insertTarget, 0, oreRemap.ProductID, b, (byte)0, ref b2);
						int num3 = oreRemap.Prod2Ore(num);
						mc.productCount -= num3;
						Interlocked.Add(ref consumeRegister[mc.productId], num3);
						Interlocked.Add(ref prodReg[oreRemap.ProductID], num);
					}
				}
				else
				{
					byte b = (byte)((mc.productCount < 4) ? ((uint)mc.productCount) : 4u);
					int num = factory.InsertInto(mc.insertTarget, 0, mc.productId, b, (byte)0, ref b2);
					mc.productCount -= num;
				}
				return;
			}
			ref EntityData reference = ref factory.entityPool[mc.entityId];
			if (reference.stationId <= 0)
			{
				return;
			}
			ref StationStore reference2 = ref factory.transport.stationPool[reference.stationId].storage[0];
			int num4 = reference2.max - reference2.count;
			if (num4 <= 0)
			{
				return;
			}
			if (OreRemap.HasRemap)
			{
				OreRemap oreRemap2 = OreRemap.Get(reference.protoId, mc.productId);
				int num;
				if (oreRemap2.IsDefault)
				{
					num = ((mc.productCount > num4) ? num4 : mc.productCount);
					mc.productCount -= num;
					Interlocked.Add(ref reference2.count, num);
					reference2.itemId = mc.productId;
					return;
				}
				int[] consumeRegister2 = GameMain.statistics.production.factoryStatPool[factory.index].consumeRegister;
				int num5 = oreRemap2.Ore2Prod(mc.productCount);
				num = ((num5 > num4) ? num4 : num5);
				int num6 = oreRemap2.Prod2Ore(num);
				mc.productCount -= num6;
				Interlocked.Add(ref reference2.count, num);
				Interlocked.Add(ref consumeRegister2[mc.productId], num6);
				Interlocked.Add(ref prodReg[oreRemap2.ProductID], num);
				reference2.itemId = oreRemap2.ProductID;
			}
			else
			{
				int num = ((mc.productCount > num4) ? num4 : mc.productCount);
				mc.productCount -= num;
				Interlocked.Add(ref reference2.count, num);
				reference2.itemId = mc.productId;
			}
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private static void _iu_prune_inline(ref MinerComponent mc, in int vcnt)
		{
			if (vcnt >= mc.veinCount || vcnt < 0)
			{
				return;
			}
			if (vcnt == 0)
			{
				Array.Clear(mc.veins, 0, mc.veins.Length);
				mc.veinCount = 0;
				return;
			}
			int veinCount = mc.veinCount;
			while (veinCount-- > 0)
			{
				if (mc.veins[veinCount] == 0)
				{
					for (int i = veinCount + 1; i < mc.veinCount; i++)
					{
						mc.veins[i - 1] = mc.veins[i];
					}
					mc.veinCount--;
				}
			}
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private static void _safeVeinAnim_largest_inline(ref AnimData anim, in float newTime)
		{
			float time;
			do
			{
				time = anim.time;
			}
			while (!(time >= newTime) && Interlocked.CompareExchange(ref anim.time, newTime, time) != time);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private static void _safeAddFlagsToFactory_inline(ref PlanetFactory factory, in EVeinType addVeinType)
		{
			int num = 1 << (int)addVeinType;
			int miningFlag;
			do
			{
				miningFlag = factory._miningFlag;
			}
			while ((miningFlag & num) != num && Interlocked.CompareExchange(ref factory._miningFlag, miningFlag | num, miningFlag) != miningFlag);
			do
			{
				miningFlag = factory._veinMiningFlag;
			}
			while ((miningFlag & num) != num && Interlocked.CompareExchange(ref factory._veinMiningFlag, miningFlag | num, miningFlag) != miningFlag);
		}
	}
	[BepInPlugin("eirshy.dsp.VeinityProject", "VeinityProject", "0.2.6")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class VeinityProject : BaseUnityPlugin
	{
		public const string MODID = "VeinityProject";

		public const string ROOT = "eirshy.dsp.";

		public const string GUID = "eirshy.dsp.VeinityProject";

		public const string VERSION = "0.2.6";

		public const string NAME = "VeinityProject";

		internal const string GUID_SmelterMiner = "Gnimaerd.DSP.plugin.SmelterMiner";

		private static readonly Lazy<Harmony> _harmony = new Lazy<Harmony>((Func<Harmony>)(() => new Harmony("eirshy.dsp.VeinityProject")));

		private static bool hasLoaded = false;

		internal static Harmony Harmony => _harmony.Value;

		internal static ManualLogSource Logs { get; private set; }

		private void Awake()
		{
			Logs = ((BaseUnityPlugin)this).Logger;
			((BaseUnityPlugin)this).Logger.LogMessage((object)"VeinityProject powdering up!");
			Config.Load(((BaseUnityPlugin)this).Config);
			SmelterMinerCompat.SetUpAwake();
			VeinityPatcher.SetUp();
			Harmony.PatchAll(typeof(VeinityProject));
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(VFPreload), "InvokeOnLoadWorkEnded")]
		public static void SetupLate()
		{
			if (!hasLoaded)
			{
				SmelterMinerCompat.SetUpLate();
				OreRemap.Bake();
				hasLoaded = true;
			}
		}
	}
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "VeinityProject";

		public const string PLUGIN_NAME = "VeinityProject";

		public const string PLUGIN_VERSION = "1.0.0";
	}
}
namespace Eirshy.DSP.VeinityProject.Helpers
{
	internal struct OreRemap
	{
		private const int PER_OUTOF = 60;

		private const int SUBKEY_ANY = 65535;

		public readonly int MinerID;

		public readonly int OreID;

		public readonly int Per;

		public readonly int ProductID;

		private static readonly Regex _deser = new Regex("^(\\d+)m:(\\d+)x(\\d+)=>(\\d+)x\\d+$");

		private static ConcurrentDictionary<int, OreRemap> _register = new ConcurrentDictionary<int, OreRemap>();

		private static Dictionary<int, OreRemap> _baked = null;

		public static bool HasRemap { get; private set; }

		public int Key => KeyFrom(MinerID, OreID);

		public bool IsDefault => ProductID == 0;

		public int Ore2Prod(int ore)
		{
			return ore * 60 / Per;
		}

		public int Prod2Ore(int product)
		{
			return product * Per / 60;
		}

		internal static int CalcOre2Product(int qtyOre, int qtyProduct)
		{
			return qtyOre * 60 / qtyProduct;
		}

		public OreRemap(int mid, int oid, int per, int prod)
		{
			MinerID = mid & 0xFFFF;
			OreID = oid & 0xFFFF;
			Per = per;
			ProductID = prod;
		}

		private OreRemap(bool ignored)
		{
			MinerID = 65535;
			OreID = 65535;
			Per = 60;
			ProductID = 0;
		}

		public string Serialize()
		{
			return $"{MinerID}m:{OreID}x{Per}=>{ProductID}x{60}";
		}

		public static string Serialize(OreRemap[] from)
		{
			return string.Join(" ", from.Select((OreRemap rm) => rm.Serialize()));
		}

		public static OreRemap[] Deserialize(string from)
		{
			return (from s in new Regex("[ .;,|-]+").Split(@from.Trim().ToLower())
				select _deser.Match(s) into m
				where m.Success
				select new OreRemap(int.Parse(m.Groups[1].Value), int.Parse(m.Groups[2].Value), int.Parse(m.Groups[3].Value), int.Parse(m.Groups[4].Value))).ToArray();
		}

		private static int KeyFrom(int MinerID, int OreID)
		{
			return (MinerID << 16) | OreID;
		}

		internal static void Register(int mid, int oid, int per, int prod)
		{
			if (_baked != null)
			{
				throw new InvalidOperationException("Remap has already been baked!");
			}
			HasRemap = true;
			OreRemap value = new OreRemap(mid, oid, per, prod);
			_register[value.Key] = value;
		}

		public static void Bake()
		{
			List<KeyValuePair<int, OreRemap>> list = _register.ToList();
			_baked = new Dictionary<int, OreRemap>(list.Count);
			foreach (KeyValuePair<int, OreRemap> item in list)
			{
				_baked.Add(item.Key, item.Value);
				VeinityProject.Logs.LogMessage((object)("Baked: " + item.Value.Serialize()));
			}
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		internal static OreRemap Get(int MinerID, int OreID)
		{
			int key = KeyFrom(MinerID, OreID);
			if (_baked.ContainsKey(key))
			{
				return _baked[key];
			}
			return default(OreRemap);
		}
	}
}
namespace Eirshy.DSP.VeinityProject.Enums
{
	internal enum EFiniteSourceConsumptionTarget
	{
		Cyclic,
		Lowest,
		Fullest
	}
	internal enum ESourceType
	{
		_UNSET,
		Infinite,
		InfiniteDiminished,
		Diminishing,
		FiniteDepleting
	}
}