Decompiled source of TropicBeltSpacing v1.5.8

BepInEx\plugins\TropicBeltSpacing\TropicBeltSpacing.dll

Decompiled a day ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyVersion("0.0.0.0")]
namespace TropicBeltSpacing;

internal static class BeltSpacingCore
{
	public const float VanillaMaxSegmentMeters = 2.302172f;

	public const float VanillaMinSegmentMeters = 0.4f;

	[ThreadStatic]
	private static bool _insideVanilla;

	[ThreadStatic]
	private static bool _prefixAppliedThisPath;

	[ThreadStatic]
	private static Vector3[] _fineBuffer;

	[ThreadStatic]
	private static Vector3[] _tempBuffer;

	private static int _appliedCount;

	private static string _lastInfo = "尚未生效 / not applied yet";

	private static float _lastLogTime = -10f;

	private static float _lastRareLogTime = -10f;

	private static float _lastVertLogTime = -10f;

	private static bool _fallbackWarned;

	public static string FallbackStatus = "节点生成:本模组(原版网格折线 + 按分带重采样)";

	private static int _lastK;

	private static float _lastCell = (float)Math.PI * 2f / 5f;

	public static bool HasEverApplied => _appliedCount > 0;

	public static string StatText()
	{
		if (_appliedCount == 0)
		{
			return "本模组重采样:还没生效。请拖一条传送带(本模组独立工作,不需要其它模组)。";
		}
		return "本模组重采样:已生效 " + _appliedCount + " 次\n最近一次 / last: " + _lastInfo;
	}

	private static float LocalCellMeters(PlanetGrid grid, Vector3 mid, Vector3 dir)
	{
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		//IL_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)
		float result = (float)Math.PI * 2f / 5f;
		if (grid == null)
		{
			return result;
		}
		if (((Vector3)(ref dir)).sqrMagnitude < 1E-08f)
		{
			dir = ((Vector3)(ref mid)).normalized;
		}
		else
		{
			((Vector3)(ref dir)).Normalize();
		}
		try
		{
			float num = grid.CalcLocalGridSize(mid, dir);
			if (num > 1E-05f && !float.IsNaN(num) && !float.IsInfinity(num))
			{
				result = num;
			}
		}
		catch
		{
		}
		return result;
	}

	private static void ComputeTarget(PlanetGrid grid, Vector3 begin, Vector3 end, out float target, out float cells, out float cellMeters, out float latDeg, out float minSeg, out float maxSeg)
	{
		//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_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		//IL_0019: Unknown result type (might be due to invalid IL or missing references)
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		Vector3 val = (begin + end) * 0.5f;
		Vector3 dir = end - begin;
		cellMeters = LocalCellMeters(grid, val, dir);
		latDeg = TropicBands.LatitudeOf(val);
		cells = TropicBands.CellsForLatitude(latDeg);
		maxSeg = Mathf.Min(ModConfig.MaxSegmentMeters.Value, 2.302172f) - 0.03f;
		minSeg = Mathf.Max(ModConfig.MinSegmentMeters.Value, 0.4f);
		if (maxSeg < minSeg)
		{
			maxSeg = minSeg;
		}
		if (Mathf.Abs(((Vector3)(ref end)).magnitude - ((Vector3)(ref begin)).magnitude) > 0.6667f)
		{
			float num = Mathf.Sqrt(Mathf.Max(0.04f, maxSeg * maxSeg - 1.7776889f));
			if (num < maxSeg)
			{
				maxSeg = num;
			}
		}
		target = Mathf.Clamp(cells * cellMeters, minSeg, maxSeg * 0.98f);
		if (target > maxSeg)
		{
			target = maxSeg;
		}
		_lastK = 0;
		_lastCell = cellMeters;
	}

	private static void GetLatLon(Vector3 npos, out float lat, out float lon)
	{
		//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_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		//IL_0019: 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_003f: 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)
		Vector3 val = npos;
		float magnitude = ((Vector3)(ref val)).magnitude;
		val = ((!(magnitude > 1E-05f)) ? Vector3.up : (val / magnitude));
		lat = Mathf.Asin(Mathf.Clamp(val.y, -1f, 1f));
		lon = Mathf.Atan2(val.x, 0f - val.z);
	}

	private static Vector3 UnitOf(float lat, float lon)
	{
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		float num = Mathf.Cos(lat);
		return new Vector3(num * Mathf.Sin(lon), Mathf.Sin(lat), (0f - num) * Mathf.Cos(lon));
	}

	private static float WrapDelta(float d)
	{
		while (d > (float)Math.PI)
		{
			d -= (float)Math.PI * 2f;
		}
		while (d < -(float)Math.PI)
		{
			d += (float)Math.PI * 2f;
		}
		return d;
	}

	private static float LonCountAt(PlanetGrid grid, float lat)
	{
		if (grid == null)
		{
			return 200f;
		}
		float num = (float)Math.PI * 2f / (float)grid.segment;
		int num2 = Mathf.FloorToInt(Mathf.Max(0f, Mathf.Abs(lat) / num - 0.1f));
		int num3;
		try
		{
			num3 = PlanetGrid.DetermineLongitudeSegmentCount(num2, grid.segment);
		}
		catch
		{
			num3 = 200;
		}
		if (num3 < 4)
		{
			num3 = 4;
		}
		return num3;
	}

	private static int BuildLeg(Vector3[] dst, int n, int cap, PlanetGrid grid, float lat0, float lon0, float lat1, float lon1, bool isMeridian, bool lattice, float target, float limit)
	{
		//IL_0239: Unknown result type (might be due to invalid IL or missing references)
		//IL_023e: Unknown result type (might be due to invalid IL or missing references)
		//IL_015d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0162: Unknown result type (might be due to invalid IL or missing references)
		//IL_0168: Unknown result type (might be due to invalid IL or missing references)
		//IL_016d: 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_0182: Unknown result type (might be due to invalid IL or missing references)
		//IL_0184: Unknown result type (might be due to invalid IL or missing references)
		//IL_013b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0140: Unknown result type (might be due to invalid IL or missing references)
		float num = (isMeridian ? (lat1 - lat0) : WrapDelta(lon1 - lon0));
		float num2 = Mathf.Abs(num);
		if (num2 < 1E-07f)
		{
			return n;
		}
		float num3 = (isMeridian ? 1f : Mathf.Max(0.02f, Mathf.Cos(0.5f * (lat0 + lat1))));
		float num4 = num2 * num3;
		if (num4 < 1E-07f)
		{
			return n;
		}
		if (lattice)
		{
			float num5 = (isMeridian ? ((float)Math.PI * 2f / ((float)grid.segment * 5f)) : ((float)Math.PI * 2f / (LonCountAt(grid, 0.5f * (lat0 + lat1)) * 5f)));
			float num6 = num5 * num3;
			int num7 = Mathf.Max(1, Mathf.RoundToInt(target / Mathf.Max(0.0001f, num6)));
			while (num7 > 1 && (float)num7 * num6 > limit)
			{
				num7--;
			}
			_lastK = num7;
			float num8 = (float)num7 * num5 * Mathf.Sign(num);
			float num9 = 0f;
			while (n < cap - 1)
			{
				float num10 = num9 + num8;
				bool num11 = Mathf.Abs(num10) >= num2 - 1E-07f;
				if (num11)
				{
					num10 = num;
				}
				float lat2 = (isMeridian ? (lat0 + num10) : lat0);
				float lon2 = (isMeridian ? lon0 : (lon0 + num10));
				dst[n++] = UnitOf(lat2, lon2);
				if (num11)
				{
					break;
				}
				num9 = num10;
			}
			if (n > 0 && n < cap)
			{
				Vector3 val = UnitOf(lat1, lon1);
				if (Vector3.Distance(dst[n - 1], val) > 1E-06f)
				{
					dst[n++] = val;
				}
			}
			return n;
		}
		int num12 = Mathf.Max(1, Mathf.RoundToInt(num4 / Mathf.Max(1E-05f, target)));
		if (num4 / (float)num12 > limit)
		{
			num12 = Mathf.CeilToInt(num4 / limit);
		}
		int num13 = cap - n;
		if (num12 >= num13)
		{
			num12 = num13 - 1;
		}
		if (num12 < 1)
		{
			num12 = 1;
		}
		_lastK = 0;
		for (int i = 1; i < num12; i++)
		{
			float num14 = (float)i / (float)num12;
			float lat3 = (isMeridian ? (lat0 + num * num14) : lat0);
			float lon3 = (isMeridian ? lon0 : (lon0 + num * num14));
			dst[n++] = UnitOf(lat3, lon3);
		}
		if (n < cap)
		{
			dst[n++] = UnitOf(lat1, lon1);
		}
		return n;
	}

