Decompiled source of HardFog v0.0.24

HardFog.dll

Decompiled 3 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using UXAssist.Common;
using UXAssist.UI;
using UnityEngine;
using UnityEngine.Events;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("HardFog")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("HardFog")]
[assembly: AssemblyCopyright("Copyright ©  2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("8cf264f1-e863-4eaf-b956-c8330da40ba6")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace HardFog;

[BepInPlugin("me.liantian.plugin.HardFog", "HardFog", "0.0.24")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class HardFogWindow : BaseUnityPlugin
{
	private const string WindowTitleKey = "hard_fog_control";

	private const string ClearCurrentPlanetKey = "clear_current_planet";

	private const string ClearCurrentStarKey = "clear_current_star";

	private const string FillGalaxyHivesKey = "fill_hive";

	private const string SuperThreatReducerHiveKey = "super-threat-reducer-hive-enabled";

	private const string SuperThreatReducerGroundKey = "super-threat-reducer-ground-enabled";

	private const string SmartRelayDispatchKey = "smart-relay-dispatch-enabled";

	private const string FasterRelayLaunchKey = "faster-relay-launch-enabled";

	private const string FasterResearchKey = "faster-research-enabled";

	private const string BuildAnywhereOnWaterKey = "build-anywhere-on-water-enabled";

	private const string VeinPlacementKey = "vein-placement-enabled";

	private const string OverpoweredMechaFightersKey = "overpowered-mecha-fighters-enabled";

	private const string ConstructLowLatitudeRuinsKey = "surface-ruins-construct-low-latitude";

	private const string ConstructMidLatitudeRuinsKey = "surface-ruins-construct-mid-latitude";

	private const string ConstructHighLatitudeRuinsKey = "surface-ruins-construct-high-latitude";

	private const string BuildGeothermalOnIdleRuinsKey = "surface-ruins-build-geothermal-on-idle-ruins";

	private static UIButton clearCurrentPlanetButton;

	private static UIButton clearCurrentStarButton;

	private static UIButton fillGalaxyHivesButton;

	private static UIButton constructLowLatitudeRuinsButton;

	private static UIButton constructMidLatitudeRuinsButton;

	private static UIButton constructHighLatitudeRuinsButton;

	private static UIButton buildGeothermalOnIdleRuinsButton;

	internal static ManualLogSource Log;

	public void Awake()
	{
		Log = ((BaseUnityPlugin)this).Logger;
		DarkFogControl.Log = ((BaseUnityPlugin)this).Logger;
		SurfaceRuinControl.Log = ((BaseUnityPlugin)this).Logger;
		SuperThreatReducerControl.Init(((BaseUnityPlugin)this).Config.Bind<bool>("DarkFog", "SuperThreatReducerHiveEnabled", false, "Enable Space Hive Suppression. Zeros space hive threat and skips assault scans."), ((BaseUnityPlugin)this).Config.Bind<bool>("DarkFog", "SuperThreatReducerGroundEnabled", false, "Enable Ground Base Suppression. Skips ground base threat accumulation and assault scans."), ((BaseUnityPlugin)this).Logger);
		RelayControl.Init(((BaseUnityPlugin)this).Config.Bind<bool>("DarkFog", "FasterRelayLaunchEnabled", false, "Enable faster relay station launch. Checks every 120 hive ticks and dispatches one idle relay when none is already outbound."), ((BaseUnityPlugin)this).Config.Bind<bool>("DarkFog", "SmartRelayDispatchEnabled", false, "Only applies when faster relay station launch is enabled. Dispatch relay stations only to markers."), ((BaseUnityPlugin)this).Logger);
		FasterResearchControl.Init(((BaseUnityPlugin)this).Config.Bind<bool>("HardFog", "FasterResearchEnabled", false, "Enable research speed multiplier. Reduces tech hash needed to about 1/36."), ((BaseUnityPlugin)this).Logger);
		BuildAnywhereOnWaterControl.Init(((BaseUnityPlugin)this).Config.Bind<bool>("HardFog", "BuildAnywhereOnWaterEnabled", true, "Enable ignoring missing ground support build failures, including water placement."), ((BaseUnityPlugin)this).Logger);
		VeinPlacementControl.Init(((BaseUnityPlugin)this).Config.Bind<bool>("HardFog", "VeinPlacementEnabled", true, "Enable better vein placement for future planet vein generation."), ((BaseUnityPlugin)this).Logger);
		OverpoweredMechaFightersControl.Init(((BaseUnityPlugin)this).Config.Bind<bool>("HardFog", "OverpoweredMechaFightersEnabled", false, "Enable stronger mecha fighters: 10x range, 10x damage, and invincibility."), ((BaseUnityPlugin)this).Logger);
		I18N.Add("hard_fog_control", "Dark Fog Control", "黑雾操控");
		I18N.Add("clear_current_planet", "Clear Dark Fog ground bases on current planet", "清理当前星球的地面黑雾基地");
		I18N.Add("clear_current_star", "Clear space Dark Fog hives in current star system", "清理当前恒星的太空黑雾巢穴");
		I18N.Add("fill_hive", "Fill the galaxy with Dark Fog hives", "为整个星系填满黑雾巢穴");
		I18N.Add("super-threat-reducer-hive-enabled", "Space Hive Suppression", "太空巢穴降压");
		I18N.Add("super-threat-reducer-ground-enabled", "Ground Base Suppression", "地面基地降压");
		I18N.Add("smart-relay-dispatch-enabled", "Relay stations only dispatch to markers", "中继站只发往信标");
		I18N.Add("faster-relay-launch-enabled", "Launch relay stations faster", "更快的发射中继站");
		I18N.Add("faster-research-enabled", "Research Speed Multiplier", "研究倍速器");
		I18N.Add("vein-placement-enabled", "Better vein placement", "更好的矿物位置");
		I18N.Add("overpowered-mecha-fighters-enabled", "Fighters fly farther", "战斗机更远的飞行距离");
		I18N.Add("surface-ruins-construct-low-latitude", "Construct low-latitude ruins", "构造低纬度废墟");
		I18N.Add("surface-ruins-construct-mid-latitude", "Construct mid-latitude ruins", "构造中纬度废墟");
		I18N.Add("surface-ruins-construct-high-latitude", "Construct high-latitude ruins", "构造高纬度废墟");
		I18N.Add("surface-ruins-build-geothermal-on-idle-ruins", "Build geothermal power stations on idle ruins", "在空闲废墟上建造地热发电站");
		I18N.Add("build-anywhere-on-water-enabled", "Ignore ground support requirement", "无需地基支撑建造");
		I18N.Apply();
		MyConfigWindow.OnUICreated = (Action<MyConfigWindow, RectTransform>)Delegate.Combine(MyConfigWindow.OnUICreated, new Action<MyConfigWindow, RectTransform>(CreateUI));
		Log.LogInfo((object)"HardFog 初始化");
	}

	public void OnDestroy()
	{
		MyConfigWindow.OnUICreated = (Action<MyConfigWindow, RectTransform>)Delegate.Remove(MyConfigWindow.OnUICreated, new Action<MyConfigWindow, RectTransform>(CreateUI));
		SuperThreatReducerControl.Uninit();
		RelayControl.Uninit();
		FasterResearchControl.Uninit();
		BuildAnywhereOnWaterControl.Uninit();
		VeinPlacementControl.Uninit();
		OverpoweredMechaFightersControl.Uninit();
	}

	private static void CreateUI(MyConfigWindow wnd, RectTransform trans)
	{
		//IL_0199: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a3: Expected O, but got Unknown
		//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01da: Expected O, but got Unknown
		//IL_0207: Unknown result type (might be due to invalid IL or missing references)
		//IL_0211: Expected O, but got Unknown
		//IL_023e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0248: Expected O, but got Unknown
		//IL_0275: Unknown result type (might be due to invalid IL or missing references)
		//IL_027f: Expected O, but got Unknown
		//IL_02ac: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b6: Expected O, but got Unknown
		float num = 10f;
		((MyWindowWithTabs)wnd).AddSplitter(trans, 10f);
		((MyWindowWithTabs)wnd).AddTabGroup(trans, "hard_fog_control", "tab-group-hard-fog");
		RectTransform val = ((MyWindowWithTabs)wnd).AddTab(trans, "hard_fog_control");
		((MyWindow)wnd).AddCheckBox(10f, num, val, SuperThreatReducerControl.EnabledConfigHive, "super-threat-reducer-hive-enabled", 16);
		num += 36f;
		((MyWindow)wnd).AddCheckBox(10f, num, val, SuperThreatReducerControl.EnabledConfigGround, "super-threat-reducer-ground-enabled", 16);
		num += 36f;
		((MyWindow)wnd).AddCheckBox(10f, num, val, RelayControl.FasterRelayLaunchEnabledConfig, "faster-relay-launch-enabled", 16);
		num += 36f;
		MyCheckBox smartRelayDispatchCheckBox = ((MyWindow)wnd).AddCheckBox(30f, num, val, RelayControl.SmartRelayDispatchEnabledConfig, "smart-relay-dispatch-enabled", 13);
		RelayControl.FasterRelayLaunchEnabledConfig.SettingChanged += RelayOptionChanged;
		((MyWindow)wnd).OnFree += delegate
		{
			RelayControl.FasterRelayLaunchEnabledConfig.SettingChanged -= RelayOptionChanged;
		};
		RelayOptionChanged(null, null);
		num += 36f;
		((MyWindow)wnd).AddCheckBox(10f, num, val, FasterResearchControl.EnabledConfig, "faster-research-enabled", 16);
		num += 36f;
		((MyWindow)wnd).AddCheckBox(10f, num, val, BuildAnywhereOnWaterControl.EnabledConfig, "build-anywhere-on-water-enabled", 16);
		num += 36f;
		((MyWindow)wnd).AddCheckBox(10f, num, val, VeinPlacementControl.EnabledConfig, "vein-placement-enabled", 16);
		num += 36f;
		((MyWindow)wnd).AddCheckBox(10f, num, val, OverpoweredMechaFightersControl.EnabledConfig, "overpowered-mecha-fighters-enabled", 16);
		num = 10f;
		clearCurrentPlanetButton = ((MyWindow)wnd).AddButton(400f, num, 240f, val, "clear_current_planet", 16, "button-clear-current-planet-dark-fog", new UnityAction(OnClearCurrentPlanetClicked));
		num += 36f;
		clearCurrentStarButton = ((MyWindow)wnd).AddButton(400f, num, 240f, val, "clear_current_star", 16, "button-clear-current-star-dark-fog", new UnityAction(OnClearCurrentStarClicked));
		num += 36f;
		fillGalaxyHivesButton = ((MyWindow)wnd).AddButton(400f, num, 240f, val, "fill_hive", 16, "button-fill-galaxy-dark-fog-hives", new UnityAction(OnFillGalaxyHivesClicked));
		num += 36f;
		constructLowLatitudeRuinsButton = ((MyWindow)wnd).AddButton(400f, num, 260f, val, "surface-ruins-construct-low-latitude", 16, "button-surface-ruins-construct-low-latitude", new UnityAction(OnConstructLowLatitudeRuinsClicked));
		num += 36f;
		constructMidLatitudeRuinsButton = ((MyWindow)wnd).AddButton(400f, num, 260f, val, "surface-ruins-construct-mid-latitude", 16, "button-surface-ruins-construct-mid-latitude", new UnityAction(OnConstructMidLatitudeRuinsClicked));
		num += 36f;
		constructHighLatitudeRuinsButton = ((MyWindow)wnd).AddButton(400f, num, 260f, val, "surface-ruins-construct-high-latitude", 16, "button-surface-ruins-construct-high-latitude", new UnityAction(OnConstructHighLatitudeRuinsClicked));
		void RelayOptionChanged(object sender, EventArgs args)
		{
			smartRelayDispatchCheckBox.SetEnable(RelayControl.FasterRelayLaunchEnabledConfig.Value);
		}
	}

	private static void OnClearCurrentPlanetClicked()
	{
		RunWithButtonDisabled(clearCurrentPlanetButton, DarkFogControl.ClearCurrentPlanetDarkFog);
	}

	private static void OnClearCurrentStarClicked()
	{
		RunWithButtonDisabled(clearCurrentStarButton, DarkFogControl.ClearCurrentStarSpaceDarkFog);
	}

	private static void OnFillGalaxyHivesClicked()
	{
		RunWithButtonDisabled(fillGalaxyHivesButton, DarkFogControl.FillGalaxyWithDarkFogHives);
	}

	private static void OnConstructLowLatitudeRuinsClicked()
	{
		RunWithButtonDisabled(constructLowLatitudeRuinsButton, SurfaceRuinControl.ConstructLowLatitudeRuinsOnCurrentPlanet);
	}

	private static void OnConstructMidLatitudeRuinsClicked()
	{
		RunWithButtonDisabled(constructMidLatitudeRuinsButton, SurfaceRuinControl.ConstructMidLatitudeRuinsOnCurrentPlanet);
	}

	private static void OnConstructHighLatitudeRuinsClicked()
	{
		RunWithButtonDisabled(constructHighLatitudeRuinsButton, SurfaceRuinControl.ConstructHighLatitudeRuinsOnCurrentPlanet);
	}

	private static void OnBuildGeothermalOnIdleRuinsClicked()
	{
		RunWithButtonDisabled(buildGeothermalOnIdleRuinsButton, SurfaceRuinControl.BuildGeothermalOnIdleRuinsCurrentPlanet);
	}

	private static void RunWithButtonDisabled(UIButton button, Action action)
	{
		if ((Object)(object)button != (Object)null)
		{
			((Behaviour)button).enabled = false;
		}
		try
		{
			action();
		}
		finally
		{
			if ((Object)(object)button != (Object)null)
			{
				((Behaviour)button).enabled = true;
			}
		}
	}
}
internal static class DarkFogControl
{
	private struct EnemyModelRef
	{
		public int ModelIndex;

		public int ModelId;
	}

	internal static ManualLogSource Log;

	internal static void ClearCurrentPlanetDarkFog()
	{
		SaveCurrentGame();
		if (GameMain.mainPlayer != null)
		{
			PlanetData localPlanet = GameMain.localPlanet;
			if (localPlanet != null)
			{
				ClearPlanetDarkFog(localPlanet);
			}
		}
	}

	private static void ClearPlanetDarkFog(PlanetData planet)
	{
		LogInfo("planet.name: " + planet.name);
		LogInfo("astroId: " + planet.astroId);
		PlanetFactory orCreateFactory = GameMain.data.GetOrCreateFactory(planet);
		if (orCreateFactory?.enemySystem?.bases != null)
		{
			ObjectPool<DFGBaseComponent> bases = orCreateFactory.enemySystem.bases;
			List<int> list = CollectGroundBaseIdsDescending(bases);
			if (list.Count <= 0)
			{
				ClearDarkFogAssaultTips();
				return;
			}
			HashSet<int> baseIds = new HashSet<int>(list);
			List<EnemyModelRef> removedModels = new List<EnemyModelRef>();
			ClearGroundUnits(orCreateFactory, baseIds, removedModels);
			ClearGroundBaseFormations(orCreateFactory, list);
			ClearGroundNonCoreBuildings(orCreateFactory, list, removedModels);
			ClearGroundBaseCores(orCreateFactory, list, removedModels);
			ReturnRelaysForGroundBases(planet, baseIds);
			UnlinkGroundBaseRuins(orCreateFactory, bases, list);
			ClearLocalDarkFogRenderResidue(planet, orCreateFactory, list, removedModels);
			RefreshGroundDefenseSearch(orCreateFactory);
			ClearDarkFogAssaultTips();
		}
	}

	private static List<int> CollectGroundBaseIdsDescending(ObjectPool<DFGBaseComponent> bases)
	{
		List<int> list = new List<int>();
		if (bases?.buffer == null)
		{
			return list;
		}
		for (int num = bases.cursor - 1; num > 0; num--)
		{
			DFGBaseComponent val = bases.buffer[num];
			if (val != null && val.id == num)
			{
				list.Add(num);
			}
		}
		return list;
	}

	private static void ClearGroundUnits(PlanetFactory planetFactory, HashSet<int> baseIds, List<EnemyModelRef> removedModels)
	{
		foreach (int item in CollectGroundUnitEnemyIdsDescending(planetFactory, baseIds))
		{
			KillGroundEnemyFinally(planetFactory, item, "unit", removedModels);
		}
	}

	private static void ClearGroundNonCoreBuildings(PlanetFactory planetFactory, List<int> baseIds, List<EnemyModelRef> removedModels)
	{
		for (int i = 0; i < 8; i++)
		{
			int num = 0;
			foreach (int baseId in baseIds)
			{
				foreach (int item in CollectGroundNonCoreBuildingEnemyIdsDescending(planetFactory, baseId))
				{
					if (KillGroundEnemyFinally(planetFactory, item, "building", removedModels))
					{
						num++;
					}
				}
			}
			ExecuteDeferredGroundEnemyChanges(planetFactory);
			if (num == 0)
			{
				break;
			}
		}
	}

	private static void ClearGroundBaseCores(PlanetFactory planetFactory, List<int> baseIds, List<EnemyModelRef> removedModels)
	{
		foreach (int baseId in baseIds)
		{
			int enemyId = GetGroundBase(planetFactory, baseId)?.enemyId ?? 0;
			if (IsGroundCoreEnemy(planetFactory, enemyId, baseId))
			{
				KillGroundEnemyFinally(planetFactory, enemyId, "core", removedModels);
			}
		}
	}

	private static List<int> CollectGroundUnitEnemyIdsDescending(PlanetFactory planetFactory, HashSet<int> baseIds)
	{
		List<int> list = new List<int>();
		HashSet<int> hashSet = new HashSet<int>();
		DataPool<EnemyUnitComponent> val = planetFactory?.enemySystem?.units;
		if (planetFactory?.enemyPool == null || baseIds == null || baseIds.Count <= 0)
		{
			return list;
		}
		if (val?.buffer != null)
		{
			for (int num = val.cursor - 1; num > 0; num--)
			{
				ref EnemyUnitComponent reference = ref val.buffer[num];
				if (reference.id == num && baseIds.Contains(reference.baseId) && IsGroundUnitEnemy(planetFactory, reference.enemyId, reference.baseId))
				{
					list.Add(reference.enemyId);
					hashSet.Add(reference.enemyId);
				}
			}
		}
		for (int num2 = planetFactory.enemyCursor - 1; num2 > 0; num2--)
		{
			ref EnemyData reference2 = ref planetFactory.enemyPool[num2];
			if (reference2.id == num2 && reference2.dynamic && !reference2.isSpace && baseIds.Contains(reference2.owner) && !hashSet.Contains(num2))
			{
				list.Add(num2);
			}
		}
		return list;
	}

	private static List<int> CollectGroundNonCoreBuildingEnemyIdsDescending(PlanetFactory planetFactory, int baseId)
	{
		List<int> list = new List<int>();
		HashSet<int> hashSet = new HashSet<int>();
		Builder[] array = GetGroundBase(planetFactory, baseId)?.pbuilders;
		if (array != null)
		{
			for (int num = array.Length - 1; num > 1; num--)
			{
				int instId = array[num].instId;
				if (IsGroundNonCoreBuildingEnemy(planetFactory, instId, baseId))
				{
					list.Add(instId);
					hashSet.Add(instId);
				}
			}
		}
		if (planetFactory?.enemyPool == null)
		{
			return list;
		}
		for (int num2 = planetFactory.enemyCursor - 1; num2 > 0; num2--)
		{
			ref EnemyData reference = ref planetFactory.enemyPool[num2];
			if (reference.id == num2 && !reference.dynamic && !reference.isSpace && reference.owner == baseId && reference.dfGBaseId != baseId && !hashSet.Contains(num2))
			{
				list.Add(num2);
			}
		}
		return list;
	}

	private static bool IsGroundUnitEnemy(PlanetFactory planetFactory, int enemyId, int baseId)
	{
		if (!IsLiveGroundEnemy(planetFactory, enemyId))
		{
			return false;
		}
		ref EnemyData reference = ref planetFactory.enemyPool[enemyId];
		if (reference.dynamic)
		{
			return reference.owner == baseId;
		}
		return false;
	}

	private static bool IsGroundNonCoreBuildingEnemy(PlanetFactory planetFactory, int enemyId, int baseId)
	{
		if (!IsLiveGroundEnemy(planetFactory, enemyId))
		{
			return false;
		}
		ref EnemyData reference = ref planetFactory.enemyPool[enemyId];
		if (!reference.dynamic && reference.owner == baseId)
		{
			return reference.dfGBaseId != baseId;
		}
		return false;
	}

	private static bool IsGroundCoreEnemy(PlanetFactory planetFactory, int enemyId, int baseId)
	{
		if (!IsLiveGroundEnemy(planetFactory, enemyId))
		{
			return false;
		}
		ref EnemyData reference = ref planetFactory.enemyPool[enemyId];
		if (!reference.dynamic)
		{
			return reference.dfGBaseId == baseId;
		}
		return false;
	}

	private static bool KillGroundEnemyFinally(PlanetFactory planetFactory, int enemyId, string kind, List<EnemyModelRef> removedModels)
	{
		if (!IsLiveGroundEnemy(planetFactory, enemyId))
		{
			return false;
		}
		try
		{
			RememberEnemyModel(planetFactory, enemyId, removedModels);
			LogInfo("KillEnemyFinally " + kind + " -> enemyData.id: " + enemyId);
			planetFactory.KillEnemyFinally(enemyId, ref CombatStat.empty);
			return true;
		}
		catch (Exception ex)
		{
			LogInfo("error to kill ground " + kind + " " + enemyId + ": " + ex.Message);
			return false;
		}
	}

	private static bool IsLiveGroundEnemy(PlanetFactory planetFactory, int enemyId)
	{
		if (planetFactory?.enemyPool != null && enemyId > 0 && enemyId < planetFactory.enemyCursor && enemyId < planetFactory.enemyPool.Length && planetFactory.enemyPool[enemyId].id == enemyId)
		{
			return !planetFactory.enemyPool[enemyId].isSpace;
		}
		return false;
	}

	private static void RememberEnemyModel(PlanetFactory planetFactory, int enemyId, List<EnemyModelRef> removedModels)
	{
		if (removedModels != null && IsLiveGroundEnemy(planetFactory, enemyId))
		{
			ref EnemyData reference = ref planetFactory.enemyPool[enemyId];
			if (reference.modelId > 0)
			{
				removedModels.Add(new EnemyModelRef
				{
					ModelIndex = reference.modelIndex,
					ModelId = reference.modelId
				});
			}
		}
	}

	private static void ClearGroundBaseFormations(PlanetFactory planetFactory, List<int> baseIds)
	{
		foreach (int baseId in baseIds)
		{
			DFGBaseComponent groundBase = GetGroundBase(planetFactory, baseId);
			if (groundBase == null || groundBase.forms == null)
			{
				continue;
			}
			for (int num = groundBase.forms.Length - 1; num >= 0; num--)
			{
				EnemyFormation val = groundBase.forms[num];
				if (val != null && val.unitCount > 0)
				{
					try
					{
						LogInfo("clear DFGBaseComponent:" + groundBase.id + " -> form count: " + val.unitCount);
						val.Clear();
					}
					catch (Exception ex)
					{
						LogInfo("error to clear form " + num + " for base " + baseId + ": " + ex.Message);
					}
				}
			}
		}
	}

	private static DFGBaseComponent GetGroundBase(PlanetFactory planetFactory, int baseId)
	{
		ObjectPool<DFGBaseComponent> val = planetFactory?.enemySystem?.bases;
		if (baseId <= 0 || val?.buffer == null || baseId >= val.cursor)
		{
			return null;
		}
		DFGBaseComponent val2 = val.buffer[baseId];
		if (val2 == null || val2.id != baseId)
		{
			return null;
		}
		return val2;
	}

	private static void ExecuteDeferredGroundEnemyChanges(PlanetFactory planetFactory)
	{
		try
		{
			if (planetFactory != null)
			{
				EnemyDFGroundSystem enemySystem = planetFactory.enemySystem;
				if (enemySystem != null)
				{
					enemySystem.ExecuteDeferredEnemyChange();
				}
			}
		}
		catch (Exception ex)
		{
			LogInfo("error to execute deferred ground enemy changes: " + ex.Message);
		}
	}

	private static void ReturnRelaysForGroundBases(PlanetData planet, HashSet<int> baseIds)
	{
		if (planet?.star != null && GameMain.spaceSector != null && baseIds != null && baseIds.Count > 0)
		{
			for (EnemyDFHiveSystem val = GameMain.spaceSector.dfHives[planet.star.index]; val != null; val = val.nextSibling)
			{
				ReturnRelaysForGroundBases(val, planet.astroId, baseIds);
			}
		}
	}

	private static void ReturnRelaysForGroundBases(EnemyDFHiveSystem hive, int planetAstroId, HashSet<int> baseIds)
	{
		if (hive?.relays?.buffer == null)
		{
			return;
		}
		for (int num = hive.relays.cursor - 1; num > 0; num--)
		{
			DFRelayComponent val = hive.relays.buffer[num];
			if (val != null && val.id == num)
			{
				bool flag = val.targetAstroId == planetAstroId && baseIds.Contains(val.baseId);
				bool flag2 = val.searchAstroId == planetAstroId;
				if (flag || flag2)
				{
					try
					{
						if (flag2)
						{
							val.ResetSearchStates();
							val.ResetTargetedMarker();
						}
						if (flag && ReturnRelay(val))
						{
							hive.relayNeutralizedCounter++;
						}
					}
					catch (Exception ex)
					{
						LogInfo("error to return relay " + val.id + ": " + ex.Message);
					}
				}
			}
		}
	}

	private static bool ReturnRelay(DFRelayComponent relay)
	{
		//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_0090: Unknown result type (might be due to invalid IL or missing references)
		LogInfo("return relay -> relay.id: " + relay.id + ", enemyId: " + relay.enemyId);
		if (relay.stage == 2)
		{
			relay.LeaveBase();
			return true;
		}
		if (relay.direction < 0)
		{
			relay.ResetSearchStates();
			relay.ResetTargetedMarker();
			return false;
		}
		relay.ClearBaseReferences();
		relay.targetAstroId = 0;
		relay.targetLPos = Vector3.zero;
		relay.targetYaw = 0f;
		relay.baseState = 0;
		relay.baseId = 0;
		relay.baseTicks = 0;
		relay.baseEvolve = default(EvolveData);
		relay.baseRespawnCD = 0;
		relay.direction = -1;
		relay.param0 = 0f;
		relay.RemoveAllCarriers();
		relay.ResetSearchStates();
		relay.ResetTargetedMarker();
		return true;
	}

	private static void UnlinkGroundBaseRuins(PlanetFactory planetFactory, ObjectPool<DFGBaseComponent> bases, List<int> baseIds)
	{
		foreach (int baseId in baseIds)
		{
			if (baseId <= 0 || bases?.buffer == null || baseId >= bases.cursor)
			{
				continue;
			}
			DFGBaseComponent val = bases.buffer[baseId];
			if (val == null || val.id != baseId)
			{
				continue;
			}
			try
			{
				int enemyId = val.enemyId;
				int ruinId = val.ruinId;
				LogInfo("unlink DFGBaseComponent -> base.id: " + baseId + ", enemyId: " + enemyId + ", ruinId: " + ruinId);
				val.relayId = 0;
				val.relayEnemyId = 0;
				val.hiveAstroId = 0;
				if (IsLiveGroundEnemy(planetFactory, enemyId))
				{
					planetFactory.RemoveEnemyWithComponents(enemyId);
				}
				else
				{
					RemoveGroundBaseComponentOnly(planetFactory, baseId);
				}
			}
			catch (Exception ex)
			{
				LogInfo("error to unlink DFGBaseComponent " + baseId + ": " + ex.Message);
			}
		}
	}

	private static void RemoveGroundBaseComponentOnly(PlanetFactory planetFactory, int baseId)
	{
		if (planetFactory?.enemySystem != null && baseId > 0)
		{
			if (planetFactory.platformSystem != null)
			{
				planetFactory.platformSystem.RemoveStateArea((uint)(0x1000000uL | (ulong)baseId));
			}
			planetFactory.enemySystem.RemoveDFGBaseComponent(baseId);
		}
	}

	private static void ClearLocalDarkFogRenderResidue(PlanetData planet, PlanetFactory planetFactory, List<int> baseIds, List<EnemyModelRef> removedModels)
	{
		if (!((Object)(object)planet?.factoryModel == (Object)null) && planetFactory != null && planet == GameMain.localPlanet && planet.factoryLoaded)
		{
			RemoveRememberedEnemyModels(planetFactory, removedModels);
			ClearLocalGroundRenderer(planet.factoryModel, planetFactory, baseIds);
			ClearLocalFormationRenderers(planet.factoryModel);
		}
	}

	private static void RemoveRememberedEnemyModels(PlanetFactory planetFactory, List<EnemyModelRef> removedModels)
	{
		if (removedModels == null || removedModels.Count <= 0)
		{
			return;
		}
		GPUInstancingManager gpuiManager = GameMain.gpuiManager;
		if (((gpuiManager != null) ? gpuiManager.activeFactory : null) != planetFactory)
		{
			return;
		}
		HashSet<int> hashSet = new HashSet<int>();
		foreach (EnemyModelRef removedModel in removedModels)
		{
			if (removedModel.ModelId > 0 && hashSet.Add(removedModel.ModelId))
			{
				try
				{
					GameMain.gpuiManager.RemoveModel(removedModel.ModelIndex, removedModel.ModelId, true);
				}
				catch (Exception ex)
				{
					int modelId = removedModel.ModelId;
					LogInfo("error to remove remembered enemy model " + modelId + ": " + ex.Message);
				}
			}
		}
	}

	private static void ClearLocalGroundRenderer(FactoryModel factoryModel, PlanetFactory planetFactory, List<int> baseIds)
	{
		EnemyDFGroundRenderer dfGroundRenderer = factoryModel.dfGroundRenderer;
		if (dfGroundRenderer == null)
		{
			return;
		}
		try
		{
			dfGroundRenderer.enemySystem = planetFactory.enemySystem;
			if (dfGroundRenderer.builderArr != null && baseIds != null)
			{
				foreach (int baseId in baseIds)
				{
					int num = baseId * 80;
					int num2 = Math.Min(num + 80, dfGroundRenderer.builderArr.Length);
					for (int i = num; i < num2; i++)
					{
						dfGroundRenderer.builderArr[i].instId = 0u;
					}
				}
			}
			if (dfGroundRenderer.truckSegments != null)
			{
				Array.Clear(dfGroundRenderer.truckSegments, 0, dfGroundRenderer.truckSegments.Length);
			}
			if (dfGroundRenderer.truckBuilderIndices != null)
			{
				Array.Clear(dfGroundRenderer.truckBuilderIndices, 0, dfGroundRenderer.truckBuilderIndices.Length);
			}
		}
		catch (Exception ex)
		{
			LogInfo("error to clear local ground renderer residue: " + ex.Message);
		}
	}

	private static void ClearLocalFormationRenderers(FactoryModel factoryModel)
	{
		EnemyFormationRenderer[] dfFormRenderers = factoryModel.dfFormRenderers;
		if (dfFormRenderers == null)
		{
			return;
		}
		EnemyFormationRenderer[] array = dfFormRenderers;
		foreach (EnemyFormationRenderer val in array)
		{
			if (val != null)
			{
				val.unitCount = 0;
				val.stateCursor = 0;
				val.groupCursor = 0;
			}
		}
	}

	private static void RefreshGroundDefenseSearch(PlanetFactory planetFactory)
	{
		try
		{
			if (planetFactory != null)
			{
				DefenseSystem defenseSystem = planetFactory.defenseSystem;
				if (defenseSystem != null)
				{
					defenseSystem.RefreshTurretSearchPair();
				}
			}
		}
		catch (Exception ex)
		{
			LogInfo("error to refresh turret search pair: " + ex.Message);
		}
	}

	private static void ClearDarkFogAssaultTips()
	{
		try
		{
			UIRoot instance = UIRoot.instance;
			if (instance == null)
			{
				return;
			}
			UIGame uiGame = instance.uiGame;
			if (uiGame != null)
			{
				UIDarkFogAssaultTip dfAssaultTip = uiGame.dfAssaultTip;
				if (dfAssaultTip != null)
				{
					dfAssaultTip.ClearAllSpots();
				}
			}
		}
		catch (Exception)
		{
			LogInfo("error to clear dark fog assault tips");
		}
	}

	internal static void ClearCurrentStarSpaceDarkFog()
	{
		SaveCurrentGame();
		if (GameMain.mainPlayer != null)
		{
			StarData localStar = GameMain.localStar;
			if (localStar != null)
			{
				ClearStarSpaceDarkFog(localStar);
			}
		}
	}

	private static void ClearStarSpaceDarkFog(StarData star)
	{
		SpaceSector spaceSector = GameMain.spaceSector;
		List<int> list = new List<int>();
		for (int num = spaceSector.enemyCursor - 1; num > 0; num--)
		{
			ref EnemyData reference = ref spaceSector.enemyPool[num];
			if (reference.id == num && !((EnemyData)(ref reference)).isInvincible && reference.dfSCoreId <= 0 && reference.astroId == star.astroId)
			{
				LogInfo("active relays -> " + reference.id);
				list.Add(reference.id);
			}
		}
		for (EnemyDFHiveSystem val = spaceSector.dfHives[star.index]; val != null; val = val.nextSibling)
		{
			if (val.isAlive)
			{
				LogInfo("hiveAstroId " + val.hiveAstroId);
				LogInfo("rootEnemyId " + val.rootEnemyId);
				CollectKillableEnemyIds<EnemyUnitComponent>(spaceSector, list, val.units, (Func<EnemyUnitComponent, int>)((EnemyUnitComponent component) => component.enemyId));
				CollectKillableEnemyIds<DFTinderComponent>(spaceSector, list, val.tinders, (Func<DFTinderComponent, int>)((DFTinderComponent component) => component.enemyId));
				CollectIdleRelayEnemyIds(spaceSector, list, val);
				CollectKillableEnemyIds<DFSTurretComponent>(spaceSector, list, val.turrets, (Func<DFSTurretComponent, int>)((DFSTurretComponent component) => component.enemyId));
				CollectKillableEnemyIds<DFSGammaComponent>(spaceSector, list, val.gammas, (Func<DFSGammaComponent, int>)((DFSGammaComponent component) => component.enemyId));
				CollectKillableEnemyIds<DFSReplicatorComponent>(spaceSector, list, val.replicators, (Func<DFSReplicatorComponent, int>)((DFSReplicatorComponent component) => component.enemyId));
				CollectKillableEnemyIds<DFSConnectorComponent>(spaceSector, list, val.connectors, (Func<DFSConnectorComponent, int>)((DFSConnectorComponent component) => component.enemyId));
				CollectKillableEnemyIds<DFSNodeComponent>(spaceSector, list, val.nodes, (Func<DFSNodeComponent, int>)((DFSNodeComponent component) => component.enemyId));
				CollectKillableEnemyIds<EnemyBuilderComponent>(spaceSector, list, val.builders, (Func<EnemyBuilderComponent, int>)((EnemyBuilderComponent component) => component.enemyId));
				ClearHiveFormations(val);
				DrainHiveCoreBuilders(val);
			}
		}
		foreach (int item in list.Distinct())
		{
			try
			{
				spaceSector.KillEnemyFinal(item, ref CombatStat.empty);
			}
			catch (Exception)
			{
				LogInfo("error to kill " + item);
			}
		}
		MakeHiveCoresInvincible(star);
	}

	private static void CollectKillableEnemyIds<T>(SpaceSector spaceSector, List<int> enemyIds, DataPool<T> pool, Func<T, int> getEnemyId) where T : struct, IPoolElement
	{
		for (int num = pool.cursor - 1; num > 0; num--)
		{
			int num2 = getEnemyId(pool.buffer[num]);
			if (CanKillSpaceEnemy(spaceSector, num2))
			{
				enemyIds.Add(num2);
			}
		}
	}

	private static void CollectIdleRelayEnemyIds(SpaceSector spaceSector, List<int> enemyIds, EnemyDFHiveSystem hive)
	{
		for (int num = hive.idleRelayCount - 1; num > 0; num--)
		{
			DFRelayComponent val = hive.relays.buffer[hive.idleRelayIds[num]];
			if (CanKillSpaceEnemy(spaceSector, val.enemyId))
			{
				enemyIds.Add(val.enemyId);
			}
		}
	}

	private static bool CanKillSpaceEnemy(SpaceSector spaceSector, int enemyId)
	{
		if (enemyId <= 0)
		{
			return false;
		}
		ref EnemyData reference = ref spaceSector.enemyPool[enemyId];
		if (!((EnemyData)(ref reference)).isInvincible)
		{
			return reference.dfSCoreId <= 0;
		}
		return false;
	}

	private static void ClearHiveFormations(EnemyDFHiveSystem hive)
	{
		EnemyFormation[] forms = hive.forms;
		for (int i = 0; i < forms.Length; i++)
		{
			if (forms[i].unitCount > 0)
			{
				LogInfo("clear form " + forms[i].unitCount);
				forms[i].Clear();
			}
		}
	}

	private static void DrainHiveCoreBuilders(EnemyDFHiveSystem hive)
	{
		for (int num = hive.cores.cursor - 1; num > 0; num--)
		{
			ref EnemyBuilderComponent reference = ref hive.builders.buffer[hive.cores.buffer[num].builderId];
			reference.matter = 0;
			reference.energy = 0;
		}
	}

	internal static void FillGalaxyWithDarkFogHives()
	{
		SaveCurrentGame();
		if (GameMain.mainPlayer == null)
		{
			return;
		}
		GalaxyData galaxy = GameMain.galaxy;
		SpaceSector spaceSector = GameMain.spaceSector;
		for (int i = 0; i < galaxy.starCount; i++)
		{
			StarData val = galaxy.stars[i];
			int num = Math.Min(val.maxHiveCount, 8);
			int num2 = CountHives(spaceSector.dfHives[val.index]);
			for (int j = 0; j < num - num2; j++)
			{
				EnemyDFHiveSystem val2 = spaceSector.TryCreateNewHive(val);
				if (val2 != null)
				{
					LogInfo(val.displayName + " Add 1 hive");
					val2.SetForNewGame();
				}
			}
		}
	}

	private static int CountHives(EnemyDFHiveSystem hive)
	{
		int num = 0;
		while (hive != null)
		{
			num++;
			hive = hive.nextSibling;
		}
		return num;
	}

	private static void MakeHiveCoresInvincible(StarData star)
	{
		SpaceSector spaceSector = GameMain.spaceSector;
		for (EnemyDFHiveSystem val = spaceSector.dfHives[star.index]; val != null; val = val.nextSibling)
		{
			for (int num = val.cores.cursor - 1; num > 0; num--)
			{
				((EnemyData)(ref spaceSector.enemyPool[val.cores.buffer[num].enemyId])).isInvincible = true;
			}
		}
	}

	private static void SaveCurrentGame()
	{
		string arg = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
		string arg2 = GameMain.data.gameDesc.galaxySeed.ToString("00000000");
		GameSave.SaveCurrentGame($"[{arg2}] {arg}");
	}

	private static void LogInfo(string message)
	{
		ManualLogSource log = Log;
		if (log != null)
		{
			log.LogInfo((object)message);
		}
	}
}
internal static class SurfaceRuinControl
{
	private enum LatitudeBand
	{
		Low,
		Mid,
		High
	}

	private const short BasePitRuinModelIndex = 406;

	private const int Level30BasePitLifeTime = -31;

	private const float DuplicateRuinRadius = 50f;

	private const float SurfaceOffset = 0.2f;

	private const float LowLatitudeMax = 28.5f;

	private const float MidLatitudeMax = 46.5f;

	internal static ManualLogSource Log;

	private static readonly Vector3[] LowLatitudeRuinPositions = (Vector3[])(object)new Vector3[76]
	{
		new Vector3(-173.0104f, -47.818897f, 88.66112f),
		new Vector3(173.0104f, -47.818897f, 88.66112f),
		new Vector3(173.0104f, 47.818897f, 88.66112f),
		new Vector3(-173.0104f, 47.818897f, 88.66112f),
		new Vector3(-117.67461f, -137.77583f, 85.15015f),
		new Vector3(117.67461f, -137.77583f, 85.15015f),
		new Vector3(117.67461f, 137.77583f, 85.15015f),
		new Vector3(-117.67461f, 137.77583f, 85.15015f),
		new Vector3(-161.9652f, -100.1f, 61.865204f),
		new Vector3(161.9652f, -100.1f, 61.865204f),
		new Vector3(161.9652f, 100.1f, 61.865204f),
		new Vector3(-161.9652f, 100.1f, 61.865204f),
		new Vector3(191.2756f, 0f, 59.10741f),
		new Vector3(-191.2756f, 0f, 59.10741f),
		new Vector3(-32.524464f, -190.40152f, 52.625683f),
		new Vector3(32.524464f, -190.40152f, 52.625683f),
		new Vector3(32.524464f, 190.40152f, 52.625683f),
		new Vector3(-32.524464f, 190.40152f, 52.625683f),
		new Vector3(-88.66112f, -173.0104f, 47.818897f),
		new Vector3(88.66112f, -173.0104f, 47.818897f),
		new Vector3(88.66112f, 173.0104f, 47.818897f),
		new Vector3(-88.66112f, 173.0104f, 47.818897f),
		new Vector3(-190.40152f, -52.625683f, 32.524464f),
		new Vector3(190.40152f, -52.625683f, 32.524464f),
		new Vector3(190.40152f, 52.625683f, 32.524464f),
		new Vector3(-190.40152f, 52.625683f, 32.524464f),
		new Vector3(-136.48001f, -143.4567f, 29.553705f),
		new Vector3(136.48001f, -143.4567f, 29.553705f),
		new Vector3(136.48001f, 143.4567f, 29.553705f),
		new Vector3(-136.48001f, 143.4567f, 29.553705f),
		new Vector3(-170.3003f, -105.251366f, 0f),
		new Vector3(-105.251366f, -170.3003f, 0f),
		new Vector3(-59.10741f, -191.2756f, 0f),
		new Vector3(0f, -200.2f, 0f),
		new Vector3(59.10741f, -191.2756f, 0f),
		new Vector3(105.251366f, -170.3003f, 0f),
		new Vector3(170.3003f, -105.251366f, 0f),
		new Vector3(200.2f, 0f, 0f),
		new Vector3(170.3003f, 105.251366f, 0f),
		new Vector3(105.251366f, 170.3003f, 0f),
		new Vector3(59.10741f, 191.2756f, 0f),
		new Vector3(0f, 200.2f, 0f),
		new Vector3(-59.10741f, 191.2756f, 0f),
		new Vector3(-105.251366f, 170.3003f, 0f),
		new Vector3(-170.3003f, 105.251366f, 0f),
		new Vector3(-200.2f, 0f, 0f),
		new Vector3(-136.48001f, -143.4567f, -29.553705f),
		new Vector3(136.48001f, -143.4567f, -29.553705f),
		new Vector3(136.48001f, 143.4567f, -29.553705f),
		new Vector3(-136.48001f, 143.4567f, -29.553705f),
		new Vector3(-190.40152f, -52.625683f, -32.524464f),
		new Vector3(190.40152f, -52.625683f, -32.524464f),
		new Vector3(190.40152f, 52.625683f, -32.524464f),
		new Vector3(-190.40152f, 52.625683f, -32.524464f),
		new Vector3(-88.66112f, -173.0104f, -47.818897f),
		new Vector3(88.66112f, -173.0104f, -47.818897f),
		new Vector3(88.66112f, 173.0104f, -47.818897f),
		new Vector3(-88.66112f, 173.0104f, -47.818897f),
		new Vector3(-32.524464f, -190.40152f, -52.625683f),
		new Vector3(32.524464f, -190.40152f, -52.625683f),
		new Vector3(32.524464f, 190.40152f, -52.625683f),
		new Vector3(-32.524464f, 190.40152f, -52.625683f),
		new Vector3(191.2756f, 0f, -59.10741f),
		new Vector3(-191.2756f, 0f, -59.10741f),
		new Vector3(-161.9652f, -100.1f, -61.865204f),
		new Vector3(161.9652f, -100.1f, -61.865204f),
		new Vector3(161.9652f, 100.1f, -61.865204f),
		new Vector3(-161.9652f, 100.1f, -61.865204f),
		new Vector3(-117.67461f, -137.77583f, -85.15015f),
		new Vector3(117.67461f, -137.77583f, -85.15015f),
		new Vector3(117.67461f, 137.77583f, -85.15015f),
		new Vector3(-117.67461f, 137.77583f, -85.15015f),
		new Vector3(-173.0104f, -47.818897f, -88.66112f),
		new Vector3(173.0104f, -47.818897f, -88.66112f),
		new Vector3(173.0104f, 47.818897f, -88.66112f),
		new Vector3(-173.0104f, 47.818897f, -88.66112f)
	};

	private static readonly Vector3[] MidLatitudeRuinPositions = (Vector3[])(object)new Vector3[48]
	{
		new Vector3(-29.553705f, -136.48001f, 143.4567f),
		new Vector3(29.553705f, -136.48001f, 143.4567f),
		new Vector3(29.553705f, 136.48001f, 143.4567f),
		new Vector3(-29.553705f, 136.48001f, 143.4567f),
		new Vector3(-85.15015f, -117.67461f, 137.77583f),
		new Vector3(85.15015f, -117.67461f, 137.77583f),
		new Vector3(85.15015f, 117.67461f, 137.77583f),
		new Vector3(-85.15015f, 117.67461f, 137.77583f),
		new Vector3(-143.4567f, -29.553705f, 136.48001f),
		new Vector3(143.4567f, -29.553705f, 136.48001f),
		new Vector3(143.4567f, 29.553705f, 136.48001f),
		new Vector3(-143.4567f, 29.553705f, 136.48001f),
		new Vector3(-137.77583f, -85.15015f, 117.67461f),
		new Vector3(137.77583f, -85.15015f, 117.67461f),
		new Vector3(137.77583f, 85.15015f, 117.67461f),
		new Vector3(-137.77583f, 85.15015f, 117.67461f),
		new Vector3(0f, -170.3003f, 105.251366f),
		new Vector3(170.3003f, 0f, 105.251366f),
		new Vector3(0f, 170.3003f, 105.251366f),
		new Vector3(-170.3003f, 0f, 105.251366f),
		new Vector3(-61.865204f, -161.9652f, 100.1f),
		new Vector3(61.865204f, -161.9652f, 100.1f),
		new Vector3(61.865204f, 161.9652f, 100.1f),
		new Vector3(-61.865204f, 161.9652f, 100.1f),
		new Vector3(-61.865204f, -161.9652f, -100.1f),
		new Vector3(61.865204f, -161.9652f, -100.1f),
		new Vector3(61.865204f, 161.9652f, -100.1f),
		new Vector3(-61.865204f, 161.9652f, -100.1f),
		new Vector3(0f, -170.3003f, -105.251366f),
		new Vector3(170.3003f, 0f, -105.251366f),
		new Vector3(0f, 170.3003f, -105.251366f),
		new Vector3(-170.3003f, 0f, -105.251366f),
		new Vector3(-137.77583f, -85.15015f, -117.67461f),
		new Vector3(137.77583f, -85.15015f, -117.67461f),
		new Vector3(137.77583f, 85.15015f, -117.67461f),
		new Vector3(-137.77583f, 85.15015f, -117.67461f),
		new Vector3(-143.4567f, -29.553705f, -136.48001f),
		new Vector3(143.4567f, -29.553705f, -136.48001f),
		new Vector3(143.4567f, 29.553705f, -136.48001f),
		new Vector3(-143.4567f, 29.553705f, -136.48001f),
		new Vector3(-85.15015f, -117.67461f, -137.77583f),
		new Vector3(85.15015f, -117.67461f, -137.77583f),
		new Vector3(85.15015f, 117.67461f, -137.77583f),
		new Vector3(-85.15015f, 117.67461f, -137.77583f),
		new Vector3(-29.553705f, -136.48001f, -143.4567f),
		new Vector3(29.553705f, -136.48001f, -143.4567f),
		new Vector3(29.553705f, 136.48001f, -143.4567f),
		new Vector3(-29.553705f, 136.48001f, -143.4567f)
	};

	private static readonly Vector3[] HighLatitudeRuinPositions = (Vector3[])(object)new Vector3[38]
	{
		new Vector3(0f, 0f, 200.2f),
		new Vector3(0f, -59.10741f, 191.2756f),
		new Vector3(0f, 59.10741f, 191.2756f),
		new Vector3(-52.625683f, -32.524464f, 190.40152f),
		new Vector3(52.625683f, -32.524464f, 190.40152f),
		new Vector3(52.625683f, 32.524464f, 190.40152f),
		new Vector3(-52.625683f, 32.524464f, 190.40152f),
		new Vector3(-47.818897f, -88.66112f, 173.0104f),
		new Vector3(47.818897f, -88.66112f, 173.0104f),
		new Vector3(47.818897f, 88.66112f, 173.0104f),
		new Vector3(-47.818897f, 88.66112f, 173.0104f),
		new Vector3(0f, -105.251366f, 170.3003f),
		new Vector3(105.251366f, 0f, 170.3003f),
		new Vector3(0f, 105.251366f, 170.3003f),
		new Vector3(-105.251366f, 0f, 170.3003f),
		new Vector3(-100.1f, -61.865204f, 161.9652f),
		new Vector3(100.1f, -61.865204f, 161.9652f),
		new Vector3(100.1f, 61.865204f, 161.9652f),
		new Vector3(-100.1f, 61.865204f, 161.9652f),
		new Vector3(-100.1f, -61.865204f, -161.9652f),
		new Vector3(100.1f, -61.865204f, -161.9652f),
		new Vector3(100.1f, 61.865204f, -161.9652f),
		new Vector3(-100.1f, 61.865204f, -161.9652f),
		new Vector3(0f, -105.251366f, -170.3003f),
		new Vector3(105.251366f, 0f, -170.3003f),
		new Vector3(0f, 105.251366f, -170.3003f),
		new Vector3(-105.251366f, 0f, -170.3003f),
		new Vector3(-47.818897f, -88.66112f, -173.0104f),
		new Vector3(47.818897f, -88.66112f, -173.0104f),
		new Vector3(47.818897f, 88.66112f, -173.0104f),
		new Vector3(-47.818897f, 88.66112f, -173.0104f),
		new Vector3(-52.625683f, -32.524464f, -190.40152f),
		new Vector3(52.625683f, -32.524464f, -190.40152f),
		new Vector3(52.625683f, 32.524464f, -190.40152f),
		new Vector3(-52.625683f, 32.524464f, -190.40152f),
		new Vector3(0f, -59.10741f, -191.2756f),
		new Vector3(0f, 59.10741f, -191.2756f),
		new Vector3(0f, 0f, -200.2f)
	};

	internal static void ConstructLowLatitudeRuinsOnCurrentPlanet()
	{
		ConstructRuinsOnCurrentPlanet(LatitudeBand.Low, "low-latitude");
	}

	internal static void ConstructMidLatitudeRuinsOnCurrentPlanet()
	{
		ConstructRuinsOnCurrentPlanet(LatitudeBand.Mid, "mid-latitude");
	}

	internal static void ConstructHighLatitudeRuinsOnCurrentPlanet()
	{
		ConstructRuinsOnCurrentPlanet(LatitudeBand.High, "high-latitude");
	}

	private static void ConstructRuinsOnCurrentPlanet(LatitudeBand targetBand, string bandName)
	{
		//IL_0062: Unknown result type (might be due to invalid IL or missing references)
		//IL_0067: Unknown result type (might be due to invalid IL or missing references)
		//IL_0069: Unknown result type (might be due to invalid IL or missing references)
		//IL_0074: Unknown result type (might be due to invalid IL or missing references)
		//IL_0076: Unknown result type (might be due to invalid IL or missing references)
		//IL_007b: Unknown result type (might be due to invalid IL or missing references)
		//IL_007e: 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_00b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b3: 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_00c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
		PlanetData localPlanet = GameMain.localPlanet;
		if (localPlanet == null)
		{
			Report("Surface Ruins: no current planet.");
			return;
		}
		PlanetFactory factory = localPlanet.factory;
		if (factory == null || factory.ruinPool == null)
		{
			Report("Surface Ruins: planet " + (localPlanet.displayName ?? localPlanet.name) + " has no loaded factory.");
			return;
		}
		int num = 0;
		int num2 = 0;
		Vector3[] allRuinPositions = GetAllRuinPositions();
		for (int i = 0; i < allRuinPositions.Length; i++)
		{
			Vector3 val = allRuinPositions[i];
			if (GetLatitudeBand(val) == targetBand)
			{
				Vector3 val2 = SnapToSurface(localPlanet, val);
				if (HasRuinWithin(factory, val2, 50f))
				{
					num2++;
					continue;
				}
				RuinData val3 = default(RuinData);
				val3.modelIndex = 406;
				val3.lifeTime = -31;
				val3.pos = val2;
				val3.rot = Maths.SphericalRotation(val2, DeterministicYaw(i));
				factory.AddRuinDataWithComponent(val3);
				num++;
			}
		}
		Report($"Surface Ruins: created {num}, skipped {num2}, total {CountRuinPositions(targetBand)} {bandName} ruins on {localPlanet.displayName ?? localPlanet.name}.");
	}

	private static Vector3[] GetAllRuinPositions()
	{
		//IL_002d: 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_005d: 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_0090: Unknown result type (might be due to invalid IL or missing references)
		//IL_0095: Unknown result type (might be due to invalid IL or missing references)
		Vector3[] array = (Vector3[])(object)new Vector3[LowLatitudeRuinPositions.Length + MidLatitudeRuinPositions.Length + HighLatitudeRuinPositions.Length];
		int num = 0;
		for (int i = 0; i < LowLatitudeRuinPositions.Length; i++)
		{
			array[num + i] = LowLatitudeRuinPositions[i];
		}
		num += LowLatitudeRuinPositions.Length;
		for (int j = 0; j < MidLatitudeRuinPositions.Length; j++)
		{
			array[num + j] = MidLatitudeRuinPositions[j];
		}
		num += MidLatitudeRuinPositions.Length;
		for (int k = 0; k < HighLatitudeRuinPositions.Length; k++)
		{
			array[num + k] = HighLatitudeRuinPositions[k];
		}
		return array;
	}

	private static int CountRuinPositions(LatitudeBand targetBand)
	{
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		int num = 0;
		Vector3[] allRuinPositions = GetAllRuinPositions();
		for (int i = 0; i < allRuinPositions.Length; i++)
		{
			if (GetLatitudeBand(allRuinPositions[i]) == targetBand)
			{
				num++;
			}
		}
		return num;
	}

	private static LatitudeBand GetLatitudeBand(Vector3 position)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		float num = Mathf.Abs(Mathf.Asin(Mathf.Clamp(((Vector3)(ref position)).normalized.y, -1f, 1f)) * 57.29578f);
		if (num < 28.5f)
		{
			return LatitudeBand.Low;
		}
		if (num < 46.5f)
		{
			return LatitudeBand.Mid;
		}
		return LatitudeBand.High;
	}

	internal static void BuildGeothermalOnIdleRuinsCurrentPlanet()
	{
		//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
		PlanetData localPlanet = GameMain.localPlanet;
		if (localPlanet == null)
		{
			Report("Surface Ruins: no current planet.");
			return;
		}
		PlanetFactory factory = localPlanet.factory;
		if (factory == null || factory.ruinPool == null || factory.powerSystem == null)
		{
			Report("Surface Ruins: planet " + (localPlanet.displayName ?? localPlanet.name) + " has no loaded factory or power system.");
			return;
		}
		ItemProto val = FindGeothermalPowerItem();
		if (val == null || val.prefabDesc == null || !val.prefabDesc.geothermal)
		{
			Report("Surface Ruins: geothermal power item not found.");
			return;
		}
		int num = 0;
		int num2 = 0;
		int num3 = 0;
		int num4 = 0;
		RuinData[] ruinPool = factory.ruinPool;
		int ruinCursor = factory.ruinCursor;
		for (int i = 1; i < ruinCursor; i++)
		{
			if (ruinPool[i].id == i && ruinPool[i].modelIndex == 406)
			{
				if (HasGeothermalOnBaseRuin(factory, i))
				{
					num2++;
				}
				else if (HasBaseOnRuin(factory, i))
				{
					num3++;
				}
				else if (BuildGeothermalEntity(factory, val, i, ruinPool[i].pos) > 0)
				{
					num++;
				}
				else
				{
					num4++;
				}
			}
		}
		Report($"Surface Ruins: built geothermal {num}, occupied {num2}, bound bases {num3}, failed {num4} on {localPlanet.displayName ?? localPlanet.name}.");
	}

	private static ItemProto FindGeothermalPowerItem()
	{
		if (((ProtoSet<ItemProto>)(object)LDB.items)?.dataArray == null)
		{
			return null;
		}
		ItemProto[] dataArray = ((ProtoSet<ItemProto>)(object)LDB.items).dataArray;
		foreach (ItemProto val in dataArray)
		{
			if (val?.prefabDesc != null && val.CanBuild && val.IsEntity && val.prefabDesc.isPowerGen && val.prefabDesc.geothermal)
			{
				return val;
			}
		}
		return null;
	}

	private static bool HasGeothermalOnBaseRuin(PlanetFactory factory, int baseRuinId)
	{
		if (factory == null || factory.powerSystem == null || baseRuinId <= 0)
		{
			return false;
		}
		PowerGeneratorComponent[] genPool = factory.powerSystem.genPool;
		int genCursor = factory.powerSystem.genCursor;
		for (int i = 1; i < genCursor; i++)
		{
			ref PowerGeneratorComponent reference = ref genPool[i];
			if (reference.id == i && reference.geothermal && reference.baseRuinId == baseRuinId)
			{
				return true;
			}
		}
		PrebuildData[] prebuildPool = factory.prebuildPool;
		int prebuildCursor = factory.prebuildCursor;
		for (int j = 1; j < prebuildCursor; j++)
		{
			ref PrebuildData reference2 = ref prebuildPool[j];
			if (reference2.id == j && reference2.paramCount > 0 && reference2.parameters != null && reference2.parameters[0] == baseRuinId)
			{
				ItemProto val = ((ProtoSet<ItemProto>)(object)LDB.items).Select((int)reference2.protoId);
				if (val?.prefabDesc != null && val.prefabDesc.geothermal)
				{
					return true;
				}
			}
		}
		return false;
	}

	private static bool HasBaseOnRuin(PlanetFactory factory, int baseRuinId)
	{
		if (factory?.enemySystem?.bases == null || baseRuinId <= 0)
		{
			return false;
		}
		ObjectPool<DFGBaseComponent> bases = factory.enemySystem.bases;
		for (int i = 1; i < bases.cursor; i++)
		{
			DFGBaseComponent val = bases.buffer[i];
			if (val != null && val.id == i && val.ruinId == baseRuinId)
			{
				return true;
			}
		}
		return false;
	}

	private static int BuildGeothermalEntity(PlanetFactory factory, ItemProto geothermalItem, int baseRuinId, Vector3 ruinPos)
	{
		//IL_0028: Unknown result type (might be due to invalid IL or missing references)
		//IL_0029: 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_0035: 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_003d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0069: Unknown result type (might be due to invalid IL or missing references)
		//IL_006a: 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_0072: Unknown result type (might be due to invalid IL or missing references)
		//IL_0079: Unknown result type (might be due to invalid IL or missing references)
		//IL_007a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0081: Unknown result type (might be due to invalid IL or missing references)
		//IL_0082: Unknown result type (might be due to invalid IL or missing references)
		//IL_008f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0099: 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_00b0: 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_00ca: 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_00d0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
		//IL_0125: Unknown result type (might be due to invalid IL or missing references)
		//IL_0179: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
		if (((factory != null) ? factory.planet : null) == null || geothermalItem?.prefabDesc == null || baseRuinId <= 0)
		{
			return 0;
		}
		Vector3 val = SnapGeothermalBuildPosition(factory.planet, ruinPos);
		Quaternion val2 = Maths.SphericalRotation(val, 0f);
		PrebuildData val3 = default(PrebuildData);
		val3.isDestroyed = false;
		val3.protoId = (short)((Proto)geothermalItem).ID;
		val3.modelIndex = (short)geothermalItem.ModelIndex;
		val3.pos = val;
		val3.pos2 = val;
		val3.rot = val2;
		val3.rot2 = val2;
		((PrebuildData)(ref val3)).InitParametersArray(1);
		val3.parameters[0] = baseRuinId;
		int num = factory.AddPrebuildDataWithComponents(val3);
		if (num <= 0)
		{
			return 0;
		}
		EntityData val4 = default(EntityData);
		val4.protoId = val3.protoId;
		val4.modelIndex = val3.modelIndex;
		val4.pos = val3.pos;
		val4.rot = val3.rot;
		val4.alt = ((Vector3)(ref val4.pos)).magnitude;
		val4.tilt = val3.tilt;
		((EntityData)(ref val4)).localized = factory.planet == GameMain.localPlanet && factory.planet.factoryLoaded;
		int num2 = factory.AddEntityDataWithComponents(val4, num);
		if (num2 <= 0)
		{
			factory.RemovePrebuildWithComponents(num);
			return 0;
		}
		Player mainPlayer = GameMain.mainPlayer;
		if (mainPlayer != null)
		{
			PlayerController controller = mainPlayer.controller;
			if (controller != null)
			{
				PlayerAction_Build actionBuild = controller.actionBuild;
				if (actionBuild != null)
				{
					actionBuild.NotifyBuilt(-num, num2);
				}
			}
		}
		factory.RemovePrebuildWithComponents(num);
		GameHistoryData history = GameMain.history;
		if (history != null)
		{
			history.MarkItemBuilt((int)val3.protoId, 1);
		}
		if (factory.entityPool[num2].beltId > 0)
		{
			factory.OnBeltBuilt(num2);
		}
		if (factory.entityPool[num2].inserterId > 0)
		{
			factory.OnInserterBuilt(num2);
		}
		if ((int)geothermalItem.prefabDesc.addonType != 0)
		{
			factory.OnAddonBuilt(num2);
		}
		factory.OnBuildEntity(num2, num);
		if (!PlanetFactory.batchBuild)
		{
			factory.OnSinglyBuildEntity(num2, num);
		}
		GameScenarioLogic gameScenario = GameMain.gameScenario;
		if (gameScenario != null)
		{
			gameScenario.NotifyOnBuild(factory.planet.id, (int)factory.entityPool[num2].protoId, num2);
		}
		return num2;
	}

	private static Vector3 SnapGeothermalBuildPosition(PlanetData planet, Vector3 ruinPos)
	{
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		if (planet.aux != null)
		{
			return planet.aux.Snap(ruinPos, true);
		}
		return ((Vector3)(ref ruinPos)).normalized * (planet.realRadius + 0.2f);
	}

	private static Vector3 SnapToSurface(PlanetData planet, Vector3 templatePos)
	{
		//IL_000f: 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_0031: Unknown result type (might be due to invalid IL or missing references)
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_002b: 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)
		float num = planet.realRadius + 0.2f;
		Vector3 val = ((Vector3)(ref templatePos)).normalized * num;
		if (planet.aux != null)
		{
			val = planet.aux.Snap(val, true);
		}
		return val;
	}

	private static bool HasRuinWithin(PlanetFactory factory, Vector3 pos, float radius)
	{
		//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_0037: Unknown result type (might be due to invalid IL or missing references)
		float num = radius * radius;
		RuinData[] ruinPool = factory.ruinPool;
		int ruinCursor = factory.ruinCursor;
		for (int i = 1; i < ruinCursor; i++)
		{
			if (ruinPool[i].id == i)
			{
				Vector3 val = ruinPool[i].pos - pos;
				if (((Vector3)(ref val)).sqrMagnitude < num)
				{
					return true;
				}
			}
		}
		return false;
	}

	private static float DeterministicYaw(int index)
	{
		return (float)index * 137.50777f % 360f;
	}

	private static void Report(string message)
	{
		ManualLogSource log = Log;
		if (log != null)
		{
			log.LogInfo((object)message);
		}
		UIRealtimeTip.Popup(message, false, 0);
	}
}
[HarmonyPatch]
internal static class BuildAnywhereOnWaterControl
{
	private const string PatchGuid = "me.liantian.plugin.HardFog.BuildAnywhereOnWater";

	private static ManualLogSource Log;

	private static Harmony harmony;

	private static EventHandler settingChangedHandler;

	internal static ConfigEntry<bool> EnabledConfig { get; private set; }

	internal static void Init(ConfigEntry<bool> enabledConfig, ManualLogSource log)
	{
		if (EnabledConfig != null && settingChangedHandler != null)
		{
			EnabledConfig.SettingChanged -= settingChangedHandler;
		}
		Log = log;
		EnabledConfig = enabledConfig;
		settingChangedHandler = OnSettingChanged;
		EnabledConfig.SettingChanged += settingChangedHandler;
		SetActive(EnabledConfig.Value);
	}

	internal static void Uninit()
	{
		if (EnabledConfig != null && settingChangedHandler != null)
		{
			EnabledConfig.SettingChanged -= settingChangedHandler;
		}
		SetActive(active: false);
		settingChangedHandler = null;
		EnabledConfig = null;
		Log = null;
	}

	private static void OnSettingChanged(object sender, EventArgs args)
	{
		SetActive(EnabledConfig != null && EnabledConfig.Value);
	}

	private static void SetActive(bool active)
	{
		if (active)
		{
			if (harmony == null)
			{
				harmony = Harmony.CreateAndPatchAll(typeof(BuildAnywhereOnWaterControl), "me.liantian.plugin.HardFog.BuildAnywhereOnWater");
				ManualLogSource log = Log;
				if (log != null)
				{
					log.LogInfo((object)"BuildAnywhereOnWater enabled");
				}
			}
		}
		else if (harmony != null)
		{
			harmony.UnpatchSelf();
			harmony = null;
			ManualLogSource log2 = Log;
			if (log2 != null)
			{
				log2.LogInfo((object)"BuildAnywhereOnWater disabled");
			}
		}
	}

	[HarmonyPostfix]
	[HarmonyPatch(typeof(BuildTool_Click), "CheckBuildConditions")]
	private static void BuildToolClickCheckBuildConditionsPostfix(BuildTool_Click __instance, ref bool __result)
	{
		if (((__instance != null) ? ((BuildTool)__instance).buildPreviews : null) != null && ClearNeedGroundConditions(((BuildTool)__instance).buildPreviews))
		{
			__result = IsManualBuildAllowed(((BuildTool)__instance).buildPreviews);
			RefreshManualCursor(__instance, __result);
		}
	}

	[HarmonyPostfix]
	[HarmonyPatch(typeof(BuildTool_BlueprintPaste), "CheckBuildConditions")]
	private static void BuildToolBlueprintPasteCheckBuildConditionsPostfix(BuildTool_BlueprintPaste __instance, ref bool __result)
	{
		if (__instance?.bpPool != null && __instance.bpCursor > 0 && ClearNeedGroundConditions(__instance.bpPool, __instance.bpCursor))
		{
			bool removeConnectionErrors = ClearConnectionErrors(__instance.bpPool, __instance.bpCursor);
			RemoveClearedBlueprintErrors(__instance, removeConnectionErrors);
			__result = IsBlueprintBuildAllowed(__instance);
			if (__result && ((BuildTool)__instance).actionBuild?.model != null)
			{
				((BuildTool)__instance).actionBuild.model.cursorState = 0;
			}
		}
	}

	private static bool ClearNeedGroundConditions(IList<BuildPreview> previews)
	{
		bool flag = false;
		for (int i = 0; i < previews.Count; i++)
		{
			flag |= ClearNeedGroundCondition(previews[i]);
		}
		return flag;
	}

	private static bool ClearNeedGroundConditions(BuildPreview[] previews, int count)
	{
		bool flag = false;
		int num = Math.Min(count, previews.Length);
		for (int i = 0; i < num; i++)
		{
			flag |= ClearNeedGroundCondition(previews[i]);
		}
		return flag;
	}

	private static bool ClearNeedGroundCondition(BuildPreview bp)
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000d: Invalid comparison between Unknown and I4
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		if (bp == null)
		{
			return false;
		}
		if ((int)bp.condition == 23)
		{
			bp.condition = (EBuildCondition)0;
			return true;
		}
		return false;
	}

	private static bool ClearConnectionErrors(BuildPreview[] previews, int count)
	{
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: Invalid comparison between Unknown and I4
		//IL_002d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0037: Invalid comparison between Unknown and I4
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		bool result = false;
		int num = Math.Min(count, previews.Length);
		for (int i = 0; i < num; i++)
		{
			BuildPreview val = previews[i];
			if (val != null && (int)val.condition == 201 && AreConnectionsAllowed(val) && (int)val.condition == 201)
			{
				val.condition = (EBuildCondition)0;
				result = true;
			}
		}
		return result;
	}

	private static bool AreConnectionsAllowed(BuildPreview bp)
	{
		if (IsConnectedPreviewAllowed(bp.input))
		{
			return IsConnectedPreviewAllowed(bp.output);
		}
		return false;
	}

	private static bool IsConnectedPreviewAllowed(BuildPreview bp)
	{
		//IL_0004: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: Invalid comparison between Unknown and I4
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		if (bp == null || (int)bp.condition == 51)
		{
			return true;
		}
		return IsBlueprintAllowedCondition(bp.condition);
	}

	private static bool IsManualBuildAllowed(IList<BuildPreview> previews)
	{
		//IL_0010: 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_001f: Invalid comparison between Unknown and I4
		for (int i = 0; i < previews.Count; i++)
		{
			BuildPreview val = previews[i];
			if (val != null && (int)val.condition != 0 && (int)val.condition != 28)
			{
				return false;
			}
		}
		return true;
	}

	private static bool IsBlueprintBuildAllowed(BuildTool_BlueprintPaste tool)
	{
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		int num = Math.Min(tool.bpCursor, tool.bpPool.Length);
		for (int i = 0; i < num; i++)
		{
			BuildPreview val = tool.bpPool[i];
			if (val != null && val.bpgpuiModelId > 0 && !IsBlueprintAllowedCondition(val.condition))
			{
				return false;
			}
		}
		return true;
	}

	private static bool IsBlueprintAllowedCondition(EBuildCondition condition)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0003: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Invalid comparison between Unknown and I4
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_000a: Invalid comparison between Unknown and I4
		if ((int)condition != 0 && (int)condition != 28)
		{
			return (int)condition == 2;
		}
		return true;
	}

	private static void RemoveClearedBlueprintErrors(BuildTool_BlueprintPaste tool, bool removeConnectionErrors)
	{
		RemoveCondition(tool._tmp_error_types, (EBuildCondition)23);
		RemoveConditionErrorBuildings(tool, (EBuildCondition)23);
		if (removeConnectionErrors)
		{
			RemoveCondition(tool._tmp_error_types, (EBuildCondition)201);
			RemoveConditionErrorBuildings(tool, (EBuildCondition)201);
		}
		if (tool.rootGridErrors == null)
		{
			return;
		}
		List<uint> list = new List<uint>();
		foreach (KeyValuePair<uint, HashSet<EBuildCondition>> rootGridError in tool.rootGridErrors)
		{
			if (rootGridError.Value == null)
			{
				list.Add(rootGridError.Key);
				continue;
			}
			rootGridError.Value.Remove((EBuildCondition)23);
			if (removeConnectionErrors)
			{
				rootGridError.Value.Remove((EBuildCondition)201);
			}
			if (rootGridError.Value.Count == 0)
			{
				list.Add(rootGridError.Key);
			}
		}
		for (int i = 0; i < list.Count; i++)
		{
			tool.rootGridErrors.Remove(list[i]);
		}
	}

	private static void RemoveCondition(List<EBuildCondition> conditions, EBuildCondition condition)
	{
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		if (conditions != null)
		{
			while (conditions.Remove(condition))
			{
			}
		}
	}

	private static void RemoveConditionErrorBuildings(BuildTool_BlueprintPaste tool, EBuildCondition condition)
	{
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: Invalid comparison between I4 and Unknown
		if (tool._tmpErrorBuildings == null || tool._tmpErrorTipsCursor <= 0)
		{
			return;
		}
		int num = 0;
		int num2 = Math.Min(tool._tmpErrorTipsCursor, tool._tmpErrorBuildings.Length);
		for (int i = 0; i < num2; i++)
		{
			ulong num3 = tool._tmpErrorBuildings[i];
			if ((int)(num3 >> 48) != (int)condition)
			{
				if (num != i)
				{
					tool._tmpErrorBuildings[num] = num3;
				}
				num++;
			}
		}
		for (int j = num; j < num2; j++)
		{
			tool._tmpErrorBuildings[j] = 0uL;
		}
		tool._tmpErrorTipsCursor = num;
	}

	private static void RefreshManualCursor(BuildTool_Click tool, bool allowed)
	{
		//IL_0055: Unknown result type (might be due to invalid IL or missing references)
		//IL_005d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0064: Invalid comparison between Unknown and I4
		if (((BuildTool)tool).actionBuild?.model == null)
		{
			return;
		}
		if (allowed)
		{
			((BuildTool)tool).actionBuild.model.cursorState = 0;
			((BuildTool)tool).actionBuild.model.cursorText = BuildPreview.GetConditionText((EBuildCondition)0);
			return;
		}
		for (int i = 0; i < ((BuildTool)tool).buildPreviews.Count; i++)
		{
			BuildPreview val = ((BuildTool)tool).buildPreviews[i];
			if (val != null && (int)val.condition != 0 && (int)val.condition != 28)
			{
				((BuildTool)tool).actionBuild.model.cursorState = -1;
				((BuildTool)tool).actionBuild.model.cursorText = val.conditionText;
				break;
			}
		}
	}
}
[HarmonyPatch]
internal static class SuperThreatReducerControl
{
	private const string PatchGuid = "me.liantian.plugin.HardFog.SuperThreatReducer";

