Decompiled source of DSPMiaoToolbox v2.23.27

BepInEx\plugins\DSPMiaoToolbox\DSPMiaoToolbox.dll

Decompiled a day ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
using BPTropicFree;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using DSPBPColliderSnap;
using DSPBlueprintOffset;
using DSPMiaoToolbox;
using HarmonyLib;
using HoverCoord;
using TropicBeltSpacing;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyFileVersion("2.23.27.0")]
[assembly: AssemblyInformationalVersion("2.23.27")]
[assembly: AssemblyVersion("2.23.27.0")]
namespace BPTropicFree
{
	internal static class TropicFreeFeature
	{
		private static KeyCode _mainKey = (KeyCode)117;

		private static KeyCode[] _mods = (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 };

		private static bool _tickLogged;

		internal static bool Enabled
		{
			get
			{
				if (ModConfig.Enable != null)
				{
					return ModConfig.Enable.Value;
				}
				return false;
			}
		}

		internal static bool IgnoreLimits
		{
			get
			{
				if (ModConfig.IgnoreTropicLimits != null)
				{
					return ModConfig.IgnoreTropicLimits.Value;
				}
				return false;
			}
		}

		internal static bool UniformGrid
		{
			get
			{
				if (ModConfig.UniformRigidGrid != null)
				{
					return ModConfig.UniformRigidGrid.Value;
				}
				return false;
			}
		}

		internal static void Init()
		{
			ModConfig.Init();
			if (ModConfig.ToggleHotKey != null)
			{
				ModConfig.ToggleHotKey.SettingChanged += OnHotkeySettingChanged;
			}
			ReparseHotkey();
		}

		private static void OnHotkeySettingChanged(object sender, EventArgs e)
		{
			ReparseHotkey();
		}