	private static int BuildLPath(PlanetGrid grid, Vector3 begin, Vector3 end, bool legAIsMeridian, bool lattice, float target, float limit, Vector3[] dst, int cap, out int cornerIdx)
	{
		//IL_0004: 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_0038: 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)
		cornerIdx = 0;
		GetLatLon(begin, out var lat, out var lon);
		GetLatLon(end, out var lat2, out var lon2);
		float num = (legAIsMeridian ? lat2 : lat);
		float num2 = (legAIsMeridian ? lon : lon2);
		int n = 0;
		dst[n++] = UnitOf(lat, lon);
		n = BuildLeg(dst, n, cap, grid, lat, lon, num, num2, legAIsMeridian, lattice, target, limit);
		cornerIdx = n - 1;
		return BuildLeg(dst, n, cap, grid, num, num2, lat2, lon2, !legAIsMeridian, lattice, target, limit);
	}

	public static string ModeText()
	{
		if (!ModConfig.BlueprintSafe.Value)
		{
			return "间距模式:自由间距 1.6~1.8 当地格(省料优先,每节≤2.272m,蓝图可保存)";
		}
		if (_lastK <= 0)
		{
			return "间距模式:蓝图安全(只使用原版整数格节点)";
		}
		return "间距模式:蓝图安全 = " + _lastK + " 当地格" + ((_lastK >= 2) ? "(已放大,且 2 格 ≤ √5.3)" : "(该纬度 2 格会超过 √5.3,只能保持原版间距)");
	}

	private static void NoteApplied(float latDeg, float cells, float target, int inCount, int outCount, float avgMeters, float cellMeters, float longestMeters)
	{
		_appliedCount++;
		float realtimeSinceStartup = Time.realtimeSinceStartup;
		bool flag = ModConfig.LogSpacing.Value && (Object)(object)Plugin.Instance != (Object)null && realtimeSinceStartup - _lastLogTime >= 1f;
		if (flag)
		{
			float num = ((inCount > 1 && outCount > 1) ? Mathf.Clamp01(1f - (float)(outCount - 1) / (float)(inCount - 1)) : 0f);
			_lastInfo = string.Format(CultureInfo.InvariantCulture, "[{0}] lat={1:0.0}° band={2} cells={3:0.000} 格长={4:0.000}m 目标={5:0.000}m 节点 {6}->{7}(省{8:0}%) 实测均长={9:0.000}m({10:0.000}格) 最长={11:0.000}m(上限{12:0.000}m)", ModConfig.BlueprintSafe.Value ? "整数格" : "自由", latDeg, TropicBands.BandIndex(latDeg), cells, cellMeters, target, inCount, outCount, num * 100f, avgMeters, (cellMeters > 0.0001f) ? (avgMeters / cellMeters) : 0f, longestMeters, 2.302172f);
			if (flag)
			{
				_lastLogTime = realtimeSinceStartup;
				Plugin.LogInfo("[TropicBeltSpacing] " + _lastInfo);
			}
		}
	}

	private static void LogRare(string message)
	{
		if (!((Object)(object)Plugin.Instance == (Object)null))
		{
			Plugin.LogInfo(message);
		}
	}

	private static bool RareLogDue()
	{
		if ((Object)(object)Plugin.Instance == (Object)null)
		{
			return false;
		}
		float realtimeSinceStartup = Time.realtimeSinceStartup;
		if (realtimeSinceStartup - _lastRareLogTime < 1f)
		{
			return false;
		}
		_lastRareLogTime = realtimeSinceStartup;
		return true;
	}

	private static void LogVert(string message)
	{
		if (!((Object)(object)Plugin.Instance == (Object)null))
		{
			Plugin.LogInfo(message);
		}
	}

	private static bool VertLogDue()
	{
		if ((Object)(object)Plugin.Instance == (Object)null)
		{
			return false;
		}
		float realtimeSinceStartup = Time.realtimeSinceStartup;
		if (realtimeSinceStartup - _lastVertLogTime < 1f)
		{
			return false;
		}
		_lastVertLogTime = realtimeSinceStartup;
		return true;
	}

	private static int BuildClimbEven(Vector3[] src, int srcCount, Vector3 begin, Vector3 end, Vector3[] dst, int cap, float targetMeters, float minSegMeters, float maxSegMeters, out int forcedOut, out float segLenMeters)
	{
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		//IL_004d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0186: Unknown result type (might be due to invalid IL or missing references)
		//IL_018b: Unknown result type (might be due to invalid IL or missing references)
		//IL_010d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0112: Unknown result type (might be due to invalid IL or missing references)
		//IL_0116: Unknown result type (might be due to invalid IL or missing references)
		//IL_011b: 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_026f: 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_015f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0144: Unknown result type (might be due to invalid IL or missing references)
		//IL_0146: 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_0154: Unknown result type (might be due to invalid IL or missing references)
		//IL_0158: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bf: 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_01fc: Unknown result type (might be due to invalid IL or missing references)
		//IL_0204: Unknown result type (might be due to invalid IL or missing references)
		//IL_0210: Unknown result type (might be due to invalid IL or missing references)
		//IL_0215: Unknown result type (might be due to invalid IL or missing references)
		//IL_0219: Unknown result type (might be due to invalid IL or missing references)
		//IL_021e: Unknown result type (might be due to invalid IL or missing references)
		//IL_024e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0253: Unknown result type (might be due to invalid IL or missing references)
		forcedOut = 0;
		segLenMeters = 0f;
		if (srcCount < 2 || cap < 4)
		{
			return 0;
		}
		float num = ((((Vector3)(ref begin)).magnitude > 0.001f) ? ((Vector3)(ref begin)).magnitude : 1f);
		float num2 = 0f;
		for (int i = 1; i < srcCount; i++)
		{
			num2 += Vector3.Distance(src[i - 1], src[i]);
		}
		float num3 = Mathf.Abs(((Vector3)(ref end)).magnitude - ((Vector3)(ref begin)).magnitude);
		float num4 = num2 * num;
		bool flag = num4 < 0.25f;
		float num5 = (flag ? num3 : Mathf.Sqrt(num4 * num4 + num3 * num3));
		if (num5 < 0.0001f)
		{
			return 0;
		}
		int num6 = Mathf.RoundToInt(num5 / Mathf.Max(0.0001f, targetMeters));
		if (num6 < 1)
		{
			num6 = 1;
		}
		if (num5 / (float)num6 > maxSegMeters)
		{
			num6 = Mathf.CeilToInt(num5 / maxSegMeters);
		}
		if (num5 / (float)num6 < minSegMeters)
		{
			num6 = Mathf.FloorToInt(num5 / minSegMeters);
		}
		if (num6 < 1)
		{
			num6 = 1;
		}
		if (num6 + 1 > cap)
		{
			num6 = cap - 1;
		}
		Vector3 val;
		if (flag)
		{
			Vector3 normalized = ((Vector3)(ref begin)).normalized;
			Vector3 normalized2 = ((Vector3)(ref end)).normalized;
			bool flag2 = Vector3.Dot(normalized, normalized2) > 0.9999995f;
			segLenMeters = num3 / (float)num6;
			for (int j = 0; j <= num6; j++)
			{
				int num7 = j;
				Vector3 val2;
				if (!flag2)
				{
					val = Vector3.Slerp(normalized, normalized2, (float)j / (float)num6);
					val2 = ((Vector3)(ref val)).normalized;
				}
				else
				{
					val2 = normalized;
				}
				dst[num7] = val2;
			}
			return num6 + 1;
		}
		float num8 = num2 / (float)num6;
		int num9 = 1;
		dst[0] = ((Vector3)(ref begin)).normalized;
		float num10 = 0f;
		int k = 1;
		for (int l = 1; l <= num6; l++)
		{
			float num11 = num8 * (float)l;
			bool flag3 = false;
			for (; k < srcCount; k++)
			{
				float num12 = Vector3.Distance(src[k - 1], src[k]);
				if (num10 + num12 >= num11 - 1E-09f)
				{
					float num13 = (num11 - num10) / Mathf.Max(1E-09f, num12);
					int num14 = num9++;
					val = Vector3.Slerp(src[k - 1], src[k], Mathf.Clamp01(num13));
					dst[num14] = ((Vector3)(ref val)).normalized;
					flag3 = true;
					break;
				}
				num10 += num12;
			}
			if (!flag3)
			{
				dst[num9++] = src[srcCount - 1];
			}
		}
		dst[num9 - 1] = ((Vector3)(ref end)).normalized;
		segLenMeters = num5 / (float)num6;
		return num9;
	}

	private static float LongestSegment(Vector3[] nodes, int count)
	{
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		float num = 0f;
		for (int i = 1; i < count; i++)
		{
			float num2 = Vector3.Distance(nodes[i - 1], nodes[i]);
			if (num2 > num)
			{
				num = num2;
			}
		}
		return num;
	}

