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();
}
}