		private static void ReparseHotkey()
		{
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: 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_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: 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_0068: 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)
			try
			{
				KeyboardShortcut val = (KeyboardShortcut)((ModConfig.ToggleHotKey != null) ? ModConfig.ToggleHotKey.Value : new KeyboardShortcut((KeyCode)117, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }));
				if ((int)((KeyboardShortcut)(ref val)).MainKey != 0)
				{
					_mainKey = ((KeyboardShortcut)(ref val)).MainKey;
				}
				List<KeyCode> list = new List<KeyCode>(4);
				if (((KeyboardShortcut)(ref val)).Modifiers != null)
				{
					foreach (KeyCode modifier in ((KeyboardShortcut)(ref val)).Modifiers)
					{
						if ((int)modifier != 0)
						{
							if (!list.Contains(modifier))
							{
								list.Add(modifier);
							}
							if (list.Count >= 4)
							{
								break;
							}
						}
					}
				}
				_mods = list.ToArray();
			}
			catch
			{
				_mainKey = (KeyCode)117;
				_mods = (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 };
			}
		}

		internal static string GetToggleHotkeyText()
		{
			//IL_0013: 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)
			try
			{
				return (ModConfig.ToggleHotKey != null) ? ((object)ModConfig.ToggleHotKey.Value/*cast due to .constrained prefix*/).ToString() : "U + LeftAlt";
			}
			catch
			{
				return "U + LeftAlt";
			}
		}

		internal static string TrySetToggleHotkey(KeyCode main, KeyCode[] modifiers)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: 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)
			try
			{
				if (ModConfig.ToggleHotKey == null)
				{
					return null;
				}
				ModConfig.ToggleHotKey.Value = new KeyboardShortcut(main, (KeyCode[])(((object)modifiers) ?? ((object)new KeyCode[0])));
				ModConfig.Save();
				return ((object)ModConfig.ToggleHotKey.Value/*cast due to .constrained prefix*/).ToString();
			}
			catch
			{
				return null;
			}
		}

		internal static void SetEnable(bool value)
		{
			try
			{
				if (ModConfig.Enable != null && ModConfig.Enable.Value != value)
				{
					ModConfig.Enable.Value = value;
					ModConfig.Save();
					PopupState();
					LogInfo("[BPTropicFree] UI 切换总开关 → " + (value ? "开" : "关"));
				}
			}
			catch
			{
			}
		}

		internal static void SetIgnoreLimits(bool value)
		{
			try
			{
				if (ModConfig.IgnoreTropicLimits != null && ModConfig.IgnoreTropicLimits.Value != value)
				{
					ModConfig.IgnoreTropicLimits.Value = value;
					ModConfig.Save();
					try
					{
						UIRealtimeTip.Popup(L10n.T("无视回归线限制:" + (value ? "已开启" : "已关闭"), "Ignore tropic limits: " + (value ? "ON" : "OFF")), true, 0);
					}
					catch
					{
					}
					LogInfo("[BPTropicFree] UI 切换无视回归线限制 → " + (value ? "开" : "关"));
				}
			}
			catch
			{
			}
		}

		internal static void SetUniformGrid(bool value)
		{
			try
			{
				if (ModConfig.UniformRigidGrid != null && ModConfig.UniformRigidGrid.Value != value)
				{
					ModConfig.UniformRigidGrid.Value = value;
					ModConfig.Save();
					try
					{
						UIRealtimeTip.Popup(L10n.T("锁死蓝图大小:" + (value ? "已开启(统一刚性摆放)" : "已关闭"), "Lock blueprint size: " + (value ? "ON (rigid placement)" : "OFF")), true, 0);
					}
					catch
					{
					}
					LogInfo("[BPTropicFree] UI 切换锁死蓝图大小 → " + (value ? "开" : "关"));
				}
			}
			catch
			{
			}
		}

		private static void PopupState()
		{
			string text = (Enabled ? L10n.T("蓝图回归线自由摆放:已开启(跨线自由移动 / 锁死蓝图大小)", "Free placement across tropics: ON (free movement / locked blueprint size)") : L10n.T("蓝图回归线自由摆放:已关闭(原版行为)", "Free placement across tropics: OFF (vanilla behaviour)"));
			try
			{
				UIRealtimeTip.Popup(text, true, 0);
			}
			catch
			{
			}
		}

		internal static void TickKey()
		{
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			if (!_tickLogged)
			{
				_tickLogged = true;
				try
				{
					LogInfo("[BPTropicFree] 快捷键监听已启动:" + GetToggleHotkeyText() + "【" + (Enabled ? "开启" : "关闭") + "】;无视回归线=" + (IgnoreLimits ? "开" : "关") + ";锁死蓝图大小=" + (UniformGrid ? "开" : "关"));
				}
				catch
				{
				}
			}
			try
			{
				if (ModConfig.Enable != null && BuildFeatures.KeyDownWithMods(_mainKey, _mods))
				{
					bool flag = !ModConfig.Enable.Value;
					ModConfig.Enable.Value = flag;
					ModConfig.Save();
					PopupState();
					LogInfo("[BPTropicFree] " + (flag ? "蓝图回归线自由摆放:已开启(跨线自由移动 / 锁死蓝图大小)" : "蓝图回归线自由摆放:已关闭(原版行为)"));
				}
			}
			catch
			{
			}
		}

		internal static void LogInfo(string message)
		{
			try
			{
				BlueprintOffsetPlugin.LogToolbox(message);
			}
			catch
			{
			}
		}

		internal static void LogError(string message)
		{
			try
			{
				Plugin.LogError(message);
			}
			catch
			{
			}
		}
	}
	internal static class ModConfig
	{
		internal const string CfgFileName = "BPTropicFree.cfg";

		internal static ConfigFile File;

		internal static ConfigEntry<bool> Enable;

		internal static ConfigEntry<int> CfgVersion;

		internal static ConfigEntry<KeyboardShortcut> ToggleHotKey;

		internal static ConfigEntry<bool> IgnoreTropicLimits;

		internal static ConfigEntry<bool> UniformRigidGrid;

		internal static ConfigEntry<bool> LogApplied;

		internal static void Init()
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Expected O, but got Unknown
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			string text;
			try
			{
				text = Path.Combine(Paths.ConfigPath, "BPTropicFree.cfg");
			}
			catch
			{
				text = "BPTropicFree.cfg";
			}
			File = new ConfigFile(text, true);
			try
			{
				File.SaveOnConfigSet = false;
			}
			catch
			{
			}
			Enable = File.Bind<bool>("General 通用", "Enable", false, "总开关(游戏内按 Alt+U 切换的就是这个值)。false = 完全恢复原版摆放行为。2.5.2 起默认改为关闭,需要时游戏内按 Alt+U 或在「快捷键修改」页开启。");
			CfgVersion = File.Bind<int>("General 通用", "CfgVersion", 0, "内部迁移标记,不需要手动改。");
			ToggleHotKey = File.Bind<KeyboardShortcut>("General 通用", "ToggleHotKey", new KeyboardShortcut((KeyCode)117, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), "开关本模组功能的快捷键(主键 + 修饰键)。默认 按住 Alt 再按 U。键名为 UnityEngine.KeyCode 枚举名。也可在游戏内「妙妙蓝图工具箱 → 快捷键修改」页直接修改。");
			IgnoreTropicLimits = File.Bind<bool>("Feature 功能", "IgnoreTropicLimits", true, "无视星球回归线:清除「区域跨越回归线(45)/空间不足(46)/未对齐回归线锚点(47)/回归线格数比错误(48)」与大网格(地基平台)区域越界条件,并跳过 SnapTropic 回归线吸附(跨线自由移动),蓝图任意纬度可直接摆放。");
			UniformRigidGrid = File.Bind<bool>("Feature 功能", "UniformRigidGrid", true, "统一刚性摆放(锁死蓝图大小):所有建筑 = 光标锚点 + 蓝图格数 × 格距。基准格 2π/(segment×5)(设计格 1.2566m),东西向格距按锚点纬度做 1/cos 补偿(球面经线收敛)→ 蓝图物理尺寸在任意纬度恒定锁死,不变形、不碰撞;cos 连续 → 跨回归线依旧零跳变。分拣器槽位与极区(大网格平台)修正结果原样保留。");
			LogApplied = File.Bind<bool>("Debug 调试", "LogApplied", false, "验证用日志:每次发生刚性重摆时输出建筑数量统计(每秒最多一条)。");
			if (CfgVersion.Value < 1)
			{
				Enable.Value = false;
				CfgVersion.Value = 1;
			}
			try
			{
				File.Save();
			}
			catch
			{
			}
		}

		internal static void Save()
		{
			try
			{
				if (File != null)
				{
					File.Save();
				}
			}
			catch
			{
			}
		}
	}
	internal static class TropicFreePatch
	{
		private const float HalfPi = (float)Math.PI / 2f;

		private const float HeightStep = 1.3333334f;

		private const float HeightBase = 0.2f;

		private const float YawQuot = 89.9f;

		private static bool _errorOnce;

		private static float _lastLogAt = -99f;

		private static int _pendingLogCount;

		private static float[] _areaLngBuf;

		private static float[] _areaLatBuf;

		private static bool[] _areaDoneBuf;

		[HarmonyPrefix]
		[HarmonyPatch(typeof(BlueprintUtils), "SnapTropic")]
		public static bool SnapTropic_Prefix()
		{
			if (ModConfig.Enable.Value && ModConfig.IgnoreTropicLimits.Value)
			{
				return false;
			}
			return true;
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(BlueprintUtils), "RefreshBuildPreview")]
		public static void RefreshBuildPreview_Postfix(PlanetData _planet, BlueprintData _blueprintData, BuildPreview[] _bpArray, Vector3[] _dots, int _dotsCursor, IntVector4[] _tropicGratBoxConditionInfo, float _yaw, int _segmentCnt)
		{
			try
			{
				Core(_planet, _blueprintData, _bpArray, _dots, _dotsCursor, _tropicGratBoxConditionInfo, _yaw, _segmentCnt);
			}
			catch (Exception ex)
			{
				if (!_errorOnce)
				{
					_errorOnce = true;
					TropicFreeFeature.LogError("[BPTropicFree] RefreshBuildPreview 后置补丁异常(本会话内不再重复报告):" + ex);
				}
			}
		}

		private static void Core(PlanetData planet, BlueprintData bpData, BuildPreview[] bpArray, Vector3[] dots, int dotsCursor, IntVector4[] gratBoxConditions, float yaw, int segmentCnt)
		{
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_041a: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Expected I4, but got Unknown
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0246: Unknown result type (might be due to invalid IL or missing references)
			//IL_024b: Unknown result type (might be due to invalid IL or missing references)
			//IL_025d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0262: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0304: Unknown result type (might be due to invalid IL or missing references)
			//IL_0317: Unknown result type (might be due to invalid IL or missing references)
			//IL_033d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0342: Unknown result type (might be due to invalid IL or missing references)
			//IL_0346: Unknown result type (might be due to invalid IL or missing references)
			//IL_034b: Unknown result type (might be due to invalid IL or missing references)
			//IL_034f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0367: Unknown result type (might be due to invalid IL or missing references)
			//IL_036c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0373: Unknown result type (might be due to invalid IL or missing references)
			//IL_038b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0390: Unknown result type (might be due to invalid IL or missing references)
			//IL_0397: Unknown result type (might be due to invalid IL or missing references)
			//IL_03aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_03af: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_026a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0274: Unknown result type (might be due to invalid IL or missing references)
			//IL_0286: Unknown result type (might be due to invalid IL or missing references)
			//IL_028b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0291: Unknown result type (might be due to invalid IL or missing references)
			//IL_029b: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ba: Unknown result type (might be due to invalid IL or missing references)
			if (ModConfig.Enable == null || !ModConfig.Enable.Value || planet == null || bpData == null || bpArray == null || dots == null || dotsCursor <= 0)
			{
				return;
			}
			BlueprintBuilding[] buildings = bpData.buildings;
			if (buildings == null || buildings.Length == 0)
			{
				return;
			}
			BlueprintArea[] areas = bpData.areas;
			int num = buildings.Length;
			int num2 = ((areas == null) ? 1 : areas.Length);
			int num3 = ((num2 > 1) ? 1 : dotsCursor);
			bool value = ModConfig.IgnoreTropicLimits.Value;
			bool value2 = ModConfig.UniformRigidGrid.Value;
			if (!value && !value2)
			{
				return;
			}
			int num4 = Mathf.FloorToInt(yaw / 89.9f);
			float num5 = ((num4 == 1 || num4 == 2) ? (-1f) : 1f);
			float num6 = ((num4 == 2 || num4 == 3) ? (-1f) : 1f);
			float latitudeRadPerGrid = BlueprintUtils.GetLatitudeRadPerGrid(segmentCnt);
			float realRadius = planet.realRadius;
			float[] oLng = null;
			float[] oLat = null;
			if (num2 > 1)
			{
				ResolveAreaOffsets(areas, bpData.primaryAreaIdx, out oLng, out oLat);
			}
			int num7 = 0;
			for (int i = 0; i < num3; i++)
			{
				Vector3 val = dots[i];
				((Vector3)(ref val)).Normalize();
				float num8 = 0f;
				float num9 = 0f;
				BlueprintUtils.GetLongitudeLatitudeRad(val, ref num8, ref num9);
				num9 = Mathf.Clamp(num9, -(float)Math.PI / 2f, (float)Math.PI / 2f);
				float num10 = Mathf.Clamp(Mathf.Cos(Mathf.Abs(num9)), 0.2f, 1f);
				float num11 = latitudeRadPerGrid / num10;
				float num12 = latitudeRadPerGrid;
				for (int j = 0; j < num; j++)
				{
					int num13 = i * num + j;
					if (num13 >= bpArray.Length)
					{
						break;
					}
					BuildPreview val2 = bpArray[num13];
					if (val2 == null || val2.desc == null)
					{
						continue;
					}
					if (value)
					{
						int num14 = (int)val2.condition;
						if (num14 >= 45 && num14 <= 48)
						{
							val2.condition = (EBuildCondition)0;
						}
					}
					if (value2)
					{
						BlueprintBuilding val3 = buildings[j];
						int num15 = ((val3.areaIndex >= 0 && val3.areaIndex < num2) ? val3.areaIndex : 0);
						float num16 = ((oLng != null && num15 < oLng.Length) ? oLng[num15] : 0f);
						float num17 = ((oLat != null && num15 < oLat.Length) ? oLat[num15] : 0f);
						bool num18 = val2.desc.isInserter || (areas != null && num15 < areas.Length && areas[num15] != null && areas[num15].areaSegments == 4);
						Vector2 val4 = BlueprintUtils.TransitionWidthAndHeight(yaw, val3.localOffset_x, val3.localOffset_y);
						Vector2 val5 = BlueprintUtils.TransitionWidthAndHeight(yaw, val3.localOffset_x2, val3.localOffset_y2);
						if (num18)
						{
							Vector3 dirR = DirFor(num8, num9, val4.x + num16, val4.y + num17, num11, num12, num5, num6);
							Vector3 dirR2 = DirFor(num8, num9, val5.x + num16, val5.y + num17, num11, num12, num5, num6);
							num7 += RebasePreview(val2, dirR, dirR2);
							continue;
						}
						float num19 = num8 + (val4.x + num16) * num11 * num5;
						float num20 = Mathf.Clamp(num9 + (val4.y + num17) * num12 * num6, -(float)Math.PI / 2f, (float)Math.PI / 2f);
						float num21 = num8 + (val5.x + num16) * num11 * num5;
						float num22 = Mathf.Clamp(num9 + (val5.y + num17) * num12 * num6, -(float)Math.PI / 2f, (float)Math.PI / 2f);
						Vector3 dir = BlueprintUtils.GetDir(num19, num20);
						Vector3 dir2 = BlueprintUtils.GetDir(num21, num22);
						val2.lpos = dir * (realRadius + val3.localOffset_z * 1.3333334f + 0.2f);
						val2.lpos2 = dir2 * (realRadius + val3.localOffset_z2 * 1.3333334f + 0.2f);
						val2.lrot = Maths.SphericalRotation(dir, val3.yaw - (float)num4 * 90f);
						val2.lrot2 = Maths.SphericalRotation(dir2, val3.yaw2 - (float)num4 * 90f);
						val2.tilt = val3.tilt;
						num7++;
					}
				}
			}
			if (value && gratBoxConditions != null)
			{
				for (int k = 0; k < gratBoxConditions.Length; k++)
				{
					gratBoxConditions[k] = default(IntVector4);
				}
			}
			if (ModConfig.LogApplied.Value && num7 > 0)
			{
				_pendingLogCount += num7;
				float realtimeSinceStartup = Time.realtimeSinceStartup;
				if (realtimeSinceStartup - _lastLogAt >= 1f)
				{
					_lastLogAt = realtimeSinceStartup;
					TropicFreeFeature.LogInfo("[BPTropicFree] 刚性重摆生效 / rigid re-place: " + _pendingLogCount + " previews (size-locked rigid placement)");
					_pendingLogCount = 0;
				}
			}
		}

		private static Vector3 DirFor(float lng0, float lat0, float cellX, float cellY, float lngPitch, float latPitch, float sx, float sy)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			float num = lng0 + cellX * lngPitch * sx;
			float num2 = Mathf.Clamp(lat0 + cellY * latPitch * sy, -(float)Math.PI / 2f, (float)Math.PI / 2f);
			return BlueprintUtils.GetDir(num, num2);
		}

		private static int RebasePreview(BuildPreview p, Vector3 dirR, Vector3 dirR2)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: 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_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: 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_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: 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_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			int num = 0;
			float magnitude = ((Vector3)(ref p.lpos)).magnitude;
			Vector3 val2;
			if (magnitude > 1E-05f)
			{
				Vector3 val = p.lpos / magnitude;
				val2 = val - dirR;
				if (((Vector3)(ref val2)).sqrMagnitude > 1E-12f)
				{
					Quaternion val3 = Quaternion.FromToRotation(val, dirR);
					p.lpos = dirR * magnitude;
					p.lrot = val3 * p.lrot;
					num++;
				}
			}
			float magnitude2 = ((Vector3)(ref p.lpos2)).magnitude;
			if (magnitude2 > 1E-05f)
			{
				Vector3 val4 = p.lpos2 / magnitude2;
				val2 = val4 - dirR2;
				if (((Vector3)(ref val2)).sqrMagnitude > 1E-12f)
				{
					Quaternion val5 = Quaternion.FromToRotation(val4, dirR2);
					p.lpos2 = dirR2 * magnitude2;
					p.lrot2 = val5 * p.lrot2;
					num++;
				}
			}
			return num;
		}

		private static void ResolveAreaOffsets(BlueprintArea[] areas, int primaryIdx, out float[] oLng, out float[] oLat)
		{
			int num = areas.Length;
			if (_areaLngBuf == null || _areaLngBuf.Length < num)
			{
				_areaLngBuf = new float[num];
				_areaLatBuf = new float[num];
				_areaDoneBuf = new bool[num];
			}
			oLng = _areaLngBuf;
			oLat = _areaLatBuf;
			bool[] areaDoneBuf = _areaDoneBuf;
			Array.Clear(oLng, 0, num);
			Array.Clear(oLat, 0, num);
			Array.Clear(areaDoneBuf, 0, num);
			if (primaryIdx < 0 || primaryIdx >= num)
			{
				primaryIdx = 0;
			}
			areaDoneBuf[primaryIdx] = true;
			for (int i = 0; i <= num; i++)
			{
				bool flag = false;
				for (int j = 0; j < num; j++)
				{
					if (areaDoneBuf[j])
					{
						continue;
					}
					BlueprintArea val = areas[j];
					if (val == null)
					{
						areaDoneBuf[j] = true;
						continue;
					}
					int num2 = SlotOfAreaIndex(areas, val.parentIndex);
					if (num2 >= 0 && areaDoneBuf[num2])
					{
						oLng[j] = oLng[num2] + (float)val.tropicAnchor - (float)val.anchorLocalOffsetX;
						oLat[j] = oLat[num2] + (float)val.anchorLocalOffsetY;
						areaDoneBuf[j] = true;
						flag = true;
					}
					else if (num2 < 0)
					{
						areaDoneBuf[j] = true;
						flag = true;
					}
				}
				if (!flag)
				{
					break;
				}
			}
		}

		private static int SlotOfAreaIndex(BlueprintArea[] areas, int index)
		{
			if (index < 0)
			{
				return -1;
			}
			for (int i = 0; i < areas.Length; i++)
			{
				if (areas[i] != null && areas[i].index == index)
				{
					return i;
				}
			}
			return -1;
		}
	}
}
namespace HoverCoord
{
	[BepInPlugin("dsh.hovercoord", "HoverCoord", "1.10.11")]
	public class HoverCoordPlugin : BaseUnityPlugin
	{
		private struct NearbyScanResult
		{
			public bool anyNearby;