	private static float AverageSegment(Vector3[] nodes, int count)
	{
		//IL_0019: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		if (count < 2)
		{
			return 0f;
		}
		float num = 0f;
		for (int i = 1; i < count; i++)
		{
			num += Vector3.Distance(nodes[i - 1], nodes[i]);
		}
		return num / (float)(count - 1);
	}

	private static int ThinOnLattice(Vector3[] src, int srcCount, Vector3[] dst, int cap, float targetU, float maxSegU, int forceIndex, out int forcedOut)
	{
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0036: 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_0057: Unknown result type (might be due to invalid IL or missing references)
		//IL_0060: Unknown result type (might be due to invalid IL or missing references)
		//IL_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)
		forcedOut = 0;
		if (srcCount < 2 || cap < 2)
		{
			return 0;
		}
		int num = 0;
		dst[num++] = src[0];
		for (int i = 1; i < srcCount; i++)
		{
			if (num >= cap)
			{
				break;
			}
			bool num2 = i == srcCount - 1;
			bool flag = i == forceIndex;
			float num3 = Vector3.Distance(dst[num - 1], src[i]);
			float num4 = ((i + 1 < srcCount) ? Vector3.Distance(src[i], src[i + 1]) : 0f);
			if (num2 || flag || num3 + num4 > maxSegU || num3 >= targetU)
			{
				dst[num] = src[i];
				if (flag)
				{
					forcedOut = num;
				}
				num++;
			}
		}
		if (num < 2)
		{
			return 0;
		}
		return num;
	}

	private static int Resample(Vector3[] src, int srcCount, Vector3[] dst, int cap, float target, float minSeg, float maxSeg, int forceIndex, out int forcedOut)
	{
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_0038: 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_003f: 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_01df: 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_00e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
		//IL_0061: Unknown result type (might be due to invalid IL or missing references)
		//IL_0062: 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_006e: 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_008a: 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_0190: Unknown result type (might be due to invalid IL or missing references)
		//IL_0192: Unknown result type (might be due to invalid IL or missing references)
		//IL_016a: Unknown result type (might be due to invalid IL or missing references)
		//IL_016f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0115: Unknown result type (might be due to invalid IL or missing references)
		//IL_011a: Unknown result type (might be due to invalid IL or missing references)
		//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_012e: 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_0144: Unknown result type (might be due to invalid IL or missing references)
		//IL_0146: Unknown result type (might be due to invalid IL or missing references)
		forcedOut = 0;
		if (srcCount < 2 || cap < 2)
		{
			return 0;
		}
		int num = 0;
		dst[num++] = src[0];
		float num2 = target;
		for (int i = 1; i < srcCount; i++)
		{
			Vector3 val = src[i - 1];
			Vector3 val2 = src[i];
			float num3 = Vector3.Distance(val, val2);
			float num4 = 0f;
			if (num3 > 1E-06f)
			{
				while (num3 - num4 >= num2 && num < cap)
				{
					num4 += num2;
					Vector3 val3 = Interp(val, val2, num4 / num3);
					if (Vector3.Distance(dst[num - 1], val3) >= minSeg)
					{
						dst[num++] = val3;
						num2 = target;
					}
					else
					{
						num2 += target;
					}
				}
				num2 -= num3 - num4;
				if (num2 < 0.0001f)
				{
					num2 = 0.0001f;
				}
			}
			bool flag = i == forceIndex;
			bool flag2 = i == srcCount - 1;
			if ((flag || flag2) && num < cap)
			{
				float num5 = Vector3.Distance(dst[num - 1], val2);
				if (num5 > maxSeg)
				{
					int num6 = Mathf.CeilToInt(num5 / maxSeg);
					if (num6 < 2)
					{
						num6 = 2;
					}
					for (int j = 1; j < num6; j++)
					{
						if (num >= cap)
						{
							break;
						}
						Vector3 val4 = Interp(dst[num - 1], val2, (float)j / (float)num6);
						if (Vector3.Distance(dst[num - 1], val4) >= minSeg)
						{
							dst[num++] = val4;
						}
					}
					num5 = ((num > 0) ? Vector3.Distance(dst[num - 1], val2) : 0f);
				}
				if ((num5 >= minSeg || flag) && num < cap)
				{
					dst[num++] = val2;
					if (flag)
					{
						forcedOut = num - 1;
					}
					num2 = target;
				}
			}
			if (num >= cap)
			{
				break;
			}
		}
		while (num >= 3 && Vector3.Distance(dst[num - 2], dst[num - 1]) < minSeg)
		{
			dst[num - 2] = dst[num - 1];
			num--;
			if (forcedOut >= num)
			{
				forcedOut = num - 1;
			}
		}
		if (num < 2)
		{
			return 0;
		}
		return num;
	}

	private static Vector3 Interp(Vector3 a, Vector3 b, float t)
	{
		//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_000a: Unknown result type (might be due to invalid IL or missing references)
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		//IL_0023: 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_002e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0033: Unknown result type (might be due to invalid IL or missing references)
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		//IL_001f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0049: 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)
		Vector3 normalized = ((Vector3)(ref a)).normalized;
		Vector3 normalized2 = ((Vector3)(ref b)).normalized;
		Vector3 val;
		if (Vector3.Dot(normalized, normalized2) > 0.9999995f)
		{
			val = normalized;
		}
		else
		{
			Vector3 val2 = Vector3.Slerp(normalized, normalized2, t);
			val = ((Vector3)(ref val2)).normalized;
		}
		float num = Mathf.Lerp(((Vector3)(ref a)).magnitude, ((Vector3)(ref b)).magnitude, t);
		return val * num;
	}

	private static bool InsertMidpoint(Vector3[] arr, ref int count, int index, int cap, ref int forcedOut)
	{
		//IL_0014: 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_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_0034: Unknown result type (might be due to invalid IL or missing references)
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_004c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0051: Unknown result type (might be due to invalid IL or missing references)
		//IL_0064: Unknown result type (might be due to invalid IL or missing references)
		//IL_0065: Unknown result type (might be due to invalid IL or missing references)
		if (index < 0 || index + 1 >= count || count >= cap)
		{
			return false;
		}
		Vector3 val = arr[index];
		Vector3 val2 = arr[index + 1];
		if (Vector3.Distance(val, val2) < 1E-06f)
		{
			return false;
		}
		Vector3 val3 = Interp(val, val2, 0.5f);
		for (int num = count; num > index + 1; num--)
		{
			arr[num] = arr[num - 1];
		}
		arr[index + 1] = val3;
		count++;
		if (forcedOut > index)
		{
			forcedOut++;
		}
		return true;
	}

	private static void EnforceMaxSegment(Vector3[] snaps, ref int outCount, int cap, float maxSeg, ref int forcedOut)
	{
		//IL_000a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		int num = 0;
		int num2 = 1;
		while (num2 < outCount && outCount < cap && num++ < 64)
		{
			if (Vector3.Distance(snaps[num2 - 1], snaps[num2]) <= maxSeg)
			{
				num2++;
			}
			else if (!InsertMidpoint(snaps, ref outCount, num2 - 1, cap, ref forcedOut))
			{
				num2++;
			}
		}
	}

	private static void ProtectEnds(Vector3[] snaps, ref int outCount, int cap, Vector3 begin, Vector3 end, float maxSeg, ref int forcedOut)
	{
		//IL_002c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0031: Unknown result type (might be due to invalid IL or missing references)
		//IL_0060: 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)
		int num = 0;
		while (outCount >= 2 && outCount < cap && num++ < 16 && Vector3.Distance(snaps[outCount - 2], end) > maxSeg && InsertMidpoint(snaps, ref outCount, outCount - 2, cap, ref forcedOut))
		{
		}
		num = 0;
		while (outCount >= 2 && outCount < cap && num++ < 16 && Vector3.Distance(begin, snaps[1]) > maxSeg && InsertMidpoint(snaps, ref outCount, 0, cap, ref forcedOut))
		{
		}
	}

