Decompiled source of DSPBlueprintTools v1.3.4

DSPBlueprintTools.dll

Decompiled 9 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("DSPBlueprintTools")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.3.4.0")]
[assembly: AssemblyInformationalVersion("1.3.4")]
[assembly: AssemblyProduct("DSPBlueprintTools")]
[assembly: AssemblyTitle("DSPBlueprintTools")]
[assembly: AssemblyVersion("1.3.4.0")]
namespace DSPBlueprintTools;

[BepInPlugin("dsp.byboy.blueprinttools", "DSPBlueprintTools", "1.3.4")]
public class BlueprintToolsPlugin : BaseUnityPlugin
{
	public const string GUID = "dsp.byboy.blueprinttools";

	public const string NAME = "DSPBlueprintTools";

	public const string VERSION = "1.3.4";

	private const int MaxBlueprintBuildings = 15000;

	private const int BeltItemId = 2001;

	private ConfigEntry<string> _hotkeyEntry;

	private ConfigEntry<float> _maxBeltLengthEntry;

	private ConfigEntry<bool> _autoBeltLatEntry;

	private KeyCode _mainKey = (KeyCode)52;

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

	private bool _showWindow;

	private Rect _winRect = new Rect(120f, 100f, 430f, 560f);

	private Vector2 _scroll;

	private string _status = "按快捷键打开/关闭本窗口";

	private BlueprintData _bp;

	private string _bpDesc = "(未载入蓝图)";

	private string _beltStat = "";

	private string _ox = "0.0000";

	private string _oy = "0.0000";

	private string _oz = "0.0000";

	private string _offCount = "1";

	private string _layers = "2";

	private string _layerHeight = "10.0000";

	private string _sx = "1.0000";

	private string _sy = "1.0000";

	private string _sz = "1.0000";

	private string _rotDeg = "0";

	private string _replaceFrom = "";

	private string _replaceTo = "";

	private UIBlueprintInspector _inspector;

	private float _nextInjectTry;

	private bool _readBtnCreated;

	private FieldInfo _fiCopyBtnTrans;

	private FieldInfo _fiCopyBtnText;

	private FieldInfo _fiPasteTool;

	private bool _uiRefsResolved;

	private static bool IsBelt(BlueprintBuilding b)
	{
		if (b.itemId == 2001)
		{
			return true;
		}
		try
		{
			ModelProto val = ((ProtoSet<ModelProto>)(object)LDB.models).Select((int)b.modelIndex);
			return val != null && val.prefabDesc != null && val.prefabDesc.isBelt;
		}
		catch
		{
			return false;
		}
	}

	private void Awake()
	{
		_hotkeyEntry = ((BaseUnityPlugin)this).Config.Bind<string>("通用", "快捷键", "LeftAlt + Alpha4", "打开/关闭蓝图工具窗口的快捷键。格式:修饰键 + 主键,用 + 分隔。键名使用 UnityEngine.KeyCode 枚举名,例如:LeftAlt + Alpha4、LeftControl + F8、None + F9(无修饰键)。");
		_hotkeyEntry.SettingChanged += delegate
		{
			ParseHotkey();
		};
		ParseHotkey();
		_maxBeltLengthEntry = ((BaseUnityPlugin)this).Config.Bind<float>("传送带", "单段最大长度", 1.8f, "传送带合并最长化时允许的单段最大长度(小数点后 4 位)。实测原版可放置上限随纬度变化:赤道约 1.8,极地约 1.6,超过则无法摆放。默认 1.8。");
		_autoBeltLatEntry = ((BaseUnityPlugin)this).Config.Bind<bool>("传送带", "按纬度自动适配上限", true, "开启后按蓝图区域纬度自动收紧上限(赤道 1.8 → 极地 1.6,线性过渡),关闭则始终使用上面配置的固定上限。");
		_status = "快捷键:" + _hotkeyEntry.Value;
	}