			public bool hasGapX;

			public float gapXCells;

			public bool hasGapZ;

			public float gapZCells;

			public bool hasSameTower;

			public float towerCenterCells;
		}

		private struct CachedBuilding
		{
			public Vector3 pos;

			public int protoId;

			public float lonGrid;

			public float latGrid;

			public string towerCategory;
		}

		public const string Guid = "dsh.hovercoord";

		internal static HoverCoordPlugin Instance;

		private const float LayerHeight = 1.3333333f;

		private const float GroundOffset = 0.2f;

		private const float DetectInterval = 0.75f;

		private const float RebuildInterval = 0.1f;

		private const float OutputMargin = 0.005f;

		private bool active;

		private ConfigEntry<KeyboardShortcut> hotkeyConfig;

		private ConfigEntry<bool> startEnabledConfig;

		private static readonly StringBuilder builder = new StringBuilder(256);

		private static readonly Dictionary<int, string> nameCache = new Dictionary<int, string>(64);

		private HoverCoordRenderer renderer;

		private PlanetData lastPlanet;

		private EntityData lastEntity;

		private bool visible;

		private float nextDetectTime;

		private float lastBuildTime;

		private bool toastActive;

		private float toastUntil;

		private bool errorLogged;

		private static PlanetData cachedScanPlanet;

		private static readonly Dictionary<int, CachedBuilding> buildingCache = new Dictionary<int, CachedBuilding>(4096);