	public static bool Prefix(PlanetGrid __instance, Vector3 begin, Vector3 end, int path, Vector3[] snaps, ref int swerveIndex, ref int __result)
	{
		//IL_02aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_0077: Unknown result type (might be due to invalid IL or missing references)
		//IL_007e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0083: Unknown result type (might be due to invalid IL or missing references)
		//IL_0088: Unknown result type (might be due to invalid IL or missing references)
		//IL_032c: Unknown result type (might be due to invalid IL or missing references)
		//IL_032d: 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_00c9: Unknown result type (might be due to invalid IL or missing references)
		//IL_0382: Unknown result type (might be due to invalid IL or missing references)
		//IL_0383: 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_00e8: Unknown result type (might be due to invalid IL or missing references)
		//IL_0152: Unknown result type (might be due to invalid IL or missing references)
		//IL_0153: Unknown result type (might be due to invalid IL or missing references)
		//IL_03c2: Unknown result type (might be due to invalid IL or missing references)
		//IL_03cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_03eb: 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_041b: Unknown result type (might be due to invalid IL or missing references)
		//IL_035a: Unknown result type (might be due to invalid IL or missing references)
		//IL_035f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0457: Unknown result type (might be due to invalid IL or missing references)
		//IL_045c: Unknown result type (might be due to invalid IL or missing references)
		//IL_04a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_04ab: Unknown result type (might be due to invalid IL or missing references)
		if (!ModConfig.EnableSpacing.Value)
		{
			return true;
		}
		if (__instance == null || snaps == null || snaps.Length <= 12)
		{
			return true;
		}
		if (_insideVanilla)
		{
			return true;
		}
		if (ModConfig.VerticalThin.Value)
		{
			float num = Mathf.Abs(((Vector3)(ref end)).magnitude - ((Vector3)(ref begin)).magnitude) / 1.3333333f;
			if (num >= ModConfig.VerticalMinHeightCells.Value)
			{
				int num2 = snaps.Length - 10;
				if (num2 >= 4)
				{
					Vector3 val = ((Vector3)(ref begin)).normalized - ((Vector3)(ref end)).normalized;
					if (((Vector3)(ref val)).magnitude <= 0.006f)
					{
						return true;
					}
					Vector3[] array = _fineBuffer;
					if (array == null || array.Length != snaps.Length)
					{
						array = (_fineBuffer = (Vector3[])(object)new Vector3[snaps.Length]);
					}
					_insideVanilla = true;
					int num3;
					try
					{
						int num4 = default(int);
						num3 = __instance.SnapLineNonAlloc(begin, end, path, array, ref num4);
					}
					finally
					{
						_insideVanilla = false;
					}
					if (num3 < 2)
					{
						return true;
					}
					ComputeTarget(__instance, begin, end, out var _, out var cells, out var cellMeters, out var latDeg, out var minSeg, out var _);
					float num5 = Mathf.Clamp(cells, Mathf.Max(1f, ModConfig.VerticalThinMinCells.Value), Mathf.Max(1f, ModConfig.VerticalThinMaxCells.Value));
					float num6 = num5 * cellMeters;
					float num7 = Mathf.Min(ModConfig.MaxSegmentMeters.Value, 2.302172f) - 0.03f;
					int forcedOut;
					float segLenMeters;
					int outCount = BuildClimbEven(array, num3, begin, end, snaps, num2, num6, minSeg, num7, out forcedOut, out segLenMeters);
					if (outCount >= 2)
					{
						float num8 = ((((Vector3)(ref begin)).magnitude > 0.001f) ? ((Vector3)(ref begin)).magnitude : 1f);
						float maxSeg2 = num7 / num8;
						EnforceMaxSegment(snaps, ref outCount, num2, maxSeg2, ref forcedOut);
						swerveIndex = Mathf.Clamp(forcedOut, 0, outCount - 1);
						__result = outCount;
						_prefixAppliedThisPath = true;
						if (cellMeters > 0.0001f)
						{
							_lastK = Mathf.RoundToInt(segLenMeters / cellMeters);
						}
						if (VertLogDue())
						{
							LogVert($"[TropicBeltSpacing] 垂直抽稀传送带生效:爬升{num:0.##}层 → {outCount - 1}节 每节约{segLenMeters:0.000}m({((cellMeters > 0.0001f) ? (segLenMeters / cellMeters) : 0f):0.00}格)");
						}
						if (ModConfig.LogSpacing.Value)
						{
							NoteApplied(latDeg, num5, num6, num3, outCount, segLenMeters, cellMeters, Mathf.Max(segLenMeters, LongestSegment(snaps, outCount) * num8));
						}
						return false;
					}
				}
			}
		}
		if (ModConfig.SkipClimb.Value && Mathf.Abs(((Vector3)(ref end)).magnitude - ((Vector3)(ref begin)).magnitude) / 1.3333333f >= ModConfig.ClimbSkipLevels.Value)
		{
			_prefixAppliedThisPath = true;
			return true;
		}
		if (ModConfig.SkipVertical.Value)
		{
			float num9 = Vector3.Angle(begin, end);
			float num10 = Mathf.Abs(((Vector3)(ref end)).magnitude - ((Vector3)(ref begin)).magnitude) / 1.3333333f;
			if (num9 <= ModConfig.VerticalAngleTolerance.Value && num10 >= ModConfig.VerticalMinHeightCells.Value)
			{
				_prefixAppliedThisPath = true;
				return true;
			}
		}
		_prefixAppliedThisPath = false;
		int num11 = snaps.Length - 10;
		if (num11 < 2)
		{
			return true;
		}
		Vector3[] array2 = _fineBuffer;
		if (array2 == null || array2.Length != snaps.Length)
		{
			array2 = (_fineBuffer = (Vector3[])(object)new Vector3[snaps.Length]);
		}
		_insideVanilla = true;
		int num12;
		int num13 = default(int);
		try
		{
			num12 = __instance.SnapLineNonAlloc(begin, end, path, array2, ref num13);
		}
		finally
		{
			_insideVanilla = false;
		}
		if (num12 < 2)
		{
			int num14 = Mathf.Min(num12, num11);
			for (int i = 0; i < num14; i++)
			{
				snaps[i] = array2[i];
			}
			swerveIndex = num13;
			__result = num14;
			_prefixAppliedThisPath = true;
			return false;
		}
		ComputeTarget(__instance, begin, end, out var target2, out var cells2, out var cellMeters2, out var latDeg2, out var minSeg2, out var maxSeg3);
		float num15 = ((Vector3)(ref begin)).magnitude;
		if (num15 < 0.001f)
		{
			num15 = 1f;
		}
		float target3 = target2 / num15;
		_ = minSeg2 / num15;
		float num16 = maxSeg3 / num15;
		GetLatLon(begin, out var lat, out var lon);
		GetLatLon(end, out var lat2, out var lon2);
		int num17 = Mathf.Clamp(num13, 1, Mathf.Max(1, num12 - 2));
		GetLatLon(array2[num17], out var lat3, out var lon3);
		bool flag = Mathf.Abs(lat3 - lat) >= Mathf.Abs(WrapDelta(lon3 - lon));
		int cornerIdx;
		int outCount2 = BuildLPath(__instance, begin, end, flag, ModConfig.BlueprintSafe.Value, target3, num16, snaps, num11, out cornerIdx);
		if (outCount2 < 2 || cornerIdx < 1)
		{
			int num18 = Mathf.Min(num12, num11);
			for (int j = 0; j < num18; j++)
			{
				snaps[j] = array2[j];
			}
			swerveIndex = num13;
			__result = num18;
			_prefixAppliedThisPath = true;
			return false;
		}
		if (outCount2 > num12 * 2 + 4 || outCount2 >= num11 - 1)
		{
			int num19 = Mathf.Min(num12, num11);
			for (int k = 0; k < num19; k++)
			{
				snaps[k] = array2[k];
			}
			swerveIndex = num13;
			__result = num19;
			_prefixAppliedThisPath = true;
			if (RareLogDue())
			{
				LogRare($"[TropicBeltSpacing] 几何异常已回退原版节点:latB={lat:0.000} lonB={lon:0.000} latE={lat2:0.000} lonE={lon2:0.000} 腿序(经线在前)={flag} 目标={target2:0.000}m 原版节点={num12} 本模组节点={outCount2}");
			}
			return false;
		}
		int forcedOut2 = cornerIdx;
		EnforceMaxSegment(snaps, ref outCount2, num11, num16, ref forcedOut2);
		swerveIndex = Mathf.Clamp(cornerIdx, 0, outCount2 - 1);
		__result = outCount2;
		_prefixAppliedThisPath = true;
		float num20 = AverageSegment(snaps, outCount2);
		if (cellMeters2 > 0.0001f)
		{
			_lastK = Mathf.RoundToInt(num20 * num15 / cellMeters2);
		}
		if (ModConfig.LogSpacing.Value)
		{
			NoteApplied(latDeg2, cells2, target2, num12, outCount2, num20 * num15, cellMeters2, LongestSegment(snaps, outCount2) * num15);
		}
		return false;
	}