	private static ManualLogSource Log;

	private static Harmony harmony;

	private static EventHandler settingChangedHandler;

	internal static ConfigEntry<bool> EnabledConfigHive { get; private set; }

	internal static ConfigEntry<bool> EnabledConfigGround { get; private set; }

	private static bool IsAnyEnabled
	{
		get
		{
			if (EnabledConfigHive == null || !EnabledConfigHive.Value)
			{
				if (EnabledConfigGround != null)
				{
					return EnabledConfigGround.Value;
				}
				return false;
			}
			return true;
		}
	}

	internal static void Init(ConfigEntry<bool> enabledConfigHive, ConfigEntry<bool> enabledConfigGround, ManualLogSource log)
	{
		if (EnabledConfigHive != null && settingChangedHandler != null)
		{
			EnabledConfigHive.SettingChanged -= settingChangedHandler;
			EnabledConfigGround.SettingChanged -= settingChangedHandler;
		}
		Log = log;
		EnabledConfigHive = enabledConfigHive;
		EnabledConfigGround = enabledConfigGround;
		settingChangedHandler = OnSettingChanged;
		EnabledConfigHive.SettingChanged += settingChangedHandler;
		EnabledConfigGround.SettingChanged += settingChangedHandler;
		UpdateHarmonyState();
	}