		private void Awake()
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			Instance = this;
			hotkeyConfig = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("General", "开关快捷键", new KeyboardShortcut((KeyCode)107, (KeyCode[])(object)new KeyCode[2]
			{
				(KeyCode)306,
				(KeyCode)304
			}), "切换指针坐标显示的快捷键(格式:主键+修饰键,如 K+LeftControl+LeftShift)");
			startEnabledConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "默认开启", false, "游戏启动后指针坐标显示是否默认开启(当前默认关闭)");
			active = startEnabledConfig.Value;
			renderer = CreateRenderer();
			renderer.Hide();
			((BaseUnityPlugin)this).Logger.LogInfo((object)("HoverCoord " + ((((BaseUnityPlugin)this).Info != null && ((BaseUnityPlugin)this).Info.Metadata != null) ? ((BaseUnityPlugin)this).Info.Metadata.Version.ToString() : "1.10.11") + " loaded. Author: 妙妙在路上 (抖音@妙妙在路上)"));
		}

		private HoverCoordRenderer CreateRenderer()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("HoverCoordRenderer");
			val.transform.SetParent(((Component)this).transform, false);
			return val.AddComponent<HoverCoordRenderer>();
		}

		internal string GetHotkeyText()
		{
			//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)
			try
			{
				return (hotkeyConfig != null) ? ((object)hotkeyConfig.Value/*cast due to .constrained prefix*/).ToString() : "K + LeftControl + LeftShift";
			}
			catch
			{
				return "K + LeftControl + LeftShift";
			}
		}

		internal string TrySetHotkey(KeyCode main, KeyCode[] modifiers)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (hotkeyConfig == null)
				{
					return null;
				}
				hotkeyConfig.Value = new KeyboardShortcut(main, (KeyCode[])(((object)modifiers) ?? ((object)new KeyCode[0])));
				try
				{
					((BaseUnityPlugin)this).Config.Save();
				}
				catch
				{
				}
				return ((object)hotkeyConfig.Value/*cast due to .constrained prefix*/).ToString();
			}
			catch
			{
				return null;
			}
		}

		private void Update()
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			if (VFInput.inputing)
			{
				return;
			}
			if ((Object)(object)renderer == (Object)null)
			{
				renderer = CreateRenderer();
				renderer.Hide();
				visible = false;
			}
			KeyboardShortcut value = hotkeyConfig.Value;
			if (((KeyboardShortcut)(ref value)).IsDown())
			{
				active = !active;
				ShowToast(L10n.T(active ? "指针坐标:开" : "指针坐标:关", active ? "Pointer coords: ON" : "Pointer coords: OFF"));
				nextDetectTime = 0f;
			}
			if (toastActive)
			{
				if (Time.unscaledTime < toastUntil)
				{
					return;
				}
				toastActive = false;
				HideTip();
				nextDetectTime = 0f;
			}
			if (!active)
			{
				if (visible)
				{
					HideTip();
				}
			}
			else
			{
				if (!(Time.unscaledTime >= nextDetectTime))
				{
					return;
				}
				nextDetectTime = Time.unscaledTime + 0.75f;
				try
				{
					UpdateHover();
				}
				catch (Exception ex)
				{
					HideTip();
					if (!errorLogged)
					{
						errorLogged = true;
						((BaseUnityPlugin)this).Logger.LogWarning((object)("HoverCoord: " + ex));
					}
				}
			}
		}

		private static bool ControlHeld()
		{
			if (!Input.GetKey((KeyCode)306))
			{
				return Input.GetKey((KeyCode)305);
			}
			return true;
		}

		private static bool ShiftHeld()
		{
			if (!Input.GetKey((KeyCode)304))
			{
				return Input.GetKey((KeyCode)303);
			}
			return true;
		}

		private void UpdateHover()
		{
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: 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_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			if (!Application.isFocused || VFInput.onGUI || VFInput.inFullscreenGUI || !VFInput.inScreen || (Object)(object)GameMain.instance == (Object)null || GameMain.isPaused || !GameMain.isRunning)
			{
				HideTip();
				return;
			}
			PlanetData localPlanet = GameMain.localPlanet;
			if (localPlanet == null || !localPlanet.factoryLoaded)
			{
				HideTip();
				return;
			}
			PlanetPhysics physics = localPlanet.physics;
			if (physics == null)
			{
				HideTip();
				return;
			}
			RaycastLogic raycastLogic = physics.raycastLogic;
			if (raycastLogic == null || !raycastLogic.castSucceed)
			{
				HideTip();
				return;
			}
			EntityData castEntity = raycastLogic.castEntity;
			if (castEntity.id <= 0)
			{
				HideTip();
				return;
			}
			float num = 0.1f;
			try
			{
				PlanetFactory val = localPlanet?.factory;
				if (val != null && val.entityCursor > 15000)
				{
					num = 0.5f;
				}
			}
			catch
			{
			}
			if (!visible || !(Time.unscaledTime - lastBuildTime < num))
			{
				if (!BuildTip(localPlanet, castEntity))
				{
					HideTip();
					return;
				}
				lastBuildTime = Time.unscaledTime;
				lastPlanet = localPlanet;
				lastEntity = castEntity;
			}
		}

		private bool BuildTip(PlanetData planet, EntityData entity)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: 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_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_020e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0252: Unknown result type (might be due to invalid IL or missing references)
			//IL_0296: Unknown result type (might be due to invalid IL or missing references)
			Vector3 pos = entity.pos;
			float magnitude = ((Vector3)(ref pos)).magnitude;
			if (magnitude < 0.001f)
			{
				return false;
			}
			Vector3 val = pos / magnitude;
			int num = 200;
			PlanetAuxData aux = planet.aux;
			if (aux != null && aux.mainGrid != null && aux.mainGrid.segment > 0)
			{
				num = aux.mainGrid.segment;
			}
			float latitudeRad = BlueprintUtils.GetLatitudeRad(val);
			float longitudeRad = BlueprintUtils.GetLongitudeRad(val);
			float latitudeGridIdx = BlueprintUtils.GetLatitudeGridIdx(val, num);
			float longitudeGridIdx = BlueprintUtils.GetLongitudeGridIdx(val, num);
			float value = (magnitude - planet.realRadius - 0.2f) / 1.3333333f;
			float num2 = (float)Math.PI * 2f * planet.realRadius / ((float)num * 5f);
			Vector3 size;
			bool num3 = TryGetCollisionSize(entity, out size);
			string itemName = GetItemName(entity.protoId);
			string towerCategory = GetTowerCategory(itemName);
			float spacingUnits = 0f;
			if (towerCategory != null)
			{
				TryGetTowerSpacing(itemName, entity, towerCategory, out spacingUnits);
			}
			builder.Length = 0;
			if (!string.IsNullOrEmpty(itemName))
			{
				builder.Append(itemName);
			}
			builder.Append(" #").Append(entity.id).Append('\n');
			bool isChinese = L10n.IsChinese;
			builder.Append(isChinese ? "经度 " : "Lng ").Append(F4(longitudeRad * 57.29578f)).Append("°");
			builder.Append(isChinese ? "    纬度 " : "    Lat ").Append(F4(latitudeRad * 57.29578f)).Append("°\n");
			builder.Append("X ").Append(F4(longitudeGridIdx));
			builder.Append("    Y ").Append(F4(latitudeGridIdx));
			builder.Append("    Z ").Append(F4(value));
			if (num3)
			{
				builder.Append('\n');
				builder.Append(isChinese ? "当前模型体积 长 " : "Model size L ").Append(F4(size.z / num2)).Append(isChinese ? "格" : "");
				builder.Append(isChinese ? "    宽 " : "    W ").Append(F4(size.x / num2)).Append(isChinese ? "格" : "");
				builder.Append(isChinese ? "    高 " : "    H ").Append(F4(size.y / 1.3333333f)).Append(isChinese ? "层" : "");
			}
			NearbyScanResult nearbyScanResult = ScanNearby(planet, entity, longitudeGridIdx, latitudeGridIdx, num, num2, towerCategory);
			if (nearbyScanResult.hasGapX || nearbyScanResult.hasGapZ)
			{
				builder.Append('\n').Append(isChinese ? "最近模型碰撞距离 " : "Nearest collider dist ");
				builder.Append(isChinese ? "X轴 " : "X-axis ").Append(nearbyScanResult.hasGapX ? (F4(nearbyScanResult.gapXCells) + (isChinese ? "格" : "")) : (isChinese ? "无" : "n/a"));
				builder.Append(isChinese ? "    Y轴 " : "    Y-axis ").Append(nearbyScanResult.hasGapZ ? (F4(nearbyScanResult.gapZCells) + (isChinese ? "格" : "")) : (isChinese ? "无" : "n/a"));
			}
			if (towerCategory != null)
			{
				builder.Append('\n').Append(towerCategory).Append(isChinese ? " 最小间距 " : " min spacing ")
					.Append(F4(spacingUnits / num2))
					.Append(isChinese ? "格" : "");
				if (nearbyScanResult.hasSameTower)
				{
					builder.Append(isChinese ? "    最近同类中心 " : "    nearest same-type ").Append(F4(nearbyScanResult.towerCenterCells)).Append(isChinese ? "格" : "");
					if (nearbyScanResult.towerCenterCells < spacingUnits / num2)
					{
						builder.Append(isChinese ? " (相隔太近)" : " (too close)");
					}
				}
			}
			ShowTip(builder.ToString());
			return true;
		}

		private static bool TryGetCollisionSize(EntityData entity, out Vector3 size)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: 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_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			size = Vector3.zero;
			PrefabDesc prefabDesc = GetPrefabDesc(entity);
			if (prefabDesc == null)
			{
				return false;
			}
			if (prefabDesc.buildCollider.ext != Vector3.zero)
			{
				size = prefabDesc.buildCollider.ext * 2f;
				return ((Vector3)(ref size)).sqrMagnitude > 0f;
			}
			if ((Object)(object)prefabDesc.mesh != (Object)null)
			{
				Bounds bounds = prefabDesc.mesh.bounds;
				size = ((Bounds)(ref bounds)).size;
				if (((Vector3)(ref size)).sqrMagnitude > 0f)
				{
					return true;
				}
			}
			if (prefabDesc.meshes != null)
			{
				bool flag = false;
				Bounds val = default(Bounds);
				for (int i = 0; i < prefabDesc.meshes.Length; i++)
				{
					Mesh val2 = prefabDesc.meshes[i];
					if (!((Object)(object)val2 == (Object)null))
					{
						if (!flag)
						{
							val = val2.bounds;
							flag = true;
						}
						else
						{
							((Bounds)(ref val)).Encapsulate(val2.bounds);
						}
					}
				}
				if (flag)
				{
					size = ((Bounds)(ref val)).size;
					return ((Vector3)(ref size)).sqrMagnitude > 0f;
				}
			}
			if (prefabDesc.roughWidth > 0f)
			{
				size = new Vector3(prefabDesc.roughWidth, Mathf.Max(1f, prefabDesc.roughHeight), prefabDesc.roughWidth);
				return true;
			}
			return false;
		}

		private static PrefabDesc GetPrefabDesc(EntityData entity)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			PrefabDesc[] prefabDescByModelIndex = PlanetFactory.PrefabDescByModelIndex;
			int modelIndex = entity.modelIndex;
			if (prefabDescByModelIndex == null || modelIndex < 0 || modelIndex >= prefabDescByModelIndex.Length)
			{
				return null;
			}
			return prefabDescByModelIndex[modelIndex];
		}

		private static Vector3 HorizontalDir(Vector3 v)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			v.y = 0f;
			float magnitude = ((Vector3)(ref v)).magnitude;
			if (!(magnitude < 1E-05f))
			{
				return v / magnitude;
			}
			return Vector3.zero;
		}

		private static CachedBuilding GetCachedBuilding(PlanetData planet, EntityData entity, int segment)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: 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_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: 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_00b6: 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)
			if (cachedScanPlanet != planet)
			{
				buildingCache.Clear();
				cachedScanPlanet = planet;
			}
			if (buildingCache.TryGetValue(entity.id, out var value) && value.protoId == entity.protoId && value.pos == entity.pos)
			{
				return value;
			}
			value = new CachedBuilding
			{
				pos = entity.pos,
				protoId = entity.protoId
			};
			Vector3 val = ((((Vector3)(ref entity.pos)).sqrMagnitude > 0f) ? ((Vector3)(ref entity.pos)).normalized : Vector3.zero);
			value.lonGrid = BlueprintUtils.GetLongitudeGridIdx(val, segment);
			value.latGrid = BlueprintUtils.GetLatitudeGridIdx(val, segment);
			value.towerCategory = GetTowerCategory(GetItemName(entity.protoId));
			buildingCache[entity.id] = value;
			return value;
		}

		private static bool IsBeltOrSorter(int protoId)
		{
			if (protoId < 2001 || protoId > 2003)
			{
				if (protoId >= 2011)
				{
					return protoId <= 2013;
				}
				return false;
			}
			return true;
		}

		private static NearbyScanResult ScanNearby(PlanetData planet, EntityData entity, float selfLonGrid, float selfLatGrid, int segment, float cellSize, string towerCategory)
		{
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: 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_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: 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_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: 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)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: 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_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0203: Unknown result type (might be due to invalid IL or missing references)
			//IL_0205: Unknown result type (might be due to invalid IL or missing references)
			//IL_020a: Unknown result type (might be due to invalid IL or missing references)
			//IL_020f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0214: Unknown result type (might be due to invalid IL or missing references)
			//IL_0219: Unknown result type (might be due to invalid IL or missing references)
			//IL_021b: Unknown result type (might be due to invalid IL or missing references)
			//IL_021d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0222: Unknown result type (might be due to invalid IL or missing references)
			//IL_0227: Unknown result type (might be due to invalid IL or missing references)
			//IL_022c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0231: Unknown result type (might be due to invalid IL or missing references)
			//IL_0233: Unknown result type (might be due to invalid IL or missing references)
			//IL_023a: Unknown result type (might be due to invalid IL or missing references)
			//IL_023c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0249: Unknown result type (might be due to invalid IL or missing references)
			//IL_0250: Unknown result type (might be due to invalid IL or missing references)
			//IL_0252: Unknown result type (might be due to invalid IL or missing references)
			//IL_0262: Unknown result type (might be due to invalid IL or missing references)
			//IL_0269: Unknown result type (might be due to invalid IL or missing references)
			//IL_026b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0278: Unknown result type (might be due to invalid IL or missing references)
			//IL_027f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0281: Unknown result type (might be due to invalid IL or missing references)
			//IL_0296: Unknown result type (might be due to invalid IL or missing references)
			//IL_02aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0201: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02dc: Unknown result type (might be due to invalid IL or missing references)
			NearbyScanResult result = default(NearbyScanResult);
			PlanetFactory factory = planet.factory;
			if (factory == null)
			{
				return result;
			}
			EntityData[] entityPool = factory.entityPool;
			if (entityPool == null)
			{
				return result;
			}
			int num = factory.entityCursor;
			if (num > entityPool.Length)
			{
				num = entityPool.Length;
			}
			Vector3 val = ((((Vector3)(ref entity.pos)).sqrMagnitude > 0f) ? ((Vector3)(ref entity.pos)).normalized : Vector3.zero);
			float num2 = Mathf.Sqrt(Mathf.Max(0f, 1f - val.y * val.y));
			int num3 = BlueprintUtils.GetLongitudeSegmentCount(val, segment);
			if (num3 <= 0)
			{
				num3 = segment;
			}
			float num4 = cellSize * ((float)segment / (float)num3) * num2;
			Vector3 val2 = HorizontalDir(entity.rot * Vector3.right);
			Vector3 val3 = HorizontalDir(entity.rot * Vector3.forward);
			Vector3 val4 = Vector3.zero;
			PrefabDesc prefabDesc = GetPrefabDesc(entity);
			if (prefabDesc != null)
			{
				val4 = prefabDesc.buildCollider.ext;
			}
			float num5 = float.MaxValue;
			float num6 = float.MaxValue;
			float num7 = float.MaxValue;
			bool anyNearby = false;
			for (int i = 1; i < num; i++)
			{
				EntityData val5 = entityPool[i];
				if (val5.id <= 0 || val5.id == entity.id || IsBeltOrSorter(val5.protoId))
				{
					continue;
				}
				Vector3 val6 = val5.pos - entity.pos;
				float sqrMagnitude = ((Vector3)(ref val6)).sqrMagnitude;
				if (!(sqrMagnitude > 3600f))
				{
					anyNearby = true;
					CachedBuilding cachedBuilding = GetCachedBuilding(planet, val5, segment);
					float num8 = cachedBuilding.lonGrid - selfLonGrid;
					float num9 = (float)num3 * 1.25f;
					if (num8 > num9)
					{
						num8 -= (float)num3 * 2.5f;
					}
					else if (num8 < 0f - num9)
					{
						num8 += (float)num3 * 2.5f;
					}
					float num10 = Mathf.Abs(num8);
					float num11 = Mathf.Abs(cachedBuilding.latGrid - selfLatGrid);
					Vector3 val7 = Vector3.zero;
					PrefabDesc prefabDesc2 = GetPrefabDesc(val5);
					if (prefabDesc2 != null)
					{
						val7 = prefabDesc2.buildCollider.ext;
					}
					Vector3 val8 = HorizontalDir(val5.rot * Vector3.right);
					Vector3 val9 = HorizontalDir(val5.rot * Vector3.forward);
					float num12 = val7.x * Mathf.Abs(Vector3.Dot(val8, val2)) + val7.z * Mathf.Abs(Vector3.Dot(val9, val2));
					float num13 = val7.x * Mathf.Abs(Vector3.Dot(val8, val3)) + val7.z * Mathf.Abs(Vector3.Dot(val9, val3));
					bool num14 = num11 * cellSize <= val4.z + num13;
					float num15 = num10 * num4 - val4.x - num12;
					if (num14 && num15 < num5)
					{
						num5 = num15;
					}
					bool num16 = num10 * num4 <= val4.x + num12;
					float num17 = num11 * cellSize - val4.z - num13;
					if (num16 && num17 < num6)
					{
						num6 = num17;
					}
					if (towerCategory != null && !(cachedBuilding.towerCategory != towerCategory) && sqrMagnitude < num7)
					{
						num7 = sqrMagnitude;
					}
				}
			}
			result.anyNearby = anyNearby;
			if (num5 != float.MaxValue)
			{
				result.hasGapX = true;
				result.gapXCells = num5 / cellSize - 0.005f;
			}
			if (num6 != float.MaxValue)
			{
				result.hasGapZ = true;
				result.gapZCells = num6 / cellSize - 0.005f;
			}
			if (num7 != float.MaxValue)
			{
				result.hasSameTower = true;
				result.towerCenterCells = Mathf.Sqrt(num7) / cellSize;
			}
			return result;
		}

		private static bool TryGetCollisionBox(EntityData entity, out Vector3 center, out Quaternion rotation, out Vector3 extents)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: 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_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: 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)
			//IL_0098: 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_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: 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_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: 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)
			center = entity.pos;
			rotation = entity.rot;
			extents = Vector3.zero;
			PrefabDesc prefabDesc = GetPrefabDesc(entity);
			if (prefabDesc == null)
			{
				return false;
			}
			ColliderData buildCollider = prefabDesc.buildCollider;
			if (buildCollider.ext == Vector3.zero)
			{
				return false;
			}
			Quaternion val = buildCollider.q;
			if (val.x == 0f && val.y == 0f && val.z == 0f && val.w == 0f)
			{
				val = Quaternion.identity;
			}
			center = entity.pos + entity.rot * buildCollider.pos;
			rotation = entity.rot * val;
			extents = buildCollider.ext;
			return true;
		}

		private void ShowTip(string text)
		{
			visible = true;
			lastBuildTime = Time.unscaledTime;
			renderer.Show(text);
		}

		private void ShowToast(string text)
		{
			toastActive = true;
			toastUntil = Time.unscaledTime + 1.2f;
			ShowTip(text);
		}

		private void HideTip()
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			if (visible)
			{
				visible = false;
				lastPlanet = null;
				lastEntity = default(EntityData);
				renderer.Hide();
			}
		}

		private static string GetItemName(short protoId)
		{
			if (nameCache.TryGetValue(protoId, out var value))
			{
				return value;
			}
			string text = null;
			try
			{
				ItemProto val = ((ProtoSet<ItemProto>)(object)LDB.items).Select((int)protoId);
				if (val != null)
				{
					text = ((Proto)val).name;
				}
			}
			catch
			{
			}
			nameCache[protoId] = text;
			return text;
		}

		private static string GetTowerCategory(string name)
		{
			if (string.IsNullOrEmpty(name))
			{
				return null;
			}
			if (name.IndexOf("轨道弹射", StringComparison.Ordinal) >= 0)
			{
				return "弹射器";
			}
			if (name.IndexOf("风力涡轮", StringComparison.Ordinal) >= 0)
			{
				return "风力涡轮机";
			}
			if (name.IndexOf("物流", StringComparison.Ordinal) >= 0)
			{
				if (name.IndexOf("星际", StringComparison.Ordinal) < 0)
				{
					return "行星物流";
				}
				return "星际物流";
			}
			if (name.IndexOf("感应塔", StringComparison.Ordinal) >= 0 || name.IndexOf("无线输电", StringComparison.Ordinal) >= 0 || name.IndexOf("卫星配电", StringComparison.Ordinal) >= 0)
			{
				return "电力设施";
			}
			return null;
		}

		private static bool TryGetTowerSpacing(string name, EntityData entity, string category, out float spacingUnits)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			spacingUnits = 0f;
			switch (category)
			{
			case "弹射器":
			{
				ColliderData val = default(ColliderData);
				PrefabDesc prefabDesc = GetPrefabDesc(entity);
				if (prefabDesc != null)
				{
					val = prefabDesc.buildCollider;
				}
				float num = Mathf.Sqrt(val.ext.x * val.ext.x + val.ext.z * val.ext.z);
				spacingUnits = 7.2f + num;
				return true;
			}
			case "风力涡轮机":
				spacingUnits = 10.5f;
				return true;
			case "星际物流":
				spacingUnits = 29f;
				return true;
			case "行星物流":
				spacingUnits = 15f;
				return true;
			case "电力设施":
				spacingUnits = 3.5f;
				return true;
			default:
				return false;
			}
		}

		private static string F4(float value)
		{
			return value.ToString("0.0000", CultureInfo.InvariantCulture);
		}

		private static string F3(float value)
		{
			return value.ToString("0.###", CultureInfo.InvariantCulture);
		}

		private static string V3(Vector3 v)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: 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)
			return "(" + F3(v.x) + "," + F3(v.y) + "," + F3(v.z) + ")";
		}

		private static string Q(Quaternion q)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: 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_0053: Unknown result type (might be due to invalid IL or missing references)
			return "(" + F3(q.x) + "," + F3(q.y) + "," + F3(q.z) + "," + F3(q.w) + ")";
		}
	}
	public sealed class HoverCoordRenderer : MonoBehaviour
	{
		private const int FontSize = 14;

		private readonly GUIContent content = new GUIContent();

		private Vector2 contentSize;

		private int textVersion;

		private int measuredVersion = -1;

		private GUIStyle style;

		private Texture2D background;

		private bool fontFailed;

		private bool visible;

		public void Show(string text)
		{
			content.text = text;
			textVersion++;
			visible = true;
			if (!((Behaviour)this).enabled)
			{
				((Behaviour)this).enabled = true;
			}
		}

		public void Hide()
		{
			visible = false;
			if (((Behaviour)this).enabled)
			{
				((Behaviour)this).enabled = false;
			}
		}

		private void OnDestroy()
		{
			if ((Object)(object)background != (Object)null)
			{
				Object.Destroy((Object)(object)background);
			}
		}

		private void OnGUI()
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Invalid comparison between Unknown and I4
			//IL_0058: 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_0042: 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_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			if (visible && Event.current != null && (int)Event.current.type == 7 && EnsureStyle())
			{
				if (measuredVersion != textVersion)
				{
					contentSize = style.CalcSize(content);
					measuredVersion = textVersion;
				}
				float x = Input.mousePosition.x;
				float num = (float)Screen.height - Input.mousePosition.y;
				float num2 = contentSize.x + 14f;
				float num3 = contentSize.y + 10f;
				float num4 = x + 22f;
				float num5 = num - 18f - num3;
				if (num4 + num2 > (float)Screen.width)
				{
					num4 = x - 22f - num2;
				}
				if (num5 < 0f)
				{
					num5 = num + 18f;
				}
				num4 = Mathf.Clamp(num4, 0f, Mathf.Max(0f, (float)Screen.width - num2));
				num5 = Mathf.Clamp(num5, 0f, Mathf.Max(0f, (float)Screen.height - num3));
				GUI.DrawTexture(new Rect(num4, num5, num2, num3), (Texture)(object)background);
				GUI.Label(new Rect(num4 + 7f, num5 + 5f, contentSize.x + 1f, contentSize.y), content, style);
			}
		}

		private bool EnsureStyle()
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Expected O, but got Unknown
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Expected O, but got Unknown
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Expected O, but got Unknown
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Expected O, but got Unknown
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			if (style != null)
			{
				return true;
			}
			if (fontFailed)
			{
				return false;
			}
			Font val = CreateFont();
			if ((Object)(object)val == (Object)null)
			{
				fontFailed = true;
				return false;
			}
			style = new GUIStyle(GUI.skin.label);
			style.font = val;
			style.fontSize = 14;
			style.alignment = (TextAnchor)0;
			style.wordWrap = false;
			style.richText = false;
			style.padding = new RectOffset(0, 0, 0, 0);
			style.margin = new RectOffset(0, 0, 0, 0);
			style.normal.textColor = new Color(1f, 0.93f, 0.55f, 1f);
			background = new Texture2D(1, 1, (TextureFormat)5, false);
			background.SetPixel(0, 0, new Color(0f, 0f, 0f, 0.61960787f));
			background.Apply();
			return true;
		}

		private static Font CreateFont()
		{
			try
			{
				Font val = Font.CreateDynamicFontFromOSFont(new string[5] { "Microsoft YaHei", "微软雅黑", "SimHei", "SimSun", "Arial" }, 14);
				if ((Object)(object)val != (Object)null)
				{
					return val;
				}
			}
			catch
			{
			}
			try
			{
				return Resources.GetBuiltinResource<Font>("Arial.ttf");
			}
			catch
			{
				return null;
			}
		}
	}
}
namespace DSPMiaoToolbox
{
	internal static class CfgMigrator
	{
		public static void RestorePluginCfg(string targetPath, string cfgFileName)
		{
			try
			{
				if (string.IsNullOrEmpty(targetPath) || string.IsNullOrEmpty(cfgFileName) || File.Exists(targetPath))
				{
					return;
				}
				string directoryName = Path.GetDirectoryName(targetPath);
				if (string.IsNullOrEmpty(directoryName) || !Directory.Exists(directoryName))
				{
					return;
				}
				string directoryName2 = Path.GetDirectoryName(directoryName.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar));
				if (string.IsNullOrEmpty(directoryName2) || !Directory.Exists(directoryName2))
				{
					return;
				}
				string text = null;
				DateTime dateTime = DateTime.MinValue;
				string[] directories = Directory.GetDirectories(directoryName2);
				foreach (string text2 in directories)
				{
					if (string.Equals(text2, directoryName, StringComparison.OrdinalIgnoreCase))
					{
						continue;
					}
					string text3 = Path.GetFileName(text2) ?? string.Empty;
					if (text3.Length == 0 || text3.StartsWith(".") || text3.StartsWith("_"))
					{
						continue;
					}
					string text4 = Path.Combine(text2, cfgFileName);
					if (File.Exists(text4))
					{
						DateTime lastWriteTimeUtc;
						try
						{
							lastWriteTimeUtc = File.GetLastWriteTimeUtc(text4);
						}
						catch
						{
							continue;
						}
						if (lastWriteTimeUtc > dateTime)
						{
							dateTime = lastWriteTimeUtc;
							text = text4;
						}
					}
				}
				if (text != null)
				{
					File.Copy(text, targetPath, overwrite: false);
					Plugin.LogInfo("[DSPMiaoToolbox] 已从 " + text + " 迁移配置到 " + targetPath);
				}
			}
			catch (Exception ex)
			{
				try
				{
					Plugin.LogInfo("[DSPMiaoToolbox] 配置迁移失败(忽略):" + ex.Message);
				}
				catch
				{
				}
			}
		}
	}
	internal static class HotkeyHub
	{
		public sealed class Entry
		{
			public string Label;

			public string LabelEn;

			public Func<string> GetText;

			public Func<KeyCode, KeyCode[], string> TrySet;
		}

		private static Entry[] _entries;

		public static Entry[] Entries
		{
			get
			{
				if (_entries == null)
				{
					_entries = new Entry[17]
					{
						new Entry
						{
							Label = "蓝图工具窗口",
							LabelEn = "Blueprint toolbox window",
							GetText = () => (!((Object)(object)BlueprintOffsetPlugin.Instance != (Object)null)) ? "LeftAlt + Alpha5" : BlueprintOffsetPlugin.Instance.GetHotkeyText(),
							TrySet = (KeyCode m, KeyCode[] ms) => (!((Object)(object)BlueprintOffsetPlugin.Instance != (Object)null)) ? null : BlueprintOffsetPlugin.Instance.TrySetHotkey(m, ms)
						},
						new Entry
						{
							Label = "回归线传送带间距",
							LabelEn = "Tropic belt spacing",
							GetText = () => Plugin.GetToggleHotkeyText(),
							TrySet = (KeyCode m, KeyCode[] ms) => Plugin.TrySetToggleHotkey(m, ms)
						},
						new Entry
						{
							Label = "悬停坐标",
							LabelEn = "Hover coordinates",
							GetText = () => (!((Object)(object)HoverCoordPlugin.Instance != (Object)null)) ? "K + LeftControl + LeftShift" : HoverCoordPlugin.Instance.GetHotkeyText(),
							TrySet = (KeyCode m, KeyCode[] ms) => (!((Object)(object)HoverCoordPlugin.Instance != (Object)null)) ? null : HoverCoordPlugin.Instance.TrySetHotkey(m, ms)
						},
						new Entry
						{
							Label = "蓝图拖拽最小间隔",
							LabelEn = "BP drag min spacing",
							GetText = () => (!((Object)(object)BPColliderSnapPlugin.Instance != (Object)null)) ? "LeftControl + LeftShift + N" : BPColliderSnapPlugin.Instance.GetHotkeyText(),
							TrySet = (KeyCode m, KeyCode[] ms) => (!((Object)(object)BPColliderSnapPlugin.Instance != (Object)null)) ? null : BPColliderSnapPlugin.Instance.TrySetHotkey(m, ms)
						},
						new Entry
						{
							Label = "无碰撞摆放",
							LabelEn = "No-collision placement",
							GetText = () => BuildFeatures.GetHotkeyText(0),
							TrySet = (KeyCode m, KeyCode[] ms) => BuildFeatures.TrySetHotkey(0, m, ms)
						},
						new Entry
						{
							Label = "隐藏建筑模型",
							LabelEn = "Hide building models",
							GetText = () => BuildFeatures.GetHotkeyText(1),
							TrySet = (KeyCode m, KeyCode[] ms) => BuildFeatures.TrySetHotkey(1, m, ms)
						},
						new Entry
						{
							Label = "指北针开关快捷键",
							LabelEn = "Compass toggle hotkey",
							GetText = () => BuildFeatures.GetHotkeyText(2),
							TrySet = (KeyCode m, KeyCode[] ms) => BuildFeatures.TrySetHotkey(2, m, ms)
						},
						new Entry
						{
							Label = "统计信息开关快捷键",
							LabelEn = "Stats overlay toggle hotkey",
							GetText = () => BuildFeatures.GetHotkeyText(6),
							TrySet = (KeyCode m, KeyCode[] ms) => BuildFeatures.TrySetHotkey(6, m, ms)
						},
						new Entry
						{
							Label = "传送带切割",
							LabelEn = "Belt cutter",
							GetText = () => BuildFeatures.GetHotkeyText(3),
							TrySet = (KeyCode m, KeyCode[] ms) => BuildFeatures.TrySetHotkey(3, m, ms)
						},
						new Entry
						{
							Label = "一键填埋矿脉",
							LabelEn = "Vein burier",
							GetText = () => BuildFeatures.GetHotkeyText(4),
							TrySet = (KeyCode m, KeyCode[] ms) => BuildFeatures.TrySetHotkey(4, m, ms)
						},
						new Entry
						{
							Label = "建造秒完成",
							LabelEn = "Instant build",
							GetText = () => InstantBuildFeature.GetToggleHotkeyText(),
							TrySet = (KeyCode m, KeyCode[] ms) => InstantBuildFeature.TrySetToggleHotkey(m, ms)
						},
						new Entry
						{
							Label = "传送带定高",
							LabelEn = "Belt height",
							GetText = () => BeltHeightInput.GetHotkeyText(),
							TrySet = (KeyCode m, KeyCode[] ms) => BeltHeightInput.TrySetHotkey(m, ms)
						},
						new Entry
						{
							Label = "悬浮传送带",
							LabelEn = "Hover belt",
							GetText = () => BuildFeatures.GetHotkeyText(5),
							TrySet = (KeyCode m, KeyCode[] ms) => BuildFeatures.TrySetHotkey(5, m, ms)
						},
						new Entry
						{
							Label = "蓝图偏移输出(框选后)",
							LabelEn = "Blueprint offset & use (after select)",
							GetText = () => BpQuickOffsetUse.GetHotkeyText(),
							TrySet = (KeyCode m, KeyCode[] ms) => BpQuickOffsetUse.TrySetHotkey(m, ms)
						},
						new Entry
						{
							Label = "星球透视开关",
							LabelEn = "Planet x-ray toggle",
							GetText = () => HideSurfaceFeature.GetHotkeyText(0),
							TrySet = (KeyCode m, KeyCode[] ms) => HideSurfaceFeature.TrySetHotkey(0, m, ms)
						},
						new Entry
						{
							Label = "地下建筑清理(按住)",
							LabelEn = "Underground cleaner (hold)",
							GetText = () => HideSurfaceFeature.GetHotkeyText(1),
							TrySet = (KeyCode m, KeyCode[] ms) => HideSurfaceFeature.TrySetHotkey(1, m, ms)
						},
						new Entry
						{
							Label = "蓝图回归线自由摆放",
							LabelEn = "Free placement across tropics",
							GetText = () => TropicFreeFeature.GetToggleHotkeyText(),
							TrySet = (KeyCode m, KeyCode[] ms) => TropicFreeFeature.TrySetToggleHotkey(m, ms)
						}
					};
				}
				return _entries;
			}
		}

		public static bool IsModifierKey(KeyCode key)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Invalid comparison between Unknown and I4
			if (key - 303 <= 10)
			{
				return true;
			}
			return false;
		}

		public static bool TryParse(string text, out KeyCode main, out KeyCode[] modifiers)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Expected I4, but got Unknown
			//IL_00cd: 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)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			main = (KeyCode)0;
			modifiers = (KeyCode[])(object)new KeyCode[0];
			if (string.IsNullOrEmpty(text))
			{
				return false;
			}
			KeyCode val = (KeyCode)0;
			List<KeyCode> list = new List<KeyCode>();
			string[] array = text.Split('+');
			for (int i = 0; i < array.Length; i++)
			{
				string text2 = ((array[i] != null) ? array[i].Trim() : "");
				if (text2.Length == 0 || string.Equals(text2, "None", StringComparison.OrdinalIgnoreCase))
				{
					continue;
				}
				if (!Enum.TryParse<KeyCode>(text2, ignoreCase: true, out KeyCode result))
				{
					return false;
				}
				if (!Enum.IsDefined(typeof(KeyCode), result))
				{
					return false;
				}
				if (IsModifierKey(result))
				{
					if (!list.Contains(result))
					{
						list.Add(result);
					}
					continue;
				}
				if ((int)val == 0)
				{
					val = result;
					continue;
				}
				return false;
			}
			if ((int)val == 0 && list.Count > 0)
			{
				val = list[list.Count - 1];
				list.RemoveAt(list.Count - 1);
			}
			if ((int)val == 0)
			{
				return false;
			}
			main = (KeyCode)(int)val;
			modifiers = list.ToArray();
			return true;
		}

		public unsafe static string Format(KeyCode main, KeyCode[] modifiers)
		{
			string text = ((object)(*(KeyCode*)(&main))/*cast due to .constrained prefix*/).ToString();
			if (modifiers != null)
			{
				for (int i = 0; i < modifiers.Length; i++)
				{
					text = text + " + " + ((object)Unsafe.As<KeyCode, KeyCode>(ref modifiers[i])/*cast due to .constrained prefix*/).ToString();
				}
			}
			return text;
		}
	}
}
namespace DSPBPColliderSnap
{
	[BepInPlugin("dsp.bpcollidersnap", "DSPBPColliderSnap", "2.2.0")]
	public class BPColliderSnapPlugin : BaseUnityPlugin
	{
		internal struct BpRect
		{
			public float lngMin;