	public static void Postfix(PlanetAuxData __instance, Vector3 begin, Vector3 end, int path, bool geodesic, bool begin_flat, Vector3[] snaps, bool forceVertical, ref float maxGridSlope, bool useOldPath, ref int __result)
	{
		//IL_004a: 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_0056: Unknown result type (might be due to invalid IL or missing references)
		//IL_005b: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
		//IL_0094: Unknown result type (might be due to invalid IL or missing references)
		//IL_0095: Unknown result type (might be due to invalid IL or missing references)
		//IL_0270: 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_010c: Unknown result type (might be due to invalid IL or missing references)
		//IL_010d: Unknown result type (might be due to invalid IL or missing references)
		//IL_010e: Unknown result type (might be due to invalid IL or missing references)
		//IL_010f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0116: Unknown result type (might be due to invalid IL or missing references)
		//IL_011b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0120: Unknown result type (might be due to invalid IL or missing references)
		//IL_0275: Unknown result type (might be due to invalid IL or missing references)
		//IL_0285: Unknown result type (might be due to invalid IL or missing references)
		//IL_0280: Unknown result type (might be due to invalid IL or missing references)
		//IL_028a: Unknown result type (might be due to invalid IL or missing references)
		//IL_03c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_03c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_03f1: Unknown result type (might be due to invalid IL or missing references)
		//IL_03f3: Unknown result type (might be due to invalid IL or missing references)
		if (!ModConfig.EnableSpacing.Value)
		{
			return;
		}
		if (_prefixAppliedThisPath)
		{
			_prefixAppliedThisPath = false;
		}
		else
		{
			if (__instance == null || snaps == null)
			{
				return;
			}
			if (ModConfig.VerticalThin.Value)
			{
				float num = Mathf.Abs(((Vector3)(ref end)).magnitude - ((Vector3)(ref begin)).magnitude);
				Vector3 val = ((Vector3)(ref begin)).normalized - ((Vector3)(ref end)).normalized;
				if (((Vector3)(ref val)).magnitude <= 0.006f && num / 1.3333333f >= ModConfig.VerticalMinHeightCells.Value && __result >= 2)
				{
					ComputeTarget(__instance.activeGrid, begin, end, out var _, out var _, out var cellMeters, out var _, out var _, out var _);
					float num2 = Mathf.Clamp(ModConfig.VerticalThinMaxCells.Value, 0.5f, 3f) * cellMeters;
					int num3 = Mathf.CeilToInt(num / Mathf.Max(0.001f, num2));
					if (num3 < 1)
					{
						num3 = 1;
					}
					int num4 = snaps.Length - 10;
					if (num3 + 1 > num4)
					{
						num3 = num4 - 1;
					}
					for (int i = 0; i <= num3; i++)
					{
						float num5 = (float)i / (float)num3;
						snaps[i] = begin + (end - begin) * num5;
					}
					__result = num3 + 1;
					if (VertLogDue())
					{
						LogVert($"[TropicBeltSpacing] 垂直抽稀传送带生效(Z轴):爬升{num / 1.3333333f:0.##}层 → {num3}节 每节约{num / (float)num3:0.000}m({((cellMeters > 0.0001f) ? (num / (float)num3 / cellMeters) : 0f):0.00}格)");
					}
					return;
				}
			}
			if (!_fallbackWarned)
			{
				_fallbackWarned = true;
				FallbackStatus = "节点生成:本次不是本模组前置补丁生成的(常见于原版测地线模式的 R 变体),已由兜底重采样处理";
				Plugin.LogInfo("[TropicBeltSpacing] " + FallbackStatus + " —— 建议关掉那个模组的路径功能,或保持 Spacing/UseVanillaGridPath = true 让本模组接管。");
			}
			int num6 = __result;
			if (num6 < 2 || num6 > snaps.Length)
			{
				return;
			}
			ComputeTarget(__instance.activeGrid, begin, end, out var target2, out var cells2, out var cellMeters2, out var latDeg2, out var minSeg2, out var maxSeg2);
			float num7 = 0f;
			for (int j = 0; j < num6; j++)
			{
				num7 += ((Vector3)(ref snaps[j])).magnitude;
			}
			num7 /= (float)num6;
			float magnitude = ((Vector3)(ref begin)).magnitude;
			float num8 = 1f;
			if (magnitude > 2f && num7 < 2f)
			{
				num8 = magnitude;
			}
			float num9 = target2 / num8;
			float minSeg3 = minSeg2 / num8;
			float maxSeg3 = maxSeg2 / num8;
			Vector3 begin2 = ((num8 > 1.0001f) ? ((Vector3)(ref begin)).normalized : begin);
			Vector3 end2 = ((num8 > 1.0001f) ? ((Vector3)(ref end)).normalized : end);
			if (ModConfig.BlueprintSafe.Value)
			{
				int num10 = snaps.Length - 10;
				if (num10 >= 2)
				{
					int outCount = num6;
					int forcedOut = 0;
					EnforceMaxSegment(snaps, ref outCount, num10, maxSeg3, ref forcedOut);
					if (outCount != num6)
					{
						__result = outCount;
						NoteApplied(latDeg2, cells2, target2, num6, outCount, AverageSegment(snaps, outCount) * num8, cellMeters2, LongestSegment(snaps, outCount) * num8);
					}
				}
				return;
			}
			float num11 = AverageSegment(snaps, num6);
			if (num11 >= num9 * 0.9f && num11 <= num9 * 1.1f)
			{
				return;
			}
			int num12 = snaps.Length - 10;
			if (num12 < 2)
			{
				return;
			}
			Vector3[] array = _tempBuffer;
			if (array == null || array.Length < snaps.Length)
			{
				array = (_tempBuffer = (Vector3[])(object)new Vector3[snaps.Length]);
			}
			int forcedOut2;
			int outCount2 = Resample(snaps, num6, array, num12, num9, minSeg3, maxSeg3, -1, out forcedOut2);
			if (outCount2 < 2)
			{
				return;
			}
			if (outCount2 > num6 * 2 + 8 || outCount2 >= num12 - 1)
			{
				if (RareLogDue())
				{
					LogRare($"[TropicBeltSpacing] 后置重采样异常已跳过:节点 {num6}->{outCount2} 目标={target2:0.000}m scale={num8:0.0}");
				}
				return;
			}
			for (int k = 0; k < outCount2; k++)
			{
				snaps[k] = array[k];
			}
			int forcedOut3 = 0;
			EnforceMaxSegment(snaps, ref outCount2, num12, maxSeg3, ref forcedOut3);
			ProtectEnds(snaps, ref outCount2, num12, begin2, end2, maxSeg3, ref forcedOut3);
			__result = outCount2;
			if (ModConfig.LogSpacing.Value)
			{
				NoteApplied(latDeg2, cells2, target2, num6, outCount2, AverageSegment(snaps, outCount2) * num8, cellMeters2, LongestSegment(snaps, outCount2) * num8);
			}
		}
	}
}
internal static class Compat
{
	public static string Status = "路径生成:原版网格折弯(R 键可切换)";