	internal static void Uninit()
	{
		if (EnabledConfigHive != null && settingChangedHandler != null)
		{
			EnabledConfigHive.SettingChanged -= settingChangedHandler;
			EnabledConfigGround.SettingChanged -= settingChangedHandler;
		}
		DestroyHarmony();
		settingChangedHandler = null;
		EnabledConfigHive = null;
		EnabledConfigGround = null;
		Log = null;
	}

	private static void OnSettingChanged(object sender, EventArgs args)
	{
		UpdateHarmonyState();
	}

	private static void UpdateHarmonyState()
	{
		if (IsAnyEnabled)
		{
			EnsureHarmony();
		}
		else
		{
			DestroyHarmony();
		}
	}

	private static void EnsureHarmony()
	{
		if (harmony == null)
		{
			harmony = Harmony.CreateAndPatchAll(typeof(SuperThreatReducerControl), "me.liantian.plugin.HardFog.SuperThreatReducer");
			ManualLogSource log = Log;
			if (log != null)
			{
				log.LogInfo((object)"SuperThreatReducer enabled");
			}
		}
	}

	private static void DestroyHarmony()
	{
		if (harmony != null)
		{
			harmony.UnpatchSelf();
			harmony = null;
			ManualLogSource log = Log;
			if (log != null)
			{
				log.LogInfo((object)"SuperThreatReducer disabled");
			}
		}
	}

