Decompiled source of SignalNexus v0.2.13

SignalNexus.dll

Decompiled a day ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Logging;
using CommonAPI.Systems.ModLocalization;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.UI;
using xiaoye97;

[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("SignalNexus")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.2.13.0")]
[assembly: AssemblyInformationalVersion("0.2.13")]
[assembly: AssemblyProduct("SignalNexus")]
[assembly: AssemblyTitle("SignalNexus")]
[assembly: AssemblyVersion("0.2.13.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace SignalNexus
{
	internal static class NexusLookup
	{
		internal static bool TryGetEntity(PlanetFactory factory, int entityId, out EntityData entity)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			entity = default(EntityData);
			if (factory == null || entityId <= 0 || entityId >= factory.entityCursor)
			{
				return false;
			}
			entity = factory.entityPool[entityId];
			if (entity.id == entityId)
			{
				return entity.protoId == Plugin.ItemId;
			}
			return false;
		}

		internal static bool TryGetFromMonitor(PlanetFactory factory, int monitorId, out EntityData entity, out MonitorComponent monitor, out MarkerComponent marker)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: 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_0052: Unknown result type (might be due to invalid IL or missing references)
			entity = default(EntityData);
			monitor = default(MonitorComponent);
			marker = null;
			if (factory?.cargoTraffic?.monitorPool == null || monitorId <= 0 || monitorId >= factory.cargoTraffic.monitorCursor)
			{
				return false;
			}
			monitor = factory.cargoTraffic.monitorPool[monitorId];
			if (monitor.id != monitorId || !TryGetEntity(factory, monitor.entityId, out entity) || entity.markerId <= 0)
			{
				return false;
			}
			marker = factory.digitalSystem.markers[entity.markerId];
			return marker != null;
		}

		internal static void SyncMarkerFromMonitor(PlanetFactory factory, EntityData entity)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: 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_0035: 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)
			if (entity.monitorId > 0 && entity.markerId > 0)
			{
				ref MonitorComponent reference = ref factory.cargoTraffic.monitorPool[entity.monitorId];
				MarkerComponent val = factory.digitalSystem.markers[entity.markerId];
				if (reference.id == entity.monitorId && val != null)
				{
					val.SetDigitalSignalId(reference.digitalSignalId);
				}
			}
		}

		internal static void SyncMonitorFromMarker(PlanetFactory factory, MarkerComponent marker)
		{
			//IL_0016: 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_003d: Unknown result type (might be due to invalid IL or missing references)
			if (factory != null && marker != null && TryGetEntity(factory, marker.entityId, out var entity) && entity.monitorId > 0)
			{
				ref MonitorComponent reference = ref factory.cargoTraffic.monitorPool[entity.monitorId];
				if (reference.id == entity.monitorId)
				{
					((MonitorComponent)(ref reference)).SetDigitalSignalId(marker.digitalSignalId);
				}
			}
		}
	}
	[HarmonyPatch(typeof(UIGame), "OnPlayerInspecteeChange")]
	internal static class NexusInspectPatch
	{
		[HarmonyPrefix]
		[HarmonyPriority(800)]
		private static bool Prefix(UIGame __instance, EObjectType objType, int objId)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			Player mainPlayer = GameMain.mainPlayer;
			PlanetFactory factory = ((mainPlayer != null) ? mainPlayer.factory : null);
			if ((int)objType != 0 || !NexusLookup.TryGetEntity(factory, objId, out var entity) || entity.monitorId <= 0)
			{
				return true;
			}
			try
			{
				__instance.nodeWindow.nodeId = 0;
				__instance.markerWindow.markerId = 0;
				__instance.ShutAllFunctionWindow();
				__instance.ShutPlayerInventory();
				__instance.monitorWindow.monitorId = entity.monitorId;
				Traverse obj = Traverse.Create((object)__instance);
				obj.Field("inspectMarkerId").SetValue((object)0);
				obj.Field("inspectNodeId").SetValue((object)0);
				obj.Field("inspectMonitorId").SetValue((object)entity.monitorId);
				__instance.OpenMonitorWindow();
				Plugin.Log.LogInfo((object)$"Opened Signal Nexus {objId} directly in the combined monitor/beacon window.");
			}
			catch (Exception arg)
			{
				Plugin.Log.LogError((object)$"Signal Nexus direct window routing failed: {arg}");
				return true;
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(PlanetFactory), "CreateEntityLogicComponents")]
	internal static class EntityComponentPatch
	{
		[HarmonyPostfix]
		private static void Postfix(PlanetFactory __instance, int entityId)
		{
			//IL_000c: 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_0050: 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_0015: 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_0076: Unknown result type (might be due to invalid IL or missing references)
			if (NexusLookup.TryGetEntity(__instance, entityId, out var entity))
			{
				if (entity.monitorId <= 0 || entity.markerId <= 0 || entity.powerNodeId <= 0)
				{
					Plugin.Log.LogError((object)$"Signal Nexus entity {entityId} is missing components: monitor={entity.monitorId}, marker={entity.markerId}, node={entity.powerNodeId}.");
				}
				else
				{
					NexusLookup.SyncMarkerFromMonitor(__instance, entity);
				}
			}
		}
	}
	[HarmonyPatch(typeof(UIMonitorWindow))]
	internal static class MonitorWindowPatch
	{
		private const float HoloSectionHeight = 196f;

		private static UIMarkerDesc _embeddedMarker;

		private static Vector2 _originalMonitorSize;

		private static Transform _originalParent;

		private static Vector2 _originalAnchorMin;

		private static Vector2 _originalAnchorMax;

		private static Vector2 _originalPivot;

		private static Vector2 _originalAnchoredPosition;

		private static Vector2 _originalMarkerSize;

		private static RectTransform _advancedRect;

		private static Transform _originalAdvancedParent;

		private static Vector2 _originalAdvancedAnchorMin;

		private static Vector2 _originalAdvancedAnchorMax;

		private static Vector2 _originalAdvancedPivot;

		private static Vector2 _originalAdvancedPosition;

		private static Vector2 _originalAdvancedSize;

		private static CanvasGroup _rootCanvas;

		private static float _originalRootAlpha;

		private static bool _originalRootBlocksRaycasts;

		private static bool _originalRootInteractable;

		private static GameObject _holoHeader;

		private static RectTransform _holoHeaderRect;

		private static float _holoBaseX;

		private static float _holoBaseY;

		private static bool _embedded;

		[HarmonyPostfix]
		[HarmonyPatch("_OnOpen")]
		private static void OpenPostfix(UIMonitorWindow __instance)
		{
			try
			{
				PlanetFactory factory = __instance.factory;
				int value = Traverse.Create((object)__instance).Field<int>("_monitorId").Value;
				if (!NexusLookup.TryGetFromMonitor(factory, value, out var _, out var _, out var marker))
				{
					Hide(__instance);
					return;
				}
				EnsureEmbedded(__instance);
				if ((Object)(object)_embeddedMarker == (Object)null)
				{
					Plugin.Log.LogWarning((object)"Signal Nexus could not find the Holo Beacon settings panel to embed.");
					return;
				}
				((Component)_embeddedMarker).gameObject.SetActive(true);
				_embeddedMarker.advancedSettingsGo.SetActive(true);
				_embeddedMarker.SetData(factory, marker, true);
				InvokeLifecycle(_embeddedMarker, "_OnOpen");
				_embeddedMarker.advancedSettingsGo.SetActive(true);
				_embeddedMarker.advancedCanvasGroup.alpha = 1f;
				_embeddedMarker.advancedCanvasGroup.blocksRaycasts = true;
				_embeddedMarker.advancedCanvasGroup.interactable = true;
				_embeddedMarker.Refresh();
				NexusLookup.SyncMonitorFromMarker(factory, marker);
				ApplyLayout(__instance);
			}
			catch (Exception arg)
			{
				Plugin.Log.LogError((object)$"Signal Nexus isolated a combined-panel opening failure: {arg}");
			}
		}

		[HarmonyFinalizer]
		[HarmonyPatch("_OnOpen")]
		private static Exception OpenFinalizer(UIMonitorWindow __instance, Exception __exception)
		{
			if (__exception == null)
			{
				return null;
			}
			if (!(__exception is NullReferenceException))
			{
				return __exception;
			}
			try
			{
				OpenPostfix(__instance);
			}
			catch (Exception arg)
			{
				Plugin.Log.LogError((object)$"Signal Nexus monitor-window recovery failed: {arg}");
			}
			Plugin.Log.LogWarning((object)string.Format("Signal Nexus suppressed DSP's null speaker-panel failure while opening monitor {0}.", Traverse.Create((object)__instance).Field<int>("_monitorId").Value));
			return null;
		}

		[HarmonyPrefix]
		[HarmonyPatch("_OnClose")]
		private static void ClosePrefix(UIMonitorWindow __instance)
		{
			Hide(__instance);
		}

		[HarmonyPostfix]
		[HarmonyPatch("_OnUpdate")]
		private static void UpdatePostfix(UIMonitorWindow __instance)
		{
			if (_embedded && !((Object)(object)_embeddedMarker == (Object)null))
			{
				InvokeLifecycle(_embeddedMarker, "_OnUpdate");
				ApplyLayout(__instance);
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch("AdaptSpeaker")]
		private static void AdaptSpeakerPostfix(UIMonitorWindow __instance)
		{
			//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)
			if (_embedded)
			{
				_originalMonitorSize = __instance.monitorWindowRect.sizeDelta;
				ApplyLayout(__instance);
			}
		}

		private static void EnsureEmbedded(UIMonitorWindow monitorWindow)
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: 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_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_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: 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_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_02b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c7: 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_02e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_030c: 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_033e: Unknown result type (might be due to invalid IL or missing references)
			//IL_034d: 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_0263: Unknown result type (might be due to invalid IL or missing references)
			//IL_0277: Unknown result type (might be due to invalid IL or missing references)
			if (_embedded)
			{
				return;
			}
			UIMarkerDesc val = UIRoot.instance?.uiGame?.markerWindow?.markerDesc;
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			RectTransform monitorWindowRect = monitorWindow.monitorWindowRect;
			_originalMonitorSize = monitorWindowRect.sizeDelta;
			_embeddedMarker = val;
			RectTransform rectTrans = _embeddedMarker.rectTrans;
			_originalParent = ((Transform)rectTrans).parent;
			_originalAnchorMin = rectTrans.anchorMin;
			_originalAnchorMax = rectTrans.anchorMax;
			_originalPivot = rectTrans.pivot;
			_originalAnchoredPosition = rectTrans.anchoredPosition;
			_originalMarkerSize = rectTrans.sizeDelta;
			Transform transform = ((Component)_embeddedMarker.advancedCanvasGroup).transform;
			_advancedRect = (RectTransform)(object)((transform is RectTransform) ? transform : null);
			if ((Object)(object)_advancedRect == (Object)null)
			{
				return;
			}
			_originalAdvancedParent = ((Transform)_advancedRect).parent;
			_originalAdvancedAnchorMin = _advancedRect.anchorMin;
			_originalAdvancedAnchorMax = _advancedRect.anchorMax;
			_originalAdvancedPivot = _advancedRect.pivot;
			_originalAdvancedPosition = _advancedRect.anchoredPosition;
			_originalAdvancedSize = _advancedRect.sizeDelta;
			_rootCanvas = ((Component)rectTrans).GetComponent<CanvasGroup>() ?? ((Component)rectTrans).gameObject.AddComponent<CanvasGroup>();
			_originalRootAlpha = _rootCanvas.alpha;
			_originalRootBlocksRaycasts = _rootCanvas.blocksRaycasts;
			_originalRootInteractable = _rootCanvas.interactable;
			_rootCanvas.alpha = 0f;
			_rootCanvas.blocksRaycasts = false;
			_rootCanvas.interactable = false;
			Text val2 = ((IEnumerable<Text>)((Component)monitorWindow).GetComponentsInChildren<Text>(true)).FirstOrDefault((Func<Text, bool>)((Text text) => (Object)(object)text != (Object)null && text.text != null && text.text.IndexOf("Alarm settings", StringComparison.OrdinalIgnoreCase) >= 0));
			if ((Object)(object)val2 == (Object)null)
			{
				val2 = ((IEnumerable<Text>)((Component)monitorWindow).GetComponentsInChildren<Text>(true)).FirstOrDefault((Func<Text, bool>)((Text text) => (Object)(object)text != (Object)null && ((Object)((Component)text).gameObject).name.IndexOf("alarm", StringComparison.OrdinalIgnoreCase) >= 0));
			}
			if ((Object)(object)val2 != (Object)null)
			{
				_holoHeader = Object.Instantiate<GameObject>(((Component)val2).gameObject, ((Component)val2).transform.parent);
				((Object)_holoHeader).name = "signal-nexus-holo-settings-header";
				Transform transform2 = _holoHeader.transform;
				_holoHeaderRect = (RectTransform)(object)((transform2 is RectTransform) ? transform2 : null);
				RectTransform rectTransform = ((Graphic)val2).rectTransform;
				((Transform)_holoHeaderRect).SetParent((Transform)(object)monitorWindowRect, true);
				((Transform)_holoHeaderRect).position = ((Transform)rectTransform).position;
				_holoBaseX = _holoHeaderRect.anchoredPosition.x;
				_holoBaseY = _holoHeaderRect.anchoredPosition.y;
				_holoHeader.GetComponent<Text>().text = Localization.Translate("SignalNexusHoloSettings");
			}
			((Transform)rectTrans).SetParent((Transform)(object)monitorWindowRect, false);
			rectTrans.anchorMin = new Vector2(0f, 1f);
			rectTrans.anchorMax = new Vector2(0f, 1f);
			rectTrans.pivot = new Vector2(0f, 1f);
			((Transform)rectTrans).localScale = Vector3.one;
			((Transform)_advancedRect).SetParent((Transform)(object)monitorWindowRect, false);
			_advancedRect.anchorMin = new Vector2(0f, 1f);
			_advancedRect.anchorMax = new Vector2(0f, 1f);
			_advancedRect.pivot = new Vector2(0f, 1f);
			((Transform)_advancedRect).localScale = Vector3.one;
			_embedded = true;
			ApplyLayout(monitorWindow);
			Plugin.Log.LogInfo((object)"Attached Holo Beacon settings beneath the Traffic Monitor alarm settings.");
		}

		private static void ApplyLayout(UIMonitorWindow monitorWindow)
		{
			//IL_0092: 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_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: 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)
			if (_embedded && !((Object)(object)_advancedRect == (Object)null))
			{
				RectTransform monitorWindowRect = monitorWindow.monitorWindowRect;
				float num = (((Object)(object)_holoHeaderRect != (Object)null) ? _holoBaseX : 20f);
				float num2 = (((Object)(object)_holoHeaderRect != (Object)null) ? _holoBaseY : (-344f)) - 92f;
				if ((Object)(object)_holoHeaderRect != (Object)null)
				{
					_holoHeader.SetActive(true);
					_holoHeaderRect.anchoredPosition = new Vector2(num, num2);
				}
				_advancedRect.anchoredPosition = new Vector2(num + 10f, num2 - 22f);
				RectTransform advancedRect = _advancedRect;
				float x = _originalAdvancedSize.x;
				Rect rect = monitorWindowRect.rect;
				advancedRect.sizeDelta = new Vector2(Math.Max(x, ((Rect)(ref rect)).width - 78f), Math.Max(_originalAdvancedSize.y, 176f));
				RectTransform rectTrans = _embeddedMarker.rectTrans;
				rectTrans.anchoredPosition = _advancedRect.anchoredPosition;
				rectTrans.sizeDelta = _advancedRect.sizeDelta;
				monitorWindowRect.sizeDelta = new Vector2(_originalMonitorSize.x, _originalMonitorSize.y + 196f);
			}
		}

		private static void Hide(UIMonitorWindow monitorWindow)
		{
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: 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_0066: 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_0084: 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_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_embeddedMarker == (Object)null) && _embedded)
			{
				if (((Component)_embeddedMarker).gameObject.activeSelf)
				{
					InvokeLifecycle(_embeddedMarker, "_OnClose");
				}
				if ((Object)(object)_advancedRect != (Object)null)
				{
					((Transform)_advancedRect).SetParent(_originalAdvancedParent, false);
					_advancedRect.anchorMin = _originalAdvancedAnchorMin;
					_advancedRect.anchorMax = _originalAdvancedAnchorMax;
					_advancedRect.pivot = _originalAdvancedPivot;
					_advancedRect.anchoredPosition = _originalAdvancedPosition;
					_advancedRect.sizeDelta = _originalAdvancedSize;
				}
				RectTransform rectTrans = _embeddedMarker.rectTrans;
				((Transform)rectTrans).SetParent(_originalParent, false);
				rectTrans.anchorMin = _originalAnchorMin;
				rectTrans.anchorMax = _originalAnchorMax;
				rectTrans.pivot = _originalPivot;
				rectTrans.anchoredPosition = _originalAnchoredPosition;
				rectTrans.sizeDelta = _originalMarkerSize;
				if ((Object)(object)_rootCanvas != (Object)null)
				{
					_rootCanvas.alpha = _originalRootAlpha;
					_rootCanvas.blocksRaycasts = _originalRootBlocksRaycasts;
					_rootCanvas.interactable = _originalRootInteractable;
				}
				_embeddedMarker.advancedSettingsGo.SetActive(false);
				((Component)_embeddedMarker).gameObject.SetActive(false);
				if ((Object)(object)_holoHeader != (Object)null)
				{
					_holoHeader.SetActive(false);
				}
				if (_originalMonitorSize != Vector2.zero)
				{
					monitorWindow.monitorWindowRect.sizeDelta = _originalMonitorSize;
				}
				_embedded = false;
			}
		}

		private static void InvokeLifecycle(object target, string method)
		{
			try
			{
				AccessTools.Method(target.GetType(), method, (Type[])null, (Type[])null)?.Invoke(target, null);
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Signal Nexus UI lifecycle " + method + " failed: " + ex.GetBaseException().Message));
			}
		}
	}
	[HarmonyPatch(typeof(UIMonitorWindow), "TryOpenSpeakerPanel")]
	internal static class MonitorSpeakerPatch
	{
		[HarmonyPrefix]
		[HarmonyPriority(800)]
		private static bool Prefix(UIMonitorWindow __instance)
		{
			try
			{
				OpenSafeSpeakerPanel(__instance);
			}
			catch (Exception arg)
			{
				Plugin.Log.LogError((object)$"Signal Nexus isolated a monitor/speaker opening failure: {arg}");
			}
			return false;
		}

		private static void OpenSafeSpeakerPanel(UIMonitorWindow __instance)
		{
			PlanetFactory factory = __instance.factory;
			CargoTraffic val = __instance.cargoTraffic ?? factory?.cargoTraffic;
			int value = Traverse.Create((object)__instance).Field<int>("_monitorId").Value;
			if (factory == null || val?.monitorPool == null || value <= 0 || value >= val.monitorCursor)
			{
				return;
			}
			ref MonitorComponent reference = ref val.monitorPool[value];
			if (reference.id != value)
			{
				return;
			}
			UISpeakerPanel speakerPanel = __instance.speakerPanel;
			if ((Object)(object)speakerPanel == (Object)null)
			{
				Plugin.Log.LogWarning((object)$"Monitor {value} opened without a UISpeakerPanel; skipping only the speaker subpanel.");
				return;
			}
			MethodInfo methodInfo = AccessTools.Method(typeof(UIMonitorWindow), "AdaptSpeaker", (Type[])null, (Type[])null);
			Action action = ((methodInfo == null) ? null : ((Action)Delegate.CreateDelegate(typeof(Action), __instance, methodInfo)));
			if (reference.alarmMode != 0)
			{
				if (reference.entityId <= 0 || reference.entityId >= factory.entityCursor)
				{
					return;
				}
				ref EntityData reference2 = ref factory.entityPool[reference.entityId];
				if (reference2.id != reference.entityId)
				{
					return;
				}
				DigitalSystem digitalSystem = factory.digitalSystem;
				int num = reference2.speakerId;
				if (digitalSystem != null && (num <= 0 || digitalSystem.speakerPool == null || num >= digitalSystem.speakerCursor || digitalSystem.speakerPool[num].id != num))
				{
					num = (reference.speakerId = (reference2.speakerId = digitalSystem.NewSpeakerComponent(reference2.id)));
					Plugin.Log.LogInfo((object)$"Repaired missing speaker component for monitor entity {reference2.id} (speaker {num}).");
				}
				if (num <= 0)
				{
					return;
				}
				reference.speakerId = num;
				Traverse obj = Traverse.Create((object)speakerPanel);
				obj.Field("factory").SetValue((object)factory);
				obj.Field("digitalSystem").SetValue((object)digitalSystem);
				obj.Field("player").SetValue((object)GameMain.mainPlayer);
				speakerPanel.speakerId = num;
				if (action != null)
				{
					speakerPanel.onWindowChange = (Action)Delegate.Remove(speakerPanel.onWindowChange, action);
					speakerPanel.onWindowChange = (Action)Delegate.Combine(speakerPanel.onWindowChange, action);
				}
				((ManualBehaviour)speakerPanel)._Open();
			}
			else
			{
				if (action != null)
				{
					speakerPanel.onWindowChange = (Action)Delegate.Remove(speakerPanel.onWindowChange, action);
				}
				((ManualBehaviour)speakerPanel)._Close();
			}
			action?.Invoke();
		}
	}
	[HarmonyPatch(typeof(UIMonitorWindow), "OnDigitalSignalIdEndEdit")]
	internal static class MonitorIpPatch
	{
		[HarmonyPostfix]
		private static void Postfix(UIMonitorWindow __instance)
		{
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			PlanetFactory value = Traverse.Create((object)__instance).Field<PlanetFactory>("factory").Value;
			int value2 = Traverse.Create((object)__instance).Field<int>("_monitorId").Value;
			if (NexusLookup.TryGetFromMonitor(value, value2, out var entity, out var _, out var _))
			{
				NexusLookup.SyncMarkerFromMonitor(value, entity);
			}
		}
	}
	[HarmonyPatch(typeof(UIMarkerDesc), "OnDigitalSignalIdEndEdit")]
	internal static class MarkerIpPatch
	{
		[HarmonyPostfix]
		private static void Postfix(UIMarkerDesc __instance)
		{
			PlanetFactory value = Traverse.Create((object)__instance).Field<PlanetFactory>("factory").Value;
			MarkerComponent value2 = Traverse.Create((object)__instance).Field<MarkerComponent>("marker").Value;
			NexusLookup.SyncMonitorFromMarker(value, value2);
		}
	}
	[HarmonyPatch(typeof(UIMarkerTipIcons), "_OnLateUpdate")]
	internal static class MarkerTipGuardPatch
	{
		[HarmonyPrefix]
		private static void Prefix(UIMarkerTipIcons __instance)
		{
			Traverse val = Traverse.Create((object)__instance);
			if (!((Object)(object)val.Field<UIMarkerTip>("markerTip").Value != (Object)null))
			{
				val.Field("hoverIdx").SetValue((object)(-1));
				val.Field("showTipIdx").SetValue((object)(-1));
				val.Field("timer").SetValue((object)0f);
			}
		}
	}
	[HarmonyPatch(typeof(BuildingParameters), "CopyFromFactoryObject")]
	internal static class BuildingCopyPatch
	{
		[HarmonyPostfix]
		private static void Postfix(ref BuildingParameters __instance, int objectId, PlanetFactory factory, bool __result)
		{
			//IL_000e: 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_002c: 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_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_019a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			if (!__result || !NexusLookup.TryGetEntity(factory, objectId, out var entity) || entity.markerId <= 0 || entity.monitorId <= 0)
			{
				return;
			}
			MarkerComponent val = factory.digitalSystem.markers[entity.markerId];
			if (val == null)
			{
				return;
			}
			ref MonitorComponent reference = ref factory.cargoTraffic.monitorPool[entity.monitorId];
			int[] array = new int[128];
			array[0] = reference.targetBeltId;
			array[1] = reference.offset;
			array[2] = reference.targetCargoBytes;
			array[3] = ((MonitorComponent)(ref reference)).curPeriodTickCount;
			array[4] = reference.passOperator;
			array[5] = reference.passColorId;
			array[6] = reference.failColorId;
			array[10] = reference.systemWarningMode;
			array[12] = reference.alarmMode;
			array[14] = reference.cargoFilter;
			array[17] = reference.systemWarningSignalId;
			array[21] = reference.digitalSignalId;
			if (entity.speakerId > 0 && factory.digitalSystem.speakerPool != null && entity.speakerId < factory.digitalSystem.speakerCursor)
			{
				ref SpeakerComponent reference2 = ref factory.digitalSystem.speakerPool[entity.speakerId];
				if (reference2.id == entity.speakerId)
				{
					array[7] = reference2.tone;
					array[8] = reference2.volume;
					array[9] = reference2.pitch;
					array[11] = (reference2.repeat ? 1 : 0);
					array[13] = Mathf.RoundToInt(reference2.length * 10000f);
					array[18] = Mathf.RoundToInt(reference2.falloffRadius0 * 10f);
					array[19] = Mathf.RoundToInt(reference2.falloffRadius1 * 10f);
				}
			}
			__instance.type = (BuildingType)15;
			__instance.mode0 = reference.spawnItemOperator;
			__instance.parameters = array;
			__instance.content = MarkerSettings.Encode(val);
		}
	}
	[HarmonyPatch(typeof(BuildingParameters), "PasteToFactoryObject")]
	internal static class BuildingPastePatch
	{
		[HarmonyPostfix]
		private static void Postfix(BuildingParameters __instance, int objectId, PlanetFactory factory, bool __result)
		{
			//IL_000e: 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_0032: Unknown result type (might be due to invalid IL or missing references)
			if (__result && NexusLookup.TryGetEntity(factory, objectId, out var entity) && entity.markerId > 0)
			{
				MarkerComponent val = factory.digitalSystem.markers[entity.markerId];
				if (val != null)
				{
					MarkerSettings.TryApply(__instance.content, val, factory.entityPool);
				}
			}
		}
	}
	[HarmonyPatch(typeof(BuildTool_Addon), "CreatePrebuilds")]
	internal static class AddonPrebuildContentPatch
	{
		[HarmonyPostfix]
		private static void Postfix(BuildTool_Addon __instance)
		{
			PlanetFactory factory = ((BuildTool)__instance).factory;
			if (factory?.prebuildPool == null || ((BuildTool)__instance).buildPreviews == null)
			{
				return;
			}
			foreach (BuildPreview buildPreview in ((BuildTool)__instance).buildPreviews)
			{
				if (buildPreview?.item == null || ((Proto)buildPreview.item).ID != Plugin.ItemId || buildPreview.objId >= 0 || string.IsNullOrEmpty(buildPreview.content))
				{
					continue;
				}
				int num = -buildPreview.objId;
				if (num > 0 && num < factory.prebuildCursor)
				{
					ref PrebuildData reference = ref factory.prebuildPool[num];
					if (reference.id == num && reference.protoId == Plugin.ItemId)
					{
						reference.content = buildPreview.content;
						Plugin.Log.LogInfo((object)$"Preserved Holo settings on copied Signal Nexus prebuild {num}.");
					}
				}
			}
		}
	}
	[HarmonyPatch(typeof(BuildingParameters), "ApplyPrebuildParametersToEntity")]
	internal static class BuildingApplyPatch
	{
		[HarmonyPostfix]
		private static void Postfix(int entityId, string content, PlanetFactory factory)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			if (NexusLookup.TryGetEntity(factory, entityId, out var entity) && entity.markerId > 0)
			{
				MarkerComponent val = factory.digitalSystem.markers[entity.markerId];
				if (val == null || !MarkerSettings.TryApply(content, val, factory.entityPool))
				{
					NexusLookup.SyncMarkerFromMonitor(factory, entity);
				}
			}
		}
	}
	internal static class MarkerSettings
	{
		private const string Prefix = "SIGNAL_NEXUS_1:";

		internal static string Encode(MarkerComponent marker)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Expected I4, but got Unknown
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Expected I4, but got Unknown
			using MemoryStream memoryStream = new MemoryStream();
			using (BinaryWriter binaryWriter = new BinaryWriter(memoryStream))
			{
				binaryWriter.Write(marker.icon);
				binaryWriter.Write(marker.word ?? string.Empty);
				binaryWriter.Write((int)marker.visibility);
				binaryWriter.Write((int)marker.detailLevel);
				binaryWriter.Write(marker.offline);
				binaryWriter.Write(marker.color);
				binaryWriter.Write(marker.height);
				binaryWriter.Write(marker.radius);
				binaryWriter.Write(marker.digitalSignalId);
				binaryWriter.Write(marker.dfAttractionFlags);
				binaryWriter.Write(marker.name ?? string.Empty);
				binaryWriter.Write(marker.tags ?? string.Empty);
			}
			return "SIGNAL_NEXUS_1:" + Convert.ToBase64String(memoryStream.ToArray());
		}

		internal static bool TryApply(string content, MarkerComponent marker, EntityData[] entities)
		{
			//IL_0058: 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)
			if (string.IsNullOrEmpty(content) || !content.StartsWith("SIGNAL_NEXUS_1:", StringComparison.Ordinal))
			{
				return false;
			}
			try
			{
				using BinaryReader binaryReader = new BinaryReader(new MemoryStream(Convert.FromBase64String(content.Substring("SIGNAL_NEXUS_1:".Length))));
				marker.icon = binaryReader.ReadInt32();
				marker.word = binaryReader.ReadString();
				marker.visibility = (EMarkerVisibility)binaryReader.ReadInt32();
				marker.detailLevel = (EMarkerDetailLevel)binaryReader.ReadInt32();
				marker.offline = binaryReader.ReadBoolean();
				marker.color = binaryReader.ReadByte();
				marker.SetHeight(entities, binaryReader.ReadSingle());
				marker.SetRadius(binaryReader.ReadSingle());
				marker.SetDigitalSignalId(binaryReader.ReadInt32());
				marker.SetDFAttractionFlags(binaryReader.ReadInt32());
				marker.name = binaryReader.ReadString();
				marker.tags = binaryReader.ReadString();
				return true;
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Could not restore Signal Nexus beacon settings: " + ex.Message));
				return false;
			}
		}
	}
	[BepInPlugin("codex.dsp.signal-nexus", "Signal Nexus", "0.2.13")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "codex.dsp.signal-nexus";

		public const string PluginName = "Signal Nexus";

		public const string PluginVersion = "0.2.13";

		private const int PreferredItemId = 9600;

		private const int PreferredRecipeId = 9600;

		private const int PreferredModelId = 722;

		internal static ManualLogSource Log;

		internal static ItemProto TrafficMonitor;

		internal static ItemProto HoloBeacon;

		internal static ItemProto TeslaTower;

		internal static ItemProto NexusItem;

		internal static RecipeProto NexusRecipe;

		internal static ModelProto NexusModel;

		private Harmony _harmony;

		public static int ItemId { get; private set; } = 9600;

		public static int RecipeId { get; private set; } = 9600;

		public static int ModelId { get; private set; } = 722;

		private void Awake()
		{
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			RegisterStrings();
			LDBTool.PreAddDataAction = (Action)Delegate.Combine(LDBTool.PreAddDataAction, new Action(AddPrototypes));
			LDBTool.PostAddDataAction = (Action)Delegate.Combine(LDBTool.PostAddDataAction, new Action(FinishPrototypes));
			_harmony = new Harmony("codex.dsp.signal-nexus");
			_harmony.PatchAll(typeof(EntityComponentPatch));
			_harmony.PatchAll(typeof(NexusInspectPatch));
			_harmony.PatchAll(typeof(MonitorWindowPatch));
			_harmony.PatchAll(typeof(MonitorSpeakerPatch));
			_harmony.PatchAll(typeof(MonitorIpPatch));
			_harmony.PatchAll(typeof(MarkerIpPatch));
			_harmony.PatchAll(typeof(MarkerTipGuardPatch));
			_harmony.PatchAll(typeof(BuildingCopyPatch));
			_harmony.PatchAll(typeof(BuildingPastePatch));
			_harmony.PatchAll(typeof(AddonPrebuildContentPatch));
			_harmony.PatchAll(typeof(BuildingApplyPatch));
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Signal Nexus prototype and combined monitor/beacon UI patches registered.");
		}

		private void OnDestroy()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			LDBTool.PreAddDataAction = (Action)Delegate.Remove(LDBTool.PreAddDataAction, new Action(AddPrototypes));
			LDBTool.PostAddDataAction = (Action)Delegate.Remove(LDBTool.PostAddDataAction, new Action(FinishPrototypes));
		}

		private static void RegisterStrings()
		{
			LocalizationModule.RegisterTranslation("SignalNexusName", "Signal Nexus", "信号枢纽", "Signal Nexus");
			LocalizationModule.RegisterTranslation("SignalNexusDesc", "A belt traffic monitor, Holo Beacon and Tesla Tower integrated into one compact facility. Its shared IP drives the beacon colour from the monitor signal, while the built-in power node connects and powers nearby facilities.", "将传送带流速监测器、全息信标与电力感应塔集成为一体。共享 IP 会使用监测信号控制信标颜色,内置电力节点还能连接并供电给附近设施。", "A belt traffic monitor, Holo Beacon and Tesla Tower integrated into one compact facility.");
			LocalizationModule.RegisterTranslation("SignalNexusRecipeDesc", "Combine three vanilla utility buildings into one Signal Nexus.", "将三种原版功能建筑组合成一个信号枢纽。", "Combine three vanilla utility buildings into one Signal Nexus.");
			LocalizationModule.RegisterTranslation("SignalNexusHoloSettings", "Holo settings", "全息设置", "Holo settings");
		}

		private static void AddPrototypes()
		{
			//IL_037a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0380: Expected O, but got Unknown
			//IL_03b9: Unknown result type (might be due to invalid IL or missing references)
			ItemId = FindFreeId(9600, from proto in ((ProtoSet<ItemProto>)(object)LDB.items).dataArray
				where proto != null
				select ((Proto)proto).ID);
			RecipeId = FindFreeId(9600, from proto in ((ProtoSet<RecipeProto>)(object)LDB.recipes).dataArray
				where proto != null
				select ((Proto)proto).ID);
			ModelId = FindFreeId(722, from proto in ((ProtoSet<ModelProto>)(object)LDB.models).dataArray
				where proto != null
				select ((Proto)proto).ID);
			TrafficMonitor = FindItem("流速器", "Traffic Monitor");
			HoloBeacon = FindItem("激光灯塔", "Holo Beacon");
			TeslaTower = FindItem("电力感应塔", "Tesla Tower");
			if (TrafficMonitor == null || HoloBeacon == null || TeslaTower == null)
			{
				Log.LogError((object)"Signal Nexus could not locate all three vanilla source prototypes.");
				return;
			}
			int gridIndex = FindFreeCraftingGridIndex(TrafficMonitor, ItemId);
			int buildIndex = FindFreeBuildIndex(TrafficMonitor.BuildIndex / 100, ItemId);
			ModelProto val = ((ProtoSet<ModelProto>)(object)LDB.models).Select(TrafficMonitor.ModelIndex);
			if (val == null)
			{
				Log.LogError((object)"Signal Nexus could not locate the Traffic Monitor model prototype.");
				return;
			}
			NexusModel = ShallowClone<ModelProto>(val);
			((Proto)NexusModel).ID = ModelId;
			((Proto)NexusModel).Name = "SignalNexusModel";
			NexusModel.prefabDesc = ShallowClone<PrefabDesc>(val.prefabDesc);
			NexusModel.prefabDesc.modelIndex = ModelId;
			Traverse.Create((object)NexusModel).Field("prewarmed").SetValue((object)false);
			LDBTool.PreAddProto((Proto)(object)NexusModel);
			NexusItem = ShallowClone<ItemProto>(TrafficMonitor);
			((Proto)NexusItem).ID = ItemId;
			((Proto)NexusItem).Name = "SignalNexusName";
			((Proto)NexusItem).name = "Signal Nexus";
			NexusItem.Description = "SignalNexusDesc";
			NexusItem.description = "SignalNexusDesc";
			NexusItem.ModelIndex = ModelId;
			NexusItem.ModelCount = 1;
			NexusItem.BuildIndex = buildIndex;
			NexusItem.GridIndex = gridIndex;
			NexusItem.StackSize = Math.Max(TrafficMonitor.StackSize, 50);
			NexusItem.prefabDesc = NexusModel.prefabDesc;
			NexusItem.handcraft = null;
			NexusItem.maincraft = null;
			NexusItem.handcrafts = new List<RecipeProto>();
			NexusItem.recipes = new List<RecipeProto>();
			NexusItem.makes = new List<RecipeProto>();
			LDBTool.PreAddProto((Proto)(object)NexusItem);
			RecipeProto val2 = new RecipeProto();
			((Proto)val2).ID = RecipeId;
			((Proto)val2).Name = "SignalNexusName";
			((Proto)val2).name = "Signal Nexus";
			val2.Description = "SignalNexusRecipeDesc";
			val2.description = "SignalNexusRecipeDesc";
			val2.Type = (ERecipeType)4;
			val2.Handcraft = true;
			val2.Explicit = false;
			val2.TimeSpend = 120;
			val2.Items = new int[3]
			{
				((Proto)TrafficMonitor).ID,
				((Proto)HoloBeacon).ID,
				((Proto)TeslaTower).ID
			};
			val2.ItemCounts = new int[3] { 1, 1, 1 };
			val2.Results = new int[1] { ItemId };
			val2.ResultCounts = new int[1] { 1 };
			val2.GridIndex = NexusItem.GridIndex;
			val2.preTech = HoloBeacon.preTech ?? TrafficMonitor.preTech;
			NexusRecipe = val2;
			LDBTool.PreAddProto((Proto)(object)NexusRecipe);
			NexusItem.handcraft = NexusRecipe;
			NexusItem.maincraft = NexusRecipe;
			NexusItem.handcrafts.Add(NexusRecipe);
			NexusItem.recipes.Add(NexusRecipe);
			Log.LogInfo((object)$"Registered Signal Nexus item {ItemId}, recipe {RecipeId}, model {ModelId}; temporary grid {NexusItem.GridIndex}, build {NexusItem.BuildIndex}. Traffic Monitor remains untouched.");
		}

		private static int FindFreeId(int preferred, IEnumerable<int> occupiedIds)
		{
			HashSet<int> hashSet = new HashSet<int>(occupiedIds);
			for (int i = preferred; i < preferred + 300; i++)
			{
				if (!hashSet.Contains(i))
				{
					return i;
				}
			}
			throw new InvalidOperationException($"Signal Nexus could not find a free prototype ID in {preferred}-{preferred + 300 - 1}.");
		}

		private static void FinishPrototypes()
		{
			//IL_0172: 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_01f6: 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_01fb: Unknown result type (might be due to invalid IL or missing references)
			NexusItem = ((ProtoSet<ItemProto>)(object)LDB.items).Select(ItemId);
			NexusRecipe = ((ProtoSet<RecipeProto>)(object)LDB.recipes).Select(RecipeId);
			NexusModel = ((ProtoSet<ModelProto>)(object)LDB.models).Select(ModelId);
			if (NexusItem != null && NexusRecipe != null && NexusModel != null && TrafficMonitor != null && HoloBeacon != null && TeslaTower != null)
			{
				int num = FindFreeCraftingGridIndex(TrafficMonitor, ItemId);
				int num2 = FindFreeBuildIndex(TrafficMonitor.BuildIndex / 100, ItemId);
				NexusItem.GridIndex = num;
				NexusRecipe.GridIndex = num;
				NexusItem.BuildIndex = num2;
				LDBTool.SetBuildBar(num2 / 100, num2 % 100, ItemId);
				PrefabDesc prefabDesc = TrafficMonitor.prefabDesc;
				PrefabDesc prefabDesc2 = HoloBeacon.prefabDesc;
				PrefabDesc prefabDesc3 = TeslaTower.prefabDesc;
				PrefabDesc val = ShallowClone<PrefabDesc>(prefabDesc);
				val.modelIndex = ModelId;
				val.dragBuild = false;
				val.isMonitor = true;
				val.isSpeaker = true;
				val.isMarker = true;
				val.markerPointDefaultHeight = prefabDesc2.markerPointDefaultHeight;
				val.markerPointDefaultRadius = prefabDesc2.markerPointDefaultRadius;
				val.isPowerNode = true;
				val.powerConnectDistance = prefabDesc3.powerConnectDistance;
				val.powerCoverRadius = prefabDesc3.powerCoverRadius;
				val.powerPoint = new Vector3(0f, Math.Max(1.7f, prefabDesc.roughHeight), 0f);
				val.isPowerConsumer = true;
				val.workEnergyPerTick = Math.Max(1L, prefabDesc.workEnergyPerTick + prefabDesc2.workEnergyPerTick);
				val.idleEnergyPerTick = Math.Max(1L, prefabDesc.idleEnergyPerTick + prefabDesc2.idleEnergyPerTick);
				TryBuildCompositeMeshes(val, prefabDesc, prefabDesc2);
				NexusModel.prefabDesc = val;
				NexusModel.meshBounds = (((Object)(object)val.mesh != (Object)null) ? val.mesh.bounds : NexusModel.meshBounds);
				NexusItem.prefabDesc = val;
				NexusItem.ModelIndex = ModelId;
				Sprite value = CreateIcon();
				Traverse.Create((object)NexusItem).Field("_iconSprite").SetValue((object)value);
				Traverse.Create((object)NexusRecipe).Field("_iconSprite").SetValue((object)value);
				NexusRecipe.IconPath = string.Empty;
				Log.LogInfo((object)$"Signal Nexus ready at grid {num}, build {num2}: monitor + marker + {val.powerConnectDistance:0.#}m power connection / {val.powerCoverRadius:0.#}m coverage. Traffic Monitor grid {TrafficMonitor.GridIndex}, build {TrafficMonitor.BuildIndex}.");
			}
		}

		private static ItemProto FindItem(params string[] names)
		{
			return ((IEnumerable<ItemProto>)((ProtoSet<ItemProto>)(object)LDB.items).dataArray).FirstOrDefault((Func<ItemProto, bool>)((ItemProto item) => item != null && names.Any((string name) => string.Equals(((Proto)item).Name, name, StringComparison.OrdinalIgnoreCase) || string.Equals(((Proto)item).name, name, StringComparison.OrdinalIgnoreCase))));
		}

		private static int FindFreeCraftingGridIndex(ItemProto template, int excludedItemId)
		{
			HashSet<int> hashSet = new HashSet<int>(from item in ((ProtoSet<ItemProto>)(object)LDB.items).dataArray
				where item != null && ((Proto)item).ID != excludedItemId && item.Type == template.Type
				select item.GridIndex);
			int baseRow = Math.Max(1, Math.Min(8, (template.GridIndex - 2000) / 100));
			int baseColumn = Math.Max(1, Math.Min(14, template.GridIndex % 100));
			foreach (var item in from slot in Enumerable.Range(1, 8).SelectMany((int row) => from column in Enumerable.Range(1, 14)
					select new { row, column })
				orderby Math.Abs(slot.row - baseRow) + Math.Abs(slot.column - baseColumn), slot.row, slot.column
				select slot)
			{
				int num = 2000 + item.row * 100 + item.column;
				if (!hashSet.Contains(num))
				{
					return num;
				}
			}
			return 2814;
		}

		private static int NextBuildIndex()
		{
			return (from x in ((ProtoSet<ItemProto>)(object)LDB.items).dataArray
				where x != null
				select x.BuildIndex).DefaultIfEmpty(700).Max() + 1;
		}

		private static int FindFreeBuildIndex(int preferredCategory, int excludedItemId = 0)
		{
			HashSet<int> hashSet = new HashSet<int>(from item in ((ProtoSet<ItemProto>)(object)LDB.items).dataArray
				where item != null && ((Proto)item).ID != excludedItemId && item.BuildIndex > 0
				select item.BuildIndex);
			if (preferredCategory >= 1 && preferredCategory <= 15)
			{
				for (int num = 12; num >= 1; num--)
				{
					int num2 = preferredCategory * 100 + num;
					if (!hashSet.Contains(num2))
					{
						return num2;
					}
				}
			}
			for (int num3 = 12; num3 >= 1; num3--)
			{
				for (int num4 = 12; num4 >= 1; num4--)
				{
					int num5 = num3 * 100 + num4;
					if (!hashSet.Contains(num5))
					{
						return num5;
					}
				}
			}
			return NextBuildIndex();
		}

		internal static T ShallowClone<T>(T source) where T : class
		{
			if (source == null)
			{
				return null;
			}
			return (T)AccessTools.Method(typeof(object), "MemberwiseClone", (Type[])null, (Type[])null).Invoke(source, null);
		}

		private static void TryBuildCompositeMeshes(PrefabDesc target, PrefabDesc traffic, PrefabDesc marker)
		{
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Expected O, but got Unknown
			//IL_027b: 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)
			try
			{
				if (traffic.lodMeshes == null || marker.lodMeshes == null)
				{
					return;
				}
				int num = Math.Max(traffic.lodMeshes.Length, marker.lodMeshes.Length);
				target.lodMeshes = (Mesh[])(object)new Mesh[num];
				target.lodMaterials = new Material[num][];
				target.lodBlueprintMaterials = new Material[num][];
				target.lodSubmeshIgnores = new bool[num][];
				Matrix4x4 transform = Matrix4x4.TRS(new Vector3(0f, Math.Max(0.75f, traffic.roughHeight * 0.55f), 0f), Quaternion.identity, Vector3.one * 0.34f);
				for (int i = 0; i < num; i++)
				{
					Mesh val = traffic.lodMeshes[Math.Min(i, traffic.lodMeshes.Length - 1)];
					Mesh val2 = marker.lodMeshes[Math.Min(i, marker.lodMeshes.Length - 1)];
					if (!((Object)(object)val == (Object)null) && !((Object)(object)val2 == (Object)null))
					{
						List<CombineInstance> list = new List<CombineInstance>();
						AddSubmeshes(list, val, Matrix4x4.identity);
						AddSubmeshes(list, val2, transform);
						Mesh val3 = new Mesh
						{
							name = $"Signal Nexus LOD {i}"
						};
						val3.CombineMeshes(list.ToArray(), false, true);
						val3.RecalculateBounds();
						target.lodMeshes[i] = val3;
						Material[] lodMaterials = GetLodMaterials(traffic.lodMaterials, i);
						Material[] lodMaterials2 = GetLodMaterials(marker.lodMaterials, i);
						target.lodMaterials[i] = lodMaterials.Concat(lodMaterials2).ToArray();
						Material[] lodMaterials3 = GetLodMaterials(traffic.lodBlueprintMaterials, i, lodMaterials);
						Material[] lodMaterials4 = GetLodMaterials(marker.lodBlueprintMaterials, i, lodMaterials2);
						target.lodBlueprintMaterials[i] = lodMaterials3.Concat(lodMaterials4).ToArray();
						target.lodSubmeshIgnores[i] = new bool[target.lodMaterials[i].Length];
					}
				}
				target.mesh = ((IEnumerable<Mesh>)target.lodMeshes).FirstOrDefault((Func<Mesh, bool>)((Mesh x) => (Object)(object)x != (Object)null)) ?? traffic.mesh;
				target.meshes = (Mesh[])((!((Object)(object)target.mesh != (Object)null)) ? ((Array)traffic.meshes) : ((Array)new Mesh[1] { target.mesh }));
				target.materials = target.lodMaterials.FirstOrDefault((Material[] x) => x != null) ?? traffic.materials;
				target.roughHeight = Math.Max(traffic.roughHeight, ((Matrix4x4)(ref transform)).MultiplyPoint3x4(Vector3.up * marker.roughHeight).y);
				target.cullingHeight = Math.Max(traffic.cullingHeight, target.roughHeight);
				Log.LogInfo((object)"Built the Traffic Monitor + roof Holo Beacon composite mesh.");
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("Composite mesh creation failed; using the Traffic Monitor body: " + ex.Message));
			}
		}

		private static void AddSubmeshes(List<CombineInstance> output, Mesh mesh, Matrix4x4 transform)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			for (int i = 0; i < mesh.subMeshCount; i++)
			{
				CombineInstance item = default(CombineInstance);
				((CombineInstance)(ref item)).mesh = mesh;
				((CombineInstance)(ref item)).subMeshIndex = i;
				((CombineInstance)(ref item)).transform = transform;
				output.Add(item);
			}
		}

		private static Material[] GetLodMaterials(Material[][] source, int lod, Material[] fallback = null)
		{
			if (source == null || source.Length == 0)
			{
				return fallback ?? Array.Empty<Material>();
			}
			return source[Math.Min(lod, source.Length - 1)] ?? fallback ?? Array.Empty<Material>();
		}

		private static Sprite CreateIcon()
		{
			//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_0016: 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_0025: Expected O, but got Unknown
			//IL_003b: 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_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: 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_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			//IL_0236: 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_01e6: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val = new Texture2D(80, 80, (TextureFormat)5, false)
			{
				name = "Signal Nexus Icon",
				filterMode = (FilterMode)1,
				wrapMode = (TextureWrapMode)1
			};
			Color[] pixels = Enumerable.Repeat<Color>(new Color(0f, 0f, 0f, 0f), 6400).ToArray();
			Color color = default(Color);
			((Color)(ref color))..ctor(0.035f, 0.12f, 0.15f, 1f);
			Color color2 = default(Color);
			((Color)(ref color2))..ctor(0.15f, 0.9f, 1f, 1f);
			Color color3 = default(Color);
			((Color)(ref color3))..ctor(0.22f, 1f, 0.42f, 1f);
			Color color4 = default(Color);
			((Color)(ref color4))..ctor(0.9f, 1f, 1f, 1f);
			Rect(13, 10, 66, 35, color);
			Rect(10, 15, 69, 30, color);
			Rect(17, 14, 62, 31, color2);
			Rect(21, 18, 58, 27, new Color(0.02f, 0.2f, 0.24f, 1f));
			for (int i = 24; i < 57; i += 7)
			{
				Rect(i, 19, i + 2, 26, color3);
			}
			Rect(35, 35, 44, 51, color4);
			Disc(40, 57, 12, new Color(0.1f, 0.55f, 0.38f, 1f));
			Disc(40, 57, 8, color3);
			Disc(40, 57, 3, color4);
			for (int j = 16; j <= 27; j += 6)
			{
				for (int k = 0; k < 360; k += 8)
				{
					float num = (float)k * (MathF.PI / 180f);
					Pixel(40 + Mathf.RoundToInt(Mathf.Cos(num) * (float)j), 57 + Mathf.RoundToInt(Mathf.Sin(num) * (float)j * 0.45f), new Color(0.15f, 1f, 0.45f, 0.72f));
				}
			}
			val.SetPixels(pixels);
			val.Apply(false, true);
			return Sprite.Create(val, new Rect(0f, 0f, 80f, 80f), new Vector2(0.5f, 0.5f), 100f);
			void Disc(int cx, int cy, int radius, Color color5)
			{
				//IL_001c: Unknown result type (might be due to invalid IL or missing references)
				for (int l = -radius; l <= radius; l++)
				{
					for (int m = -radius; m <= radius; m++)
					{
						if (m * m + l * l <= radius * radius)
						{
							Pixel(cx + m, cy + l, color5);
						}
					}
				}
			}
			void Pixel(int x, int y, Color val2)
			{
				//IL_0016: 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)
				if ((uint)x < 80u && (uint)y < 80u)
				{
					pixels[y * 80 + x] = val2;
				}
			}
			void Rect(int x0, int y0, int x1, int y1, Color color5)
			{
				//IL_000a: Unknown result type (might be due to invalid IL or missing references)
				for (int l = y0; l <= y1; l++)
				{
					for (int m = x0; m <= x1; m++)
					{
						Pixel(m, l, color5);
					}
				}
			}
		}
	}
}