	public static void Install(Harmony harmony)
	{
		//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dc: Expected O, but got Unknown
		//IL_0070: Unknown result type (might be due to invalid IL or missing references)
		//IL_007e: Expected O, but got Unknown
		if (!ModConfig.UseVanillaGridPath.Value)
		{
			Status = "路径生成:未接管其它模组(UseVanillaGridPath = false)";
			return;
		}
		Type type = null;
		try
		{
			type = AccessTools.TypeByName("LongerBelts");
		}
		catch
		{
			type = null;
		}
		if (type == null)
		{
			Status = "路径生成:原版网格折弯(R 键可切换)";
			return;
		}
		int num = 0;
		MethodInfo methodInfo = AccessTools.Method(type, "LongerSnapLineNonAlloc", (Type[])null, (Type[])null);
		if (methodInfo != null)
		{
			try
			{
				harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(AccessTools.Method(typeof(Compat), "LongerBelts_Snap_Prefix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				num++;
			}
			catch (Exception ex)
			{
				Plugin.LogError("接管 LongerBelts.LongerSnapLineNonAlloc 失败: " + ex.Message);
			}
		}
		MethodInfo methodInfo2 = AccessTools.Method(type, "LongerGeodesic", (Type[])null, (Type[])null);
		if (methodInfo2 != null)
		{
			try
			{
				harmony.Patch((MethodBase)methodInfo2, new HarmonyMethod(AccessTools.Method(typeof(Compat), "LongerBelts_Geodesic_Prefix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				num++;
			}
			catch (Exception ex2)
			{
				Plugin.LogError("接管 LongerBelts.LongerGeodesic 失败: " + ex2.Message);
			}
		}
		if (num > 0)
		{
			Status = "路径生成:已接管 LongerBelts(" + num + " 个函数),改为原版网格折弯 + R 键切换";
			Plugin.LogInfo("[TropicBeltSpacing] " + Status);
		}
		else
		{
			Status = "路径生成:检测到 LongerBelts,但没找到可接管的函数(版本不同?)";
			Plugin.LogInfo("[TropicBeltSpacing] " + Status);
		}
	}

	public static bool LongerBelts_Snap_Prefix(PlanetGrid planetGrid, Vector3 begin, Vector3 end, int path, Vector3[] snaps, ref int swerveIndex, ref int __result)
	{
		//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)
		if (planetGrid == null || snaps == null)
		{
			return true;
		}
		try
		{
			__result = planetGrid.SnapLineNonAlloc(begin, end, path, snaps, ref swerveIndex);
			return false;
		}
		catch (Exception ex)
		{
			Plugin.LogError("LongerBelts_Snap_Prefix: " + ex.Message);
			return true;
		}
	}

	public static bool LongerBelts_Geodesic_Prefix(Vector3 begin, Vector3 end, ref int counts, Vector3[] snaps)
	{
		//IL_002b: 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)
		try
		{
			PlanetGrid val = null;
			PlanetData localPlanet = GameMain.localPlanet;
			if (localPlanet != null && localPlanet.aux != null)
			{
				val = localPlanet.aux.activeGrid;
			}
			if (val == null || snaps == null)
			{
				return true;
			}
			int num = default(int);
			counts = val.SnapLineNonAlloc(begin, end, 0, snaps, ref num);
			return false;
		}
		catch (Exception ex)
		{
			Plugin.LogError("LongerBelts_Geodesic_Prefix: " + ex.Message);
			return true;
		}
	}
}
internal static class Flatten
{
	public static void Apply(BuildTool_Path tool)
	{
		//IL_0071: Unknown result type (might be due to invalid IL or missing references)
		//IL_0076: Unknown result type (might be due to invalid IL or missing references)
		//IL_0080: 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_00aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
		if (!ModConfig.EnableFlatten.Value || tool == null || !ModConfig.ClearTilt.Value)
		{
			return;
		}
		List<BuildPreview> buildPreviews = ((BuildTool)tool).buildPreviews;
		if (buildPreviews == null)
		{
			return;
		}
		int count = buildPreviews.Count;
		if (count < 2)
		{
			return;
		}
		for (int i = 0; i < count; i++)
		{
			BuildPreview val = buildPreviews[i];
			if (val == null || val.desc == null || !val.desc.isBelt)
			{
				return;
			}
		}
		Vector3 lpos = buildPreviews[0].lpos;
		Vector3 lpos2 = buildPreviews[count - 1].lpos;
		float num = Mathf.Abs(((Vector3)(ref lpos2)).magnitude - ((Vector3)(ref lpos)).magnitude) / 1.3333333f;
		if (tool.forceVertical || (Vector3.Angle(lpos, lpos2) <= ModConfig.VerticalAngleTolerance.Value && num >= ModConfig.VerticalMinHeightCells.Value))
		{
			for (int j = 0; j < count; j++)
			{
				buildPreviews[j].tilt = 0f;
			}
		}
	}
}
internal static class Hotkeys
{
	private static KeyCode _main = (KeyCode)0;

	private static KeyCode[] _mods;

	private static float _parsedAt = -99f;

	public static bool TogglePressed()
	{
		//IL_0005: 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_0053: Unknown result type (might be due to invalid IL or missing references)
		EnsureParsed();
		if ((int)_main == 0)
		{
			return false;
		}
		if (Input.GetKeyDown(_main))
		{
			bool flag = true;
			if (_mods != null)
			{
				for (int i = 0; i < _mods.Length; i++)
				{
					if (!Input.GetKey(_mods[i]))
					{
						flag = false;
						break;
					}
				}
			}
			if (flag)
			{
				return true;
			}
		}
		if (_mods != null && Input.GetKey(_main))
		{
			for (int j = 0; j < _mods.Length; j++)
			{
				if (Input.GetKeyDown(_mods[j]))
				{
					return true;
				}
			}
		}
		return false;
	}

	private static void EnsureParsed()
	{
		//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)
		//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)
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0040: Unknown result type (might be due to invalid IL or missing references)
		KeyboardShortcut value = ModConfig.ToggleHotKey.Value;
		float realtimeSinceStartup = Time.realtimeSinceStartup;
		if (((KeyboardShortcut)(ref value)).MainKey != _main || !(realtimeSinceStartup - _parsedAt <= 1f))
		{
			_parsedAt = realtimeSinceStartup;
			_main = ((KeyboardShortcut)(ref value)).MainKey;
			_mods = ReadModifiers(value);
		}
	}

	private static KeyCode[] ReadModifiers(KeyboardShortcut k)
	{
		//IL_0021: 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_0069: Unknown result type (might be due to invalid IL or missing references)
		//IL_0075: Unknown result type (might be due to invalid IL or missing references)
		//IL_0078: Expected I4, but got Unknown
		try
		{
			IEnumerable<KeyCode> modifiers = ((KeyboardShortcut)(ref k)).Modifiers;
			if (modifiers == null)
			{
				return null;
			}
			int num = 0;
			foreach (KeyCode item in modifiers)
			{
				_ = item;
				num++;
				if (num >= 4)
				{
					break;
				}
			}
			if (num <= 0)
			{
				return null;
			}
			KeyCode[] array = (KeyCode[])(object)new KeyCode[num];
			int num2 = 0;
			foreach (KeyCode item2 in modifiers)
			{
				if (num2 < num)
				{
					array[num2++] = (KeyCode)(int)item2;
					continue;
				}
				break;
			}
			return array;
		}
		catch
		{
			return null;
		}
	}
}
internal static class ModConfig
{
	public const string ConfigVersion = "1.5.8";

	public static ConfigFile File;

	public static ConfigEntry<string> VersionMarker;

	public static ConfigEntry<KeyboardShortcut> ToggleHotKey;

	public static ConfigEntry<bool> EnableSpacing;

	public static ConfigEntry<float> EquatorBandCells;

	public static ConfigEntry<float> PolarBandCells;

	public static ConfigEntry<string> SpacingPerBand;

	public static ConfigEntry<string> BandLatitudes;

	public static ConfigEntry<float> MaxSegmentMeters;

	public static ConfigEntry<float> MinSegmentMeters;

	public static ConfigEntry<bool> LogSpacing;

	public static ConfigEntry<bool> UseVanillaGridPath;

	public static ConfigEntry<bool> BlueprintSafe;

	public static ConfigEntry<bool> SkipVertical;

	public static ConfigEntry<bool> SkipClimb;

	public static ConfigEntry<float> ClimbSkipLevels;

	public static ConfigEntry<bool> VerticalThin;

	public static ConfigEntry<float> VerticalThinMinCells;

	public static ConfigEntry<float> VerticalThinMaxCells;

	public static ConfigEntry<bool> EnableFlatten;

	public static ConfigEntry<bool> ClearTilt;

	public static ConfigEntry<bool> StraightenVertical;

	public static ConfigEntry<bool> EvenAltitude;

	public static ConfigEntry<float> VerticalAngleTolerance;

	public static ConfigEntry<float> VerticalMinHeightCells;

	internal static void Init(ConfigFile cfg)
	{
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		File = cfg;
		ToggleHotKey = cfg.Bind<KeyboardShortcut>("General 通用", "ToggleHotKey", new KeyboardShortcut((KeyCode)290, Array.Empty<KeyCode>()), "开关本模组功能的快捷键(游戏内唯一的按键操作)。默认 F9。\nBepInEx 写法是「最后按下的键写在前面,修饰键写在后面」,例如:\n  F9                 = 直接按 F9(默认)\n  Alpha4 + LeftAlt   = 按住 Alt 再按 4\n两种顺序本模组都能识别。Hotkey to toggle this mod on/off (default F9).");
		VersionMarker = cfg.Bind<string>("General 通用", "ConfigVersion", "1.5.8", "配置版本号,程序自动迁移用,不需要手动改。\nConfig version marker (used for automatic migration).");
		EnableSpacing = cfg.Bind<bool>("Spacing 间距", "Enable", true, "按回归线分带自动调整传送带节点间距(关掉即完全恢复原版行为)。\nEnable tropic-band based belt node spacing.");
		EquatorBandCells = cfg.Bind<float>("Spacing 间距", "EquatorBandCells", 1.8f, "赤道侧第一带(0°~28.8°)的节点间距,单位:格(当地格)。越往极点越小。\nNode spacing of the equator-side band, in LOCAL grid cells (this is the largest).");
		PolarBandCells = cfg.Bind<float>("Spacing 间距", "PolarBandCells", 1.6f, "最靠极点的带(88.2°~90°)的节点间距,单位:格(当地格)。中间各带在此区间线性插值。\nNode spacing of the pole-side band, in LOCAL grid cells (this is the smallest).");
		SpacingPerBand = cfg.Bind<string>("Spacing 间距", "SpacingPerBand", "", "可选的逐带间距表(逗号分隔,单位:格),例如 1.8,1.78,1.76,...;留空则用上面两个值线性插值。\nOptional explicit per-band spacing list (equator band first); empty = lerp between the two above.");
		BandLatitudes = cfg.Bind<string>("Spacing 间距", "BandLatitudes", "0,28.8,46.8,55.8,64.8,70.2,75.6,79.2,82.8,84.6,86.4,88.2,90", "回归线纬度表(度,逗号分隔,南半球镜像使用)。这是游戏网格疏密变化的真实界线。\nTropic latitudes in degrees (the real DSP grid-density boundaries).");
		MaxSegmentMeters = cfg.Bind<float>("Spacing 间距", "MaxSegmentMeters", 2.302172f, "单节传送带长度上限(米)。原版判定 = sqrt(5.3) = 2.302172 m,超过就是 TooFar,蓝图无法在原版重建,\n因此本模组永远把实际间距钳制在这个值以内(不要改大)。当地格较大时高纬度可能因此达不到目标格数。\nVanilla legal maximum of one belt segment = sqrt(5.3) m.");
		MinSegmentMeters = cfg.Bind<float>("Spacing 间距", "MinSegmentMeters", 0.4f, "单节传送带长度下限(米)。原版连接判定为 0.4 m(TooClose)。\nVanilla minimum belt connection distance.");
		LogSpacing = cfg.Bind<bool>("Spacing 间距", "LogSpacing", false, "(默认关闭)在 BepInEx 日志里输出每次计算的带号/目标间距/实测均长(每秒最多一条);\n需要验证模组是否生效时再打开。\nLog computed band/spacing (max 1 line per second) to verify the mod works.");
		UseVanillaGridPath = cfg.Bind<bool>("Spacing 间距", "UseVanillaGridPath", true, "斜拉传送带时强制使用原版网格折线(先经后纬/先纬后经,R 键可切换),\n并接管其它模组(例如 LongerBelts 的经纬线模式)的节点生成,避免它改变折弯与 R 键行为。\nForce the vanilla grid polyline (so the bend and the R-key path variants stay vanilla), and take\nover node generation from other mods such as LongerBelts' gridline mode.");
		BlueprintSafe = cfg.Bind<bool>("Spacing 间距", "BlueprintSafe", false, "【默认关闭 = 自由间距(省料优先,蓝图也合法)】按回归线分带做 1.6~1.8 个当地格,\n每节硬性 ≤ √5.3−3cm = 2.2722 m,蓝图里的 belt 位置以 float 的 localOffset 保存(不取整),\n所以只要不超 2.302 m,蓝图就能保存并在原版重建。\n\n开启 = 整数格模式(几乎不省料,只用于需要与原版逐格一致的特殊情况)。\n");
		SkipVertical = cfg.Bind<bool>("Spacing 间距", "SkipVertical", false, "(默认关闭)竖直方向也交给本模组重排成严格 90° 的 L 形折线:竖的那一段是真的竖直;\n若改成 true,竖直方向完全交给原版 —— 原版会把两端直接连成一条斜线(看着是歪的)。\nWhen true, near-vertical runs are left to vanilla (vanilla draws one slanted line).");
		SkipClimb = cfg.Bind<bool>("Spacing 间距", "SkipClimb", true, "有爬坡的路径整条交给原版。**只在 VerticalThin = false 时生效**\n(或垂直抽稀构造失败时的兜底)—— 默认垂直抽稀开启时,斜坡带由它接管;\n纯竖直(X/Y 相同只有 Z 不同)受 √5.3 限制保持原版每节 1 层。\n背景:带面的 pitch/tilt 是游戏按**每一节各自爬升的高度**算出来的,\n各节爬升量不一致时带面朝向就会不一致 —— 表现为“带面轮廓扭曲”。\nOnly used when VerticalThin = false.");
		ClimbSkipLevels = cfg.Bind<float>("Spacing 间距", "ClimbSkipLevels", 0.25f, "判定“有爬坡”的高度差阈值(单位:高度层,1 层 = 1.3333 m)。\nHeight difference (in altitude levels) above which the run is left to vanilla.");
		bool flag = true;
		float num = 1.5f;
		try
		{
			ConfigEntry<bool> val = default(ConfigEntry<bool>);
			if (cfg.TryGetEntry<bool>("Spacing 间距", "VerticalEvenSpacing", ref val))
			{
				flag = val.Value;
			}
			ConfigEntry<float> val2 = default(ConfigEntry<float>);
			if (cfg.TryGetEntry<float>("Spacing 间距", "VerticalMinCells", ref val2))
			{
				num = val2.Value;
			}
			ConfigEntry<float> val3 = default(ConfigEntry<float>);
			if (cfg.TryGetEntry<float>("Spacing 间距", "VerticalMaxCells", ref val3))
			{
				_ = val3.Value;
			}
		}
		catch
		{
		}
		VerticalThin = cfg.Bind<bool>("Spacing 间距", "VerticalThin", flag, "垂直抽稀传送带(默认开启):**斜坡带和垂直带都生效**。\n<斜坡带>:沿原版路径按弧长均分抽稀(每节 1.5~1.8 格,等长等爬升、带面不扭曲)。\n<纯竖直>(X/Y 相同只有 Z 不同):利用游戏「≤1.5 格高度差直接连接」的机制 ——\n在后置补丁把高度差均分成 ≤ VerticalThinMaxCells(默认 1.45)格的节,\nX/Y 完全不变、只有 Z 变化,每一段都被游戏直接连接 → Z 轴抽稀生效。\nAuto-thinning for climbing belts, BOTH slope and vertical (on by default).");
		VerticalThinMinCells = cfg.Bind<float>("Spacing 间距", "VerticalThinMinCells", num, "垂直抽稀(斜坡带)的每节最小长度(单位:当地格)。\nMin per-segment length (local cells) for vertical thinning.");
		VerticalThinMaxCells = cfg.Bind<float>("Spacing 间距", "VerticalThinMaxCells", 1.45f, "垂直抽稀(Z 轴)的每节最大高度(单位:格)。游戏本体对 ≤1.5 格的 Z 轴高度差\n会「直接连接」,所以默认 1.45(略低于阈值)—— 每节都不超过它,整条竖直带\n全部按直接连接搭建,实现 X/Y 不变、只变 Z 的抽稀。不要改到 1.5 及以上。\nMax per-segment height (cells) for Z-axis thinning; keep below the game's 1.5 direct-connect threshold.");
		EnableFlatten = cfg.Bind<bool>("Flatten 自动拉平", "Enable", false, "自动拉平(默认关闭)。原版竖直带本来就是平直的,本模组去改它的 tilt/朝向\n反而会把竖直带弄成歪歪扭扭的,所以默认关闭;需要时可自行开启。\nAuto flatten (OFF by default: vanilla vertical belts are already straight).");
		ClearTilt = cfg.Bind<bool>("Flatten 自动拉平", "ClearTilt", true, "清除传送带倾角(tilt),带面始终水平,不会翻转扭曲。\nClear belt tilt so the belt surface stays flat.");
		StraightenVertical = cfg.Bind<bool>("Flatten 自动拉平", "StraightenVertical", true, "竖直连接时把整条带子拉成一条竖直直线(同一经纬度),并统一朝向。\nStraighten vertical runs onto one column and unify rotation.");
		EvenAltitude = cfg.Bind<bool>("Flatten 自动拉平", "EvenAltitude", false, "竖直连接时把高度按 1.3333(每层) 均分,爬升更均匀(可能改变端点高度层,默认关闭)。\nDistribute altitudes evenly across levels when straightening.");
		VerticalAngleTolerance = cfg.Bind<float>("Flatten 自动拉平", "VerticalAngleTolerance", 15f, "判定「竖直方向拉带」的两端水平偏角容差(度)。默认 15°,即两端水平偏一点也算竖直,\n会被拉成一条笔直的竖带(高度层不变、两端位置不变,所以连接不会被破坏)。\nAngle tolerance (degrees) to treat the run as vertical and straighten it.");
		VerticalMinHeightCells = cfg.Bind<float>("Flatten 自动拉平", "VerticalMinHeightCells", 0.5f, "判定竖直连接所需的最小高度差(单位:高度层,1 层 = 1.3333 m)。\nMinimum height difference in altitude levels.");
		Migrate(cfg);
	}

	private static void Migrate(ConfigFile cfg)
	{
		if (!(VersionMarker.Value == "1.5.8"))
		{
			if (Mathf.Abs(EquatorBandCells.Value - 1.6f) < 0.001f && Mathf.Abs(PolarBandCells.Value - 1.8f) < 0.001f)
			{
				EquatorBandCells.Value = 1.8f;
				PolarBandCells.Value = 1.6f;
				Plugin.LogInfo("[TropicBeltSpacing] 已把间距方向校正为:赤道带 1.8 格 → 极区带 1.6 格(原配置 1.6/1.8 是反的)。");
			}
			VersionMarker.Value = "1.5.8";
			cfg.Save();
		}
	}

	internal static void Save()
	{
		if (File != null)
		{
			File.Save();
		}
	}

	internal static void ApplyChanges()
	{
		TropicBands.Reload(BandLatitudes.Value, SpacingPerBand.Value, EquatorBandCells.Value, PolarBandCells.Value);
		Save();
	}
}
internal static class PatchGridSnap
{
	[HarmonyPrefix]
	[HarmonyPatch(typeof(PlanetGrid), "SnapLineNonAlloc")]
	private static bool Prefix(PlanetGrid __instance, Vector3 begin, Vector3 end, int path, Vector3[] snaps, ref int swerveIndex, ref int __result)
	{
		//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)
		return BeltSpacingCore.Prefix(__instance, begin, end, path, snaps, ref swerveIndex, ref __result);
	}
}
internal static class PatchAuxThin
{
	[HarmonyPostfix]
	[HarmonyPatch(typeof(PlanetAuxData), "SnapLineNonAlloc")]
	private static void Postfix(PlanetAuxData __instance, Vector3 begin, Vector3 end, int path, bool geodesic, bool begin_flat, Vector3[] snaps, bool forceVertical, ref float maxGridSlope, bool useOldPath, ref int __result)
	{
		//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)
		BeltSpacingCore.Postfix(__instance, begin, end, path, geodesic, begin_flat, snaps, forceVertical, ref maxGridSlope, useOldPath, ref __result);
	}
}
internal static class PatchFlatten
{
	[HarmonyPostfix]
	[HarmonyPatch(typeof(BuildTool_Path), "DeterminePreviews")]
	private static void Postfix(BuildTool_Path __instance)
	{
		Flatten.Apply(__instance);
	}
}
[BepInPlugin("TropicBeltSpacing", "Tropic Belt Spacing", "1.5.8")]
public class Plugin : BaseUnityPlugin
{
	public const string Guid = "TropicBeltSpacing";

	public const string Name = "Tropic Belt Spacing";

	public const string Version = "1.5.8";

	internal static Plugin Instance;

	internal static Harmony HarmonyInstance;

	private void Awake()
	{
		//IL_006d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0077: Expected O, but got Unknown
		//IL_00e0: 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)
		Instance = this;
		try
		{
			ModConfig.Init(((BaseUnityPlugin)this).Config);
			TropicBands.Reload(ModConfig.BandLatitudes.Value, ModConfig.SpacingPerBand.Value, ModConfig.EquatorBandCells.Value, ModConfig.PolarBandCells.Value);
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("配置初始化失败 / config init failed: " + ex));
			return;
		}
		HarmonyInstance = new Harmony("TropicBeltSpacing");
		PatchSafe(typeof(PatchGridSnap), "PlanetGrid.SnapLineNonAlloc (间距核心)");
		PatchSafe(typeof(PatchAuxThin), "PlanetAuxData.SnapLineNonAlloc (兜底重采样)");
		PatchSafe(typeof(PatchFlatten), "BuildTool_Path.DeterminePreviews (自动拉平)");
		Compat.Install(HarmonyInstance);
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Tropic Belt Spacing 1.5.8 已加载 / loaded.");
		((BaseUnityPlugin)this).Logger.LogInfo((object)("  开关快捷键 / toggle hotkey = " + ((object)ModConfig.ToggleHotKey.Value/*cast due to .constrained prefix*/).ToString() + "   (默认 F9;本模组没有游戏内 UI,全部设置都在 BepInEx\\config\\TropicBeltSpacing.cfg)"));
		((BaseUnityPlugin)this).Logger.LogInfo((object)("  当前状态 / spacing = " + (ModConfig.EnableSpacing.Value ? "开启(省料间距)" : "关闭(原版间距)")));
	}

	private void PatchSafe(Type patchType, string label)
	{
		try
		{
			HarmonyInstance.PatchAll(patchType);
			((BaseUnityPlugin)this).Logger.LogInfo((object)("  补丁成功 / patch OK: " + label));
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("  补丁失败 / patch FAILED: " + label + " -> " + ex.Message));
		}
	}

	private void Update()
	{
		try
		{
			if (Hotkeys.TogglePressed())
			{
				bool flag = !ModConfig.EnableSpacing.Value;
				ModConfig.EnableSpacing.Value = flag;
				ModConfig.Save();
				string text = (flag ? "回归线传送带间距:已开启(省料间距)" : "回归线传送带间距:已关闭(原版间距)");
				try
				{
					UIRealtimeTip.Popup(text, true, 0);
				}
				catch
				{
				}
				((BaseUnityPlugin)this).Logger.LogInfo((object)("[TropicBeltSpacing] " + text));
			}
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)ex);
		}
	}

	private void OnDestroy()
	{
		try
		{
			if (HarmonyInstance != null)
			{
				HarmonyInstance.UnpatchSelf();
			}
			ModConfig.Save();
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)ex);
		}
	}

	internal static void LogInfo(string message)
	{
		if ((Object)(object)Instance != (Object)null)
		{
			((BaseUnityPlugin)Instance).Logger.LogInfo((object)message);
		}
	}

	internal static void LogError(string message)
	{
		if ((Object)(object)Instance != (Object)null)
		{
			((BaseUnityPlugin)Instance).Logger.LogError((object)message);
		}
	}
}
internal static class TropicBands
{
	public static readonly float[] DefaultLatitudes = new float[13]
	{
		0f, 28.8f, 46.8f, 55.8f, 64.8f, 70.2f, 75.6f, 79.2f, 82.8f, 84.6f,
		86.4f, 88.2f, 90f
	};