	[HarmonyPostfix]
	[HarmonyPatch(typeof(EnemyDFHiveSystem), "DecisionAI")]
	private static void EnemyDFHiveSystem_DecisionAI_Postfix(EnemyDFHiveSystem __instance)
	{
		if (EnabledConfigHive != null && EnabledConfigHive.Value && __instance != null && __instance.realized && __instance.isAlive)
		{
			__instance.evolve.threat = 0;
			__instance.evolve.threatshr = 0;
		}
	}

	[HarmonyPrefix]
	[HarmonyPatch(typeof(EnemyDFHiveSystem), "AssaultingWavesDetermineAI")]
	private static bool EnemyDFHiveSystem_AssaultingWavesDetermineAI_Prefix()
	{
		if (EnabledConfigHive == null || !EnabledConfigHive.Value)
		{
			return true;
		}
		return false;
	}

	[HarmonyPrefix]
	[HarmonyPatch(typeof(DFGBaseComponent), "UpdateFactoryThreat")]
	private static bool DFGBaseComponent_UpdateFactoryThreat_Prefix()
	{
		if (EnabledConfigGround == null || !EnabledConfigGround.Value)
		{
			return true;
		}
		return false;
	}
}
[HarmonyPatch]
internal static class RelayControl
{
	private const string PatchGuid = "me.liantian.plugin.HardFog.RelayControl";