			public float lngMax;

			public float latMin;

			public float latMax;
		}

		private struct EntityIntervalInfo
		{
			public int poolIndex;

			public float lngMin;

			public float lngMax;

			public float latMin;

			public float latMax;
		}

		internal struct Footprint
		{
			public float minE;

			public float maxE;

			public float minN;

			public float maxN;
		}

		public const string GUID = "dsp.bpcollidersnap";

		public const string NAME = "DSPBPColliderSnap";

		public const string VERSION = "2.2.0";

		internal static ManualLogSource Log;

		internal static BPColliderSnapPlugin Instance;

		private Harmony _harmony;

		private ConfigFile _cfg;

		private ConfigEntry<bool> _enableSnap;

		private ConfigEntry<bool> _magnetEnable;

		private ConfigEntry<float> _gap;

		private ConfigEntry<float> _snapRedundancy;

		private ConfigEntry<float> _snapRedundancyLat;

		private ConfigEntry<float> _magnetRadius;

		private ConfigEntry<float> _lateralAlign;

		private ConfigEntry<int> _dragLimit;

		private ConfigEntry<float> _hiLatSlack;

		private ConfigEntry<string> _relaxItemIds;

		private ConfigEntry<bool> _debugDump;

		private ConfigEntry<string> _hotkey;