	private static float[] _latitudes = (float[])DefaultLatitudes.Clone();

	private static float[] _perBand;

	private static float _equatorCells = 1.8f;

	private static float _polarCells = 1.6f;

	private static string _warning = string.Empty;

	public const float EquatorCellMeters = (float)Math.PI * 2f / 5f;

	public static float[] Latitudes => _latitudes;

	public static int BandCount => Mathf.Max(1, _latitudes.Length - 1);

	public static string Warning => _warning;

	public static void Reload(string latitudeCsv, string perBandCsv, float equatorCells, float polarCells)
	{
		_equatorCells = equatorCells;
		_polarCells = polarCells;
		_warning = string.Empty;
		List<float> list = ParseFloats(latitudeCsv);
		list.RemoveAll((float v) => v < 0f || v > 90f);
		list.Sort();
		if (list.Count < 2)
		{
			_warning = "回归线纬度表无效,已改用默认表。";
			list = new List<float>(DefaultLatitudes);
		}
		if (list[0] > 0.001f)
		{
			list.Insert(0, 0f);
		}
		if (list[list.Count - 1] < 89.999f)
		{
			list.Add(90f);
		}
		_latitudes = list.ToArray();
		List<float> list2 = ParseFloats(perBandCsv);
		if (list2.Count == BandCount)
		{
			_perBand = list2.ToArray();
			return;
		}
		if (list2.Count > 0)
		{
			_warning = "SpacingPerBand 数量(" + list2.Count + ")与带数(" + BandCount + ")不一致,已改用线性插值。";
		}
		_perBand = null;
	}