	private const int VanillaRelayDemandInterval = 600;

	private const int FasterRelayDemandInterval = 120;

	private static ManualLogSource Log;

	private static Harmony harmony;

	private static EventHandler fasterRelayLaunchChangedHandler;

	internal static ConfigEntry<bool> FasterRelayLaunchEnabledConfig { get; private set; }

	internal static ConfigEntry<bool> SmartRelayDispatchEnabledConfig { get; private set; }

	internal static void Init(ConfigEntry<bool> fasterRelayLaunchEnabledConfig, ConfigEntry<bool> smartRelayDispatchEnabledConfig, ManualLogSource log)
	{
		if (FasterRelayLaunchEnabledConfig != null && fasterRelayLaunchChangedHandler != null)
		{
			FasterRelayLaunchEnabledConfig.SettingChanged -= fasterRelayLaunchChangedHandler;
		}
		Log = log;
		FasterRelayLaunchEnabledConfig = fasterRelayLaunchEnabledConfig;
		SmartRelayDispatchEnabledConfig = smartRelayDispatchEnabledConfig;
		fasterRelayLaunchChangedHandler = OnFasterRelayLaunchChanged;
		FasterRelayLaunchEnabledConfig.SettingChanged += fasterRelayLaunchChangedHandler;
		SetActive(FasterRelayLaunchEnabledConfig.Value);
	}