		private ConfigEntry<int> _cfgVersion;

		private string _cfgPath = "";

		private KeyCode _mainKey = (KeyCode)110;

		private KeyCode[] _modifierKeys = (KeyCode[])(object)new KeyCode[2]
		{
			(KeyCode)306,
			(KeyCode)304
		};

		private string _hotkeyText = "LeftControl + LeftShift + N";

		private BlueprintData _dumpedBp;

		private static readonly List<ColliderData> ReuseColliderList = new List<ColliderData>(32);

		private const float MaxLayoutLatitudeRad = 1.4835f;

		private const float TwoPi = (float)Math.PI * 2f;

		private const float PiF = (float)Math.PI;

		private static float _lastPlacementLog;

		private static int _lastMagnetAxis = -1;

		private static float _lastMagnetLog;

		private static readonly HashSet<short> RelaxIds = new HashSet<short>();

		private static readonly List<BpRect> BpRects = new List<BpRect>(64);

		private static readonly List<EntityIntervalInfo> NearbyEntities = new List<EntityIntervalInfo>(64);

		private void Awake()
		{
			//IL_0448: Unknown result type (might be due to invalid IL or missing references)
			//IL_0452: Expected O, but got Unknown
			//IL_0490: Unknown result type (might be due to invalid IL or missing references)
			//IL_049d: Expected O, but got Unknown
			//IL_04fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0509: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			try
			{
				_cfg = CreatePluginConfig(out _cfgPath);
				_cfg.SaveOnConfigSet = false;
				_enableSnap = _cfg.Bind<bool>("对齐/Align", "启用碰撞盒对齐", false, "v2.1.9 起默认关闭:进游戏后按快捷键【Ctrl+Shift+N】开启(游戏内会弹出“已开启/已关闭”提示)。开启后拖拽铺设蓝图时,拷贝间距按建筑真实碰撞盒排布(忽略地面网格格数),并磁吸最近建筑。false = 完全恢复原版行为。");
				_magnetEnable = _cfg.Bind<bool>("对齐/Align", "磁吸已有建筑", true, "拖拽蓝图时,落点靠近已建成建筑会自动贴合其碰撞盒边缘(整组拷贝一起平移)。");
				_gap = _cfg.Bind<float>("对齐/Align", "紧贴间距(米)", 0f, "拷贝之间、以及磁吸贴合时的留缝,单位米。0 = 完全紧贴(碰撞盒边缘对碰撞盒边缘)。");
				_snapRedundancy = _cfg.Bind<float>("对齐/Align", "吸附冗余(米)", 0.0025f, "磁吸与拷贝步距在“经纬度区间恰好相接”之外额外留的安全余量。v2.1.3 起默认 0.0025 m(2.5 mm):0 间距实测在部分坡地/浮点场景仍会临界判红;2.5 mm 肉眼不可见。想完全零容错可设 0。");
				_snapRedundancyLat = _cfg.Bind<float>("对齐/Align", "南北吸附冗余(米)", 0.01f, "南北向(Y 轴:上下拖拽 / 纵向贴合)额外留的冗余。v2.2.0 起默认 0.01 m(1 cm):纵向贴合时相邻结构的纬度位置会随经度格宽取档轻微跳动,1 cm 更稳;东西向仍用“吸附冗余(米)”。");
				_magnetRadius = _cfg.Bind<float>("对齐/Align", "磁吸半径(米)", 7f, "落点与已有建筑碰撞盒边缘的距离小于该值时触发贴合(跨小空隙也能吸过去)。0 = 关闭磁吸。");
				_lateralAlign = _cfg.Bind<float>("对齐/Align", "横向对齐阈值(米)", 0f, "贴合时若横向错位小于该值则强制对齐到同一条线。0 = 自动取磁吸半径。");
				_dragLimit = _cfg.Bind<int>("对齐/Align", "拖拽份数上限", 99, "拖拽铺设的最大拷贝份数(默认 99)。原版上限 15(dotsSnapped 数组容量),本模组放宽到最多 255;受游戏蓝图建筑总量上限(默认 15000)约束,份数×蓝图建筑数超限后游戏会拒绝粘贴。范围自动收敛到 15~255。");
				_hiLatSlack = _cfg.Bind<float>("对齐/Align", "高纬度放宽(米)", 0f, "v2.1.2 起已无实际作用(保留兼容):碰撞足迹按游戏本体摆放公式逐栋精确重建,曲率外扩与分拣器 pitch/tilt 旋转已自动计入,拷贝间距与磁吸都按经纬度区间恰好相接(0 间距)计算。");
				_relaxItemIds = _cfg.Bind<string>("对齐/Align", "放宽建筑ID列表", "2310,2318,2309,2317", "享受高纬度放宽的建筑物品ID(逗号分隔)。2310 = 微型粒子对撞机,2309 = 化工厂,2317 = 量子化工厂(化工厂模型的两个ID)。列表为空 = 不放宽任何建筑。");
				_debugDump = _cfg.Bind<bool>("调试/Debug", "输出碰撞盒核实数据", false, "v2.1.9 起默认关闭。开启后,拖拽时会在日志输出实摆验证(游戏实际摆放 vs 模组预测的逐楼偏差)、极限拷贝步距与磁吸决策,供核对问题;平时关闭以免日志刷屏。");
				_hotkey = _cfg.Bind<string>("快捷键/Hotkey", "快捷键", "LeftControl + LeftShift + N", "运行时开启/关闭本模组对齐功能的快捷键(开关时游戏内会弹出提示)。格式与原版键名一致,例如 LeftControl + LeftShift + N、None + F8。");
				_cfgVersion = _cfg.Bind<int>("内部/Internal", "配置版本", 0, "内部使用:记录配置默认值迁移版本,请勿手动修改。");
				SaveQuiet();
				ParseHotkey();
				if (_cfgVersion.Value < 2)
				{
					if (_hotkey.Value == "LeftAlt + B" || _hotkey.Value == "LeftControl + LeftShift + M")
					{
						_hotkey.Value = "LeftControl + LeftShift + N";
					}
					if (Mathf.Abs(_magnetRadius.Value - 3f) < 0.0001f || Mathf.Abs(_magnetRadius.Value - 5f) < 0.0001f)
					{
						_magnetRadius.Value = 7f;
					}
					if (Mathf.Abs(_snapRedundancy.Value - 0.05f) < 0.0001f || Mathf.Abs(_snapRedundancy.Value - 0.005f) < 0.0001f || Mathf.Abs(_snapRedundancy.Value) < 1E-06f)
					{
						_snapRedundancy.Value = 0.0025f;
					}
					if (Mathf.Abs(_hiLatSlack.Value - 0.75f) < 0.0001f || Mathf.Abs(_hiLatSlack.Value - 0.25f) < 0.0001f || Mathf.Abs(_hiLatSlack.Value - 0.45f) < 0.0001f)
					{
						_hiLatSlack.Value = 0f;
					}
					if (_relaxItemIds.Value == "2310,2318,2309")
					{
						_relaxItemIds.Value = "2310,2318,2309,2317";
					}
					if (Mathf.Abs(_snapRedundancyLat.Value - 0.005f) < 0.0001f)
					{
						_snapRedundancyLat.Value = 0.01f;
					}
					if (_cfgVersion.Value < 1)
					{
						_enableSnap.Value = false;
						_debugDump.Value = false;
					}
					_cfgVersion.Value = 2;
				}
				ParseHotkey();
				RefreshRelaxIds();
				SaveQuiet();
				_hotkey.SettingChanged += delegate
				{
					ParseHotkey();
				};
				_relaxItemIds.SettingChanged += delegate
				{
					RefreshRelaxIds();
				};
				_harmony = new Harmony("dsp.bpcollidersnap");
				MethodInfo methodInfo = AccessTools.Method(typeof(BuildTool_BlueprintPaste), "DetermineDragDots", (Type[])null, (Type[])null);
				if (methodInfo != null)
				{
					_harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(BPColliderSnapPlugin), "DetermineDragDots_Postfix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					Log.LogInfo((object)"已挂载补丁:BuildTool_BlueprintPaste.DetermineDragDots(拖拽落点重排)。");
				}
				else
				{
					Log.LogError((object)"找不到 BuildTool_BlueprintPaste.DetermineDragDots,本模组无法工作(游戏版本不匹配?)。");
				}
				MethodInfo methodInfo2 = AccessTools.Method(typeof(BuildTool_BlueprintPaste), "DeterminePreviewsPrestage", (Type[])null, (Type[])null);
				if (methodInfo2 != null)
				{
					_harmony.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(BPColliderSnapPlugin), "DeterminePreviewsPrestage_Postfix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					Log.LogInfo((object)"已挂载补丁:BuildTool_BlueprintPaste.DeterminePreviewsPrestage(实摆位置验证)。");
				}
			}
			catch (Exception ex)
			{
				Log.LogError((object)("初始化失败:" + ex));
			}
			Log.LogInfo((object)string.Format(CultureInfo.InvariantCulture, "{0} v{1} 已加载(默认关闭,进游戏按 {2} 开启)。快捷键:{2};配置文件:{3}", "DSPBPColliderSnap", "2.2.0", _hotkeyText, _cfgPath));
		}