	private void ParseHotkey()
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_006d: 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_0075: Unknown result type (might be due to invalid IL or missing references)
		//IL_0072: Unknown result type (might be due to invalid IL or missing references)
		//IL_005c: 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_0058: Unknown result type (might be due to invalid IL or missing references)
		List<KeyCode> list = new List<KeyCode>();
		KeyCode val = (KeyCode)0;
		string[] array = _hotkeyEntry.Value.Split('+');
		for (int i = 0; i < array.Length; i++)
		{
			string text = array[i].Trim();
			if (text.Length != 0 && !string.Equals(text, "None", StringComparison.OrdinalIgnoreCase) && Enum.TryParse<KeyCode>(text, ignoreCase: true, out KeyCode result))
			{
				if (i == array.Length - 1)
				{
					val = result;
				}
				else
				{
					list.Add(result);
				}
			}
		}
		if ((int)val == 0)
		{
			val = (KeyCode)52;
		}
		_mainKey = val;
		_modifierKeys = list.ToArray();
	}

	private static bool ParseF4(string text, out float v)
	{
		if (float.TryParse(text, NumberStyles.Float, CultureInfo.InvariantCulture, out v))
		{
			v = (float)Math.Round(v, 4);
			return true;
		}
		v = 0f;
		return false;
	}

	private void Update()
	{
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		bool flag = true;
		KeyCode[] modifierKeys = _modifierKeys;
		for (int i = 0; i < modifierKeys.Length; i++)
		{
			if (!Input.GetKey(modifierKeys[i]))
			{
				flag = false;
				break;
			}
		}
		if (flag && Input.GetKeyDown(_mainKey))
		{
			_showWindow = !_showWindow;
		}
		if (!_readBtnCreated && Time.unscaledTime >= _nextInjectTry)
		{
			_nextInjectTry = Time.unscaledTime + 2f;
			EnsureInspectorReadButton();
		}
	}

	private void OnGUI()
	{
		//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: Expected O, but got Unknown
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		if (_showWindow)
		{
			_winRect = GUILayout.Window(17072, _winRect, new WindowFunction(DrawWindow), "蓝图工具 DSPBlueprintTools (v1.3.4)", Array.Empty<GUILayoutOption>());
		}
	}

	private void EnsureInspectorReadButton()
	{
		//IL_014b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0150: 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_016b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0177: Unknown result type (might be due to invalid IL or missing references)
		//IL_0183: Unknown result type (might be due to invalid IL or missing references)
		//IL_018f: Unknown result type (might be due to invalid IL or missing references)
		//IL_019b: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01fd: 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_0290: Expected O, but got Unknown
		//IL_029c: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a6: Expected O, but got Unknown
		//IL_0243: 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_0265: Unknown result type (might be due to invalid IL or missing references)
		//IL_0276: Unknown result type (might be due to invalid IL or missing references)
		if (!_uiRefsResolved)
		{
			_fiCopyBtnTrans = typeof(UIBlueprintInspector).GetField("copyBtnTrans", BindingFlags.Instance | BindingFlags.NonPublic);
			_fiCopyBtnText = typeof(UIBlueprintInspector).GetField("copyBtnText", BindingFlags.Instance | BindingFlags.NonPublic);
			_fiPasteTool = typeof(UIBlueprintInspector).GetField("pasteBuildTool", BindingFlags.Instance | BindingFlags.NonPublic);
			_uiRefsResolved = true;
		}
		if (_fiCopyBtnTrans == null || _fiCopyBtnText == null)
		{
			return;
		}
		try
		{
			_inspector = Object.FindObjectOfType<UIBlueprintInspector>();
		}
		catch
		{
			_inspector = null;
		}
		if ((Object)(object)_inspector == (Object)null)
		{
			return;
		}
		object? value = _fiCopyBtnTrans.GetValue(_inspector);
		RectTransform val = (RectTransform)((value is RectTransform) ? value : null);
		object? value2 = _fiCopyBtnText.GetValue(_inspector);
		Text val2 = (Text)((value2 is Text) ? value2 : null);
		if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null || !((Component)_inspector).gameObject.activeInHierarchy)
		{
			return;
		}
		Button component = ((Component)val).GetComponent<Button>();
		Image component2 = ((Component)val).GetComponent<Image>();
		if (!((Object)(object)component == (Object)null) && !((Object)(object)component2 == (Object)null))
		{
			GameObject val3 = new GameObject("DSPBlueprintTools_ReadBtn", new Type[3]
			{
				typeof(RectTransform),
				typeof(Image),
				typeof(Button)
			});
			val3.transform.SetParent(((Transform)val).parent, false);
			RectTransform component3 = val3.GetComponent<RectTransform>();
			component3.anchorMin = val.anchorMin;
			component3.anchorMax = val.anchorMax;
			component3.pivot = val.pivot;
			component3.sizeDelta = val.sizeDelta;
			component3.anchoredPosition = val.anchoredPosition - new Vector2(val.sizeDelta.x + 6f, 0f);
			Image component4 = val3.GetComponent<Image>();
			component4.sprite = component2.sprite;
			component4.type = component2.type;
			((Graphic)component4).color = new Color(0.65f, 0.92f, 1f, ((Graphic)component2).color.a);
			GameObject obj2 = Object.Instantiate<GameObject>(((Component)val2).gameObject, (Transform)(object)component3, false);
			((Object)obj2).name = "Text";
			Text component5 = obj2.GetComponent<Text>();
			if ((Object)(object)component5 != (Object)null)
			{
				component5.text = "读取";
				((Graphic)component5).rectTransform.anchorMin = Vector2.zero;
				((Graphic)component5).rectTransform.anchorMax = Vector2.one;
				((Graphic)component5).rectTransform.offsetMin = Vector2.zero;
				((Graphic)component5).rectTransform.offsetMax = Vector2.zero;
			}
			Button component6 = val3.GetComponent<Button>();
			component6.onClick = new ButtonClickedEvent();
			((UnityEvent)component6.onClick).AddListener((UnityAction)delegate
			{
				ReadFromClipboard();
				_showWindow = true;
			});
			_readBtnCreated = true;
		}
	}

	private void DrawWindow(int id)
	{
		//IL_00b1: 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_00c0: 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)
		GUILayout.BeginVertical(Array.Empty<GUILayoutOption>());
		GUILayout.Label(_bpDesc, GUI.skin.box, Array.Empty<GUILayoutOption>());
		GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
		if (GUILayout.Button("从剪贴板读取蓝图", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(26f) }))
		{
			ReadFromClipboard();
		}
		if (GUILayout.Button("写回剪贴板", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(26f) }))
		{
			WriteToClipboard();
		}
		if (GUILayout.Button("应用/预览", (GUILayoutOption[])(object)new GUILayoutOption[2]
		{
			GUILayout.Height(26f),
			GUILayout.Width(80f)
		}))
		{
			ApplyToPasteTool();
		}
		GUILayout.EndHorizontal();
		_scroll = GUILayout.BeginScrollView(_scroll, Array.Empty<GUILayoutOption>());
		GUILayout.Label("── 1. 坐标偏移(小数点后 4 位)──", GUI.skin.box, Array.Empty<GUILayoutOption>());
		DrawGridRow("X 偏移", ref _ox, "Y 偏移", ref _oy);
		DrawGridRow("Z 偏移(高度)", ref _oz, "重复数量", ref _offCount);
		GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
		if (GUILayout.Button("偏移(净偏移 = 偏移量 × 数量)", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(24f) }))
		{
			DoOffset();
		}
		GUILayout.EndHorizontal();
		GUILayout.Space(6f);
		GUILayout.Label("── 2. 垂直叠加(层高精确到小数点后 4 位)──", GUI.skin.box, Array.Empty<GUILayoutOption>());
		DrawGridRow("叠加层数", ref _layers, "每层高度", ref _layerHeight);
		GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
		if (GUILayout.Button("垂直叠加建筑层数", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(24f) }))
		{
			DoStack();
		}
		GUILayout.EndHorizontal();
		GUILayout.Space(6f);
		GUILayout.Label("── 3. 线性变换(批量设置建筑模型)──", GUI.skin.box, Array.Empty<GUILayoutOption>());
		DrawGridRow("X 缩放", ref _sx, "Y 缩放", ref _sy);
		DrawGridRow("Z 缩放", ref _sz, "旋转(度)", ref _rotDeg);
		GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
		if (GUILayout.Button("应用缩放/旋转", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(24f) }))
		{
			DoLinearTransform();
		}
		GUILayout.EndHorizontal();
		GUILayout.Space(4f);
		DrawGridRow("原建筑ID", ref _replaceFrom, "替换为ID", ref _replaceTo);
		GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
		if (GUILayout.Button("批量替换建筑型号", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(24f) }))
		{
			DoReplace();
		}
		GUILayout.FlexibleSpace();
		GUILayout.EndHorizontal();
		GUILayout.Space(6f);
		GUILayout.Label("── 4. 传送带合并最长化(省带子)──", GUI.skin.box, Array.Empty<GUILayoutOption>());
		GUILayout.Label(string.IsNullOrEmpty(_beltStat) ? "读取蓝图后自动探测传送带长度(合并以此为参考)" : _beltStat, Array.Empty<GUILayoutOption>());
		GUILayout.Label("合并上限按纬度自动适配(赤道 1.8 / 极地 1.6,端点 0.5 格步进,配置文件可调)", Array.Empty<GUILayoutOption>());
		GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
		if (GUILayout.Button("传送带最长化", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(24f) }))
		{
			DoBeltMerge();
		}
		GUILayout.EndHorizontal();
		GUILayout.Space(6f);
		GUILayout.Label("提示:处理结果自动写回游戏剪贴板,可在蓝图粘贴界面直接使用;\"应用/预览\"会直接替换当前蓝图粘贴工具中的蓝图。", GUI.skin.label, Array.Empty<GUILayoutOption>());
		GUILayout.EndScrollView();
		GUILayout.Label(_status, Array.Empty<GUILayoutOption>());
		GUILayout.EndVertical();
		GUI.DragWindow(new Rect(0f, 0f, 10000f, 24f));
	}

	private static void DrawGridRow(string l1, ref string v1, string l2, ref string v2)
	{
		GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
		GUILayout.Label(l1, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(80f) });
		v1 = GUILayout.TextField(v1, Array.Empty<GUILayoutOption>());
		GUILayout.Label(l2, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(80f) });
		v2 = GUILayout.TextField(v2, Array.Empty<GUILayoutOption>());
		GUILayout.EndHorizontal();
	}

	private unsafe void ReadFromClipboard()
	{
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_0031: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			string systemCopyBuffer = GUIUtility.systemCopyBuffer;
			if (string.IsNullOrEmpty(systemCopyBuffer))
			{
				_status = "剪贴板为空";
				return;
			}
			BlueprintData val = BlueprintData.CreateNew();
			BlueprintDataIOError val2 = val.FromBase64String(systemCopyBuffer.Trim());
			if ((int)val2 != 0 || val.buildings == null)
			{
				_status = "读取失败:" + ((object)(*(BlueprintDataIOError*)(&val2))/*cast due to .constrained prefix*/).ToString();
				_bp = null;
				_bpDesc = "(未载入蓝图)";
			}
			else
			{
				_bp = val;
				_bpDesc = $"已载入:{val.shortDesc} | 建筑 {val.buildings.Length} 个";
				AnalyzeBelts();
				_status = "从剪贴板读取成功";
			}
		}
		catch (Exception ex)
		{
			_status = "读取异常:" + ex.Message;
		}
	}

	private void WriteToClipboard()
	{
		if (_bp == null)
		{
			_status = "没有蓝图可写回";
			return;
		}
		try
		{
			_bp.CheckBuildingData();
			GUIUtility.systemCopyBuffer = _bp.ToBase64String();
			_status = $"已写回剪贴板(建筑 {_bp.buildings.Length} 个)";
		}
		catch (Exception ex)
		{
			_status = "写回异常:" + ex.Message;
		}
	}

	private void DoOffset()
	{
		if (!RequireBlueprint())
		{
			return;
		}
		if (!ParseF4(_ox, out var v) | !ParseF4(_oy, out var v2) | !ParseF4(_oz, out var v3) | !int.TryParse(_offCount, out var result))
		{
			_status = "输入格式错误(数值需为合法数字,数量需为整数)";
			return;
		}
		if (result < 1)
		{
			result = 1;
		}
		try
		{
			BlueprintData val = _bp.Clone();
			BlueprintBuilding[] buildings = val.buildings;
			foreach (BlueprintBuilding obj in buildings)
			{
				obj.localOffset_x = R4(obj.localOffset_x + v * (float)result);
				obj.localOffset_y = R4(obj.localOffset_y + v2 * (float)result);
				obj.localOffset_z = R4(obj.localOffset_z + v3 * (float)result);
				obj.localOffset_x2 = R4(obj.localOffset_x2 + v * (float)result);
				obj.localOffset_y2 = R4(obj.localOffset_y2 + v2 * (float)result);
				obj.localOffset_z2 = R4(obj.localOffset_z2 + v3 * (float)result);
			}
			Commit(val, $"坐标偏移完成:({v:F4}, {v2:F4}, {v3:F4}) × {result}");
		}
		catch (Exception ex)
		{
			_status = "偏移异常:" + ex.Message;
		}
	}

	private void DoStack()
	{
		if (!RequireBlueprint())
		{
			return;
		}
		if (!int.TryParse(_layers, out var result) | !ParseF4(_layerHeight, out var v))
		{
			_status = "输入格式错误(层数需为整数,层高需为数字)";
			return;
		}
		if (result < 1)
		{
			result = 1;
		}
		try
		{
			int num = _bp.buildings.Length;
			if ((long)num * (long)result > 15000)
			{
				_status = $"叠加后建筑数 {num * result} 超过上限 {15000}";
				return;
			}
			BlueprintData val = _bp.Clone();
			List<BlueprintBuilding> list = new List<BlueprintBuilding>(val.buildings);
			for (int i = 1; i < result; i++)
			{
				BlueprintData val2 = _bp.Clone();
				BlueprintBuilding[] buildings = val2.buildings;
				foreach (BlueprintBuilding obj in buildings)
				{
					obj.localOffset_z = R4(obj.localOffset_z + v * (float)i);
					obj.localOffset_z2 = R4(obj.localOffset_z2 + v * (float)i);
				}
				list.AddRange(val2.buildings);
			}
			BlueprintBuilding[] array = list.ToArray();
			for (int k = 0; k < array.Length; k++)
			{
				array[k].index = k;
			}
			val.buildings = array;
			Commit(val, $"垂直叠加完成:{result} 层 × 层高 {v:F4},共 {array.Length} 个建筑");
		}
		catch (Exception ex)
		{
			_status = "叠加异常:" + ex.Message;
		}
	}

	private void DoLinearTransform()
	{
		if (!RequireBlueprint())
		{
			return;
		}
		if (!ParseF4(_sx, out var v) | !ParseF4(_sy, out var v2) | !ParseF4(_sz, out var v3) | !float.TryParse(_rotDeg, NumberStyles.Float, CultureInfo.InvariantCulture, out var result))
		{
			_status = "输入格式错误";
			return;
		}
		try
		{
			BlueprintData val = _bp.Clone();
			double num = (double)result * Math.PI / 180.0;
			double num2 = Math.Cos(num);
			double num3 = Math.Sin(num);
			BlueprintBuilding[] buildings = val.buildings;
			foreach (BlueprintBuilding val2 in buildings)
			{
				float num4 = (float)Math.Round(val2.localOffset_x * v, 4);
				float num5 = (float)Math.Round(val2.localOffset_y * v2, 4);
				float localOffset_z = (float)Math.Round(val2.localOffset_z * v3, 4);
				float num6 = (float)Math.Round(val2.localOffset_x2 * v, 4);
				float num7 = (float)Math.Round(val2.localOffset_y2 * v2, 4);
				float localOffset_z2 = (float)Math.Round(val2.localOffset_z2 * v3, 4);
				if (Math.Abs(result) > 0.0001f)
				{
					float num8 = (float)Math.Round((double)num4 * num2 + (double)num5 * num3, 4);
					float num9 = (float)Math.Round((double)(0f - num4) * num3 + (double)num5 * num2, 4);
					num4 = num8;
					num5 = num9;
					float num10 = (float)Math.Round((double)num6 * num2 + (double)num7 * num3, 4);
					float num11 = (float)Math.Round((double)(0f - num6) * num3 + (double)num7 * num2, 4);
					num6 = num10;
					num7 = num11;
					val2.yaw = (float)Math.Round(val2.yaw + result, 4);
				}
				val2.localOffset_x = num4;
				val2.localOffset_y = num5;
				val2.localOffset_z = localOffset_z;
				val2.localOffset_x2 = num6;
				val2.localOffset_y2 = num7;
				val2.localOffset_z2 = localOffset_z2;
			}
			Commit(val, $"线性变换完成:缩放({v:F4}, {v2:F4}, {v3:F4}),旋转 {result:F4}°");
		}
		catch (Exception ex)
		{
			_status = "变换异常:" + ex.Message;
		}
	}

	private void DoReplace()
	{
		if (!RequireBlueprint())
		{
			return;
		}
		if (!short.TryParse(_replaceFrom.Trim(), out var result) || !short.TryParse(_replaceTo.Trim(), out var result2))
		{
			_status = "输入格式错误(建筑 ID 需为整数,如 2001 分拣器)";
			return;
		}
		try
		{
			BlueprintData val = _bp.Clone();
			int num = 0;
			BlueprintBuilding[] buildings = val.buildings;
			foreach (BlueprintBuilding val2 in buildings)
			{
				if (val2.itemId == result)
				{
					val2.itemId = result2;
					val2.modelIndex = (short)((ProtoSet<ItemProto>)(object)LDB.items).Select((int)result2).ModelIndex;
					num++;
				}
			}
			Commit(val, $"批量替换完成:{num} 个建筑从 ID {result} 替换为 {result2}");
		}
		catch (Exception ex)
		{
			_status = "替换异常:" + ex.Message;
		}
	}

	private void DoBeltMerge()
	{
		//IL_012c: 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)
		if (!RequireBlueprint())
		{
			return;
		}
		try
		{
			float num = (float)Math.Round(_maxBeltLengthEntry.Value, 4);
			if (num < 1f)
			{
				num = 1f;
			}
			BlueprintData val = _bp.Clone();
			List<BlueprintBuilding> list = new List<BlueprintBuilding>();
			List<BlueprintBuilding> list2 = new List<BlueprintBuilding>();
			BlueprintBuilding[] buildings = val.buildings;
			foreach (BlueprintBuilding val2 in buildings)
			{
				if (IsBelt(val2))
				{
					list2.Add(val2);
				}
				else
				{
					list.Add(val2);
				}
			}
			if (list2.Count == 0)
			{
				_status = "蓝图中没有传送带( itemId=2001 )";
				return;
			}
			HashSet<BlueprintBuilding> hashSet = new HashSet<BlueprintBuilding>();
			List<BlueprintBuilding> list3 = new List<BlueprintBuilding>();
			float latitudeRadPerGrid = BlueprintUtils.GetLatitudeRadPerGrid(200);
			Dictionary<int, float> dictionary = new Dictionary<int, float>();
			if (val.areas != null)
			{
				BlueprintArea[] areas = val.areas;
				foreach (BlueprintArea val3 in areas)
				{
					dictionary[val3.index] = (float)val3.tropicAnchor * latitudeRadPerGrid;
				}
			}
			float num2 = 0f;
			foreach (BlueprintBuilding item in list2)
			{
				float num3 = Vector3.Distance(new Vector3(item.localOffset_x, item.localOffset_y, item.localOffset_z), new Vector3(item.localOffset_x2, item.localOffset_y2, item.localOffset_z2));
				if (num3 > num2)
				{
					num2 = num3;
				}
			}
			bool flag = num2 > 1.05f;
			Dictionary<long, BlueprintBuilding> dictionary2 = new Dictionary<long, BlueprintBuilding>();
			foreach (BlueprintBuilding item2 in list2)
			{
				if (!(BeltLen(item2) >= 0.0001f))
				{
					dictionary2[BeltCellKey(item2)] = item2;
				}
			}
			foreach (BlueprintBuilding item3 in list2)
			{
				if (!hashSet.Contains(item3))
				{
					float num4 = ComputeBeltLimit(item3, dictionary, latitudeRadPerGrid, 2.3022f, 200, 200f);
					if (!_autoBeltLatEntry.Value)
					{
						num4 = num;
					}
					if (flag)
					{
						num4 = Math.Min(num4, num2);
					}
					MergeBeltChain(item3, list2, dictionary2, hashSet, num4, list3);
				}
			}
			BlueprintBuilding[] array = (BlueprintBuilding[])(object)new BlueprintBuilding[list.Count + list3.Count];
			list.CopyTo(array, 0);
			list3.CopyTo(array, list.Count);
			for (int j = 0; j < array.Length; j++)
			{
				array[j].index = j;
			}
			val.buildings = array;
			int num5 = list2.Count - list3.Count;
			Commit(val, $"传送带最长化完成:{list2.Count} 段 → {list3.Count} 段,省下 {num5} 段带子" + (flag ? $"(按探测上限 {num2:F4})" : "(按纬度/高度自适应)"));
		}
		catch (Exception ex)
		{
			_status = "传送带合并异常:" + ex.Message;
		}
	}

	private float ComputeBeltLimit(BlueprintBuilding b, Dictionary<int, float> areaLatRad, float latRadPerGrid, float maxWorldLen, int segmentCnt, float planetRadius)
	{
		try
		{
			float num = b.localOffset_x2 - b.localOffset_x;
			float num2 = b.localOffset_y2 - b.localOffset_y;
			float num3 = (float)Math.Sqrt(num * num + num2 * num2);
			if (num3 < 0.0001f)
			{
				return 1.8f;
			}
			areaLatRad.TryGetValue(b.areaIndex, out var value);
			value += b.localOffset_y * latRadPerGrid;
			value = Mathf.Clamp(value, -MathF.PI / 2f, MathF.PI / 2f);
			float num4 = 0.2f + 1.3333333f * Math.Max(0f, b.localOffset_z);
			float num5 = planetRadius + num4;
			float num6 = num5 * latRadPerGrid;
			float num7 = num5 * BlueprintUtils.GetLongitudeRadPerGrid(value, segmentCnt);
			float num8 = num / num3;
			float num9 = num2 / num3;
			float num10 = (float)Math.Sqrt(num8 * num8 * num7 * num7 + num9 * num9 * num6 * num6);
			if (num10 < 0.0001f)
			{
				return 1.8f;
			}
			float num11 = maxWorldLen / num10;
			if (float.IsNaN(num11) || num11 < 1f)
			{
				num11 = 1f;
			}
			return (float)Math.Round(num11, 4);
		}
		catch
		{
			return 1.8f;
		}
	}

	private void MergeBeltChain(BlueprintBuilding start, List<BlueprintBuilding> belts, Dictionary<long, BlueprintBuilding> byPos, HashSet<BlueprintBuilding> used, float maxLen, List<BlueprintBuilding> output)
	{
		//IL_0113: 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_011a: Unknown result type (might be due to invalid IL or missing references)
		//IL_011f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0120: Unknown result type (might be due to invalid IL or missing references)
		//IL_0125: Unknown result type (might be due to invalid IL or missing references)
		//IL_005d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0064: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_00bc: 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_01de: 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_01ed: 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_0238: Unknown result type (might be due to invalid IL or missing references)
		//IL_0245: 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_024c: 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_0263: 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_027f: 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_0286: Unknown result type (might be due to invalid IL or missing references)
		//IL_029c: Unknown result type (might be due to invalid IL or missing references)
		//IL_029d: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_02bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_02bd: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c3: 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)
		//IL_02dd: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_02fc: Unknown result type (might be due to invalid IL or missing references)
		//IL_0309: Unknown result type (might be due to invalid IL or missing references)
		//IL_0316: Unknown result type (might be due to invalid IL or missing references)
		//IL_0323: Unknown result type (might be due to invalid IL or missing references)
		//IL_0330: 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_034f: Expected O, but got Unknown
		bool flag = BeltLen(start) < 0.0001f;
		List<BlueprintBuilding> list;
		if (flag)
		{
			list = BuildPerCellRun(start, byPos, used);
		}
		else
		{
			list = new List<BlueprintBuilding> { start };
			used.Add(start);
			BlueprintBuilding val = start;
			Vector3 val2;
			while (true)
			{
				BlueprintBuilding outputObj = val.outputObj;
				if (outputObj == null || !IsBelt(outputObj) || used.Contains(outputObj))
				{
					break;
				}
				val2 = P(outputObj) - P2(val);
				if (((Vector3)(ref val2)).sqrMagnitude > 0.0004f)
				{
					break;
				}
				list.Add(outputObj);
				used.Add(outputObj);
				val = outputObj;
			}
			val = start;
			while (true)
			{
				BlueprintBuilding inputObj = val.inputObj;
				if (inputObj == null || !IsBelt(inputObj) || used.Contains(inputObj))
				{
					break;
				}
				val2 = P(val) - P2(inputObj);
				if (((Vector3)(ref val2)).sqrMagnitude > 0.0004f)
				{
					break;
				}
				list.Insert(0, inputObj);
				used.Add(inputObj);
				val = inputObj;
			}
		}
		if (flag)
		{
			List<BlueprintBuilding> chain = BuildPerCellRun(start, byPos, used);
			MergePerCellChain(chain, maxLen, output);
			return;
		}
		Vector3 val3 = P(start);
		Vector3 val4 = P2(start) - val3;
		float num = 0f;
		foreach (BlueprintBuilding item in list)
		{
			num += BeltLen(item);
		}
		if (((Vector3)(ref val4)).sqrMagnitude < 1E-08f || num <= maxLen)
		{
			output.AddRange(list);
			return;
		}
		int num2 = (int)Math.Round((double)num / 0.5);
		int num3 = (int)Math.Floor((double)maxLen / 0.5);
		if (num3 < 1 || num2 < 2)
		{
			output.AddRange(list);
			return;
		}
		int num4 = (int)Math.Ceiling((double)num2 / (double)num3);
		int num5 = num2 / num4;
		int num6 = num2 % num4;
		Vector3 val5 = ((Vector3)(ref val4)).normalized * 0.5f;
		List<BlueprintBuilding> list2 = new List<BlueprintBuilding>();
		int num7 = 0;
		for (int i = 0; i < num4; i++)
		{
			int num8 = num5 + ((i < num6) ? 1 : 0);
			BlueprintBuilding val6 = list[Math.Min((int)((double)num7 / (double)num2 * (double)list.Count), list.Count - 1)];
			list2.Add(new BlueprintBuilding
			{
				areaIndex = val6.areaIndex,
				localOffset_x = R4(val3.x + val5.x * (float)num7),
				localOffset_y = R4(val3.y + val5.y * (float)num7),
				localOffset_z = R4(val3.z + val5.z * (float)num7),
				localOffset_x2 = R4(val3.x + val5.x * (float)(num7 + num8)),
				localOffset_y2 = R4(val3.y + val5.y * (float)(num7 + num8)),
				localOffset_z2 = R4(val3.z + val5.z * (float)(num7 + num8)),
				pitch = val6.pitch,
				yaw = val6.yaw,
				tilt = val6.tilt,
				itemId = val6.itemId,
				modelIndex = val6.modelIndex,
				filterId = val6.filterId
			});
			num7 += num8;
		}
		Rechain(list2, list);
		output.AddRange(list2);
	}

	private void MergePerCellChain(List<BlueprintBuilding> chain, float maxLen, List<BlueprintBuilding> output)
	{
		//IL_001a: 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_002b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_0086: 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_004f: 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_0060: Unknown result type (might be due to invalid IL or missing references)
		//IL_0065: Unknown result type (might be due to invalid IL or missing references)
		//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
		//IL_0202: Unknown result type (might be due to invalid IL or missing references)
		//IL_020b: Unknown result type (might be due to invalid IL or missing references)
		int count = chain.Count;
		if (count < 3)
		{
			output.AddRange(chain);
			return;
		}
		Vector3 val = P(chain[1]) - P(chain[0]);
		if (((Vector3)(ref val)).sqrMagnitude < 1E-06f && chain.Count > 2)
		{
			val = P(chain[2]) - P(chain[1]);
		}
		if (((Vector3)(ref val)).sqrMagnitude < 1E-06f)
		{
			output.AddRange(chain);
			return;
		}
		float magnitude = ((Vector3)(ref val)).magnitude;
		Vector3 normalized = ((Vector3)(ref val)).normalized;
		HashSet<int> hashSet = new HashSet<int>
		{
			0,
			count - 1
		};
		HashSet<BlueprintBuilding> hashSet2 = new HashSet<BlueprintBuilding>(chain);
		for (int i = 0; i < count; i++)
		{
			BlueprintBuilding val2 = chain[i];
			if ((val2.inputObj != null && !hashSet2.Contains(val2.inputObj)) || (val2.outputObj != null && !hashSet2.Contains(val2.outputObj)))
			{
				hashSet.Add(i);
			}
		}
		List<int> list = hashSet.OrderBy((int x) => x).ToList();
		List<BlueprintBuilding> list2 = new List<BlueprintBuilding>();
		for (int num = 0; num < list.Count - 1; num++)
		{
			int num2 = list[num];
			double num3 = (float)(list[num + 1] - num2) * magnitude;
			list2.Add(chain[num2]);
			if (!(num3 <= (double)maxLen))
			{
				double num4 = Math.Max(0.5, Math.Floor(Math.Min(maxLen, num3) * 2.0) / 2.0);
				double num5 = Math.Ceiling(num3 / num4);
				double num6 = num3 / num5;
				for (int num7 = 1; num7 < (int)num5; num7++)
				{
					double num8 = num6 * (double)num7;
					BlueprintBuilding val3 = CloneBelt(chain[num2 + (int)Math.Round(num8 / (double)magnitude)]);
					Vector3 v = P(chain[num2]) + normalized * (float)num8;
					SetP(val3, v);
					SetP2(val3, v);
					list2.Add(val3);
				}
			}
		}
		list2.Add(chain[count - 1]);
		Rechain(list2, chain);
		output.AddRange(list2);
	}

	private List<BlueprintBuilding> BuildPerCellRun(BlueprintBuilding start, Dictionary<long, BlueprintBuilding> byPos, HashSet<BlueprintBuilding> used)
	{
		List<BlueprintBuilding> list = new List<BlueprintBuilding> { start };
		used.Add(start);
		float z = start.localOffset_z;
		float yaw = start.yaw;
		int[][] array = new int[8][]
		{
			new int[2] { 1, 0 },
			new int[2] { -1, 0 },
			new int[2] { 0, 1 },
			new int[2] { 0, -1 },
			new int[2] { 1, 1 },
			new int[2] { 1, -1 },
			new int[2] { -1, 1 },
			new int[2] { -1, -1 }
		};
		foreach (int[] array2 in array)
		{
			if (Neighbor(start, array2[0], array2[1]) == null)
			{
				continue;
			}
			BlueprintBuilding b = start;
			while (true)
			{
				BlueprintBuilding val = Neighbor(b, array2[0], array2[1]);
				if (val == null)
				{
					break;
				}
				list.Add(val);
				used.Add(val);
				b = val;
			}
			b = start;
			while (true)
			{
				BlueprintBuilding val2 = Neighbor(b, -array2[0], -array2[1]);
				if (val2 == null)
				{
					break;
				}
				list.Insert(0, val2);
				used.Add(val2);
				b = val2;
			}
			break;
		}
		return list;
		BlueprintBuilding Neighbor(BlueprintBuilding val3, int dx, int dy)
		{
			long key = BeltCellKeyOf(Mathf.RoundToInt(val3.localOffset_x * 2f) + dx, Mathf.RoundToInt(val3.localOffset_y * 2f) + dy, z);
			if (!byPos.TryGetValue(key, out var value) || used.Contains(value) || value.yaw != yaw)
			{
				return null;
			}
			return value;
		}
	}

	private static long BeltCellKey(BlueprintBuilding b)
	{
		return BeltCellKeyOf(Mathf.RoundToInt(b.localOffset_x * 2f), Mathf.RoundToInt(b.localOffset_y * 2f), b.localOffset_z);
	}

	private static long BeltCellKeyOf(int x2, int y2, float z)
	{
		int num = (int)Mathf.Round(z * 0.75f);
		return ((long)(x2 + 40000) << 42) | ((long)(y2 + 40000) << 20) | (uint)(num + 5000);
	}

	private static void Rechain(List<BlueprintBuilding> kept, List<BlueprintBuilding> chain)
	{
		if (kept.Count != 0)
		{
			for (int i = 0; i < kept.Count; i++)
			{
				kept[i].outputObj = ((i + 1 < kept.Count) ? kept[i + 1] : chain[chain.Count - 1].outputObj);
				kept[i].inputObj = ((i > 0) ? kept[i - 1] : chain[0].inputObj);
			}
		}
	}

	private static Vector3 P(BlueprintBuilding b)
	{
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		return new Vector3(b.localOffset_x, b.localOffset_y, b.localOffset_z);
	}

	private static Vector3 P2(BlueprintBuilding b)
	{
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		return new Vector3(b.localOffset_x2, b.localOffset_y2, b.localOffset_z2);
	}

	private static void SetP(BlueprintBuilding b, Vector3 v)
	{
		//IL_0001: 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_0023: Unknown result type (might be due to invalid IL or missing references)
		b.localOffset_x = R4(v.x);
		b.localOffset_y = R4(v.y);
		b.localOffset_z = R4(v.z);
	}

	private static void SetP2(BlueprintBuilding b, Vector3 v)
	{
		//IL_0001: 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_0023: Unknown result type (might be due to invalid IL or missing references)
		b.localOffset_x2 = R4(v.x);
		b.localOffset_y2 = R4(v.y);
		b.localOffset_z2 = R4(v.z);
	}

	private static float BeltLen(BlueprintBuilding b)
	{
		//IL_0001: 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)
		return Vector3.Distance(P(b), P2(b));
	}

	private static float CellDist(BlueprintBuilding a, BlueprintBuilding b)
	{
		//IL_0001: 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)
		return Vector3.Distance(P(a), P(b));
	}

	private static float CellDistOf(BlueprintBuilding a, BlueprintBuilding b)
	{
		//IL_0001: 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)
		return Vector3.Distance(P(a), P(b));
	}

	private static BlueprintBuilding CloneBelt(BlueprintBuilding src)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0005: 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_001d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_0035: 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_004d: 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_0066: Expected O, but got Unknown
		return new BlueprintBuilding
		{
			areaIndex = src.areaIndex,
			pitch = src.pitch,
			yaw = src.yaw,
			tilt = src.tilt,
			itemId = src.itemId,
			modelIndex = src.modelIndex,
			filterId = src.filterId,
			parameters = src.parameters
		};
	}

	private void Commit(BlueprintData bp, string message)
	{
		bp.CheckBuildingData();
		_bp = bp;
		_bpDesc = $"当前蓝图 | 建筑 {bp.buildings.Length} 个";
		AnalyzeBelts();
		GUIUtility.systemCopyBuffer = bp.ToBase64String();
		_status = message + ";已写回剪贴板";
	}

	private void AnalyzeBelts()
	{
		//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
		_beltStat = "";
		if (_bp?.buildings == null)
		{
			return;
		}
		int num = 0;
		int num2 = 0;
		float num3 = float.MaxValue;
		float num4 = 0f;
		Dictionary<int, int> dictionary = new Dictionary<int, int>();
		BlueprintBuilding[] buildings = _bp.buildings;
		foreach (BlueprintBuilding val in buildings)
		{
			if (!dictionary.ContainsKey(val.itemId))
			{
				dictionary[val.itemId] = 0;
			}
			dictionary[val.itemId]++;
			if (IsBelt(val))
			{
				num++;
				float num5 = Vector3.Distance(new Vector3(val.localOffset_x, val.localOffset_y, val.localOffset_z), new Vector3(val.localOffset_x2, val.localOffset_y2, val.localOffset_z2));
				if (num5 < 0.0001f)
				{
					num2++;
				}
				if (num5 < num3)
				{
					num3 = num5;
				}
				if (num5 > num4)
				{
					num4 = num5;
				}
			}
		}
		if (num > 0)
		{
			_beltStat = ((num2 == num) ? $"探测到传送带 {num} 段(逐格存储,方向由朝向决定)" : $"探测到传送带 {num} 段,长度 {num3:F4} ~ {num4:F4}(其中首尾重合 {num2} 段)");
		}
		else
		{
			IEnumerable<string> values = from p in dictionary
				orderby p.Key
				select p.Key + "×" + p.Value;
			_beltStat = "未探测到传送带;蓝图物品ID分布: " + string.Join(", ", values);
		}
	}

	private void ApplyToPasteTool()
	{
		if (!RequireBlueprint())
		{
			return;
		}
		try
		{
			UIBlueprintInspector val = (((Object)(object)_inspector != (Object)null) ? _inspector : Object.FindObjectOfType<UIBlueprintInspector>());
			if ((Object)(object)val == (Object)null || _fiPasteTool == null)
			{
				_status = "未找到蓝图粘贴工具(请先打开蓝图界面)";
				return;
			}
			object? value = _fiPasteTool.GetValue(val);
			BuildTool_BlueprintPaste val2 = (BuildTool_BlueprintPaste)((value is BuildTool_BlueprintPaste) ? value : null);
			if (val2 == null)
			{
				_status = "粘贴工具不可用";
				return;
			}
			BlueprintData val3 = _bp.Clone();
			val3.CheckBuildingData();
			val2.blueprint = val3;
			try
			{
				val2.ForceDetermineBP();
			}
			catch
			{
			}
			try
			{
				val2.RefreshBlueprintUI();
			}
			catch
			{
			}
			_status = $"已替换粘贴工具中的蓝图(建筑 {val3.buildings.Length} 个)";
		}
		catch (Exception ex)
		{
			_status = "应用异常:" + ex.Message;
		}
	}

	private bool RequireBlueprint()
	{
		if (_bp != null && _bp.buildings != null)
		{
			return true;
		}
		_status = "请先从剪贴板读取蓝图";
		return false;
	}

	private static float R4(float v)
	{
		return (float)Math.Round(v, 4);
	}
}