	internal static void Uninit()
	{
		if (FasterRelayLaunchEnabledConfig != null && fasterRelayLaunchChangedHandler != null)
		{
			FasterRelayLaunchEnabledConfig.SettingChanged -= fasterRelayLaunchChangedHandler;
		}
		SetActive(active: false);
		fasterRelayLaunchChangedHandler = null;
		FasterRelayLaunchEnabledConfig = null;
		SmartRelayDispatchEnabledConfig = null;
		Log = null;
	}

	private static void OnFasterRelayLaunchChanged(object sender, EventArgs args)
	{
		SetActive(FasterRelayLaunchEnabledConfig != null && FasterRelayLaunchEnabledConfig.Value);
	}

	private static void SetActive(bool active)
	{
		if (active)
		{
			if (harmony == null)
			{
				harmony = Harmony.CreateAndPatchAll(typeof(RelayControl), "me.liantian.plugin.HardFog.RelayControl");
				ManualLogSource log = Log;
				if (log != null)
				{
					log.LogInfo((object)"RelayControl enabled");
				}
			}
		}
		else if (harmony != null)
		{
			harmony.UnpatchSelf();
			harmony = null;
			ManualLogSource log2 = Log;
			if (log2 != null)
			{
				log2.LogInfo((object)"RelayControl disabled");
			}
		}
	}

	[HarmonyPrefix]
	[HarmonyPatch(typeof(EnemyDFHiveSystem), "DetermineRelayDemand")]
	private static bool EnemyDFHiveSystemDetermineRelayDemandPrefix(EnemyDFHiveSystem __instance)
	{
		DispatchOneIdleRelayIfAllowed(__instance);
		return false;
	}

	[HarmonyTranspiler]
	[HarmonyPatch(typeof(EnemyDFHiveSystem), "UpdateMatterStatisticsVirtual")]
	private static IEnumerable<CodeInstruction> EnemyDFHiveSystemUpdateMatterStatisticsVirtualTranspiler(IEnumerable<CodeInstruction> instructions)
	{
		return ReplaceRelayDemandInterval(instructions);
	}