		private void OnDestroy()
		{
			try
			{
				if (_harmony != null)
				{
					_harmony.UnpatchSelf();
				}
			}
			catch
			{
			}
			Instance = null;
		}

		private void Update()
		{
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (VFInput.inputing)
				{
					return;
				}
				if (_modifierKeys != null)
				{
					for (int i = 0; i < _modifierKeys.Length; i++)
					{
						if (!Input.GetKey(_modifierKeys[i]))
						{
							return;
						}
					}
				}
				if (Input.GetKeyDown(_mainKey))
				{
					_enableSnap.Value = !_enableSnap.Value;
					SaveQuiet();
					string text = L10n.T("蓝图碰撞盒对齐 v2.2.0 已" + (_enableSnap.Value ? "开启" : "关闭"), "BP collider snap v2.2.0 turned " + (_enableSnap.Value ? "ON" : "OFF"));
					Tip(text);
					Log.LogInfo((object)text);
				}
			}
			catch
			{
			}
		}

		private ConfigFile CreatePluginConfig(out string path)
		{
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Expected O, but got Unknown
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Expected O, but got Unknown
			string text = null;
			try
			{
				if (((BaseUnityPlugin)this).Info != null && !string.IsNullOrEmpty(((BaseUnityPlugin)this).Info.Location))
				{
					text = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location);
				}
			}
			catch
			{
			}
			if (string.IsNullOrEmpty(text) || !Directory.Exists(text))
			{
				text = Path.Combine(Paths.PluginPath, "DSPBPColliderSnap");
			}
			string text2 = text.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
			if (string.Equals(Path.GetFileName(text2), "plugins", StringComparison.OrdinalIgnoreCase))
			{
				text = Path.Combine(text2, "DSPBPColliderSnap");
			}
			try
			{
				Directory.CreateDirectory(text);
			}
			catch
			{
			}
			path = Path.Combine(text, "DSPBPColliderSnap.cfg");
			CfgMigrator.RestorePluginCfg(path, "DSPBPColliderSnap.cfg");
			try
			{
				return new ConfigFile(path, true);
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("插件目录无法写入配置(" + ex.Message + "),改用 BepInEx/config。"));
				path = Path.Combine(Paths.ConfigPath, "dsp.bpcollidersnap.cfg");
				return new ConfigFile(path, true);
			}
		}

		private void SaveQuiet()
		{
			try
			{
				if (_cfg != null)
				{
					_cfg.Save();
				}
			}
			catch
			{
			}
		}

		private static bool IsModifierKey(KeyCode key)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Invalid comparison between Unknown and I4
			if (key - 303 <= 9)
			{
				return true;
			}
			return false;
		}

		private void ParseHotkey()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: 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_0084: 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_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: 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)
			List<KeyCode> list = new List<KeyCode>();
			KeyCode val = (KeyCode)0;
			string text = ((_hotkey != null) ? _hotkey.Value : null);
			if (!string.IsNullOrEmpty(text))
			{
				string[] array = text.Split('+');
				for (int i = 0; i < array.Length; i++)
				{
					string text2 = array[i].Trim();
					if (text2.Length == 0 || string.Equals(text2, "None", StringComparison.OrdinalIgnoreCase) || !Enum.TryParse<KeyCode>(text2, ignoreCase: true, out KeyCode result))
					{
						continue;
					}
					if (IsModifierKey(result))
					{
						if (!list.Contains(result))
						{
							list.Add(result);
						}
					}
					else if ((int)val == 0)
					{
						val = result;
					}
				}
			}
			if ((int)val == 0 && list.Count > 0)
			{
				val = list[list.Count - 1];
				list.RemoveAt(list.Count - 1);
			}
			if ((int)val == 0)
			{
				val = (KeyCode)110;
				list.Clear();
				list.Add((KeyCode)306);
				list.Add((KeyCode)304);
			}
			_mainKey = val;
			_modifierKeys = list.ToArray();
			List<string> list2 = new List<string>();
			list2.Add(((object)Unsafe.As<KeyCode, KeyCode>(ref _mainKey)/*cast due to .constrained prefix*/).ToString());
			for (int j = 0; j < _modifierKeys.Length; j++)
			{
				list2.Add(((object)Unsafe.As<KeyCode, KeyCode>(ref _modifierKeys[j])/*cast due to .constrained prefix*/).ToString());
			}
			list2.Sort();
			_hotkeyText = string.Join(" + ", list2.ToArray());
		}

		internal string GetHotkeyText()
		{
			try
			{
				return (_hotkey != null) ? _hotkey.Value : "LeftControl + LeftShift + N";
			}
			catch
			{
				return "LeftControl + LeftShift + N";
			}
		}

		internal string TrySetHotkey(KeyCode main, KeyCode[] modifiers)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (_hotkey == null)
				{
					return null;
				}
				string text = HotkeyHub.Format(main, modifiers);
				if (string.Equals(_hotkey.Value, text, StringComparison.Ordinal))
				{
					return _hotkeyText;
				}
				_hotkey.Value = text;
				SaveQuiet();
				return text;
			}
			catch
			{
				return null;
			}
		}

		internal bool GetEnableSnap()
		{
			try
			{
				return _enableSnap != null && _enableSnap.Value;
			}
			catch
			{
				return false;
			}
		}

		internal void SetEnableSnap(bool value)
		{
			try
			{
				if (_enableSnap != null && _enableSnap.Value != value)
				{
					_enableSnap.Value = value;
					SaveQuiet();
					string text = L10n.T("蓝图碰撞盒对齐 v2.2.0 已" + (value ? "开启" : "关闭"), "BP collider snap v2.2.0 turned " + (value ? "ON" : "OFF"));
					Tip(text);
					Log.LogInfo((object)text);
				}
			}
			catch
			{
			}
		}

		internal int GetDragLimit()
		{
			try
			{
				return (_dragLimit != null) ? Mathf.Clamp(_dragLimit.Value, 15, 255) : 255;
			}
			catch
			{
				return 255;
			}
		}

		internal int TrySetDragLimit(int value)
		{
			try
			{
				if (_dragLimit == null)
				{
					return -1;
				}
				int num = Mathf.Clamp(value, 15, 255);
				if (_dragLimit.Value != num)
				{
					_dragLimit.Value = num;
					SaveQuiet();
				}
				return num;
			}
			catch
			{
				return -1;
			}
		}

		private static void RefreshRelaxIds()
		{
			RelaxIds.Clear();
			BPColliderSnapPlugin instance = Instance;
			if ((Object)(object)instance == (Object)null || instance._relaxItemIds == null || string.IsNullOrEmpty(instance._relaxItemIds.Value))
			{
				return;
			}
			string[] array = instance._relaxItemIds.Value.Split(',');
			for (int i = 0; i < array.Length; i++)
			{
				if (short.TryParse(array[i].Trim(), out var result) && result > 0)
				{
					RelaxIds.Add(result);
				}
			}
		}

		private static bool IsRelaxItem(short itemId)
		{
			if (itemId > 0)
			{
				return RelaxIds.Contains(itemId);
			}
			return false;
		}

		private static float Round2Int(float d)
		{
			return (d > 0f) ? ((int)(d + 0.5f)) : ((int)(d - 0.5f));
		}

		private static bool MagnetLogDue()
		{
			BPColliderSnapPlugin instance = Instance;
			if ((Object)(object)instance == (Object)null || !instance._debugDump.Value)
			{
				return false;
			}
			if (Time.unscaledTime < _lastMagnetLog + 0.5f)
			{
				return false;
			}
			_lastMagnetLog = Time.unscaledTime;
			return true;
		}

		internal static void DetermineDragDots_Postfix(BuildTool_BlueprintPaste __instance)
		{
			try
			{
				RealignmentCore(__instance);
			}
			catch (Exception ex)
			{
				if (Log != null)
				{
					Log.LogWarning((object)("拖拽落点对齐失败(已退回原版行为):" + ex.Message));
				}
			}
		}

		private static void RealignmentCore(BuildTool_BlueprintPaste tool)
		{
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_024f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0254: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_030b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0310: Unknown result type (might be due to invalid IL or missing references)
			//IL_0312: Unknown result type (might be due to invalid IL or missing references)
			//IL_031b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0325: Unknown result type (might be due to invalid IL or missing references)
			//IL_0339: Unknown result type (might be due to invalid IL or missing references)
			//IL_033e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0340: Unknown result type (might be due to invalid IL or missing references)
			//IL_0342: Unknown result type (might be due to invalid IL or missing references)
			//IL_0346: Unknown result type (might be due to invalid IL or missing references)
			//IL_034b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0350: Unknown result type (might be due to invalid IL or missing references)
			//IL_0361: Unknown result type (might be due to invalid IL or missing references)
			//IL_0366: Unknown result type (might be due to invalid IL or missing references)
			//IL_0368: Unknown result type (might be due to invalid IL or missing references)
			//IL_036d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0380: Unknown result type (might be due to invalid IL or missing references)
			//IL_038c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0445: Unknown result type (might be due to invalid IL or missing references)
			//IL_0447: Unknown result type (might be due to invalid IL or missing references)
			//IL_042d: Unknown result type (might be due to invalid IL or missing references)
			//IL_050d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0512: Unknown result type (might be due to invalid IL or missing references)
			//IL_0514: Unknown result type (might be due to invalid IL or missing references)
			//IL_051d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0536: Unknown result type (might be due to invalid IL or missing references)
			//IL_053a: Unknown result type (might be due to invalid IL or missing references)
			//IL_053f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0664: Unknown result type (might be due to invalid IL or missing references)
			//IL_066b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0670: Unknown result type (might be due to invalid IL or missing references)
			//IL_05d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_05d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_05dc: Unknown result type (might be due to invalid IL or missing references)
			BPColliderSnapPlugin instance = Instance;
			if ((Object)(object)instance == (Object)null || tool == null || !instance._enableSnap.Value)
			{
				return;
			}
			BlueprintData blueprint = tool.blueprint;
			if (blueprint == null || blueprint.buildings == null || blueprint.buildings.Length == 0)
			{
				return;
			}
			PlanetData planet = ((BuildTool)tool).planet;
			if (planet == null || !planet.factoryLoaded)
			{
				return;
			}
			PlanetFactory factory = planet.factory;
			if (factory == null || factory.entityPool == null)
			{
				return;
			}
			Vector3[] array = tool.dotsSnapped;
			if (array == null || array.Length == 0 || tool.dotsCursor <= 0)
			{
				return;
			}
			if (tool.dotsCursor > array.Length)
			{
				tool.dotsCursor = array.Length;
			}
			int num = Mathf.Clamp(instance._dragLimit.Value, 15, 255);
			if (array.Length < num)
			{
				Vector3[] array2 = (Vector3[])(object)new Vector3[num];
				Array.Copy(array, array2, array.Length);
				tool.dotsSnapped = array2;
				array = array2;
			}
			if (tool.bpGratBoxArr == null || tool.bpGratBoxArr.Length < num)
			{
				tool.bpGratBoxArr = (BPGratBox[])(object)new BPGratBox[num];
				tool.gratBoxCursor = 0;
			}
			if (tool.bpGratBoxConditionArr == null || tool.bpGratBoxConditionArr.Length < num)
			{
				tool.bpGratBoxConditionArr = (IntVector4[])(object)new IntVector4[num];
			}
			Vector3 snappedAnchor = array[0];
			if (((Vector3)(ref snappedAnchor)).sqrMagnitude < 1E-08f)
			{
				return;
			}
			float realRadius = planet.realRadius;
			if (realRadius <= 1f)
			{
				return;
			}
			Vector3 normalized = ((Vector3)(ref snappedAnchor)).normalized;
			float latitudeRad = BlueprintUtils.GetLatitudeRad(normalized);
			float longitudeRad = BlueprintUtils.GetLongitudeRad(normalized);
			float num2 = Mathf.Cos(latitudeRad);
			float num3 = Mathf.Sin(latitudeRad);
			float num4 = Mathf.Cos(longitudeRad);
			float num5 = Mathf.Sin(longitudeRad);
			Vector3 east = default(Vector3);
			((Vector3)(ref east))..ctor(num4, 0f, num5);
			Vector3 north = default(Vector3);
			((Vector3)(ref north))..ctor((0f - num3) * num5, num2, num3 * num4);
			int segment = tool.segment;
			float latitudeRadPerGrid = BlueprintUtils.GetLatitudeRadPerGrid(segment);
			int num6 = Mathf.FloorToInt(tool.yaw / 89.9f);
			num6 = (num6 % 4 + 4) % 4;
			bool lngNeg = num6 == 1 || num6 == 2;
			bool latNeg = num6 == 2 || num6 == 3;
			BlueprintAre