	private static List<float> ParseFloats(string csv)
	{
		List<float> list = new List<float>();
		if (string.IsNullOrEmpty(csv))
		{
			return list;
		}
		string[] array = csv.Split(new char[4] { ',', ';', ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries);
		for (int i = 0; i < array.Length; i++)
		{
			if (float.TryParse(array[i], NumberStyles.Float, CultureInfo.InvariantCulture, out var result))
			{
				list.Add(result);
			}
		}
		return list;
	}

	public static int BandIndex(float absLatitudeDeg)
	{
		float num = Mathf.Abs(absLatitudeDeg);
		for (int i = 0; i < BandCount; i++)
		{
			if (num < _latitudes[i + 1])
			{
				return i;
			}
		}
		return BandCount - 1;
	}

	public static float CellsForLatitude(float absLatitudeDeg)
	{
		int num = BandIndex(absLatitudeDeg);
		if (_perBand != null && num < _perBand.Length)
		{
			return _perBand[num];
		}
		if (BandCount <= 1)
		{
			return _equatorCells;
		}
		float num2 = (float)num / (float)(BandCount - 1);
		return Mathf.Lerp(_equatorCells, _polarCells, num2);
	}

	public static float CellsForPosition(Vector3 planetLocalPos)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		return CellsForLatitude(Mathf.Asin(Mathf.Clamp(((Vector3)(ref planetLocalPos)).normalized.y, -1f, 1f)) * 57.29578f);
	}

	public static float LatitudeOf(Vector3 planetLocalPos)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		return Mathf.Asin(Mathf.Clamp(((Vector3)(ref planetLocalPos)).normalized.y, -1f, 1f)) * 57.29578f;
	}

	public static string BandLabel(int index)
	{
		if (index < 0 || index + 1 >= _latitudes.Length)
		{
			return "?";
		}
		return _latitudes[index].ToString("0.#") + "° ~ " + _latitudes[index + 1].ToString("0.#") + "°";
	}

	public static string TableText()
	{
		StringBuilder stringBuilder = new StringBuilder();
		for (int i = 0; i < BandCount; i++)
		{
			stringBuilder.Append(BandLabel(i));
			stringBuilder.Append("  →  ");
			stringBuilder.Append(CellsForLatitude((_latitudes[i] + _latitudes[i + 1]) * 0.5f).ToString("0.000"));
			stringBuilder.Append(" 格");
			if (i < BandCount - 1)
			{
				stringBuilder.Append('\n');
			}
		}
		return stringBuilder.ToString();
	}
}