	[HarmonyTranspiler]
	[HarmonyPatch(typeof(EnemyDFHiveSystem), "UpdateMatterStatisticsRealized")]
	private static IEnumerable<CodeInstruction> EnemyDFHiveSystemUpdateMatterStatisticsRealizedTranspiler(IEnumerable<CodeInstruction> instructions)
	{
		return ReplaceRelayDemandInterval(instructions);
	}

	[HarmonyPrefix]
	[HarmonyPatch(typeof(DFRelayComponent), "SearchTargetPlaceProcess")]
	private static bool DFRelayComponentSearchTargetPlaceProcessPrefix(DFRelayComponent __instance, ref bool __result)
	{
		//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)
		if (__instance == null)
		{
			return true;
		}
		if (IsMarkerOnlyEnabled())
		{
			if (IsRelayMarkerStillValid(__instance))
			{
				return true;
			}
			CancelDockDispatch(__instance);
			__result = false;
			return false;
		}
		if (__instance.dstMarkerAstroId > 0 || __instance.dstMarkerId > 0 || __instance.searchAstroId != 0)
		{
			return true;
		}
		EnemyDFHiveSystem hive = __instance.hive;
		StarData val = hive?.starData;
		if (val == null)
		{
			return true;
		}
		int num = CountNonGasPlanets(val);
		if (num <= 0)
		{
			return true;
		}
		int pick = RandomTable.Integer(ref hive.rtseed, num);
		PlanetData val2 = PickNonGasPlanet(val, pick);
		if (val2 == null)
		{
			return true;
		}
		__instance.searchAstroId = val2.astroId;
		__instance.searchBaseId = 0;
		__instance.searchChance = 5;
		__instance.searchLPos = Vector3.zero;
		__instance.searchEntityCursor = 0;
		__result = false;
		return false;
	}

	private static IEnumerable<CodeInstruction> ReplaceRelayDemandInterval(IEnumerable<CodeInstruction> instructions)
	{
		List<CodeInstruction> list = new List<CodeInstruction>(instructions);
		int num = 0;
		for (int i = 0; i < list.Count; i++)
		{
			if (LoadsInt(list[i], 600))
			{
				list[i].opcode = OpCodes.Ldc_I4;
				list[i].operand = 120;
				num++;
			}
		}
		if (num == 0)
		{
			ManualLogSource log = Log;
			if (log != null)
			{
				log.LogWarning((object)"Failed to patch relay demand interval.");
			}
		}
		return list;
	}

	private static bool LoadsInt(CodeInstruction code, int value)
	{
		if (code.opcode == OpCodes.Ldc_I4 && code.operand is int num)
		{
			return num == value;
		}
		if (code.opcode == OpCodes.Ldc_I4_S && code.operand is sbyte b)
		{
			return b == value;
		}
		if (code.opcode == OpCodes.Ldc_I4_0)
		{
			return value == 0;
		}
		if (code.opcode == OpCodes.Ldc_I4_1)
		{
			return value == 1;
		}
		if (code.opcode == OpCodes.Ldc_I4_2)
		{
			return value == 2;
		}
		if (code.opcode == OpCodes.Ldc_I4_3)
		{
			return value == 3;
		}
		if (code.opcode == OpCodes.Ldc_I4_4)
		{
			return value == 4;
		}
		if (code.opcode == OpCodes.Ldc_I4_5)
		{
			return value == 5;
		}
		if (code.opcode == OpCodes.Ldc_I4_6)
		{
			return value == 6;
		}
		if (code.opcode == OpCodes.Ldc_I4_7)
		{
			return value == 7;
		}
		if (code.opcode == OpCodes.Ldc_I4_8)
		{
			return value == 8;
		}
		return false;
	}

	private static void DispatchOneIdleRelayIfAllowed(EnemyDFHiveSystem hive)
	{
		if (hive == null || hive.relays == null || hive.idleRelayCount <= 0 || HasOutgoingRelay(hive))
		{
			return;
		}
		if (IsMarkerOnlyEnabled())
		{
			DispatchOneIdleRelayToMarkerIfAllowed(hive);
			return;
		}
		for (int i = 0; i < hive.idleRelayCount; i++)
		{
			int num = hive.idleRelayIds[i];
			if (num > 0)
			{
				DFRelayComponent val = hive.relays.buffer[num];
				if (val != null && val.id == num && val.TryDispatchFromHive())
				{
					break;
				}
			}
		}
	}

	private static void DispatchOneIdleRelayToMarkerIfAllowed(EnemyDFHiveSystem hive)
	{
		if (!TryPickAvailableRelayMarker(hive, out var factory, out var markerId))
		{
			return;
		}
		for (int i = 0; i < hive.idleRelayCount; i++)
		{
			int num = hive.idleRelayIds[i];
			if (num <= 0)
			{
				continue;
			}
			DFRelayComponent val = hive.relays.buffer[num];
			if (val != null && val.id == num && val.TryDispatchFromHive())
			{
				val.SetTargetedMarker(factory, markerId);
				if (!IsRelayMarkerStillValid(val))
				{
					CancelDockDispatch(val);
				}
				break;
			}
		}
	}

	private static bool TryPickAvailableRelayMarker(EnemyDFHiveSystem hive, out PlanetFactory factory, out int markerId)
	{
		factory = null;
		markerId = 0;
		int num = CountAvailableRelayMarkers(hive);
		if (num <= 0)
		{
			return false;
		}
		int num2 = num;
		StarData starData = hive.starData;
		for (int i = 0; i < starData.planetCount; i++)
		{
			PlanetData planet = starData.planets[i];
			PlanetFactory markerPlanetFactory = GetMarkerPlanetFactory(hive, planet);
			if (markerPlanetFactory == null)
			{
				continue;
			}
			ObjectPool<MarkerComponent> markers = markerPlanetFactory.digitalSystem.markers;
			for (int j = 1; j < markers.cursor; j++)
			{
				MarkerComponent val = markers[j];
				if (IsAvailableRelayMarker(hive, markerPlanetFactory, val, j))
				{
					float num3 = val.power / (float)num2;
					if (Random.value < num3)
					{
						factory = markerPlanetFactory;
						markerId = j;
						return true;
					}
					num2--;
				}
			}
		}
		return false;
	}

	private static int CountAvailableRelayMarkers(EnemyDFHiveSystem hive)
	{
		int num = 0;
		StarData starData = hive.starData;
		for (int i = 0; i < starData.planetCount; i++)
		{
			PlanetData planet = starData.planets[i];
			PlanetFactory markerPlanetFactory = GetMarkerPlanetFactory(hive, planet);
			if (markerPlanetFactory == null)
			{
				continue;
			}
			ObjectPool<MarkerComponent> markers = markerPlanetFactory.digitalSystem.markers;
			for (int j = 1; j < markers.cursor; j++)
			{
				if (IsAvailableRelayMarker(hive, markerPlanetFactory, markers[j], j))
				{
					num++;
				}
			}
		}
		return num;
	}

	private static PlanetFactory GetMarkerPlanetFactory(EnemyDFHiveSystem hive, PlanetData planet)
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_000d: Invalid comparison between Unknown and I4
		if (hive == null || planet == null || (int)planet.type == 5 || planet.star != hive.starData || planet.factory == null || planet.factory.entityCount == 0 || planet.factory.digitalSystem == null)
		{
			return null;
		}
		return planet.factory;
	}

	private static bool IsAvailableRelayMarker(EnemyDFHiveSystem hive, PlanetFactory factory, MarkerComponent marker, int markerId)
	{
		if (marker != null && marker.id == markerId && marker.attractsDFRelay)
		{
			return !IsMarkerAlreadyTargeted(hive, factory.planet.astroId, markerId);
		}
		return false;
	}

	private static bool IsMarkerAlreadyTargeted(EnemyDFHiveSystem hive, int astroId, int markerId)
	{
		for (EnemyDFHiveSystem val = hive.firstSibling; val != null; val = val.nextSibling)
		{
			DFRelayComponent[] buffer = val.relays.buffer;
			int cursor = val.relays.cursor;
			for (int i = 1; i < cursor; i++)
			{
				DFRelayComponent val2 = buffer[i];
				if (val2 != null && val2.id == i && val2.direction > 0 && val2.dstMarkerAstroId == astroId && val2.dstMarkerId == markerId)
				{
					return true;
				}
			}
		}
		return false;
	}

	private static bool HasOutgoingRelay(EnemyDFHiveSystem hive)
	{
		DFRelayComponent[] buffer = hive.relays.buffer;
		int cursor = hive.relays.cursor;
		for (int i = 1; i < cursor; i++)
		{
			DFRelayComponent val = buffer[i];
			if (val != null && val.id == i && val.direction > 0)
			{
				return true;
			}
		}
		return false;
	}

	private static bool IsRelayMarkerStillValid(DFRelayComponent relay)
	{
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_0048: Invalid comparison between Unknown and I4
		//IL_0114: Unknown result type (might be due to invalid IL or missing references)
		//IL_011a: Unknown result type (might be due to invalid IL or missing references)
		//IL_011f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0124: Unknown result type (might be due to invalid IL or missing references)
		if (relay.dstMarkerAstroId <= 0 || relay.dstMarkerId <= 0 || relay.hive == null)
		{
			return false;
		}
		PlanetFactory val = relay.hive.sector.galaxy.astrosFactory[relay.dstMarkerAstroId];
		if (val == null || (int)val.planet.type == 5 || val.planet.star != relay.hive.starData || val.digitalSystem == null || relay.dstMarkerId >= val.digitalSystem.markers.cursor)
		{
			return false;
		}
		MarkerComponent val2 = val.digitalSystem.markers[relay.dstMarkerId];
		if (val2 == null || val2.id != relay.dstMarkerId || !val2.attractsDFRelay)
		{
			return false;
		}
		if (((Vector3)(ref relay.dstMarkerLPos)).sqrMagnitude < (val.planet.realRadius - 2f) * (val.planet.realRadius - 2f))
		{
			return false;
		}
		if (val2.entityId <= 0 || val2.entityId >= val.entityPool.Length)
		{
			return false;
		}
		Vector3 val3 = val.entityPool[val2.entityId].pos - relay.dstMarkerLPos;
		return ((Vector3)(ref val3)).sqrMagnitude <= 0.25f;
	}

	private static void CancelDockDispatch(DFRelayComponent relay)
	{
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_000d: 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)
		relay.targetAstroId = 0;
		relay.targetLPos = Vector3.zero;
		relay.targetYaw = 0f;
		relay.baseState = 0;
		relay.baseId = 0;
		relay.baseTicks = 0;
		relay.baseEvolve = default(EvolveData);
		relay.baseRespawnCD = 0;
		relay.direction = 0;
		relay.param0 = 0f;
		relay.uSpeed = 0f;
		relay.ResetSearchStates();
		relay.ResetTargetedMarker();
	}

	private static bool IsMarkerOnlyEnabled()
	{
		if (FasterRelayLaunchEnabledConfig != null && FasterRelayLaunchEnabledConfig.Value && SmartRelayDispatchEnabledConfig != null)
		{
			return SmartRelayDispatchEnabledConfig.Value;
		}
		return false;
	}

	private static int CountNonGasPlanets(StarData starData)
	{
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		//IL_0019: Invalid comparison between Unknown and I4
		int num = 0;
		for (int i = 0; i < starData.planetCount; i++)
		{
			PlanetData val = starData.planets[i];
			if (val != null && (int)val.type != 5)
			{
				num++;
			}
		}
		return num;
	}

	private static PlanetData PickNonGasPlanet(StarData starData, int pick)
	{
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_0017: Invalid comparison between Unknown and I4
		for (int i = 0; i < starData.planetCount; i++)
		{
			PlanetData val = starData.planets[i];
			if (val != null && (int)val.type != 5)
			{
				if (pick == 0)
				{
					return val;
				}
				pick--;
			}
		}
		return null;
	}
}
[HarmonyPatch]
internal static class FasterResearchControl
{
	private const string PatchGuid = "me.liantian.plugin.HardFog.FasterResearch";

	private const int Multiplier = 48;

	private static ManualLogSource Log;

	private static Harmony harmony;

	private static EventHandler settingChangedHandler;

	internal static ConfigEntry<bool> EnabledConfig { get; private set; }

	internal static void Init(ConfigEntry<bool> enabledConfig, ManualLogSource log)
	{
		if (EnabledConfig != null && settingChangedHandler != null)
		{
			EnabledConfig.SettingChanged -= settingChangedHandler;
		}
		Log = log;
		EnabledConfig = enabledConfig;
		settingChangedHandler = OnSettingChanged;
		EnabledConfig.SettingChanged += settingChangedHandler;
		SetActive(EnabledConfig.Value);
	}

	internal static void Uninit()
	{
		if (EnabledConfig != null && settingChangedHandler != null)
		{
			EnabledConfig.SettingChanged -= settingChangedHandler;
		}
		SetActive(active: false);
		settingChangedHandler = null;
		EnabledConfig = null;
		Log = null;
	}

	private static void OnSettingChanged(object sender, EventArgs args)
	{
		SetActive(EnabledConfig != null && EnabledConfig.Value);
	}

	private static void SetActive(bool active)
	{
		if (active)
		{
			if (harmony == null)
			{
				harmony = Harmony.CreateAndPatchAll(typeof(FasterResearchControl), "me.liantian.plugin.HardFog.FasterResearch");
				ManualLogSource log = Log;
				if (log != null)
				{
					log.LogInfo((object)("FasterResearch enabled, multiplier = " + 48));
				}
			}
			SyncCurrentTechHashNeeded(GameMain.history);
		}
		else if (harmony != null)
		{
			harmony.UnpatchSelf();
			harmony = null;
			ManualLogSource log2 = Log;
			if (log2 != null)
			{
				log2.LogInfo((object)"FasterResearch disabled");
			}
			SyncCurrentTechHashNeeded(GameMain.history);
		}
	}

