Decompiled source of DSPMiaoToolbox v2.23.27
BepInEx\plugins\DSPMiaoToolbox\DSPMiaoToolbox.dll
Decompiled a day ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Text; using BPTropicFree; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using DSPBPColliderSnap; using DSPBlueprintOffset; using DSPMiaoToolbox; using HarmonyLib; using HoverCoord; using TropicBeltSpacing; using UnityEngine; using UnityEngine.Events; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyFileVersion("2.23.27.0")] [assembly: AssemblyInformationalVersion("2.23.27")] [assembly: AssemblyVersion("2.23.27.0")] namespace BPTropicFree { internal static class TropicFreeFeature { private static KeyCode _mainKey = (KeyCode)117; private static KeyCode[] _mods = (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }; private static bool _tickLogged; internal static bool Enabled { get { if (ModConfig.Enable != null) { return ModConfig.Enable.Value; } return false; } } internal static bool IgnoreLimits { get { if (ModConfig.IgnoreTropicLimits != null) { return ModConfig.IgnoreTropicLimits.Value; } return false; } } internal static bool UniformGrid { get { if (ModConfig.UniformRigidGrid != null) { return ModConfig.UniformRigidGrid.Value; } return false; } } internal static void Init() { ModConfig.Init(); if (ModConfig.ToggleHotKey != null) { ModConfig.ToggleHotKey.SettingChanged += OnHotkeySettingChanged; } ReparseHotkey(); } private static void OnHotkeySettingChanged(object sender, EventArgs e) { ReparseHotkey(); } private static void ReparseHotkey() { //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) try { KeyboardShortcut val = (KeyboardShortcut)((ModConfig.ToggleHotKey != null) ? ModConfig.ToggleHotKey.Value : new KeyboardShortcut((KeyCode)117, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 })); if ((int)((KeyboardShortcut)(ref val)).MainKey != 0) { _mainKey = ((KeyboardShortcut)(ref val)).MainKey; } List<KeyCode> list = new List<KeyCode>(4); if (((KeyboardShortcut)(ref val)).Modifiers != null) { foreach (KeyCode modifier in ((KeyboardShortcut)(ref val)).Modifiers) { if ((int)modifier != 0) { if (!list.Contains(modifier)) { list.Add(modifier); } if (list.Count >= 4) { break; } } } } _mods = list.ToArray(); } catch { _mainKey = (KeyCode)117; _mods = (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }; } } internal static string GetToggleHotkeyText() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) try { return (ModConfig.ToggleHotKey != null) ? ((object)ModConfig.ToggleHotKey.Value/*cast due to .constrained prefix*/).ToString() : "U + LeftAlt"; } catch { return "U + LeftAlt"; } } internal static string TrySetToggleHotkey(KeyCode main, KeyCode[] modifiers) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) try { if (ModConfig.ToggleHotKey == null) { return null; } ModConfig.ToggleHotKey.Value = new KeyboardShortcut(main, (KeyCode[])(((object)modifiers) ?? ((object)new KeyCode[0]))); ModConfig.Save(); return ((object)ModConfig.ToggleHotKey.Value/*cast due to .constrained prefix*/).ToString(); } catch { return null; } } internal static void SetEnable(bool value) { try { if (ModConfig.Enable != null && ModConfig.Enable.Value != value) { ModConfig.Enable.Value = value; ModConfig.Save(); PopupState(); LogInfo("[BPTropicFree] UI 切换总开关 → " + (value ? "开" : "关")); } } catch { } } internal static void SetIgnoreLimits(bool value) { try { if (ModConfig.IgnoreTropicLimits != null && ModConfig.IgnoreTropicLimits.Value != value) { ModConfig.IgnoreTropicLimits.Value = value; ModConfig.Save(); try { UIRealtimeTip.Popup(L10n.T("无视回归线限制:" + (value ? "已开启" : "已关闭"), "Ignore tropic limits: " + (value ? "ON" : "OFF")), true, 0); } catch { } LogInfo("[BPTropicFree] UI 切换无视回归线限制 → " + (value ? "开" : "关")); } } catch { } } internal static void SetUniformGrid(bool value) { try { if (ModConfig.UniformRigidGrid != null && ModConfig.UniformRigidGrid.Value != value) { ModConfig.UniformRigidGrid.Value = value; ModConfig.Save(); try { UIRealtimeTip.Popup(L10n.T("锁死蓝图大小:" + (value ? "已开启(统一刚性摆放)" : "已关闭"), "Lock blueprint size: " + (value ? "ON (rigid placement)" : "OFF")), true, 0); } catch { } LogInfo("[BPTropicFree] UI 切换锁死蓝图大小 → " + (value ? "开" : "关")); } } catch { } } private static void PopupState() { string text = (Enabled ? L10n.T("蓝图回归线自由摆放:已开启(跨线自由移动 / 锁死蓝图大小)", "Free placement across tropics: ON (free movement / locked blueprint size)") : L10n.T("蓝图回归线自由摆放:已关闭(原版行为)", "Free placement across tropics: OFF (vanilla behaviour)")); try { UIRealtimeTip.Popup(text, true, 0); } catch { } } internal static void TickKey() { //IL_0099: Unknown result type (might be due to invalid IL or missing references) if (!_tickLogged) { _tickLogged = true; try { LogInfo("[BPTropicFree] 快捷键监听已启动:" + GetToggleHotkeyText() + "【" + (Enabled ? "开启" : "关闭") + "】;无视回归线=" + (IgnoreLimits ? "开" : "关") + ";锁死蓝图大小=" + (UniformGrid ? "开" : "关")); } catch { } } try { if (ModConfig.Enable != null && BuildFeatures.KeyDownWithMods(_mainKey, _mods)) { bool flag = !ModConfig.Enable.Value; ModConfig.Enable.Value = flag; ModConfig.Save(); PopupState(); LogInfo("[BPTropicFree] " + (flag ? "蓝图回归线自由摆放:已开启(跨线自由移动 / 锁死蓝图大小)" : "蓝图回归线自由摆放:已关闭(原版行为)")); } } catch { } } internal static void LogInfo(string message) { try { BlueprintOffsetPlugin.LogToolbox(message); } catch { } } internal static void LogError(string message) { try { Plugin.LogError(message); } catch { } } } internal static class ModConfig { internal const string CfgFileName = "BPTropicFree.cfg"; internal static ConfigFile File; internal static ConfigEntry<bool> Enable; internal static ConfigEntry<int> CfgVersion; internal static ConfigEntry<KeyboardShortcut> ToggleHotKey; internal static ConfigEntry<bool> IgnoreTropicLimits; internal static ConfigEntry<bool> UniformRigidGrid; internal static ConfigEntry<bool> LogApplied; internal static void Init() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown //IL_0094: Unknown result type (might be due to invalid IL or missing references) string text; try { text = Path.Combine(Paths.ConfigPath, "BPTropicFree.cfg"); } catch { text = "BPTropicFree.cfg"; } File = new ConfigFile(text, true); try { File.SaveOnConfigSet = false; } catch { } Enable = File.Bind<bool>("General 通用", "Enable", false, "总开关(游戏内按 Alt+U 切换的就是这个值)。false = 完全恢复原版摆放行为。2.5.2 起默认改为关闭,需要时游戏内按 Alt+U 或在「快捷键修改」页开启。"); CfgVersion = File.Bind<int>("General 通用", "CfgVersion", 0, "内部迁移标记,不需要手动改。"); ToggleHotKey = File.Bind<KeyboardShortcut>("General 通用", "ToggleHotKey", new KeyboardShortcut((KeyCode)117, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), "开关本模组功能的快捷键(主键 + 修饰键)。默认 按住 Alt 再按 U。键名为 UnityEngine.KeyCode 枚举名。也可在游戏内「妙妙蓝图工具箱 → 快捷键修改」页直接修改。"); IgnoreTropicLimits = File.Bind<bool>("Feature 功能", "IgnoreTropicLimits", true, "无视星球回归线:清除「区域跨越回归线(45)/空间不足(46)/未对齐回归线锚点(47)/回归线格数比错误(48)」与大网格(地基平台)区域越界条件,并跳过 SnapTropic 回归线吸附(跨线自由移动),蓝图任意纬度可直接摆放。"); UniformRigidGrid = File.Bind<bool>("Feature 功能", "UniformRigidGrid", true, "统一刚性摆放(锁死蓝图大小):所有建筑 = 光标锚点 + 蓝图格数 × 格距。基准格 2π/(segment×5)(设计格 1.2566m),东西向格距按锚点纬度做 1/cos 补偿(球面经线收敛)→ 蓝图物理尺寸在任意纬度恒定锁死,不变形、不碰撞;cos 连续 → 跨回归线依旧零跳变。分拣器槽位与极区(大网格平台)修正结果原样保留。"); LogApplied = File.Bind<bool>("Debug 调试", "LogApplied", false, "验证用日志:每次发生刚性重摆时输出建筑数量统计(每秒最多一条)。"); if (CfgVersion.Value < 1) { Enable.Value = false; CfgVersion.Value = 1; } try { File.Save(); } catch { } } internal static void Save() { try { if (File != null) { File.Save(); } } catch { } } } internal static class TropicFreePatch { private const float HalfPi = (float)Math.PI / 2f; private const float HeightStep = 1.3333334f; private const float HeightBase = 0.2f; private const float YawQuot = 89.9f; private static bool _errorOnce; private static float _lastLogAt = -99f; private static int _pendingLogCount; private static float[] _areaLngBuf; private static float[] _areaLatBuf; private static bool[] _areaDoneBuf; [HarmonyPrefix] [HarmonyPatch(typeof(BlueprintUtils), "SnapTropic")] public static bool SnapTropic_Prefix() { if (ModConfig.Enable.Value && ModConfig.IgnoreTropicLimits.Value) { return false; } return true; } [HarmonyPostfix] [HarmonyPatch(typeof(BlueprintUtils), "RefreshBuildPreview")] public static void RefreshBuildPreview_Postfix(PlanetData _planet, BlueprintData _blueprintData, BuildPreview[] _bpArray, Vector3[] _dots, int _dotsCursor, IntVector4[] _tropicGratBoxConditionInfo, float _yaw, int _segmentCnt) { try { Core(_planet, _blueprintData, _bpArray, _dots, _dotsCursor, _tropicGratBoxConditionInfo, _yaw, _segmentCnt); } catch (Exception ex) { if (!_errorOnce) { _errorOnce = true; TropicFreeFeature.LogError("[BPTropicFree] RefreshBuildPreview 后置补丁异常(本会话内不再重复报告):" + ex); } } } private static void Core(PlanetData planet, BlueprintData bpData, BuildPreview[] bpArray, Vector3[] dots, int dotsCursor, IntVector4[] gratBoxConditions, float yaw, int segmentCnt) { //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_041a: Unknown result type (might be due to invalid IL or missing references) //IL_018a: Unknown result type (might be due to invalid IL or missing references) //IL_0191: Expected I4, but got Unknown //IL_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_0246: Unknown result type (might be due to invalid IL or missing references) //IL_024b: Unknown result type (might be due to invalid IL or missing references) //IL_025d: Unknown result type (might be due to invalid IL or missing references) //IL_0262: Unknown result type (might be due to invalid IL or missing references) //IL_02cb: Unknown result type (might be due to invalid IL or missing references) //IL_02e0: Unknown result type (might be due to invalid IL or missing references) //IL_0304: Unknown result type (might be due to invalid IL or missing references) //IL_0317: Unknown result type (might be due to invalid IL or missing references) //IL_033d: Unknown result type (might be due to invalid IL or missing references) //IL_0342: Unknown result type (might be due to invalid IL or missing references) //IL_0346: Unknown result type (might be due to invalid IL or missing references) //IL_034b: Unknown result type (might be due to invalid IL or missing references) //IL_034f: Unknown result type (might be due to invalid IL or missing references) //IL_0367: Unknown result type (might be due to invalid IL or missing references) //IL_036c: Unknown result type (might be due to invalid IL or missing references) //IL_0373: Unknown result type (might be due to invalid IL or missing references) //IL_038b: Unknown result type (might be due to invalid IL or missing references) //IL_0390: Unknown result type (might be due to invalid IL or missing references) //IL_0397: Unknown result type (might be due to invalid IL or missing references) //IL_03aa: Unknown result type (might be due to invalid IL or missing references) //IL_03af: Unknown result type (might be due to invalid IL or missing references) //IL_03b6: Unknown result type (might be due to invalid IL or missing references) //IL_03c9: Unknown result type (might be due to invalid IL or missing references) //IL_03ce: Unknown result type (might be due to invalid IL or missing references) //IL_026a: Unknown result type (might be due to invalid IL or missing references) //IL_0274: Unknown result type (might be due to invalid IL or missing references) //IL_0286: Unknown result type (might be due to invalid IL or missing references) //IL_028b: Unknown result type (might be due to invalid IL or missing references) //IL_0291: Unknown result type (might be due to invalid IL or missing references) //IL_029b: Unknown result type (might be due to invalid IL or missing references) //IL_02ad: Unknown result type (might be due to invalid IL or missing references) //IL_02b2: Unknown result type (might be due to invalid IL or missing references) //IL_02b8: Unknown result type (might be due to invalid IL or missing references) //IL_02ba: Unknown result type (might be due to invalid IL or missing references) if (ModConfig.Enable == null || !ModConfig.Enable.Value || planet == null || bpData == null || bpArray == null || dots == null || dotsCursor <= 0) { return; } BlueprintBuilding[] buildings = bpData.buildings; if (buildings == null || buildings.Length == 0) { return; } BlueprintArea[] areas = bpData.areas; int num = buildings.Length; int num2 = ((areas == null) ? 1 : areas.Length); int num3 = ((num2 > 1) ? 1 : dotsCursor); bool value = ModConfig.IgnoreTropicLimits.Value; bool value2 = ModConfig.UniformRigidGrid.Value; if (!value && !value2) { return; } int num4 = Mathf.FloorToInt(yaw / 89.9f); float num5 = ((num4 == 1 || num4 == 2) ? (-1f) : 1f); float num6 = ((num4 == 2 || num4 == 3) ? (-1f) : 1f); float latitudeRadPerGrid = BlueprintUtils.GetLatitudeRadPerGrid(segmentCnt); float realRadius = planet.realRadius; float[] oLng = null; float[] oLat = null; if (num2 > 1) { ResolveAreaOffsets(areas, bpData.primaryAreaIdx, out oLng, out oLat); } int num7 = 0; for (int i = 0; i < num3; i++) { Vector3 val = dots[i]; ((Vector3)(ref val)).Normalize(); float num8 = 0f; float num9 = 0f; BlueprintUtils.GetLongitudeLatitudeRad(val, ref num8, ref num9); num9 = Mathf.Clamp(num9, -(float)Math.PI / 2f, (float)Math.PI / 2f); float num10 = Mathf.Clamp(Mathf.Cos(Mathf.Abs(num9)), 0.2f, 1f); float num11 = latitudeRadPerGrid / num10; float num12 = latitudeRadPerGrid; for (int j = 0; j < num; j++) { int num13 = i * num + j; if (num13 >= bpArray.Length) { break; } BuildPreview val2 = bpArray[num13]; if (val2 == null || val2.desc == null) { continue; } if (value) { int num14 = (int)val2.condition; if (num14 >= 45 && num14 <= 48) { val2.condition = (EBuildCondition)0; } } if (value2) { BlueprintBuilding val3 = buildings[j]; int num15 = ((val3.areaIndex >= 0 && val3.areaIndex < num2) ? val3.areaIndex : 0); float num16 = ((oLng != null && num15 < oLng.Length) ? oLng[num15] : 0f); float num17 = ((oLat != null && num15 < oLat.Length) ? oLat[num15] : 0f); bool num18 = val2.desc.isInserter || (areas != null && num15 < areas.Length && areas[num15] != null && areas[num15].areaSegments == 4); Vector2 val4 = BlueprintUtils.TransitionWidthAndHeight(yaw, val3.localOffset_x, val3.localOffset_y); Vector2 val5 = BlueprintUtils.TransitionWidthAndHeight(yaw, val3.localOffset_x2, val3.localOffset_y2); if (num18) { Vector3 dirR = DirFor(num8, num9, val4.x + num16, val4.y + num17, num11, num12, num5, num6); Vector3 dirR2 = DirFor(num8, num9, val5.x + num16, val5.y + num17, num11, num12, num5, num6); num7 += RebasePreview(val2, dirR, dirR2); continue; } float num19 = num8 + (val4.x + num16) * num11 * num5; float num20 = Mathf.Clamp(num9 + (val4.y + num17) * num12 * num6, -(float)Math.PI / 2f, (float)Math.PI / 2f); float num21 = num8 + (val5.x + num16) * num11 * num5; float num22 = Mathf.Clamp(num9 + (val5.y + num17) * num12 * num6, -(float)Math.PI / 2f, (float)Math.PI / 2f); Vector3 dir = BlueprintUtils.GetDir(num19, num20); Vector3 dir2 = BlueprintUtils.GetDir(num21, num22); val2.lpos = dir * (realRadius + val3.localOffset_z * 1.3333334f + 0.2f); val2.lpos2 = dir2 * (realRadius + val3.localOffset_z2 * 1.3333334f + 0.2f); val2.lrot = Maths.SphericalRotation(dir, val3.yaw - (float)num4 * 90f); val2.lrot2 = Maths.SphericalRotation(dir2, val3.yaw2 - (float)num4 * 90f); val2.tilt = val3.tilt; num7++; } } } if (value && gratBoxConditions != null) { for (int k = 0; k < gratBoxConditions.Length; k++) { gratBoxConditions[k] = default(IntVector4); } } if (ModConfig.LogApplied.Value && num7 > 0) { _pendingLogCount += num7; float realtimeSinceStartup = Time.realtimeSinceStartup; if (realtimeSinceStartup - _lastLogAt >= 1f) { _lastLogAt = realtimeSinceStartup; TropicFreeFeature.LogInfo("[BPTropicFree] 刚性重摆生效 / rigid re-place: " + _pendingLogCount + " previews (size-locked rigid placement)"); _pendingLogCount = 0; } } } private static Vector3 DirFor(float lng0, float lat0, float cellX, float cellY, float lngPitch, float latPitch, float sx, float sy) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) float num = lng0 + cellX * lngPitch * sx; float num2 = Mathf.Clamp(lat0 + cellY * latPitch * sy, -(float)Math.PI / 2f, (float)Math.PI / 2f); return BlueprintUtils.GetDir(num, num2); } private static int RebasePreview(BuildPreview p, Vector3 dirR, Vector3 dirR2) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) int num = 0; float magnitude = ((Vector3)(ref p.lpos)).magnitude; Vector3 val2; if (magnitude > 1E-05f) { Vector3 val = p.lpos / magnitude; val2 = val - dirR; if (((Vector3)(ref val2)).sqrMagnitude > 1E-12f) { Quaternion val3 = Quaternion.FromToRotation(val, dirR); p.lpos = dirR * magnitude; p.lrot = val3 * p.lrot; num++; } } float magnitude2 = ((Vector3)(ref p.lpos2)).magnitude; if (magnitude2 > 1E-05f) { Vector3 val4 = p.lpos2 / magnitude2; val2 = val4 - dirR2; if (((Vector3)(ref val2)).sqrMagnitude > 1E-12f) { Quaternion val5 = Quaternion.FromToRotation(val4, dirR2); p.lpos2 = dirR2 * magnitude2; p.lrot2 = val5 * p.lrot2; num++; } } return num; } private static void ResolveAreaOffsets(BlueprintArea[] areas, int primaryIdx, out float[] oLng, out float[] oLat) { int num = areas.Length; if (_areaLngBuf == null || _areaLngBuf.Length < num) { _areaLngBuf = new float[num]; _areaLatBuf = new float[num]; _areaDoneBuf = new bool[num]; } oLng = _areaLngBuf; oLat = _areaLatBuf; bool[] areaDoneBuf = _areaDoneBuf; Array.Clear(oLng, 0, num); Array.Clear(oLat, 0, num); Array.Clear(areaDoneBuf, 0, num); if (primaryIdx < 0 || primaryIdx >= num) { primaryIdx = 0; } areaDoneBuf[primaryIdx] = true; for (int i = 0; i <= num; i++) { bool flag = false; for (int j = 0; j < num; j++) { if (areaDoneBuf[j]) { continue; } BlueprintArea val = areas[j]; if (val == null) { areaDoneBuf[j] = true; continue; } int num2 = SlotOfAreaIndex(areas, val.parentIndex); if (num2 >= 0 && areaDoneBuf[num2]) { oLng[j] = oLng[num2] + (float)val.tropicAnchor - (float)val.anchorLocalOffsetX; oLat[j] = oLat[num2] + (float)val.anchorLocalOffsetY; areaDoneBuf[j] = true; flag = true; } else if (num2 < 0) { areaDoneBuf[j] = true; flag = true; } } if (!flag) { break; } } } private static int SlotOfAreaIndex(BlueprintArea[] areas, int index) { if (index < 0) { return -1; } for (int i = 0; i < areas.Length; i++) { if (areas[i] != null && areas[i].index == index) { return i; } } return -1; } } } namespace HoverCoord { [BepInPlugin("dsh.hovercoord", "HoverCoord", "1.10.11")] public class HoverCoordPlugin : BaseUnityPlugin { private struct NearbyScanResult { public bool anyNearby; public bool hasGapX; public float gapXCells; public bool hasGapZ; public float gapZCells; public bool hasSameTower; public float towerCenterCells; } private struct CachedBuilding { public Vector3 pos; public int protoId; public float lonGrid; public float latGrid; public string towerCategory; } public const string Guid = "dsh.hovercoord"; internal static HoverCoordPlugin Instance; private const float LayerHeight = 1.3333333f; private const float GroundOffset = 0.2f; private const float DetectInterval = 0.75f; private const float RebuildInterval = 0.1f; private const float OutputMargin = 0.005f; private bool active; private ConfigEntry<KeyboardShortcut> hotkeyConfig; private ConfigEntry<bool> startEnabledConfig; private static readonly StringBuilder builder = new StringBuilder(256); private static readonly Dictionary<int, string> nameCache = new Dictionary<int, string>(64); private HoverCoordRenderer renderer; private PlanetData lastPlanet; private EntityData lastEntity; private bool visible; private float nextDetectTime; private float lastBuildTime; private bool toastActive; private float toastUntil; private bool errorLogged; private static PlanetData cachedScanPlanet; private static readonly Dictionary<int, CachedBuilding> buildingCache = new Dictionary<int, CachedBuilding>(4096); private void Awake() { //IL_002f: Unknown result type (might be due to invalid IL or missing references) Instance = this; hotkeyConfig = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("General", "开关快捷键", new KeyboardShortcut((KeyCode)107, (KeyCode[])(object)new KeyCode[2] { (KeyCode)306, (KeyCode)304 }), "切换指针坐标显示的快捷键(格式:主键+修饰键,如 K+LeftControl+LeftShift)"); startEnabledConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "默认开启", false, "游戏启动后指针坐标显示是否默认开启(当前默认关闭)"); active = startEnabledConfig.Value; renderer = CreateRenderer(); renderer.Hide(); ((BaseUnityPlugin)this).Logger.LogInfo((object)("HoverCoord " + ((((BaseUnityPlugin)this).Info != null && ((BaseUnityPlugin)this).Info.Metadata != null) ? ((BaseUnityPlugin)this).Info.Metadata.Version.ToString() : "1.10.11") + " loaded. Author: 妙妙在路上 (抖音@妙妙在路上)")); } private HoverCoordRenderer CreateRenderer() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("HoverCoordRenderer"); val.transform.SetParent(((Component)this).transform, false); return val.AddComponent<HoverCoordRenderer>(); } internal string GetHotkeyText() { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) try { return (hotkeyConfig != null) ? ((object)hotkeyConfig.Value/*cast due to .constrained prefix*/).ToString() : "K + LeftControl + LeftShift"; } catch { return "K + LeftControl + LeftShift"; } } internal string TrySetHotkey(KeyCode main, KeyCode[] modifiers) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) try { if (hotkeyConfig == null) { return null; } hotkeyConfig.Value = new KeyboardShortcut(main, (KeyCode[])(((object)modifiers) ?? ((object)new KeyCode[0]))); try { ((BaseUnityPlugin)this).Config.Save(); } catch { } return ((object)hotkeyConfig.Value/*cast due to .constrained prefix*/).ToString(); } catch { return null; } } private void Update() { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) if (VFInput.inputing) { return; } if ((Object)(object)renderer == (Object)null) { renderer = CreateRenderer(); renderer.Hide(); visible = false; } KeyboardShortcut value = hotkeyConfig.Value; if (((KeyboardShortcut)(ref value)).IsDown()) { active = !active; ShowToast(L10n.T(active ? "指针坐标:开" : "指针坐标:关", active ? "Pointer coords: ON" : "Pointer coords: OFF")); nextDetectTime = 0f; } if (toastActive) { if (Time.unscaledTime < toastUntil) { return; } toastActive = false; HideTip(); nextDetectTime = 0f; } if (!active) { if (visible) { HideTip(); } } else { if (!(Time.unscaledTime >= nextDetectTime)) { return; } nextDetectTime = Time.unscaledTime + 0.75f; try { UpdateHover(); } catch (Exception ex) { HideTip(); if (!errorLogged) { errorLogged = true; ((BaseUnityPlugin)this).Logger.LogWarning((object)("HoverCoord: " + ex)); } } } } private static bool ControlHeld() { if (!Input.GetKey((KeyCode)306)) { return Input.GetKey((KeyCode)305); } return true; } private static bool ShiftHeld() { if (!Input.GetKey((KeyCode)304)) { return Input.GetKey((KeyCode)303); } return true; } private void UpdateHover() { //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) if (!Application.isFocused || VFInput.onGUI || VFInput.inFullscreenGUI || !VFInput.inScreen || (Object)(object)GameMain.instance == (Object)null || GameMain.isPaused || !GameMain.isRunning) { HideTip(); return; } PlanetData localPlanet = GameMain.localPlanet; if (localPlanet == null || !localPlanet.factoryLoaded) { HideTip(); return; } PlanetPhysics physics = localPlanet.physics; if (physics == null) { HideTip(); return; } RaycastLogic raycastLogic = physics.raycastLogic; if (raycastLogic == null || !raycastLogic.castSucceed) { HideTip(); return; } EntityData castEntity = raycastLogic.castEntity; if (castEntity.id <= 0) { HideTip(); return; } float num = 0.1f; try { PlanetFactory val = localPlanet?.factory; if (val != null && val.entityCursor > 15000) { num = 0.5f; } } catch { } if (!visible || !(Time.unscaledTime - lastBuildTime < num)) { if (!BuildTip(localPlanet, castEntity)) { HideTip(); return; } lastBuildTime = Time.unscaledTime; lastPlanet = localPlanet; lastEntity = castEntity; } } private bool BuildTip(PlanetData planet, EntityData entity) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_02c4: Unknown result type (might be due to invalid IL or missing references) //IL_020e: Unknown result type (might be due to invalid IL or missing references) //IL_0252: Unknown result type (might be due to invalid IL or missing references) //IL_0296: Unknown result type (might be due to invalid IL or missing references) Vector3 pos = entity.pos; float magnitude = ((Vector3)(ref pos)).magnitude; if (magnitude < 0.001f) { return false; } Vector3 val = pos / magnitude; int num = 200; PlanetAuxData aux = planet.aux; if (aux != null && aux.mainGrid != null && aux.mainGrid.segment > 0) { num = aux.mainGrid.segment; } float latitudeRad = BlueprintUtils.GetLatitudeRad(val); float longitudeRad = BlueprintUtils.GetLongitudeRad(val); float latitudeGridIdx = BlueprintUtils.GetLatitudeGridIdx(val, num); float longitudeGridIdx = BlueprintUtils.GetLongitudeGridIdx(val, num); float value = (magnitude - planet.realRadius - 0.2f) / 1.3333333f; float num2 = (float)Math.PI * 2f * planet.realRadius / ((float)num * 5f); Vector3 size; bool num3 = TryGetCollisionSize(entity, out size); string itemName = GetItemName(entity.protoId); string towerCategory = GetTowerCategory(itemName); float spacingUnits = 0f; if (towerCategory != null) { TryGetTowerSpacing(itemName, entity, towerCategory, out spacingUnits); } builder.Length = 0; if (!string.IsNullOrEmpty(itemName)) { builder.Append(itemName); } builder.Append(" #").Append(entity.id).Append('\n'); bool isChinese = L10n.IsChinese; builder.Append(isChinese ? "经度 " : "Lng ").Append(F4(longitudeRad * 57.29578f)).Append("°"); builder.Append(isChinese ? " 纬度 " : " Lat ").Append(F4(latitudeRad * 57.29578f)).Append("°\n"); builder.Append("X ").Append(F4(longitudeGridIdx)); builder.Append(" Y ").Append(F4(latitudeGridIdx)); builder.Append(" Z ").Append(F4(value)); if (num3) { builder.Append('\n'); builder.Append(isChinese ? "当前模型体积 长 " : "Model size L ").Append(F4(size.z / num2)).Append(isChinese ? "格" : ""); builder.Append(isChinese ? " 宽 " : " W ").Append(F4(size.x / num2)).Append(isChinese ? "格" : ""); builder.Append(isChinese ? " 高 " : " H ").Append(F4(size.y / 1.3333333f)).Append(isChinese ? "层" : ""); } NearbyScanResult nearbyScanResult = ScanNearby(planet, entity, longitudeGridIdx, latitudeGridIdx, num, num2, towerCategory); if (nearbyScanResult.hasGapX || nearbyScanResult.hasGapZ) { builder.Append('\n').Append(isChinese ? "最近模型碰撞距离 " : "Nearest collider dist "); builder.Append(isChinese ? "X轴 " : "X-axis ").Append(nearbyScanResult.hasGapX ? (F4(nearbyScanResult.gapXCells) + (isChinese ? "格" : "")) : (isChinese ? "无" : "n/a")); builder.Append(isChinese ? " Y轴 " : " Y-axis ").Append(nearbyScanResult.hasGapZ ? (F4(nearbyScanResult.gapZCells) + (isChinese ? "格" : "")) : (isChinese ? "无" : "n/a")); } if (towerCategory != null) { builder.Append('\n').Append(towerCategory).Append(isChinese ? " 最小间距 " : " min spacing ") .Append(F4(spacingUnits / num2)) .Append(isChinese ? "格" : ""); if (nearbyScanResult.hasSameTower) { builder.Append(isChinese ? " 最近同类中心 " : " nearest same-type ").Append(F4(nearbyScanResult.towerCenterCells)).Append(isChinese ? "格" : ""); if (nearbyScanResult.towerCenterCells < spacingUnits / num2) { builder.Append(isChinese ? " (相隔太近)" : " (too close)"); } } } ShowTip(builder.ToString()); return true; } private static bool TryGetCollisionSize(EntityData entity, out Vector3 size) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) size = Vector3.zero; PrefabDesc prefabDesc = GetPrefabDesc(entity); if (prefabDesc == null) { return false; } if (prefabDesc.buildCollider.ext != Vector3.zero) { size = prefabDesc.buildCollider.ext * 2f; return ((Vector3)(ref size)).sqrMagnitude > 0f; } if ((Object)(object)prefabDesc.mesh != (Object)null) { Bounds bounds = prefabDesc.mesh.bounds; size = ((Bounds)(ref bounds)).size; if (((Vector3)(ref size)).sqrMagnitude > 0f) { return true; } } if (prefabDesc.meshes != null) { bool flag = false; Bounds val = default(Bounds); for (int i = 0; i < prefabDesc.meshes.Length; i++) { Mesh val2 = prefabDesc.meshes[i]; if (!((Object)(object)val2 == (Object)null)) { if (!flag) { val = val2.bounds; flag = true; } else { ((Bounds)(ref val)).Encapsulate(val2.bounds); } } } if (flag) { size = ((Bounds)(ref val)).size; return ((Vector3)(ref size)).sqrMagnitude > 0f; } } if (prefabDesc.roughWidth > 0f) { size = new Vector3(prefabDesc.roughWidth, Mathf.Max(1f, prefabDesc.roughHeight), prefabDesc.roughWidth); return true; } return false; } private static PrefabDesc GetPrefabDesc(EntityData entity) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) PrefabDesc[] prefabDescByModelIndex = PlanetFactory.PrefabDescByModelIndex; int modelIndex = entity.modelIndex; if (prefabDescByModelIndex == null || modelIndex < 0 || modelIndex >= prefabDescByModelIndex.Length) { return null; } return prefabDescByModelIndex[modelIndex]; } private static Vector3 HorizontalDir(Vector3 v) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) v.y = 0f; float magnitude = ((Vector3)(ref v)).magnitude; if (!(magnitude < 1E-05f)) { return v / magnitude; } return Vector3.zero; } private static CachedBuilding GetCachedBuilding(PlanetData planet, EntityData entity, int segment) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) if (cachedScanPlanet != planet) { buildingCache.Clear(); cachedScanPlanet = planet; } if (buildingCache.TryGetValue(entity.id, out var value) && value.protoId == entity.protoId && value.pos == entity.pos) { return value; } value = new CachedBuilding { pos = entity.pos, protoId = entity.protoId }; Vector3 val = ((((Vector3)(ref entity.pos)).sqrMagnitude > 0f) ? ((Vector3)(ref entity.pos)).normalized : Vector3.zero); value.lonGrid = BlueprintUtils.GetLongitudeGridIdx(val, segment); value.latGrid = BlueprintUtils.GetLatitudeGridIdx(val, segment); value.towerCategory = GetTowerCategory(GetItemName(entity.protoId)); buildingCache[entity.id] = value; return value; } private static bool IsBeltOrSorter(int protoId) { if (protoId < 2001 || protoId > 2003) { if (protoId >= 2011) { return protoId <= 2013; } return false; } return true; } private static NearbyScanResult ScanNearby(PlanetData planet, EntityData entity, float selfLonGrid, float selfLatGrid, int segment, float cellSize, string towerCategory) { //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_01e1: Unknown result type (might be due to invalid IL or missing references) //IL_01e6: Unknown result type (might be due to invalid IL or missing references) //IL_01e8: Unknown result type (might be due to invalid IL or missing references) //IL_0203: Unknown result type (might be due to invalid IL or missing references) //IL_0205: Unknown result type (might be due to invalid IL or missing references) //IL_020a: Unknown result type (might be due to invalid IL or missing references) //IL_020f: Unknown result type (might be due to invalid IL or missing references) //IL_0214: Unknown result type (might be due to invalid IL or missing references) //IL_0219: Unknown result type (might be due to invalid IL or missing references) //IL_021b: Unknown result type (might be due to invalid IL or missing references) //IL_021d: Unknown result type (might be due to invalid IL or missing references) //IL_0222: Unknown result type (might be due to invalid IL or missing references) //IL_0227: Unknown result type (might be due to invalid IL or missing references) //IL_022c: Unknown result type (might be due to invalid IL or missing references) //IL_0231: Unknown result type (might be due to invalid IL or missing references) //IL_0233: Unknown result type (might be due to invalid IL or missing references) //IL_023a: Unknown result type (might be due to invalid IL or missing references) //IL_023c: Unknown result type (might be due to invalid IL or missing references) //IL_0249: Unknown result type (might be due to invalid IL or missing references) //IL_0250: Unknown result type (might be due to invalid IL or missing references) //IL_0252: Unknown result type (might be due to invalid IL or missing references) //IL_0262: Unknown result type (might be due to invalid IL or missing references) //IL_0269: Unknown result type (might be due to invalid IL or missing references) //IL_026b: Unknown result type (might be due to invalid IL or missing references) //IL_0278: Unknown result type (might be due to invalid IL or missing references) //IL_027f: Unknown result type (might be due to invalid IL or missing references) //IL_0281: Unknown result type (might be due to invalid IL or missing references) //IL_0296: Unknown result type (might be due to invalid IL or missing references) //IL_02aa: Unknown result type (might be due to invalid IL or missing references) //IL_01fc: Unknown result type (might be due to invalid IL or missing references) //IL_0201: Unknown result type (might be due to invalid IL or missing references) //IL_02c8: Unknown result type (might be due to invalid IL or missing references) //IL_02dc: Unknown result type (might be due to invalid IL or missing references) NearbyScanResult result = default(NearbyScanResult); PlanetFactory factory = planet.factory; if (factory == null) { return result; } EntityData[] entityPool = factory.entityPool; if (entityPool == null) { return result; } int num = factory.entityCursor; if (num > entityPool.Length) { num = entityPool.Length; } Vector3 val = ((((Vector3)(ref entity.pos)).sqrMagnitude > 0f) ? ((Vector3)(ref entity.pos)).normalized : Vector3.zero); float num2 = Mathf.Sqrt(Mathf.Max(0f, 1f - val.y * val.y)); int num3 = BlueprintUtils.GetLongitudeSegmentCount(val, segment); if (num3 <= 0) { num3 = segment; } float num4 = cellSize * ((float)segment / (float)num3) * num2; Vector3 val2 = HorizontalDir(entity.rot * Vector3.right); Vector3 val3 = HorizontalDir(entity.rot * Vector3.forward); Vector3 val4 = Vector3.zero; PrefabDesc prefabDesc = GetPrefabDesc(entity); if (prefabDesc != null) { val4 = prefabDesc.buildCollider.ext; } float num5 = float.MaxValue; float num6 = float.MaxValue; float num7 = float.MaxValue; bool anyNearby = false; for (int i = 1; i < num; i++) { EntityData val5 = entityPool[i]; if (val5.id <= 0 || val5.id == entity.id || IsBeltOrSorter(val5.protoId)) { continue; } Vector3 val6 = val5.pos - entity.pos; float sqrMagnitude = ((Vector3)(ref val6)).sqrMagnitude; if (!(sqrMagnitude > 3600f)) { anyNearby = true; CachedBuilding cachedBuilding = GetCachedBuilding(planet, val5, segment); float num8 = cachedBuilding.lonGrid - selfLonGrid; float num9 = (float)num3 * 1.25f; if (num8 > num9) { num8 -= (float)num3 * 2.5f; } else if (num8 < 0f - num9) { num8 += (float)num3 * 2.5f; } float num10 = Mathf.Abs(num8); float num11 = Mathf.Abs(cachedBuilding.latGrid - selfLatGrid); Vector3 val7 = Vector3.zero; PrefabDesc prefabDesc2 = GetPrefabDesc(val5); if (prefabDesc2 != null) { val7 = prefabDesc2.buildCollider.ext; } Vector3 val8 = HorizontalDir(val5.rot * Vector3.right); Vector3 val9 = HorizontalDir(val5.rot * Vector3.forward); float num12 = val7.x * Mathf.Abs(Vector3.Dot(val8, val2)) + val7.z * Mathf.Abs(Vector3.Dot(val9, val2)); float num13 = val7.x * Mathf.Abs(Vector3.Dot(val8, val3)) + val7.z * Mathf.Abs(Vector3.Dot(val9, val3)); bool num14 = num11 * cellSize <= val4.z + num13; float num15 = num10 * num4 - val4.x - num12; if (num14 && num15 < num5) { num5 = num15; } bool num16 = num10 * num4 <= val4.x + num12; float num17 = num11 * cellSize - val4.z - num13; if (num16 && num17 < num6) { num6 = num17; } if (towerCategory != null && !(cachedBuilding.towerCategory != towerCategory) && sqrMagnitude < num7) { num7 = sqrMagnitude; } } } result.anyNearby = anyNearby; if (num5 != float.MaxValue) { result.hasGapX = true; result.gapXCells = num5 / cellSize - 0.005f; } if (num6 != float.MaxValue) { result.hasGapZ = true; result.gapZCells = num6 / cellSize - 0.005f; } if (num7 != float.MaxValue) { result.hasSameTower = true; result.towerCenterCells = Mathf.Sqrt(num7) / cellSize; } return result; } private static bool TryGetCollisionBox(EntityData entity, out Vector3 center, out Quaternion rotation, out Vector3 extents) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) center = entity.pos; rotation = entity.rot; extents = Vector3.zero; PrefabDesc prefabDesc = GetPrefabDesc(entity); if (prefabDesc == null) { return false; } ColliderData buildCollider = prefabDesc.buildCollider; if (buildCollider.ext == Vector3.zero) { return false; } Quaternion val = buildCollider.q; if (val.x == 0f && val.y == 0f && val.z == 0f && val.w == 0f) { val = Quaternion.identity; } center = entity.pos + entity.rot * buildCollider.pos; rotation = entity.rot * val; extents = buildCollider.ext; return true; } private void ShowTip(string text) { visible = true; lastBuildTime = Time.unscaledTime; renderer.Show(text); } private void ShowToast(string text) { toastActive = true; toastUntil = Time.unscaledTime + 1.2f; ShowTip(text); } private void HideTip() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) if (visible) { visible = false; lastPlanet = null; lastEntity = default(EntityData); renderer.Hide(); } } private static string GetItemName(short protoId) { if (nameCache.TryGetValue(protoId, out var value)) { return value; } string text = null; try { ItemProto val = ((ProtoSet<ItemProto>)(object)LDB.items).Select((int)protoId); if (val != null) { text = ((Proto)val).name; } } catch { } nameCache[protoId] = text; return text; } private static string GetTowerCategory(string name) { if (string.IsNullOrEmpty(name)) { return null; } if (name.IndexOf("轨道弹射", StringComparison.Ordinal) >= 0) { return "弹射器"; } if (name.IndexOf("风力涡轮", StringComparison.Ordinal) >= 0) { return "风力涡轮机"; } if (name.IndexOf("物流", StringComparison.Ordinal) >= 0) { if (name.IndexOf("星际", StringComparison.Ordinal) < 0) { return "行星物流"; } return "星际物流"; } if (name.IndexOf("感应塔", StringComparison.Ordinal) >= 0 || name.IndexOf("无线输电", StringComparison.Ordinal) >= 0 || name.IndexOf("卫星配电", StringComparison.Ordinal) >= 0) { return "电力设施"; } return null; } private static bool TryGetTowerSpacing(string name, EntityData entity, string category, out float spacingUnits) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) spacingUnits = 0f; switch (category) { case "弹射器": { ColliderData val = default(ColliderData); PrefabDesc prefabDesc = GetPrefabDesc(entity); if (prefabDesc != null) { val = prefabDesc.buildCollider; } float num = Mathf.Sqrt(val.ext.x * val.ext.x + val.ext.z * val.ext.z); spacingUnits = 7.2f + num; return true; } case "风力涡轮机": spacingUnits = 10.5f; return true; case "星际物流": spacingUnits = 29f; return true; case "行星物流": spacingUnits = 15f; return true; case "电力设施": spacingUnits = 3.5f; return true; default: return false; } } private static string F4(float value) { return value.ToString("0.0000", CultureInfo.InvariantCulture); } private static string F3(float value) { return value.ToString("0.###", CultureInfo.InvariantCulture); } private static string V3(Vector3 v) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) return "(" + F3(v.x) + "," + F3(v.y) + "," + F3(v.z) + ")"; } private static string Q(Quaternion q) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) return "(" + F3(q.x) + "," + F3(q.y) + "," + F3(q.z) + "," + F3(q.w) + ")"; } } public sealed class HoverCoordRenderer : MonoBehaviour { private const int FontSize = 14; private readonly GUIContent content = new GUIContent(); private Vector2 contentSize; private int textVersion; private int measuredVersion = -1; private GUIStyle style; private Texture2D background; private bool fontFailed; private bool visible; public void Show(string text) { content.text = text; textVersion++; visible = true; if (!((Behaviour)this).enabled) { ((Behaviour)this).enabled = true; } } public void Hide() { visible = false; if (((Behaviour)this).enabled) { ((Behaviour)this).enabled = false; } } private void OnDestroy() { if ((Object)(object)background != (Object)null) { Object.Destroy((Object)(object)background); } } private void OnGUI() { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Invalid comparison between Unknown and I4 //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Unknown result type (might be due to invalid IL or missing references) if (visible && Event.current != null && (int)Event.current.type == 7 && EnsureStyle()) { if (measuredVersion != textVersion) { contentSize = style.CalcSize(content); measuredVersion = textVersion; } float x = Input.mousePosition.x; float num = (float)Screen.height - Input.mousePosition.y; float num2 = contentSize.x + 14f; float num3 = contentSize.y + 10f; float num4 = x + 22f; float num5 = num - 18f - num3; if (num4 + num2 > (float)Screen.width) { num4 = x - 22f - num2; } if (num5 < 0f) { num5 = num + 18f; } num4 = Mathf.Clamp(num4, 0f, Mathf.Max(0f, (float)Screen.width - num2)); num5 = Mathf.Clamp(num5, 0f, Mathf.Max(0f, (float)Screen.height - num3)); GUI.DrawTexture(new Rect(num4, num5, num2, num3), (Texture)(object)background); GUI.Label(new Rect(num4 + 7f, num5 + 5f, contentSize.x + 1f, contentSize.y), content, style); } } private bool EnsureStyle() { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Expected O, but got Unknown //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Expected O, but got Unknown //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Expected O, but got Unknown //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Expected O, but got Unknown //IL_00fa: Unknown result type (might be due to invalid IL or missing references) if (style != null) { return true; } if (fontFailed) { return false; } Font val = CreateFont(); if ((Object)(object)val == (Object)null) { fontFailed = true; return false; } style = new GUIStyle(GUI.skin.label); style.font = val; style.fontSize = 14; style.alignment = (TextAnchor)0; style.wordWrap = false; style.richText = false; style.padding = new RectOffset(0, 0, 0, 0); style.margin = new RectOffset(0, 0, 0, 0); style.normal.textColor = new Color(1f, 0.93f, 0.55f, 1f); background = new Texture2D(1, 1, (TextureFormat)5, false); background.SetPixel(0, 0, new Color(0f, 0f, 0f, 0.61960787f)); background.Apply(); return true; } private static Font CreateFont() { try { Font val = Font.CreateDynamicFontFromOSFont(new string[5] { "Microsoft YaHei", "微软雅黑", "SimHei", "SimSun", "Arial" }, 14); if ((Object)(object)val != (Object)null) { return val; } } catch { } try { return Resources.GetBuiltinResource<Font>("Arial.ttf"); } catch { return null; } } } } namespace DSPMiaoToolbox { internal static class CfgMigrator { public static void RestorePluginCfg(string targetPath, string cfgFileName) { try { if (string.IsNullOrEmpty(targetPath) || string.IsNullOrEmpty(cfgFileName) || File.Exists(targetPath)) { return; } string directoryName = Path.GetDirectoryName(targetPath); if (string.IsNullOrEmpty(directoryName) || !Directory.Exists(directoryName)) { return; } string directoryName2 = Path.GetDirectoryName(directoryName.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar)); if (string.IsNullOrEmpty(directoryName2) || !Directory.Exists(directoryName2)) { return; } string text = null; DateTime dateTime = DateTime.MinValue; string[] directories = Directory.GetDirectories(directoryName2); foreach (string text2 in directories) { if (string.Equals(text2, directoryName, StringComparison.OrdinalIgnoreCase)) { continue; } string text3 = Path.GetFileName(text2) ?? string.Empty; if (text3.Length == 0 || text3.StartsWith(".") || text3.StartsWith("_")) { continue; } string text4 = Path.Combine(text2, cfgFileName); if (File.Exists(text4)) { DateTime lastWriteTimeUtc; try { lastWriteTimeUtc = File.GetLastWriteTimeUtc(text4); } catch { continue; } if (lastWriteTimeUtc > dateTime) { dateTime = lastWriteTimeUtc; text = text4; } } } if (text != null) { File.Copy(text, targetPath, overwrite: false); Plugin.LogInfo("[DSPMiaoToolbox] 已从 " + text + " 迁移配置到 " + targetPath); } } catch (Exception ex) { try { Plugin.LogInfo("[DSPMiaoToolbox] 配置迁移失败(忽略):" + ex.Message); } catch { } } } } internal static class HotkeyHub { public sealed class Entry { public string Label; public string LabelEn; public Func<string> GetText; public Func<KeyCode, KeyCode[], string> TrySet; } private static Entry[] _entries; public static Entry[] Entries { get { if (_entries == null) { _entries = new Entry[17] { new Entry { Label = "蓝图工具窗口", LabelEn = "Blueprint toolbox window", GetText = () => (!((Object)(object)BlueprintOffsetPlugin.Instance != (Object)null)) ? "LeftAlt + Alpha5" : BlueprintOffsetPlugin.Instance.GetHotkeyText(), TrySet = (KeyCode m, KeyCode[] ms) => (!((Object)(object)BlueprintOffsetPlugin.Instance != (Object)null)) ? null : BlueprintOffsetPlugin.Instance.TrySetHotkey(m, ms) }, new Entry { Label = "回归线传送带间距", LabelEn = "Tropic belt spacing", GetText = () => Plugin.GetToggleHotkeyText(), TrySet = (KeyCode m, KeyCode[] ms) => Plugin.TrySetToggleHotkey(m, ms) }, new Entry { Label = "悬停坐标", LabelEn = "Hover coordinates", GetText = () => (!((Object)(object)HoverCoordPlugin.Instance != (Object)null)) ? "K + LeftControl + LeftShift" : HoverCoordPlugin.Instance.GetHotkeyText(), TrySet = (KeyCode m, KeyCode[] ms) => (!((Object)(object)HoverCoordPlugin.Instance != (Object)null)) ? null : HoverCoordPlugin.Instance.TrySetHotkey(m, ms) }, new Entry { Label = "蓝图拖拽最小间隔", LabelEn = "BP drag min spacing", GetText = () => (!((Object)(object)BPColliderSnapPlugin.Instance != (Object)null)) ? "LeftControl + LeftShift + N" : BPColliderSnapPlugin.Instance.GetHotkeyText(), TrySet = (KeyCode m, KeyCode[] ms) => (!((Object)(object)BPColliderSnapPlugin.Instance != (Object)null)) ? null : BPColliderSnapPlugin.Instance.TrySetHotkey(m, ms) }, new Entry { Label = "无碰撞摆放", LabelEn = "No-collision placement", GetText = () => BuildFeatures.GetHotkeyText(0), TrySet = (KeyCode m, KeyCode[] ms) => BuildFeatures.TrySetHotkey(0, m, ms) }, new Entry { Label = "隐藏建筑模型", LabelEn = "Hide building models", GetText = () => BuildFeatures.GetHotkeyText(1), TrySet = (KeyCode m, KeyCode[] ms) => BuildFeatures.TrySetHotkey(1, m, ms) }, new Entry { Label = "指北针开关快捷键", LabelEn = "Compass toggle hotkey", GetText = () => BuildFeatures.GetHotkeyText(2), TrySet = (KeyCode m, KeyCode[] ms) => BuildFeatures.TrySetHotkey(2, m, ms) }, new Entry { Label = "统计信息开关快捷键", LabelEn = "Stats overlay toggle hotkey", GetText = () => BuildFeatures.GetHotkeyText(6), TrySet = (KeyCode m, KeyCode[] ms) => BuildFeatures.TrySetHotkey(6, m, ms) }, new Entry { Label = "传送带切割", LabelEn = "Belt cutter", GetText = () => BuildFeatures.GetHotkeyText(3), TrySet = (KeyCode m, KeyCode[] ms) => BuildFeatures.TrySetHotkey(3, m, ms) }, new Entry { Label = "一键填埋矿脉", LabelEn = "Vein burier", GetText = () => BuildFeatures.GetHotkeyText(4), TrySet = (KeyCode m, KeyCode[] ms) => BuildFeatures.TrySetHotkey(4, m, ms) }, new Entry { Label = "建造秒完成", LabelEn = "Instant build", GetText = () => InstantBuildFeature.GetToggleHotkeyText(), TrySet = (KeyCode m, KeyCode[] ms) => InstantBuildFeature.TrySetToggleHotkey(m, ms) }, new Entry { Label = "传送带定高", LabelEn = "Belt height", GetText = () => BeltHeightInput.GetHotkeyText(), TrySet = (KeyCode m, KeyCode[] ms) => BeltHeightInput.TrySetHotkey(m, ms) }, new Entry { Label = "悬浮传送带", LabelEn = "Hover belt", GetText = () => BuildFeatures.GetHotkeyText(5), TrySet = (KeyCode m, KeyCode[] ms) => BuildFeatures.TrySetHotkey(5, m, ms) }, new Entry { Label = "蓝图偏移输出(框选后)", LabelEn = "Blueprint offset & use (after select)", GetText = () => BpQuickOffsetUse.GetHotkeyText(), TrySet = (KeyCode m, KeyCode[] ms) => BpQuickOffsetUse.TrySetHotkey(m, ms) }, new Entry { Label = "星球透视开关", LabelEn = "Planet x-ray toggle", GetText = () => HideSurfaceFeature.GetHotkeyText(0), TrySet = (KeyCode m, KeyCode[] ms) => HideSurfaceFeature.TrySetHotkey(0, m, ms) }, new Entry { Label = "地下建筑清理(按住)", LabelEn = "Underground cleaner (hold)", GetText = () => HideSurfaceFeature.GetHotkeyText(1), TrySet = (KeyCode m, KeyCode[] ms) => HideSurfaceFeature.TrySetHotkey(1, m, ms) }, new Entry { Label = "蓝图回归线自由摆放", LabelEn = "Free placement across tropics", GetText = () => TropicFreeFeature.GetToggleHotkeyText(), TrySet = (KeyCode m, KeyCode[] ms) => TropicFreeFeature.TrySetToggleHotkey(m, ms) } }; } return _entries; } } public static bool IsModifierKey(KeyCode key) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Invalid comparison between Unknown and I4 if (key - 303 <= 10) { return true; } return false; } public static bool TryParse(string text, out KeyCode main, out KeyCode[] modifiers) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Expected I4, but got Unknown //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) main = (KeyCode)0; modifiers = (KeyCode[])(object)new KeyCode[0]; if (string.IsNullOrEmpty(text)) { return false; } KeyCode val = (KeyCode)0; List<KeyCode> list = new List<KeyCode>(); string[] array = text.Split('+'); for (int i = 0; i < array.Length; i++) { string text2 = ((array[i] != null) ? array[i].Trim() : ""); if (text2.Length == 0 || string.Equals(text2, "None", StringComparison.OrdinalIgnoreCase)) { continue; } if (!Enum.TryParse<KeyCode>(text2, ignoreCase: true, out KeyCode result)) { return false; } if (!Enum.IsDefined(typeof(KeyCode), result)) { return false; } if (IsModifierKey(result)) { if (!list.Contains(result)) { list.Add(result); } continue; } if ((int)val == 0) { val = result; continue; } return false; } if ((int)val == 0 && list.Count > 0) { val = list[list.Count - 1]; list.RemoveAt(list.Count - 1); } if ((int)val == 0) { return false; } main = (KeyCode)(int)val; modifiers = list.ToArray(); return true; } public unsafe static string Format(KeyCode main, KeyCode[] modifiers) { string text = ((object)(*(KeyCode*)(&main))/*cast due to .constrained prefix*/).ToString(); if (modifiers != null) { for (int i = 0; i < modifiers.Length; i++) { text = text + " + " + ((object)Unsafe.As<KeyCode, KeyCode>(ref modifiers[i])/*cast due to .constrained prefix*/).ToString(); } } return text; } } } namespace DSPBPColliderSnap { [BepInPlugin("dsp.bpcollidersnap", "DSPBPColliderSnap", "2.2.0")] public class BPColliderSnapPlugin : BaseUnityPlugin { internal struct BpRect { public float lngMin; public float lngMax; public float latMin; public float latMax; } private struct EntityIntervalInfo { public int poolIndex; public float lngMin; public float lngMax; public float latMin; public float latMax; } internal struct Footprint { public float minE; public float maxE; public float minN; public float maxN; } public const string GUID = "dsp.bpcollidersnap"; public const string NAME = "DSPBPColliderSnap"; public const string VERSION = "2.2.0"; internal static ManualLogSource Log; internal static BPColliderSnapPlugin Instance; private Harmony _harmony; private ConfigFile _cfg; private ConfigEntry<bool> _enableSnap; private ConfigEntry<bool> _magnetEnable; private ConfigEntry<float> _gap; private ConfigEntry<float> _snapRedundancy; private ConfigEntry<float> _snapRedundancyLat; private ConfigEntry<float> _magnetRadius; private ConfigEntry<float> _lateralAlign; private ConfigEntry<int> _dragLimit; private ConfigEntry<float> _hiLatSlack; private ConfigEntry<string> _relaxItemIds; private ConfigEntry<bool> _debugDump; private ConfigEntry<string> _hotkey; private ConfigEntry<int> _cfgVersion; private string _cfgPath = ""; private KeyCode _mainKey = (KeyCode)110; private KeyCode[] _modifierKeys = (KeyCode[])(object)new KeyCode[2] { (KeyCode)306, (KeyCode)304 }; private string _hotkeyText = "LeftControl + LeftShift + N"; private BlueprintData _dumpedBp; private static readonly List<ColliderData> ReuseColliderList = new List<ColliderData>(32); private const float MaxLayoutLatitudeRad = 1.4835f; private const float TwoPi = (float)Math.PI * 2f; private const float PiF = (float)Math.PI; private static float _lastPlacementLog; private static int _lastMagnetAxis = -1; private static float _lastMagnetLog; private static readonly HashSet<short> RelaxIds = new HashSet<short>(); private static readonly List<BpRect> BpRects = new List<BpRect>(64); private static readonly List<EntityIntervalInfo> NearbyEntities = new List<EntityIntervalInfo>(64); private void Awake() { //IL_0448: Unknown result type (might be due to invalid IL or missing references) //IL_0452: Expected O, but got Unknown //IL_0490: Unknown result type (might be due to invalid IL or missing references) //IL_049d: Expected O, but got Unknown //IL_04fc: Unknown result type (might be due to invalid IL or missing references) //IL_0509: Expected O, but got Unknown Instance = this; Log = ((BaseUnityPlugin)this).Logger; try { _cfg = CreatePluginConfig(out _cfgPath); _cfg.SaveOnConfigSet = false; _enableSnap = _cfg.Bind<bool>("对齐/Align", "启用碰撞盒对齐", false, "v2.1.9 起默认关闭:进游戏后按快捷键【Ctrl+Shift+N】开启(游戏内会弹出“已开启/已关闭”提示)。开启后拖拽铺设蓝图时,拷贝间距按建筑真实碰撞盒排布(忽略地面网格格数),并磁吸最近建筑。false = 完全恢复原版行为。"); _magnetEnable = _cfg.Bind<bool>("对齐/Align", "磁吸已有建筑", true, "拖拽蓝图时,落点靠近已建成建筑会自动贴合其碰撞盒边缘(整组拷贝一起平移)。"); _gap = _cfg.Bind<float>("对齐/Align", "紧贴间距(米)", 0f, "拷贝之间、以及磁吸贴合时的留缝,单位米。0 = 完全紧贴(碰撞盒边缘对碰撞盒边缘)。"); _snapRedundancy = _cfg.Bind<float>("对齐/Align", "吸附冗余(米)", 0.0025f, "磁吸与拷贝步距在“经纬度区间恰好相接”之外额外留的安全余量。v2.1.3 起默认 0.0025 m(2.5 mm):0 间距实测在部分坡地/浮点场景仍会临界判红;2.5 mm 肉眼不可见。想完全零容错可设 0。"); _snapRedundancyLat = _cfg.Bind<float>("对齐/Align", "南北吸附冗余(米)", 0.01f, "南北向(Y 轴:上下拖拽 / 纵向贴合)额外留的冗余。v2.2.0 起默认 0.01 m(1 cm):纵向贴合时相邻结构的纬度位置会随经度格宽取档轻微跳动,1 cm 更稳;东西向仍用“吸附冗余(米)”。"); _magnetRadius = _cfg.Bind<float>("对齐/Align", "磁吸半径(米)", 7f, "落点与已有建筑碰撞盒边缘的距离小于该值时触发贴合(跨小空隙也能吸过去)。0 = 关闭磁吸。"); _lateralAlign = _cfg.Bind<float>("对齐/Align", "横向对齐阈值(米)", 0f, "贴合时若横向错位小于该值则强制对齐到同一条线。0 = 自动取磁吸半径。"); _dragLimit = _cfg.Bind<int>("对齐/Align", "拖拽份数上限", 99, "拖拽铺设的最大拷贝份数(默认 99)。原版上限 15(dotsSnapped 数组容量),本模组放宽到最多 255;受游戏蓝图建筑总量上限(默认 15000)约束,份数×蓝图建筑数超限后游戏会拒绝粘贴。范围自动收敛到 15~255。"); _hiLatSlack = _cfg.Bind<float>("对齐/Align", "高纬度放宽(米)", 0f, "v2.1.2 起已无实际作用(保留兼容):碰撞足迹按游戏本体摆放公式逐栋精确重建,曲率外扩与分拣器 pitch/tilt 旋转已自动计入,拷贝间距与磁吸都按经纬度区间恰好相接(0 间距)计算。"); _relaxItemIds = _cfg.Bind<string>("对齐/Align", "放宽建筑ID列表", "2310,2318,2309,2317", "享受高纬度放宽的建筑物品ID(逗号分隔)。2310 = 微型粒子对撞机,2309 = 化工厂,2317 = 量子化工厂(化工厂模型的两个ID)。列表为空 = 不放宽任何建筑。"); _debugDump = _cfg.Bind<bool>("调试/Debug", "输出碰撞盒核实数据", false, "v2.1.9 起默认关闭。开启后,拖拽时会在日志输出实摆验证(游戏实际摆放 vs 模组预测的逐楼偏差)、极限拷贝步距与磁吸决策,供核对问题;平时关闭以免日志刷屏。"); _hotkey = _cfg.Bind<string>("快捷键/Hotkey", "快捷键", "LeftControl + LeftShift + N", "运行时开启/关闭本模组对齐功能的快捷键(开关时游戏内会弹出提示)。格式与原版键名一致,例如 LeftControl + LeftShift + N、None + F8。"); _cfgVersion = _cfg.Bind<int>("内部/Internal", "配置版本", 0, "内部使用:记录配置默认值迁移版本,请勿手动修改。"); SaveQuiet(); ParseHotkey(); if (_cfgVersion.Value < 2) { if (_hotkey.Value == "LeftAlt + B" || _hotkey.Value == "LeftControl + LeftShift + M") { _hotkey.Value = "LeftControl + LeftShift + N"; } if (Mathf.Abs(_magnetRadius.Value - 3f) < 0.0001f || Mathf.Abs(_magnetRadius.Value - 5f) < 0.0001f) { _magnetRadius.Value = 7f; } if (Mathf.Abs(_snapRedundancy.Value - 0.05f) < 0.0001f || Mathf.Abs(_snapRedundancy.Value - 0.005f) < 0.0001f || Mathf.Abs(_snapRedundancy.Value) < 1E-06f) { _snapRedundancy.Value = 0.0025f; } if (Mathf.Abs(_hiLatSlack.Value - 0.75f) < 0.0001f || Mathf.Abs(_hiLatSlack.Value - 0.25f) < 0.0001f || Mathf.Abs(_hiLatSlack.Value - 0.45f) < 0.0001f) { _hiLatSlack.Value = 0f; } if (_relaxItemIds.Value == "2310,2318,2309") { _relaxItemIds.Value = "2310,2318,2309,2317"; } if (Mathf.Abs(_snapRedundancyLat.Value - 0.005f) < 0.0001f) { _snapRedundancyLat.Value = 0.01f; } if (_cfgVersion.Value < 1) { _enableSnap.Value = false; _debugDump.Value = false; } _cfgVersion.Value = 2; } ParseHotkey(); RefreshRelaxIds(); SaveQuiet(); _hotkey.SettingChanged += delegate { ParseHotkey(); }; _relaxItemIds.SettingChanged += delegate { RefreshRelaxIds(); }; _harmony = new Harmony("dsp.bpcollidersnap"); MethodInfo methodInfo = AccessTools.Method(typeof(BuildTool_BlueprintPaste), "DetermineDragDots", (Type[])null, (Type[])null); if (methodInfo != null) { _harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(BPColliderSnapPlugin), "DetermineDragDots_Postfix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Log.LogInfo((object)"已挂载补丁:BuildTool_BlueprintPaste.DetermineDragDots(拖拽落点重排)。"); } else { Log.LogError((object)"找不到 BuildTool_BlueprintPaste.DetermineDragDots,本模组无法工作(游戏版本不匹配?)。"); } MethodInfo methodInfo2 = AccessTools.Method(typeof(BuildTool_BlueprintPaste), "DeterminePreviewsPrestage", (Type[])null, (Type[])null); if (methodInfo2 != null) { _harmony.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(BPColliderSnapPlugin), "DeterminePreviewsPrestage_Postfix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Log.LogInfo((object)"已挂载补丁:BuildTool_BlueprintPaste.DeterminePreviewsPrestage(实摆位置验证)。"); } } catch (Exception ex) { Log.LogError((object)("初始化失败:" + ex)); } Log.LogInfo((object)string.Format(CultureInfo.InvariantCulture, "{0} v{1} 已加载(默认关闭,进游戏按 {2} 开启)。快捷键:{2};配置文件:{3}", "DSPBPColliderSnap", "2.2.0", _hotkeyText, _cfgPath)); } private void OnDestroy() { try { if (_harmony != null) { _harmony.UnpatchSelf(); } } catch { } Instance = null; } private void Update() { //IL_003c: Unknown result type (might be due to invalid IL or missing references) try { if (VFInput.inputing) { return; } if (_modifierKeys != null) { for (int i = 0; i < _modifierKeys.Length; i++) { if (!Input.GetKey(_modifierKeys[i])) { return; } } } if (Input.GetKeyDown(_mainKey)) { _enableSnap.Value = !_enableSnap.Value; SaveQuiet(); string text = L10n.T("蓝图碰撞盒对齐 v2.2.0 已" + (_enableSnap.Value ? "开启" : "关闭"), "BP collider snap v2.2.0 turned " + (_enableSnap.Value ? "ON" : "OFF")); Tip(text); Log.LogInfo((object)text); } } catch { } } private ConfigFile CreatePluginConfig(out string path) { //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Expected O, but got Unknown //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Expected O, but got Unknown string text = null; try { if (((BaseUnityPlugin)this).Info != null && !string.IsNullOrEmpty(((BaseUnityPlugin)this).Info.Location)) { text = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location); } } catch { } if (string.IsNullOrEmpty(text) || !Directory.Exists(text)) { text = Path.Combine(Paths.PluginPath, "DSPBPColliderSnap"); } string text2 = text.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar); if (string.Equals(Path.GetFileName(text2), "plugins", StringComparison.OrdinalIgnoreCase)) { text = Path.Combine(text2, "DSPBPColliderSnap"); } try { Directory.CreateDirectory(text); } catch { } path = Path.Combine(text, "DSPBPColliderSnap.cfg"); CfgMigrator.RestorePluginCfg(path, "DSPBPColliderSnap.cfg"); try { return new ConfigFile(path, true); } catch (Exception ex) { Log.LogWarning((object)("插件目录无法写入配置(" + ex.Message + "),改用 BepInEx/config。")); path = Path.Combine(Paths.ConfigPath, "dsp.bpcollidersnap.cfg"); return new ConfigFile(path, true); } } private void SaveQuiet() { try { if (_cfg != null) { _cfg.Save(); } } catch { } } private static bool IsModifierKey(KeyCode key) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Invalid comparison between Unknown and I4 if (key - 303 <= 9) { return true; } return false; } private void ParseHotkey() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) List<KeyCode> list = new List<KeyCode>(); KeyCode val = (KeyCode)0; string text = ((_hotkey != null) ? _hotkey.Value : null); if (!string.IsNullOrEmpty(text)) { string[] array = text.Split('+'); for (int i = 0; i < array.Length; i++) { string text2 = array[i].Trim(); if (text2.Length == 0 || string.Equals(text2, "None", StringComparison.OrdinalIgnoreCase) || !Enum.TryParse<KeyCode>(text2, ignoreCase: true, out KeyCode result)) { continue; } if (IsModifierKey(result)) { if (!list.Contains(result)) { list.Add(result); } } else if ((int)val == 0) { val = result; } } } if ((int)val == 0 && list.Count > 0) { val = list[list.Count - 1]; list.RemoveAt(list.Count - 1); } if ((int)val == 0) { val = (KeyCode)110; list.Clear(); list.Add((KeyCode)306); list.Add((KeyCode)304); } _mainKey = val; _modifierKeys = list.ToArray(); List<string> list2 = new List<string>(); list2.Add(((object)Unsafe.As<KeyCode, KeyCode>(ref _mainKey)/*cast due to .constrained prefix*/).ToString()); for (int j = 0; j < _modifierKeys.Length; j++) { list2.Add(((object)Unsafe.As<KeyCode, KeyCode>(ref _modifierKeys[j])/*cast due to .constrained prefix*/).ToString()); } list2.Sort(); _hotkeyText = string.Join(" + ", list2.ToArray()); } internal string GetHotkeyText() { try { return (_hotkey != null) ? _hotkey.Value : "LeftControl + LeftShift + N"; } catch { return "LeftControl + LeftShift + N"; } } internal string TrySetHotkey(KeyCode main, KeyCode[] modifiers) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) try { if (_hotkey == null) { return null; } string text = HotkeyHub.Format(main, modifiers); if (string.Equals(_hotkey.Value, text, StringComparison.Ordinal)) { return _hotkeyText; } _hotkey.Value = text; SaveQuiet(); return text; } catch { return null; } } internal bool GetEnableSnap() { try { return _enableSnap != null && _enableSnap.Value; } catch { return false; } } internal void SetEnableSnap(bool value) { try { if (_enableSnap != null && _enableSnap.Value != value) { _enableSnap.Value = value; SaveQuiet(); string text = L10n.T("蓝图碰撞盒对齐 v2.2.0 已" + (value ? "开启" : "关闭"), "BP collider snap v2.2.0 turned " + (value ? "ON" : "OFF")); Tip(text); Log.LogInfo((object)text); } } catch { } } internal int GetDragLimit() { try { return (_dragLimit != null) ? Mathf.Clamp(_dragLimit.Value, 15, 255) : 255; } catch { return 255; } } internal int TrySetDragLimit(int value) { try { if (_dragLimit == null) { return -1; } int num = Mathf.Clamp(value, 15, 255); if (_dragLimit.Value != num) { _dragLimit.Value = num; SaveQuiet(); } return num; } catch { return -1; } } private static void RefreshRelaxIds() { RelaxIds.Clear(); BPColliderSnapPlugin instance = Instance; if ((Object)(object)instance == (Object)null || instance._relaxItemIds == null || string.IsNullOrEmpty(instance._relaxItemIds.Value)) { return; } string[] array = instance._relaxItemIds.Value.Split(','); for (int i = 0; i < array.Length; i++) { if (short.TryParse(array[i].Trim(), out var result) && result > 0) { RelaxIds.Add(result); } } } private static bool IsRelaxItem(short itemId) { if (itemId > 0) { return RelaxIds.Contains(itemId); } return false; } private static float Round2Int(float d) { return (d > 0f) ? ((int)(d + 0.5f)) : ((int)(d - 0.5f)); } private static bool MagnetLogDue() { BPColliderSnapPlugin instance = Instance; if ((Object)(object)instance == (Object)null || !instance._debugDump.Value) { return false; } if (Time.unscaledTime < _lastMagnetLog + 0.5f) { return false; } _lastMagnetLog = Time.unscaledTime; return true; } internal static void DetermineDragDots_Postfix(BuildTool_BlueprintPaste __instance) { try { RealignmentCore(__instance); } catch (Exception ex) { if (Log != null) { Log.LogWarning((object)("拖拽落点对齐失败(已退回原版行为):" + ex.Message)); } } } private static void RealignmentCore(BuildTool_BlueprintPaste tool) { //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) //IL_024f: Unknown result type (might be due to invalid IL or missing references) //IL_0254: Unknown result type (might be due to invalid IL or missing references) //IL_02a8: Unknown result type (might be due to invalid IL or missing references) //IL_02aa: Unknown result type (might be due to invalid IL or missing references) //IL_02ac: Unknown result type (might be due to invalid IL or missing references) //IL_02ba: Unknown result type (might be due to invalid IL or missing references) //IL_030b: Unknown result type (might be due to invalid IL or missing references) //IL_0310: Unknown result type (might be due to invalid IL or missing references) //IL_0312: Unknown result type (might be due to invalid IL or missing references) //IL_031b: Unknown result type (might be due to invalid IL or missing references) //IL_0325: Unknown result type (might be due to invalid IL or missing references) //IL_0339: Unknown result type (might be due to invalid IL or missing references) //IL_033e: Unknown result type (might be due to invalid IL or missing references) //IL_0340: Unknown result type (might be due to invalid IL or missing references) //IL_0342: Unknown result type (might be due to invalid IL or missing references) //IL_0346: Unknown result type (might be due to invalid IL or missing references) //IL_034b: Unknown result type (might be due to invalid IL or missing references) //IL_0350: Unknown result type (might be due to invalid IL or missing references) //IL_0361: Unknown result type (might be due to invalid IL or missing references) //IL_0366: Unknown result type (might be due to invalid IL or missing references) //IL_0368: Unknown result type (might be due to invalid IL or missing references) //IL_036d: Unknown result type (might be due to invalid IL or missing references) //IL_0380: Unknown result type (might be due to invalid IL or missing references) //IL_038c: Unknown result type (might be due to invalid IL or missing references) //IL_0445: Unknown result type (might be due to invalid IL or missing references) //IL_0447: Unknown result type (might be due to invalid IL or missing references) //IL_042d: Unknown result type (might be due to invalid IL or missing references) //IL_050d: Unknown result type (might be due to invalid IL or missing references) //IL_0512: Unknown result type (might be due to invalid IL or missing references) //IL_0514: Unknown result type (might be due to invalid IL or missing references) //IL_051d: Unknown result type (might be due to invalid IL or missing references) //IL_0536: Unknown result type (might be due to invalid IL or missing references) //IL_053a: Unknown result type (might be due to invalid IL or missing references) //IL_053f: Unknown result type (might be due to invalid IL or missing references) //IL_0664: Unknown result type (might be due to invalid IL or missing references) //IL_066b: Unknown result type (might be due to invalid IL or missing references) //IL_0670: Unknown result type (might be due to invalid IL or missing references) //IL_05d0: Unknown result type (might be due to invalid IL or missing references) //IL_05d7: Unknown result type (might be due to invalid IL or missing references) //IL_05dc: Unknown result type (might be due to invalid IL or missing references) BPColliderSnapPlugin instance = Instance; if ((Object)(object)instance == (Object)null || tool == null || !instance._enableSnap.Value) { return; } BlueprintData blueprint = tool.blueprint; if (blueprint == null || blueprint.buildings == null || blueprint.buildings.Length == 0) { return; } PlanetData planet = ((BuildTool)tool).planet; if (planet == null || !planet.factoryLoaded) { return; } PlanetFactory factory = planet.factory; if (factory == null || factory.entityPool == null) { return; } Vector3[] array = tool.dotsSnapped; if (array == null || array.Length == 0 || tool.dotsCursor <= 0) { return; } if (tool.dotsCursor > array.Length) { tool.dotsCursor = array.Length; } int num = Mathf.Clamp(instance._dragLimit.Value, 15, 255); if (array.Length < num) { Vector3[] array2 = (Vector3[])(object)new Vector3[num]; Array.Copy(array, array2, array.Length); tool.dotsSnapped = array2; array = array2; } if (tool.bpGratBoxArr == null || tool.bpGratBoxArr.Length < num) { tool.bpGratBoxArr = (BPGratBox[])(object)new BPGratBox[num]; tool.gratBoxCursor = 0; } if (tool.bpGratBoxConditionArr == null || tool.bpGratBoxConditionArr.Length < num) { tool.bpGratBoxConditionArr = (IntVector4[])(object)new IntVector4[num]; } Vector3 snappedAnchor = array[0]; if (((Vector3)(ref snappedAnchor)).sqrMagnitude < 1E-08f) { return; } float realRadius = planet.realRadius; if (realRadius <= 1f) { return; } Vector3 normalized = ((Vector3)(ref snappedAnchor)).normalized; float latitudeRad = BlueprintUtils.GetLatitudeRad(normalized); float longitudeRad = BlueprintUtils.GetLongitudeRad(normalized); float num2 = Mathf.Cos(latitudeRad); float num3 = Mathf.Sin(latitudeRad); float num4 = Mathf.Cos(longitudeRad); float num5 = Mathf.Sin(longitudeRad); Vector3 east = default(Vector3); ((Vector3)(ref east))..ctor(num4, 0f, num5); Vector3 north = default(Vector3); ((Vector3)(ref north))..ctor((0f - num3) * num5, num2, num3 * num4); int segment = tool.segment; float latitudeRadPerGrid = BlueprintUtils.GetLatitudeRadPerGrid(segment); int num6 = Mathf.FloorToInt(tool.yaw / 89.9f); num6 = (num6 % 4 + 4) % 4; bool lngNeg = num6 == 1 || num6 == 2; bool latNeg = num6 == 2 || num6 == 3; BlueprintAre