	[HarmonyPostfix]
	[HarmonyPatch(typeof(TechProto), "GetHashNeeded")]
	private static void TechProtoGetHashNeededPostfix(ref long __result)
	{
		__result = DivideRoundUp(__result, 48);
	}

	[HarmonyPostfix]
	[HarmonyPatch(typeof(GameHistoryData), "SetForNewGame")]
	private static void GameHistoryDataSetForNewGamePostfix(GameHistoryData __instance)
	{
		SyncCurrentTechHashNeeded(__instance);
	}

	[HarmonyPostfix]
	[HarmonyPatch(typeof(GameHistoryData), "Import")]
	private static void GameHistoryDataImportPostfix(GameHistoryData __instance, bool isPreview)
	{
		if (!isPreview)
		{
			SyncCurrentTechHashNeeded(__instance);
		}
	}

	private static long DivideRoundUp(long value, int divisor)
	{
		if (value <= 0)
		{
			return value;
		}
		return (value + divisor - 1) / divisor;
	}

	private static void SyncCurrentTechHashNeeded(GameHistoryData history)
	{
		//IL_0036: 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_003c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0056: 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_006c: 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_0076: Unknown result type (might be due to invalid IL or missing references)
		if (history?.techStates == null)
		{
			return;
		}
		foreach (int item in new List<int>(history.techStates.Keys))
		{
			TechState val = history.techStates[item];
			if (val.unlocked)
			{
				continue;
			}
			TechProto val2 = ((ProtoSet<TechProto>)(object)LDB.techs).Select(item);
			if (val2 != null)
			{
				val.hashNeeded = val2.GetHashNeeded(val.curLevel);
				if (val.hashUploaded >= val.hashNeeded)
				{
					val.hashUploaded = val.hashNeeded - 1;
				}
				history.techStates[item] = val;
			}
		}
	}
}
[HarmonyPatch]
internal static class VeinPlacementControl
{
	private sealed class VeinGroupWork
	{
		public readonly short GroupIndex;

		public readonly EVeinType Type;

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

		public VeinGroupWork(short groupIndex, EVeinType type)
		{
			//IL_0019: 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)
			GroupIndex = groupIndex;
			Type = type;
		}
	}

	private const string PatchGuid = "me.liantian.plugin.HardFog.VeinPlacement";

	private const int ModSeedSalt = 1448095793;

	private const float TargetLatitudeDegrees = 40f;

	private const float TargetLongitudeDegrees = 80f;

	private const float NormalGroupSpacing = 196f;

	private const float OilGroupSpacing = 100f;

	private const float InnerVeinMinDistanceSqr = 0.5f;

	private const float InnerVeinMaxRadiusSqr = 13f;

	private const int GroupPlacementAttempts = 24;

	private const int LongitudeExpansionPasses = 100;

	private const float LongitudeExpansionStepDegrees = 30f;

	private const int LocalShapePasses = 20;

	private const int LocalFallbackAttempts = 8192;

	private static ManualLogSource Log;

	private static Harmony harmony;

	private static EventHandler settingChangedHandler;

	private static readonly FieldRef<PlanetAlgorithm, PlanetData> PlanetRef = AccessTools.FieldRefAccess<PlanetAlgorithm, PlanetData>("planet");

	internal static ConfigEntry<bool> EnabledConfig { get; private set; }

	internal static void Init(ConfigEntry<bool> enabledConfig, ManualLogSource log)
	{
		if (EnabledConfig != null && settingChangedHandler != null)
		{
			EnabledConfig.SettingChanged -= settingChangedHandler;
		}
		Log = log;
		EnabledConfig = enabledConfig;
		settingChangedHandler = OnSettingChanged;
		EnabledConfig.SettingChanged += settingChangedHandler;
		SetActive(EnabledConfig.Value);
	}

	internal static void Uninit()
	{
		if (EnabledConfig != null && settingChangedHandler != null)
		{
			EnabledConfig.SettingChanged -= settingChangedHandler;
		}
		SetActive(active: false);
		settingChangedHandler = null;
		EnabledConfig = null;
		Log = null;
	}

	private static void OnSettingChanged(object sender, EventArgs args)
	{
		SetActive(EnabledConfig != null && EnabledConfig.Value);
	}

	private static void SetActive(bool active)
	{
		if (active)
		{
			if (harmony == null)
			{
				harmony = Harmony.CreateAndPatchAll(typeof(VeinPlacementControl), "me.liantian.plugin.HardFog.VeinPlacement");
				ManualLogSource log = Log;
				if (log != null)
				{
					log.LogInfo((object)"VeinPlacement enabled");
				}
			}
		}
		else if (harmony != null)
		{
			harmony.UnpatchSelf();
			harmony = null;
			ManualLogSource log2 = Log;
			if (log2 != null)
			{
				log2.LogInfo((object)"VeinPlacement disabled");
			}
		}
	}

	private static void ApplyPlacement(PlanetAlgorithm algorithm)
	{
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Invalid comparison between Unknown and I4
		//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_0094: 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)
		//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
		PlanetData planet = GetPlanet(algorithm);
		if (planet == null || (int)planet.type == 5 || planet.data == null || planet.data.veinPool == null || planet.data.veinCursor <= 1)
		{
			return;
		}
		List<VeinGroupWork> list = InterleaveGroupsByType(CollectGroups(planet));
		if (list.Count == 0)
		{
			return;
		}
		DotNet35Random rng = CreateRandom(planet);
		Vector3 birthDirection = EnsureBirthPointDirection(planet);
		if (((Vector3)(ref birthDirection)).sqrMagnitude < 0.5f)
		{
			ManualLogSource log = Log;
			if (log != null)
			{
				log.LogWarning((object)("Unable to read birth point on planet " + (planet.displayName ?? planet.name)));
			}
			return;
		}
		List<Vector3> list2 = PlaceGroupCenters(planet, list, birthDirection, rng);
		PlanetRawData data = planet.data;
		for (int i = 0; i < list.Count; i++)
		{
			Vector3 val = list2[i];
			if (!(((Vector3)(ref val)).sqrMagnitude < 0.5f))
			{
				RegenerateGroupVeins(planet, data, list[i], list2[i], rng);
			}
		}
		planet.SummarizeVeinGroups();
	}

	private static PlanetData GetPlanet(PlanetAlgorithm algorithm)
	{
		if (algorithm == null)
		{
			return null;
		}
		try
		{
			return PlanetRef.Invoke(algorithm);
		}
		catch (Exception ex)
		{
			ManualLogSource log = Log;
			if (log != null)
			{
				log.LogWarning((object)("Unable to read PlanetAlgorithm.planet: " + ex.Message));
			}
			return null;
		}
	}

	private static DotNet35Random CreateRandom(PlanetData planet)
	{
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_002c: Expected O, but got Unknown
		return new DotNet35Random((((planet.seed * 397) ^ planet.id) * 397) ^ planet.algoId ^ 0x56503031);
	}

	private static List<VeinGroupWork> CollectGroups(PlanetData planet)
	{
		//IL_0042: 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)
		Dictionary<short, VeinGroupWork> dictionary = new Dictionary<short, VeinGroupWork>();
		List<VeinGroupWork> list = new List<VeinGroupWork>();
		VeinData[] veinPool = planet.data.veinPool;
		int veinCursor = planet.data.veinCursor;
		for (int i = 1; i < veinCursor; i++)
		{
			if (veinPool[i].id != i || (int)veinPool[i].type == 0)
			{
				continue;
			}
			short groupIndex = veinPool[i].groupIndex;
			if (groupIndex > 0)
			{
				if (!dictionary.TryGetValue(groupIndex, out var value))
				{
					value = (dictionary[groupIndex] = new VeinGroupWork(groupIndex, veinPool[i].type));
					list.Add(value);
				}
				value.VeinIds.Add(i);
			}
		}
		return list;
	}

	private static List<VeinGroupWork> InterleaveGroupsByType(List<VeinGroupWork> groups)
	{
		//IL_0020: 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)
		Dictionary<EVeinType, List<VeinGroupWork>> dictionary = new Dictionary<EVeinType, List<VeinGroupWork>>();
		List<List<VeinGroupWork>> list = new List<List<VeinGroupWork>>();
		int num = 0;
		for (int i = 0; i < groups.Count; i++)
		{
			VeinGroupWork veinGroupWork = groups[i];
			if (!dictionary.TryGetValue(veinGroupWork.Type, out var value))
			{
				value = new List<VeinGroupWork>();
				dictionary[veinGroupWork.Type] = value;
				list.Add(value);
			}
			value.Add(veinGroupWork);
			if (value.Count > num)
			{
				num = value.Count;
			}
		}
		List<VeinGroupWork> list2 = new List<VeinGroupWork>(groups.Count);
		for (int j = 0; j < num; j++)
		{
			for (int k = 0; k < list.Count; k++)
			{
				if (j < list[k].Count)
				{
					list2.Add(list[k][j]);
				}
			}
		}
		return list2;
	}

	private static void Shuffle<T>(IList<T> items, DotNet35Random rng)
	{
		for (int num = items.Count - 1; num > 0; num--)
		{
			int index = rng.Next(num + 1);
			T value = items[num];
			items[num] = items[index];
			items[index] = value;
		}
	}

	private static Vector3 EnsureBirthPointDirection(PlanetData planet)
	{
		//IL_0070: 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)
		if (((Vector3)(ref planet.birthPoint)).sqrMagnitude < 1E-08f)
		{
			try
			{
				planet.GenBirthPoints();
			}
			catch (Exception ex)
			{
				ManualLogSource log = Log;
				if (log != null)
				{
					log.LogWarning((object)("Unable to generate birth point on planet " + (planet.displayName ?? planet.name) + ": " + ex.Message));
				}
			}
		}
		if (((Vector3)(ref planet.birthPoint)).sqrMagnitude < 1E-08f)
		{
			return Vector3.zero;
		}
		return ((Vector3)(ref planet.birthPoint)).normalized;
	}

	private static List<Vector3> PlaceGroupCenters(PlanetData planet, List<VeinGroupWork> groups, Vector3 birthDirection, DotNet35Random rng)
	{
		//IL_0022: 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_0037: 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_0047: Unknown result type (might be due to invalid IL or missing references)
		//IL_006a: Unknown result type (might be due to invalid IL or missing references)
		//IL_007d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0082: 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_005d: 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_0066: Unknown result type (might be due to invalid IL or missing references)
		//IL_0093: Unknown result type (might be due to invalid IL or missing references)
		List<Vector3> list = new List<Vector3>(groups.Count);
		List<Vector3> list2 = new List<Vector3>(groups.Count);
		if (groups.Count == 0)
		{
			return list;
		}
		float centerLongitude = LongitudeFromDirection(birthDirection);
		list.Add(birthDirection);
		list2.Add(birthDirection);
		Vector3 anchor = birthDirection;
		for (int i = 1; i < groups.Count; i++)
		{
			if (TryPlaceGroupCenter(planet, groups[i], anchor, centerLongitude, rng, list2, out var center))
			{
				list.Add(center);
				list2.Add(center);
				anchor = center;
				continue;
			}
			list.Add(Vector3.zero);
			Vector3 originalGroupCenter = GetOriginalGroupCenter(planet, groups[i]);
			if (((Vector3)(ref originalGroupCenter)).sqrMagnitude > 0.5f)
			{
				list2.Add(originalGroupCenter);
			}
		}
		return list;
	}

	private static bool TryPlaceGroupCenter(PlanetData planet, VeinGroupWork group, Vector3 anchor, float centerLongitude, DotNet35Random rng, List<Vector3> placedCenters, out Vector3 center)
	{
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_008a: Unknown result type (might be due to invalid IL or missing references)
		//IL_008f: Unknown result type (might be due to invalid IL or missing references)
		float minDistanceSqr = GetMinDistanceSqr(planet, group);
		float num = Mathf.Sqrt(minDistanceSqr);
		for (int i = 1; i <= 3; i++)
		{
			if (TryPlaceOnDistanceBand(planet, group, anchor, num * (float)i, num * (float)(i + 1), centerLongitude, 80f, rng, placedCenters, minDistanceSqr, out center))
			{
				return true;
			}
		}
		if (TryPlaceRandomInWindow(planet, group, centerLongitude, 80f, rng, placedCenters, minDistanceSqr, out center))
		{
			return true;
		}
		for (int j = 1; j <= 100; j++)
		{
			float longitudeHalfWidthDegrees = 80f + 30f * (float)j;
			if (TryPlaceRandomInWindow(planet, group, centerLongitude, longitudeHalfWidthDegrees, rng, placedCenters, minDistanceSqr, out center))
			{
				return true;
			}
		}
		center = Vector3.zero;
		return false;
	}

	private static bool TryPlaceOnDistanceBand(PlanetData planet, VeinGroupWork group, Vector3 anchor, float minDistance, float maxDistance, float centerLongitude, float longitudeHalfWidthDegrees, DotNet35Random rng, List<Vector3> placedCenters, float minDistanceSqr, out Vector3 center)
	{
		//IL_0031: 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_0039: 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_0061: 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_004e: 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)
		for (int i = 0; i < 24; i++)
		{
			float chordDistance = minDistance + (float)rng.NextDouble() * (maxDistance - minDistance);
			float angle = (float)(rng.NextDouble() * Math.PI * 2.0);
			Vector3 val = DirectionAtChordDistance(anchor, chordDistance, angle);
			if (IsValidCandidate(p