Decompiled source of ShipSystems v1.0.0

Y4NGZShipSystems.dll

Decompiled 21 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Cryptography;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using Dawn;
using GameNetcodeStuff;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using Unity.AI.Navigation;
using Unity.Collections;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.Audio;
using UnityEngine.Events;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.Networking;
using UnityEngine.Rendering;
using UnityEngine.Rendering.HighDefinition;
using UnityEngine.Rendering.RendererUtils;
using UnityEngine.SceneManagement;
using UnityEngine.TextCore;
using UnityEngine.UI;
using Y4NGZCompany.Bootstrap;
using Y4NGZCompany.Core;
using Y4NGZCompany.Core.Compat;
using Y4NGZCompany.Experience.Fonts;
using Y4NGZCompany.Experience.UITheme;
using Y4NGZCompany.Facility.Shared;
using Y4NGZCompany.ShipSystems.Assets;
using Y4NGZCompany.ShipSystems.Fuel;
using Y4NGZCompany.ShipSystems.Fuel.Economy;
using Y4NGZCompany.ShipSystems.Layout;
using Y4NGZCompany.ShipSystems.Power;
using Y4NGZCompany.ShipSystems.Rendering;
using Y4NGZCompany.ShipSystems.Rendering.Outlines;
using Y4NGZCompany.ShipSystems.ShipTerminal;
using Y4NGZCompany.ShipSystems.Store;
using Y4NGZCompany.ShipSystems.Turret;
using Y4NGZCompany.ShipSystems.Upgrades.BatteryShield;
using Y4NGZCompany.ShipSystems.Upgrades.Beacon;
using Y4NGZCompany.ShipSystems.Upgrades.DoorCapacitor;
using Y4NGZCompany.ShipSystems.Upgrades.FlashlightShelf;
using Y4NGZCompany.ShipSystems.Upgrades.FuelEfficiency;
using Y4NGZCompany.ShipSystems.Upgrades.PaintJobs;
using Y4NGZCompany.ShipSystems.Upgrades.ReserveCell;
using Y4NGZCompany.ShipSystems.Upgrades.ShipCameras.Compatibility;
using Y4NGZCompany.ShipSystems.Upgrades.SurgeGuard;
using Y4NGZCompany.TerminalCompatibility;
using Y4NGZCore.Diagnostics;
using Y4NGZCore.Lifecycle;
using Y4NGZCore.Modules;
using Y4NGZCore.Modules.Environment;
using Y4NGZCore.Modules.Hud;
using Y4NGZCore.Modules.Layout;
using Y4NGZCore.Modules.Monitor;
using Y4NGZCore.Modules.Net;
using Y4NGZCore.Modules.Objectives;
using Y4NGZCore.Modules.Presentation;
using Y4NGZCore.Modules.Quota;
using Y4NGZCore.Modules.Routes;
using Y4NGZCore.Modules.Security;
using Y4NGZCore.Modules.ShipSystems;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("AmazingAssets.TerrainToMesh")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp-firstpass")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: IgnoresAccessChecksTo("ClientNetworkTransform")]
[assembly: IgnoresAccessChecksTo("com.olegknyazev.softmask")]
[assembly: IgnoresAccessChecksTo("DissonanceVoip")]
[assembly: IgnoresAccessChecksTo("DunGen")]
[assembly: IgnoresAccessChecksTo("DunGen.Integration.ASPP")]
[assembly: IgnoresAccessChecksTo("DunGen.Integration.UnityNav")]
[assembly: IgnoresAccessChecksTo("EasyTextEffects")]
[assembly: IgnoresAccessChecksTo("Facepunch Transport for Netcode for GameObjects")]
[assembly: IgnoresAccessChecksTo("Facepunch.Steamworks.Win64")]
[assembly: IgnoresAccessChecksTo("Unity.AI.Navigation")]
[assembly: IgnoresAccessChecksTo("Unity.Animation.Rigging")]
[assembly: IgnoresAccessChecksTo("Unity.Animation.Rigging.DocCodeExamples")]
[assembly: IgnoresAccessChecksTo("Unity.Burst")]
[assembly: IgnoresAccessChecksTo("Unity.Burst.Unsafe")]
[assembly: IgnoresAccessChecksTo("Unity.Collections")]
[assembly: IgnoresAccessChecksTo("Unity.Collections.LowLevel.ILSupport")]
[assembly: IgnoresAccessChecksTo("Unity.InputSystem")]
[assembly: IgnoresAccessChecksTo("Unity.InputSystem.ForUI")]
[assembly: IgnoresAccessChecksTo("Unity.Jobs")]
[assembly: IgnoresAccessChecksTo("Unity.Mathematics")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.Common")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.MetricTypes")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStats")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Component")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Configuration")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Implementation")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsReporting")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetworkProfiler.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetworkSolutionInterface")]
[assembly: IgnoresAccessChecksTo("Unity.Netcode.Components")]
[assembly: IgnoresAccessChecksTo("Unity.Netcode.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.Networking.Transport")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Csg")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder.KdTree")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Poly2Tri")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Stl")]
[assembly: IgnoresAccessChecksTo("Unity.Profiling.Core")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.ShaderLibrary")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.HighDefinition.Config.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.HighDefinition.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.ShaderGraph.ShaderGraphLibrary")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Authentication")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Analytics")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Components")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Configuration")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Device")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Environments")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Environments.Internal")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Internal")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Networking")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Registration")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Scheduler")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Telemetry")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Threading")]
[assembly: IgnoresAccessChecksTo("Unity.Services.QoS")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Relay")]
[assembly: IgnoresAccessChecksTo("Unity.TextMeshPro")]
[assembly: IgnoresAccessChecksTo("Unity.Timeline")]
[assembly: IgnoresAccessChecksTo("Unity.VisualEffectGraph.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.XR.CoreUtils")]
[assembly: IgnoresAccessChecksTo("Unity.XR.Management")]
[assembly: IgnoresAccessChecksTo("Unity.XR.OpenXR")]
[assembly: IgnoresAccessChecksTo("Unity.XR.OpenXR.Features.ConformanceAutomation")]
[assembly: IgnoresAccessChecksTo("Unity.XR.OpenXR.Features.MetaQuestSupport")]
[assembly: IgnoresAccessChecksTo("Unity.XR.OpenXR.Features.MockRuntime")]
[assembly: IgnoresAccessChecksTo("Unity.XR.OpenXR.Features.OculusQuestSupport")]
[assembly: IgnoresAccessChecksTo("Unity.XR.OpenXR.Features.RuntimeDebugger")]
[assembly: IgnoresAccessChecksTo("UnityEngine.ARModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.NVIDIAModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.SpatialTracking")]
[assembly: IgnoresAccessChecksTo("UnityEngine.UI")]
[assembly: IgnoresAccessChecksTo("UnityEngine.XR.LegacyInputHelpers")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("Y4NGZShipSystems")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("ShipSystems: fuel-priced travel, collectible fuel, fuel monitor and chute, battery sabotage and apparatus recovery, Wider Ship / Two-Story Ship refits and an optional custom terminal")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+e071550df30750a4ec361e6f04ecb815d327e6f2")]
[assembly: AssemblyProduct("ShipSystems")]
[assembly: AssemblyTitle("Y4NGZShipSystems")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[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 Y4NGZCompany.TerminalCompatibility
{
	internal static class MoonCatalogueDetailRow
	{
		private static readonly Regex OwnedRow = new Regex("^  (?=<color=)(?:(?<contract><color=#00D7E6>Contract: [^<>\\r\\n]+</color>)(?: \\| )?)?(?<fuel><color=#EFB939>Fuel: [^<>\\r\\n]+</color>)?\\r?$", RegexOptions.CultureInvariant);

		internal static bool HasDetails(string text)
		{
			if (string.IsNullOrEmpty(text))
			{
				return false;
			}
			string[] array = text.Split('\n');
			foreach (string input in array)
			{
				if (OwnedRow.IsMatch(input))
				{
					return true;
				}
			}
			return false;
		}

		internal static bool TryRead(string line, out string contractField, out string fuelField)
		{
			Match match = OwnedRow.Match(line);
			contractField = match.Groups["contract"].Value;
			fuelField = match.Groups["fuel"].Value;
			return match.Success;
		}

		internal static string Field(string value, bool contract)
		{
			string text = value?.Replace("<", "").Replace(">", "").Replace("\r", " ")
				.Replace("\n", " ");
			if (!string.IsNullOrWhiteSpace(text))
			{
				if (!contract)
				{
					return "<color=#EFB939>Fuel: " + text + "</color>";
				}
				return "<color=#00D7E6>Contract: " + text + "</color>";
			}
			return string.Empty;
		}

		internal static string Join(string contractField, string fuelField)
		{
			return contractField + ((contractField.Length > 0 && fuelField.Length > 0) ? " | " : "") + fuelField;
		}

		internal static string Annotate(string text, Func<string, string> resolve, bool contract)
		{
			if (string.IsNullOrEmpty(text))
			{
				return text;
			}
			string[] array = text.Split('\n');
			List<string> list = new List<string>(array.Length);
			for (int i = 0; i < array.Length; i++)
			{
				string text2 = array[i];
				list.Add(text2);
				string text3 = resolve(text2);
				Match match = ((i + 1 < array.Length) ? OwnedRow.Match(array[i + 1]) : Match.Empty);
				if (text3 != null || match.Success)
				{
					string contractField = (match.Success ? match.Groups["contract"].Value : string.Empty);
					string fuelField = (match.Success ? match.Groups["fuel"].Value : string.Empty);
					if (match.Success)
					{
						i++;
					}
					string text4 = Field(text3, contract);
					if (contract)
					{
						contractField = text4;
					}
					else
					{
						fuelField = text4;
					}
					string text5 = Join(contractField, fuelField);
					if (text5.Length > 0)
					{
						list.Add("  " + text5 + (text2.EndsWith("\r", StringComparison.Ordinal) ? "\r" : ""));
					}
				}
			}
			return string.Join("\n", list);
		}
	}
	internal static class MoonCatalogueColumns
	{
		private sealed class Row
		{
			internal int Index;

			internal string Base;

			internal string Name;

			internal string Contract;

			internal string Weather;

			internal string Ending;

			internal bool HasWeather;

			internal Match Fuel;
		}

		private const string GapLink = "y4ngz.catalogue-gap";

		private static readonly Regex Gap = new Regex(" ?<link=\"y4ngz.catalogue-gap\"><space=[0-9.]+></link>", RegexOptions.CultureInvariant);

		private static readonly Regex Contract = new Regex("<color=#00D7E6>\\[(?<value>[^<>\\r\\n\\]]+)\\]</color>", RegexOptions.CultureInvariant);

		private static readonly Regex RawFuel = new Regex("<color=#FF5220>FUEL (?<value>[^<>\\r\\n]+)</color>", RegexOptions.CultureInvariant);

		private static readonly Regex RenderedFuel = new Regex("(?<owned><link=\"y4ngz.catalogue-fuel\">)?<pos=100%><space=-[0-9.]+><color=#EFB939>(?<icon><sprite name=\"ship_fuel\" tint=1>|FUEL)(?<value>[^<>\\r\\n]+)</color>(?(owned)</link>)", RegexOptions.CultureInvariant);

		private static readonly Regex Tags = new Regex("<[^>]*>", RegexOptions.CultureInvariant);

		private static readonly Regex MoonRow = new Regex("^(?:\\s|<[^>]*>)*\\*", RegexOptions.CultureInvariant);

		private static readonly Regex ForeignLayout = new Regex("<(?:pos|space|indent|line-indent|width|align|margin|size|mspace|cspace|sprite|link|font|b|i|voffset|rotate|nobr|style)\\b", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant);

		private static readonly Regex Weather = new Regex("^(?:(?:\\([^()\\r\\n]+\\)|\\[planetTime\\])\\s*)*$", RegexOptions.CultureInvariant);

		internal static string RemoveLayout(string text)
		{
			if (!string.IsNullOrEmpty(text))
			{
				return Gap.Replace(text, " ");
			}
			return text;
		}

		internal static string RestoreFuel(string text)
		{
			if (!string.IsNullOrEmpty(text))
			{
				return RenderedFuel.Replace(text, (Match m) => "<color=#FF5220>FUEL " + m.Groups["value"].Value + "</color>");
			}
			return text;
		}

		internal static string RemoveFuel(string line)
		{
			return RemoveMatches(RemoveMatches(line, RenderedFuel), RawFuel);
		}

		internal static bool RequiresDetails(string text, Func<string, int> nameEnd)
		{
			if (ForeignLayout.IsMatch(RemoveFuel(text)))
			{
				return true;
			}
			string[] array = text.Split('\n');
			foreach (string text2 in array)
			{
				int num = nameEnd(text2);
				if (num >= 0 && !IsWeather(RemoveMatches(RemoveFuel(text2.Substring(num)), Contract)))
				{
					return true;
				}
			}
			return false;
		}

		internal static string RenderFuel(string text, string icon, Func<string, float> measure)
		{
			return RawFuel.Replace(text, delegate(Match m)
			{
				string text2 = icon + m.Groups["value"].Value;
				float num = measure(text2) + 2f;
				return (!Finite(num) || num <= 0f) ? m.Value : ("<link=\"y4ngz.catalogue-fuel\"><pos=100%><space=-" + Number(num) + "><color=#EFB939>" + text2 + "</color></link>");
			});
		}

		internal static string FixedFuelCell(string digits, string icon, int width)
		{
			int num = digits.Length + ((icon.Length > 0) ? 1 : 0);
			return new string(' ', Math.Max(0, width - num)) + icon + digits;
		}

		internal static string Arrange(string text, float availableWidth, Func<string, float> measure)
		{
			if (string.IsNullOrEmpty(text) || measure == null || !Finite(availableWidth) || availableWidth <= 0f)
			{
				return text;
			}
			text = RemoveLayout(text);
			if (MoonCatalogueDetailRow.HasDetails(text))
			{
				return text;
			}
			string[] array = text.Split('\n');
			List<Row> list = new List<Row>();
			float num = 0f;
			float num2 = 0f;
			float num3 = measure(" ");
			float num4 = Math.Max(1f, Math.Max(num3, measure("MM") - measure("M"))) * 2f;
			if (!Finite(num4))
			{
				return PromoteToDetails(text);
			}
			for (int i = 0; i < array.Length; i++)
			{
				string text2 = array[i];
				if (!MoonRow.IsMatch(text2))
				{
					continue;
				}
				Match match = Contract.Match(text2);
				Match match2 = FuelMatch(text2);
				if (!match.Success && !match2.Success)
				{
					continue;
				}
				string text3 = RemoveFuel(text2).TrimEnd('\r');
				match = Contract.Match(text3);
				Row row = new Row
				{
					Index = i,
					Base = text3,
					Fuel = match2,
					Ending = (text2.EndsWith("\r", StringComparison.Ordinal) ? "\r" : "")
				};
				if (match.Success)
				{
					row.Name = text3.Substring(0, match.Index).TrimEnd();
					row.Contract = match.Value;
					row.Weather = TrimVisibleStart(text3.Substring(match.Index + match.Length));
					row.HasWeather = Tags.Replace(row.Weather, "").Trim().Length > 0;
					if (!IsWeather(row.Weather) || ForeignLayout.IsMatch(row.Name))
					{
						return PromoteToDetails(text);
					}
					num = Math.Max(num, measure(row.Name));
					num2 = Math.Max(num2, measure(row.Contract));
				}
				list.Add(row);
			}
			float num5 = num + num4;
			float num6 = num5 + num2 + num4;
			foreach (Row item in list)
			{
				string arg = ((item.Fuel.Success && item.Fuel.Groups["icon"].Success) ? (item.Fuel.Groups["icon"].Value + item.Fuel.Groups["value"].Value) : item.Fuel.Value);
				float num7 = (item.Fuel.Success ? (measure(arg) + 2f) : 0f);
				float num8 = ((item.Contract == null) ? measure(item.Base) : (item.HasWeather ? (num6 + measure(item.Weather)) : (num5 + measure(item.Contract))));
				if (!Finite(num8) || !Finite(num7) || num8 > availableWidth - (item.Fuel.Success ? (num7 + num4) : 0f))
				{
					return PromoteToDetails(text);
				}
			}
			foreach (Row item2 in list)
			{
				string text4 = item2.Base;
				if (item2.Contract != null)
				{
					text4 = item2.Name + Padding(num5 - measure(item2.Name), num3) + item2.Contract;
					if (item2.HasWeather)
					{
						text4 += Padding(num6 - num5 - measure(item2.Contract), num3);
					}
					text4 += item2.Weather;
				}
				if (item2.Fuel.Success)
				{
					text4 = text4 + " " + item2.Fuel.Value;
				}
				array[item2.Index] = text4 + item2.Ending;
			}
			return string.Join("\n", array);
		}

		internal static string PromoteToDetails(string text)
		{
			string[] array = RemoveLayout(text).Split('\n');
			List<string> list = new List<string>(array.Length);
			for (int i = 0; i < array.Length; i++)
			{
				string text2 = array[i];
				if (!MoonRow.IsMatch(text2))
				{
					list.Add(text2);
					continue;
				}
				Match match = Contract.Match(text2);
				Match match2 = FuelMatch(text2);
				if (!match.Success && !match2.Success)
				{
					list.Add(text2);
					continue;
				}
				string text3 = RemoveMatches(RemoveFuel(text2), Contract);
				string contractField = "";
				string fuelField = "";
				if (i + 1 < array.Length && MoonCatalogueDetailRow.TryRead(array[i + 1], out contractField, out fuelField))
				{
					i++;
				}
				if (match.Success)
				{
					contractField = MoonCatalogueDetailRow.Field(match.Groups["value"].Value, contract: true);
				}
				if (match2.Success)
				{
					fuelField = MoonCatalogueDetailRow.Field(match2.Groups["value"].Value, contract: false);
				}
				list.Add(text3);
				list.Add("  " + MoonCatalogueDetailRow.Join(contractField, fuelField) + (text3.EndsWith("\r", StringComparison.Ordinal) ? "\r" : ""));
			}
			return string.Join("\n", list);
		}

		private static Match FuelMatch(string line)
		{
			Match match = RenderedFuel.Match(line);
			if (!match.Success)
			{
				return RawFuel.Match(line);
			}
			return match;
		}

		private static bool IsWeather(string text)
		{
			return Weather.IsMatch(Tags.Replace(text, "").Trim());
		}

		private static string Padding(float width, float spaceWidth)
		{
			return " <link=\"y4ngz.catalogue-gap\"><space=" + Number(Math.Max(0f, width - spaceWidth)) + "></link>";
		}

		private static string Number(float value)
		{
			return value.ToString("0.###", CultureInfo.InvariantCulture);
		}

		private static bool Finite(float value)
		{
			if (!float.IsNaN(value))
			{
				return !float.IsInfinity(value);
			}
			return false;
		}

		private static string RemoveMatches(string line, Regex pattern)
		{
			MatchCollection matchCollection = pattern.Matches(line);
			for (int num = matchCollection.Count - 1; num >= 0; num--)
			{
				int num2 = matchCollection[num].Index;
				int num3 = matchCollection[num].Length;
				if (num2 > 0 && line[num2 - 1] == ' ')
				{
					num2--;
					num3++;
				}
				line = line.Remove(num2, num3);
			}
			return line;
		}

		private static string TrimVisibleStart(string text)
		{
			string text2 = "";
			int num = 0;
			while (num < text.Length)
			{
				if (char.IsWhiteSpace(text[num]))
				{
					num++;
					continue;
				}
				if (text[num] != '<')
				{
					break;
				}
				int num2 = text.IndexOf('>', num);
				if (num2 < 0)
				{
					break;
				}
				text2 += text.Substring(num, num2 - num + 1);
				num = num2 + 1;
			}
			return text2 + text.Substring(num);
		}
	}
}
namespace Y4NGZCompany.ShipSystems
{
	[BepInPlugin("com.y4ngz.company.shipsystems", "ShipSystems", "1.0.0")]
	[BepInDependency("com.y4ngz.core", "1.0.13")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public sealed class ShipSystemsPlugin : BaseUnityPlugin
	{
		public const string Guid = "com.y4ngz.company.shipsystems";

		public const string Name = "ShipSystems";

		public const string Version = "1.0.0";

		public const int ShipSystemsProtocolRevision = 13;

		internal const string HarmonyId = "com.y4ngz.company.shipsystems";

		internal const string HostObjectName = "Y4NGZShipSystems_Host";

		private Harmony _harmony;

		private ShipSystemsHost _host;

		private bool _applicationQuitting;

		internal static ShipSystemsPlugin Instance { get; private set; }

		internal static MonoBehaviour CoroutineHost { get; private set; }

		private void Awake()
		{
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Expected O, but got Unknown
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Expected O, but got Unknown
			Instance = this;
			ModuleLog.ShipSystems = ((BaseUnityPlugin)this).Logger;
			ModuleLog.Store = ((BaseUnityPlugin)this).Logger;
			ModuleLog.Terminal = ((BaseUnityPlugin)this).Logger;
			ModuleTickRegistry.WarningSink = delegate(string message)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)message);
			};
			RefitEffects.WarningSink = delegate(string message)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)message);
			};
			SplitAssemblyDiagnostics.Report(((BaseUnityPlugin)this).Logger);
			GameObject val = new GameObject("Y4NGZShipSystems_Host")
			{
				hideFlags = (HideFlags)61
			};
			Object.DontDestroyOnLoad((Object)(object)val);
			_host = val.AddComponent<ShipSystemsHost>();
			CoroutineHost = (MonoBehaviour)(object)_host;
			ModuleHandshakeService.Publish("shipsystems", 13, "1.0.0");
			_harmony = new Harmony("com.y4ngz.company.shipsystems");
			Initialize(((BaseUnityPlugin)this).Config, ((BaseUnityPlugin)this).Logger, _harmony, InitializeModule);
			_host.Activate(_harmony, ((BaseUnityPlugin)this).Logger);
			((BaseUnityPlugin)this).Logger.LogInfo((object)"ShipSystems v1.0.0 loaded.");
		}

		private void OnApplicationQuit()
		{
			_applicationQuitting = true;
		}

		private void OnDestroy()
		{
			if (ShipSystemsHost.HasTornDown)
			{
				return;
			}
			if ((Object)(object)_host != (Object)null && _host.IsActivated)
			{
				if (_applicationQuitting)
				{
					((BaseUnityPlugin)this).Logger.LogDebug((object)"[Y4NGZShipSystems] Plugin component destroyed during application quit; 'Y4NGZShipSystems_Host' is still alive and owns the shutdown.");
				}
				else
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)("[Y4NGZShipSystems] The plugin component's GameObject was destroyed mid-session " + $"(frame={Time.frameCount}; BepInEx [Chainloader] HideManagerGameObject is " + "false, so BepInEx_Manager is destroyable by any mod's Find-based cleanup). 'Y4NGZShipSystems_Host' is alive, so nothing was torn down: the tick registrations and every Harmony patch this plugin applied remain ACTIVE and gameplay continues normally."));
				}
			}
			else
			{
				ShipSystemsHost.TearDown(_harmony, ((BaseUnityPlugin)this).Logger);
			}
		}

		internal static void Initialize(ConfigFile config, ManualLogSource logger, Harmony harmony, Action<string, Action> isolate)
		{
			isolate("Ship Systems", delegate
			{
				ShipSystemsBootstrap.Initialize(config, logger, harmony);
			});
			isolate("Ship Layout", delegate
			{
				ShipLayoutBootstrap.Initialize(logger, harmony);
			});
			isolate("Terminal", delegate
			{
				TerminalBootstrap.Initialize(logger, harmony);
			});
			ModuleTickRegistry.RegisterTeardown("com.y4ngz.company.shipsystems", 100, "ShipSystemsBootstrap", (Action)ShipSystemsBootstrap.Shutdown);
			ModuleTickRegistry.RegisterTeardown("com.y4ngz.company.shipsystems", 120, "ShipLayoutBootstrap", (Action)ShipLayoutBootstrap.Shutdown);
			ModuleTickRegistry.RegisterTeardown("com.y4ngz.company.shipsystems", 200, "TerminalBootstrap", (Action)TerminalBootstrap.Shutdown);
			InputWatchdogWriterRegistry.Register(typeof(ShipCommandController), "Ship Systems", new string[1] { "RestorePlayersAfterRefit" });
		}

		internal static void InitializeModule(string label, Action initialize)
		{
			try
			{
				initialize();
			}
			catch (Exception arg)
			{
				ManualLogSource shipSystems = ModuleLog.ShipSystems;
				if (shipSystems != null)
				{
					shipSystems.LogError((object)$"Y4NGZShipSystems module '{label}' failed to initialize: {arg}");
				}
			}
		}
	}
	internal sealed class ShipSystemsHost : MonoBehaviour
	{
		private static bool _tornDown;

		private Harmony _harmony;

		private ManualLogSource _log;

		private bool _activated;

		private bool _applicationQuitting;

		internal static bool HasTornDown => _tornDown;

		internal bool IsActivated => _activated;

		internal void Activate(Harmony harmony, ManualLogSource log)
		{
			_harmony = harmony;
			_log = log;
			_activated = true;
		}

		private void LateUpdate()
		{
			if (_activated)
			{
				ModuleTickRegistry.Tick(Time.frameCount);
			}
		}

		private void OnApplicationQuit()
		{
			_applicationQuitting = true;
		}

		private void OnDestroy()
		{
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			if (!_activated)
			{
				return;
			}
			if (!_applicationQuitting)
			{
				ManualLogSource log = _log;
				if (log != null)
				{
					string[] obj = new string[5]
					{
						"[Y4NGZShipSystems] Host destroyed outside application shutdown ",
						string.Format("(frame={0}, host='{1}', ", Time.frameCount, ((Object)(object)((Component)this).gameObject != (Object)null) ? ((Object)((Component)this).gameObject).name : "<null>"),
						"scene='",
						null,
						null
					};
					object obj2;
					if (!((Object)(object)((Component)this).gameObject != (Object)null))
					{
						obj2 = "<null>";
					}
					else
					{
						Scene scene = ((Component)this).gameObject.scene;
						obj2 = ((Scene)(ref scene)).name;
					}
					obj[3] = (string)obj2;
					obj[4] = "'). Ship systems, the terminal and every Harmony patch this plugin applied are going down with it.";
					log.LogError((object)string.Concat(obj));
				}
			}
			TearDown(_harmony, _log);
		}

		internal static void TearDown(Harmony harmony, ManualLogSource log)
		{
			if (_tornDown)
			{
				return;
			}
			_tornDown = true;
			ModuleTickRegistry.RunTeardown(new string[1] { "com.y4ngz.company.shipsystems" });
			if (harmony == null)
			{
				return;
			}
			try
			{
				harmony.UnpatchSelf();
			}
			catch (Exception ex)
			{
				if (log != null)
				{
					log.LogWarning((object)("Y4NGZShipSystems shutdown warning: UnpatchSelf failed for Harmony id '" + harmony.Id + "': " + ex.Message));
				}
			}
		}
	}
}
namespace Y4NGZCompany.ShipSystems.Upgrades.SurgeGuard
{
	internal static class SurgeGuardArc
	{
		private const string RootName = "Y4NGZ_SurgeGuardArc";

		private const string LogPrefix = "[ShipSystems.SurgeGuard] ";

		private const string HdrpUnlitShader = "HDRP/Unlit";

		private static GameObject _root;

		private static SurgeGuardArcView _view;

		private static Material _material;

		private static bool _materialWarned;

		private static bool _materialHdrp;

		private static ItemCharger _charger;

		private static float _pendingAt;

		private static bool _audioWarned;

		private static bool _coldWarned;

		private static bool _wanted;

		private static float _nextChargerSearch;

		private static bool _pending;

		private static Vector3 _pendingSocket;

		private static Transform _pendingTarget;

		private static Vector3 _pendingFallback;

		private const float ChargerRetrySeconds = 5f;

		private const float PendingMaxSeconds = 1f;

		internal static bool Wanted
		{
			get
			{
				return _wanted;
			}
			set
			{
				_wanted = value;
			}
		}

		internal static void Prepare()
		{
			EnsureView();
			ResolveMaterial();
			if ((Object)(object)_charger == (Object)null)
			{
				SearchCharger(Time.unscaledTime);
			}
		}

		internal static void Play(Vector3 socketWorld, Transform target, Vector3 targetFallbackWorld)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_root == (Object)null || (Object)(object)_view == (Object)null)
			{
				if (_wanted)
				{
					_pending = true;
					_pendingAt = Time.unscaledTime;
					_pendingSocket = socketWorld;
					_pendingTarget = target;
					_pendingFallback = targetFallbackWorld;
				}
			}
			else
			{
				Begin(socketWorld, target, targetFallbackWorld);
			}
		}

		internal static void Tick(float unscaledNow)
		{
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			if (!_wanted)
			{
				return;
			}
			if (_pending && unscaledNow - _pendingAt > 1f)
			{
				_pending = false;
				_pendingTarget = null;
			}
			if ((Object)(object)_root == (Object)null || (Object)(object)_view == (Object)null)
			{
				Prepare();
				if (_pending && !_coldWarned)
				{
					_coldWarned = true;
					ModuleLog.ShipSystems.LogWarning((object)"[ShipSystems.SurgeGuard] Arc was cold; rebuilt on the presentation tick.");
				}
			}
			else if ((Object)(object)_charger == (Object)null && unscaledNow >= _nextChargerSearch)
			{
				SearchCharger(unscaledNow);
			}
			if (_pending && (Object)(object)_root != (Object)null && (Object)(object)_view != (Object)null)
			{
				_pending = false;
				Transform pendingTarget = _pendingTarget;
				_pendingTarget = null;
				Begin(_pendingSocket, pendingTarget, _pendingFallback);
			}
		}

		internal static void Teardown()
		{
			_pendingAt = 0f;
			_wanted = false;
			_pending = false;
			_pendingTarget = null;
			if ((Object)(object)_root != (Object)null)
			{
				Object.Destroy((Object)(object)_root);
			}
			if ((Object)(object)_material != (Object)null)
			{
				Object.Destroy((Object)(object)_material);
			}
			_root = null;
			_view = null;
			_material = null;
			_materialWarned = false;
			_materialHdrp = false;
			_charger = null;
			_nextChargerSearch = 0f;
		}

		private static void Begin(Vector3 socketWorld, Transform target, Vector3 targetFallbackWorld)
		{
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			AudioSource val = (((Object)(object)_charger != (Object)null) ? _charger.zapAudio : null);
			AudioClip val2 = (((Object)(object)val != (Object)null) ? val.clip : null);
			AudioMixerGroup mixer = (((Object)(object)val2 != (Object)null) ? val.outputAudioMixerGroup : null);
			_root.SetActive(true);
			_view.Begin(socketWorld, target, targetFallbackWorld, _material, _materialHdrp, val2, mixer);
		}

		private static void EnsureView()
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Expected O, but got Unknown
			if (!((Object)(object)_root != (Object)null) || !((Object)(object)_view != (Object)null))
			{
				if ((Object)(object)_root != (Object)null)
				{
					Object.Destroy((Object)(object)_root);
				}
				_root = new GameObject("Y4NGZ_SurgeGuardArc");
				_root.SetActive(false);
				_view = _root.AddComponent<SurgeGuardArcView>();
				_view.Build();
				_view.Warm();
			}
		}

		private static void SearchCharger(float unscaledNow)
		{
			_nextChargerSearch = unscaledNow + 5f;
			_charger = Object.FindObjectOfType<ItemCharger>();
			AudioSource val = (((Object)(object)_charger != (Object)null) ? _charger.zapAudio : null);
			if (((Object)(object)val == (Object)null || (Object)(object)val.clip == (Object)null) && !_audioWarned)
			{
				_audioWarned = true;
				ModuleLog.ShipSystems.LogWarning((object)"[ShipSystems.SurgeGuard] No ItemCharger zapAudio clip found; the arc plays silent.");
			}
		}

		private static Material ResolveMaterial()
		{
			//IL_006f: 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_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_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Expected O, but got Unknown
			//IL_00a0: 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_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: 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)
			if ((Object)(object)_material != (Object)null)
			{
				return _material;
			}
			Shader val = Shader.Find("HDRP/Unlit") ?? Shader.Find("Sprites/Default") ?? Shader.Find("Unlit/Color") ?? Shader.Find("Standard");
			if ((Object)(object)val == (Object)null)
			{
				if (!_materialWarned)
				{
					_materialWarned = true;
					ModuleLog.ShipSystems.LogWarning((object)"[ShipSystems.SurgeGuard] No unlit shader found; the arc plays without beams.");
				}
				return null;
			}
			Color arcColor = SurgeGuardArcView.ArcColor;
			Material val2 = new Material(val)
			{
				name = "Y4NGZ_SurgeGuardArc",
				hideFlags = (HideFlags)61,
				renderQueue = 3100
			};
			SetColorIfPresent(val2, "_UnlitColor", arcColor);
			SetColorIfPresent(val2, "_BaseColor", arcColor);
			SetColorIfPresent(val2, "_Color", arcColor);
			SetColorIfPresent(val2, "_EmissiveColor", arcColor * 4f);
			SetFloatIfPresent(val2, "_SurfaceType", 1f);
			SetFloatIfPresent(val2, "_BlendMode", 1f);
			SetFloatIfPresent(val2, "_AlphaCutoffEnable", 0f);
			SetFloatIfPresent(val2, "_ZWrite", 0f);
			SetFloatIfPresent(val2, "_TransparentZWrite", 0f);
			SetFloatIfPresent(val2, "_SrcBlend", 5f);
			SetFloatIfPresent(val2, "_DstBlend", 1f);
			SetFloatIfPresent(val2, "_AlphaSrcBlend", 5f);
			SetFloatIfPresent(val2, "_AlphaDstBlend", 1f);
			SetFloatIfPresent(val2, "_CullMode", 0f);
			SetFloatIfPresent(val2, "_TransparentCullMode", 0f);
			SetFloatIfPresent(val2, "_DoubleSidedEnable", 1f);
			val2.SetOverrideTag("RenderType", "Transparent");
			val2.EnableKeyword("_SURFACE_TYPE_TRANSPARENT");
			val2.EnableKeyword("_BLENDMODE_ADD");
			val2.DisableKeyword("_BLENDMODE_ALPHA");
			val2.EnableKeyword("_ENABLE_FOG_ON_TRANSPARENT");
			val2.EnableKeyword("_ALPHABLEND_ON");
			val2.DisableKeyword("_ALPHATEST_ON");
			val2.DisableKeyword("_ALPHAPREMULTIPLY_ON");
			_materialHdrp = ((Object)val).name == "HDRP/Unlit";
			if (_materialHdrp)
			{
				try
				{
					HDMaterial.ValidateMaterial(val2);
				}
				catch (Exception ex)
				{
					ModuleLog.ShipSystems.LogWarning((object)("[ShipSystems.SurgeGuard] Arc material validation skipped: " + ex.Message));
				}
			}
			_material = val2;
			return val2;
		}

		private static void SetColorIfPresent(Material material, string property, Color value)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			if (material.HasProperty(property))
			{
				material.SetColor(property, value);
			}
		}

		private static void SetFloatIfPresent(Material material, string property, float value)
		{
			if (material.HasProperty(property))
			{
				material.SetFloat(property, value);
			}
		}
	}
	internal sealed class SurgeGuardArcView : MonoBehaviour
	{
		internal static readonly Color ArcColor = new Color(0.6f, 0.85f, 1f, 1f);

		internal const float Emission = 4f;

		private const int Strands = 3;

		private const int MainPoints = 10;

		private const int BranchPoints = 8;

		private const float ArcSeconds = 0.45f;

		private const float JitterInterval = 0.035f;

		private const float MainWidth = 0.07f;

		private const float BranchWidth = 0.035f;

		private const float MainJitterMetres = 0.22f;

		private const float BranchJitterMetres = 0.12f;

		private const float FlashSeconds = 0.2f;

		private const float FlashRise = 0.15f;

		private const float FlashPeakLumens = 3000f;

		private const float FlashRange = 6f;

		private const float AudioMinDistance = 4f;

		private const float AudioMaxDistance = 30f;

		private const float FallbackBodyHeight = 1f;

		private static readonly int UnlitColorId = Shader.PropertyToID("_UnlitColor");

		private static readonly int EmissiveColorId = Shader.PropertyToID("_EmissiveColor");

		private static readonly List<Collider> ColliderBuffer = new List<Collider>(16);

		private readonly LineRenderer[] _lines = (LineRenderer[])(object)new LineRenderer[3];

		private readonly Vector3[][] _points = new Vector3[3][];

		private readonly Vector2[][] _offsets = new Vector2[3][];

		private readonly int[] _branchIndex = new int[2];

		private readonly float[] _branchForward = new float[2];

		private readonly Vector2[] _branchSide = (Vector2[])(object)new Vector2[2];

		private MaterialPropertyBlock _block;

		private Light _light;

		private HDAdditionalLightData _lightData;

		private AudioSource _audio;

		private Vector3 _socket;

		private Transform _target;

		private Vector3 _bodyLocal;

		private Vector3 _fallback;

		private bool _hdrp;

		private bool _beams;

		private bool _arcLive;

		private bool _flashLive;

		private float _age;

		private float _nextJitter;

		private float _flicker = 1f;

		private float _busyUntil;

		internal void Build()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Expected O, but got Unknown
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			_block = new MaterialPropertyBlock();
			for (int i = 0; i < 3; i++)
			{
				int num = ((i == 0) ? 10 : 8);
				_points[i] = (Vector3[])(object)new Vector3[num];
				_offsets[i] = (Vector2[])(object)new Vector2[num];
				GameObject val = new GameObject((i == 0) ? "ArcMain" : ("ArcBranch" + i));
				val.transform.SetParent(((Component)this).transform, false);
				LineRenderer val2 = val.AddComponent<LineRenderer>();
				val2.useWorldSpace = true;
				val2.positionCount = num;
				val2.numCapVertices = 2;
				val2.numCornerVertices = 1;
				val2.alignment = (LineAlignment)0;
				val2.textureMode = (LineTextureMode)0;
				((Renderer)val2).shadowCastingMode = (ShadowCastingMode)0;
				((Renderer)val2).receiveShadows = false;
				val2.widthMultiplier = ((i == 0) ? 0.07f : 0.035f);
				val2.startColor = ArcColor;
				val2.endColor = ArcColor;
				((Renderer)val2).enabled = false;
				_lines[i] = val2;
			}
			GameObject val3 = new GameObject("ArcFlash");
			val3.transform.SetParent(((Component)this).transform, false);
			_light = val3.AddComponent<Light>();
			_light.type = (LightType)2;
			_light.color = ArcColor;
			_light.range = 6f;
			_light.shadows = (LightShadows)0;
			_lightData = val3.GetComponent<HDAdditionalLightData>();
			if ((Object)(object)_lightData == (Object)null)
			{
				_lightData = val3.AddComponent<HDAdditionalLightData>();
			}
			((Behaviour)_light).enabled = false;
			_audio = ((Component)this).gameObject.AddComponent<AudioSource>();
			_audio.playOnAwake = false;
			_audio.loop = false;
			_audio.spatialBlend = 1f;
			_audio.dopplerLevel = 0f;
			_audio.rolloffMode = (AudioRolloffMode)1;
			_audio.minDistance = 4f;
			_audio.maxDistance = 30f;
		}

		internal void Warm()
		{
			((Component)this).gameObject.SetActive(true);
			for (int i = 0; i < 3; i++)
			{
				((Renderer)_lines[i]).enabled = true;
			}
			_lightData.SetIntensity(0f, (LightUnit)0);
			((Behaviour)_light).enabled = true;
			for (int j = 0; j < 3; j++)
			{
				((Renderer)_lines[j]).enabled = false;
			}
			((Behaviour)_light).enabled = false;
			((Component)this).gameObject.SetActive(false);
		}

		internal void Begin(Vector3 socketWorld, Transform target, Vector3 fallbackWorld, Material material, bool hdrp, AudioClip clip, AudioMixerGroup mixer)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: 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_0027: 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_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			_socket = socketWorld;
			_fallback = fallbackWorld;
			_target = target;
			_bodyLocal = (((Object)(object)target != (Object)null) ? ResolveBodyLocal(target) : Vector3.zero);
			_hdrp = hdrp;
			_beams = (Object)(object)material != (Object)null;
			_age = 0f;
			_nextJitter = 0f;
			_arcLive = true;
			_flashLive = true;
			((Component)this).transform.position = socketWorld;
			for (int i = 0; i < 3; i++)
			{
				LineRenderer obj = _lines[i];
				((Renderer)obj).sharedMaterial = material;
				((Renderer)obj).enabled = _beams;
			}
			((Behaviour)_light).enabled = true;
			float num = 0.45f;
			if ((Object)(object)clip != (Object)null)
			{
				_audio.outputAudioMixerGroup = mixer;
				_audio.PlayOneShot(clip);
				if (clip.length > num)
				{
					num = clip.length;
				}
			}
			_busyUntil = num + 0.1f;
			Tick();
		}

		private void Update()
		{
			_age += Time.deltaTime;
			Tick();
		}

		private void Tick()
		{
			if (_arcLive)
			{
				if (_age >= 0.45f)
				{
					_arcLive = false;
					for (int i = 0; i < 3; i++)
					{
						((Renderer)_lines[i]).enabled = false;
					}
				}
				else if (_beams)
				{
					DrawArc(_age / 0.45f);
				}
			}
			if (_flashLive)
			{
				if (_age >= 0.2f)
				{
					_flashLive = false;
					_lightData.SetIntensity(0f, (LightUnit)0);
					((Behaviour)_light).enabled = false;
				}
				else
				{
					float num = _age / 0.2f;
					float num2 = ((num < 0.15f) ? (num / 0.15f) : ((1f - num) / 0.85f));
					_lightData.SetIntensity(3000f * num2 * num2, (LightUnit)0);
				}
			}
			if (!_arcLive && !_flashLive && _age >= _busyUntil)
			{
				((Component)this).gameObject.SetActive(false);
			}
		}

		private void DrawArc(float t)
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: 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_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: 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_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: 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_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: 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_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_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//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_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: 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_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: 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)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01db: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ee: 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_01f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0201: Unknown result type (might be due to invalid IL or missing references)
			//IL_0203: Unknown result type (might be due to invalid IL or missing references)
			//IL_020a: Unknown result type (might be due to invalid IL or missing references)
			//IL_020f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0214: Unknown result type (might be due to invalid IL or missing references)
			//IL_0317: Unknown result type (might be due to invalid IL or missing references)
			//IL_0329: Unknown result type (might be due to invalid IL or missing references)
			//IL_0336: Unknown result type (might be due to invalid IL or missing references)
			//IL_023d: Unknown result type (might be due to invalid IL or missing references)
			//IL_023f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0243: Unknown result type (might be due to invalid IL or missing references)
			//IL_0248: Unknown result type (might be due to invalid IL or missing references)
			//IL_024d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0260: 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_026a: Unknown result type (might be due to invalid IL or missing references)
			//IL_027d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0282: Unknown result type (might be due to invalid IL or missing references)
			//IL_0287: Unknown result type (might be due to invalid IL or missing references)
			//IL_036c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0375: Unknown result type (might be due to invalid IL or missing references)
			if (_age >= _nextJitter)
			{
				_nextJitter = _age + 0.035f;
				Rejitter();
			}
			Vector3 val = (((Object)(object)_target != (Object)null) ? _target.TransformPoint(_bodyLocal) : _fallback);
			Vector3 val2 = val - _socket;
			float magnitude = ((Vector3)(ref val2)).magnitude;
			Vector3 val3 = ((magnitude > 0.0001f) ? (val2 / magnitude) : Vector3.down);
			Vector3 val4 = Vector3.Cross(val3, Vector3.up);
			if (((Vector3)(ref val4)).sqrMagnitude < 0.0001f)
			{
				val4 = Vector3.Cross(val3, Vector3.right);
			}
			((Vector3)(ref val4)).Normalize();
			Vector3 val5 = Vector3.Cross(val4, val3);
			Vector3[] array = _points[0];
			Vector2[] array2 = _offsets[0];
			float num = Mathf.Min(0.22f, magnitude * 0.15f);
			int num2 = 9;
			for (int i = 0; i < 10; i++)
			{
				float num3 = (float)i / (float)num2;
				float num4 = Mathf.Sin(num3 * MathF.PI) * num;
				array[i] = _socket + val2 * num3 + val4 * (array2[i].x * num4) + val5 * (array2[i].y * num4);
			}
			array[0] = _socket;
			array[num2] = val;
			_lines[0].SetPositions(array);
			float num5 = Mathf.Min(0.12f, magnitude * 0.1f);
			for (int j = 0; j < 2; j++)
			{
				Vector3[] array3 = _points[j + 1];
				Vector2[] array4 = _offsets[j + 1];
				Vector3 val6 = array[_branchIndex[j]];
				Vector2 val7 = _branchSide[j];
				Vector3 val8 = val3 * (magnitude * _branchForward[j]) + val4 * val7.x + val5 * val7.y;
				int num6 = 7;
				for (int k = 0; k < 8; k++)
				{
					float num7 = (float)k / (float)num6;
					float num8 = Mathf.Sin(num7 * MathF.PI) * num5;
					array3[k] = val6 + val8 * num7 + val4 * (array4[k].x * num8) + val5 * (array4[k].y * num8);
				}
				_lines[j + 1].SetPositions(array3);
			}
			float num9 = 1f - t * t;
			float num10 = num9 * _flicker;
			float num11 = 0.35f + 0.65f * num9;
			Color val9 = default(Color);
			((Color)(ref val9))..ctor(ArcColor.r, ArcColor.g, ArcColor.b, num10);
			if (_hdrp)
			{
				_block.SetColor(UnlitColorId, val9);
				_block.SetColor(EmissiveColorId, ArcColor * (4f * num10));
			}
			for (int l = 0; l < 3; l++)
			{
				LineRenderer val10 = _lines[l];
				val10.widthMultiplier = ((l == 0) ? 0.07f : 0.035f) * num11;
				val10.startColor = val9;
				val10.endColor = val9;
				if (_hdrp)
				{
					((Renderer)val10).SetPropertyBlock(_block);
				}
			}
		}

		private void Rejitter()
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			for (int i = 0; i < 3; i++)
			{
				Vector2[] array = _offsets[i];
				for (int j = 0; j < array.Length; j++)
				{
					array[j] = Random.insideUnitCircle;
				}
			}
			for (int k = 0; k < 2; k++)
			{
				_branchIndex[k] = Random.Range(2, 7);
				_branchForward[k] = Random.Range(0.12f, 0.25f);
				Vector2[] branchSide = _branchSide;
				int num = k;
				Vector2 insideUnitCircle = Random.insideUnitCircle;
				branchSide[num] = ((Vector2)(ref insideUnitCircle)).normalized * Random.Range(0.35f, 0.8f);
			}
			_flicker = Random.Range(0.7f, 1f);
		}

		private static Vector3 ResolveBodyLocal(Transform target)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			ColliderBuffer.Clear();
			((Component)target).GetComponentsInChildren<Collider>(false, ColliderBuffer);
			bool flag = false;
			Bounds val = default(Bounds);
			for (int i = 0; i < ColliderBuffer.Count; i++)
			{
				Collider val2 = ColliderBuffer[i];
				if (!((Object)(object)val2 == (Object)null) && val2.enabled && !val2.isTrigger)
				{
					if (flag)
					{
						((Bounds)(ref val)).Encapsulate(val2.bounds);
						continue;
					}
					val = val2.bounds;
					flag = true;
				}
			}
			ColliderBuffer.Clear();
			Vector3 val3 = (flag ? ((Bounds)(ref val)).center : (target.position + Vector3.up * 1f));
			return target.InverseTransformPoint(val3);
		}
	}
	internal sealed class SurgeGuardEffect : IRefitEffect
	{
		private static bool _teardownRegistered;

		private static SurgeGuardPresentationTick _tick;

		public ShipUpgradeId Id => ShipUpgradeId.SurgeGuard;

		public void Apply(int level, RefitEffectContext context)
		{
			int num = (InActiveSession() ? level : 0);
			if (num >= 1 && !_teardownRegistered)
			{
				_teardownRegistered = true;
				ShipLayoutBootstrap.Registrations.Add("surge guard", Teardown);
			}
			SurgeGuardHost.Apply(num, context.IsHost);
			if (num >= 1)
			{
				SurgeGuardArc.Wanted = true;
				SurgeGuardArc.Prepare();
				Transform shipRoot = context.ShipRoot;
				if ((Object)(object)shipRoot != (Object)null && ((Object)(object)_tick == (Object)null || (Object)(object)((Component)_tick).gameObject != (Object)(object)((Component)shipRoot).gameObject))
				{
					DestroyTick();
					_tick = ((Component)shipRoot).gameObject.AddComponent<SurgeGuardPresentationTick>();
				}
			}
			else
			{
				DestroyTick();
				SurgeGuardArc.Teardown();
			}
		}

		private static bool InActiveSession()
		{
			NetworkManager singleton = NetworkManager.Singleton;
			if ((Object)(object)StartOfRound.Instance != (Object)null && (Object)(object)singleton != (Object)null)
			{
				return singleton.IsListening;
			}
			return false;
		}

		private static void Teardown()
		{
			_teardownRegistered = false;
			SurgeGuardHost.Apply(0, isHost: false);
			DestroyTick();
			SurgeGuardArc.Teardown();
		}

		private static void DestroyTick()
		{
			if ((Object)(object)_tick != (Object)null)
			{
				Object.Destroy((Object)(object)_tick);
			}
			_tick = null;
		}
	}
	internal static class SurgeGuardHost
	{
		internal static bool Installed { get; private set; }

		internal static void Apply(int level, bool isHost)
		{
			bool flag = isHost && level >= 1;
			if (Installed != flag)
			{
				Installed = flag;
				if (Installed)
				{
					ModuleLog.ShipSystems.LogInfo((object)$"[ShipSystems.SurgeGuard] Host surge guard installed (level {level}).");
				}
				else
				{
					ModuleLog.ShipSystems.LogInfo((object)"[ShipSystems.SurgeGuard] Host surge guard removed.");
				}
			}
		}
	}
	internal sealed class SurgeGuardPresentationTick : MonoBehaviour
	{
		private void LateUpdate()
		{
			SurgeGuardArc.Tick(Time.unscaledTime);
		}
	}
}
namespace Y4NGZCompany.ShipSystems.Upgrades.ShipCameras
{
	internal static class ShipCameraMounts
	{
		internal readonly struct Mount
		{
			internal readonly string Label;

			internal readonly (float X, float Y, float Z) LocalPosition;

			internal readonly (float X, float Y, float Z) LocalEulerAngles;

			internal readonly (float X, float Y, float Z) SwivelLocalEulerAngles;

			internal Mount(string label, (float X, float Y, float Z) localPosition, (float X, float Y, float Z) localEulerAngles, (float X, float Y, float Z) swivelLocalEulerAngles)
			{
				Label = label;
				LocalPosition = localPosition;
				LocalEulerAngles = localEulerAngles;
				SwivelLocalEulerAngles = swivelLocalEulerAngles;
			}
		}

		internal static readonly Mount[] All = new Mount[4]
		{
			new Mount("SHIP DOOR", (X: -7.551876f, Y: 3f, Z: -9.099232f), (X: 0f, Y: -87.066505f, Z: 0f), (X: 30f, Y: 20f, Z: 0f)),
			new Mount("SHIP REAR", (X: 11.296872f, Y: 3.3f, Z: -5.5f), (X: 0f, Y: 90f, Z: 0f), (X: 30f, Y: 0f, Z: 0f)),
			new Mount("SHIP LEFT", (X: 4.395189f, Y: 3.302852f, Z: -2.839003f), (X: -10.959491f, Y: -19.06751f, Z: 0f), (X: 40.95949f, Y: -30f, Z: 0f)),
			new Mount("SHIP RIGHT", (X: -3.5f, Y: 3.302295f, Z: -9.701332f), (X: -8.799781f, Y: 180f, Z: 0f), (X: 38.79978f, Y: -30f, Z: 0f))
		};
	}
	internal interface IShipCameraScene
	{
		object CreateProp(object parent, int mountIndex);

		bool Register(object prop, string label);

		void Unregister(object prop);

		void Destroy(object prop);
	}
	internal sealed class ShipCameraRig
	{
		private readonly IShipCameraScene _scene;

		private readonly object[] _props = new object[ShipCameraMounts.All.Length];

		private readonly bool[] _registered = new bool[ShipCameraMounts.All.Length];

		private object _parent;

		private int _propCount;

		private bool _unavailable;

		internal ShipCameraRig(IShipCameraScene scene)
		{
			_scene = scene ?? throw new ArgumentNullException("scene");
		}

		internal static int EffectiveLevel(int level, bool hostEnabled)
		{
			if (!hostEnabled)
			{
				return 0;
			}
			return Math.Max(0, Math.Min(1, level));
		}

		internal (int Built, int Removed) Apply(int effectiveLevel, object parent)
		{
			bool num = effectiveLevel >= 1 && parent != null;
			int num2 = 0;
			if (!num || _parent != parent)
			{
				num2 = Remove();
			}
			if (!num || _unavailable || _propCount > 0)
			{
				return (Built: 0, Removed: num2);
			}
			_parent = parent;
			for (int i = 0; i < _props.Length; i++)
			{
				object obj = _scene.CreateProp(parent, i);
				if (obj == null)
				{
					_unavailable = true;
					return (Built: 0, Removed: num2 + Remove());
				}
				_props[i] = obj;
				_propCount++;
			}
			for (int j = 0; j < _propCount; j++)
			{
				_registered[j] = _scene.Register(_props[j], ShipCameraMounts.All[j].Label);
			}
			return (Built: _propCount, Removed: num2);
		}

		private int Remove()
		{
			int propCount = _propCount;
			for (int i = 0; i < _propCount; i++)
			{
				if (_registered[i])
				{
					_scene.Unregister(_props[i]);
				}
				_registered[i] = false;
			}
			for (int j = 0; j < _propCount; j++)
			{
				_scene.Destroy(_props[j]);
				_props[j] = null;
			}
			_propCount = 0;
			_parent = null;
			return propCount;
		}
	}
	internal sealed class ShipCamerasEffect : IRefitEffect, IShipCameraScene
	{
		private sealed class CameraProp
		{
			internal readonly GameObject Visual;

			internal readonly Transform Lens;

			internal CameraProp(GameObject visual, Transform lens)
			{
				Visual = visual;
				Lens = lens;
			}
		}

		internal const string BundleFileName = "y4ngz-ship-cameras.bundle";

		internal const string PrefabAddress = "assets/y4ngz/shipsystems/cameras/shipcamera.prefab";

		private readonly ShipCameraRig _rig;

		private bool _disposed;

		public ShipUpgradeId Id => ShipUpgradeId.ShipCameras;

		internal ShipCamerasEffect()
		{
			_rig = new ShipCameraRig(this);
			ShipLayoutBootstrap.Registrations.Add("ship cameras effect", Dispose);
		}

		public void Apply(int level, RefitEffectContext context)
		{
			if (!_disposed)
			{
				Transform shipRoot = context.ShipRoot;
				Reconcile(ShipCameraRig.EffectiveLevel(level, context.HostEnabled), ((Object)(object)shipRoot != (Object)null) ? shipRoot : null);
			}
		}

		private void Reconcile(int effectiveLevel, Transform parent)
		{
			var (num, num2) = _rig.Apply(effectiveLevel, parent);
			if (num2 > 0)
			{
				ModuleLog.ShipSystems.LogInfo((object)$"[ShipSystems.ShipCameras] Removed {num2} camera props and their held feeds.");
			}
			if (num > 0)
			{
				ModuleLog.ShipSystems.LogInfo((object)$"[ShipSystems.ShipCameras] Built {num} hull camera props.");
			}
		}

		object IShipCameraScene.CreateProp(object parent, int mountIndex)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			if (!SidecarBundle.TryLoad("y4ngz-ship-cameras.bundle", out var bundle) || !SidecarBundle.TryInstantiate(bundle, "assets/y4ngz/shipsystems/cameras/shipcamera.prefab", (Transform)parent, out var instance))
			{
				ModuleLog.ShipSystems.LogWarning((object)"[ShipSystems.ShipCameras] Camera prefab unavailable; no camera props or feeds will be built this session.");
				return null;
			}
			ShipCameraMounts.Mount mount = ShipCameraMounts.All[mountIndex];
			Transform transform = instance.transform;
			transform.localPosition = Vector(mount.LocalPosition);
			transform.localRotation = Quaternion.Euler(Vector(mount.LocalEulerAngles));
			transform.localScale = Vector3.one;
			Transform val = transform.Find("Swivel");
			Transform val2 = transform.Find("Swivel/Lens");
			if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null)
			{
				ModuleLog.ShipSystems.LogWarning((object)"[ShipSystems.ShipCameras] Camera prefab has no Swivel/Lens joint; camera props and feeds are disabled this session.");
				DestroyVisual(instance);
				return null;
			}
			val.localRotation = Quaternion.Euler(Vector(mount.SwivelLocalEulerAngles));
			return new CameraProp(instance, val2);
		}

		bool IShipCameraScene.Register(object prop, string label)
		{
			return LethalCCTVBridge.Register((Component)(object)((CameraProp)prop).Lens, label);
		}

		void IShipCameraScene.Unregister(object prop)
		{
			LethalCCTVBridge.Unregister((Component)(object)((CameraProp)prop).Lens);
		}

		void IShipCameraScene.Destroy(object prop)
		{
			DestroyVisual(((CameraProp)prop).Visual);
		}

		private static Vector3 Vector((float X, float Y, float Z) value)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			return new Vector3(value.X, value.Y, value.Z);
		}

		private static void DestroyVisual(GameObject visual)
		{
			if (!((Object)(object)visual == (Object)null))
			{
				visual.SetActive(false);
				Object.Destroy((Object)(object)visual);
			}
		}

		private void Dispose()
		{
			if (!_disposed)
			{
				_disposed = true;
				Reconcile(0, null);
			}
		}
	}
}
namespace Y4NGZCompany.ShipSystems.Upgrades.ShipCameras.Compatibility
{
	internal static class LethalCCTVBridge
	{
		private static bool _resolved;

		private static Func<Component, string, bool> _register;

		private static Func<Component, bool> _unregister;

		private static bool _registerWarning;

		private static bool _unregisterWarning;

		internal static bool Register(Component cameraRoot, string label)
		{
			if ((Object)(object)cameraRoot == (Object)null)
			{
				return false;
			}
			Resolve();
			if (_register == null)
			{
				return false;
			}
			try
			{
				return _register(cameraRoot, label);
			}
			catch (Exception ex)
			{
				if (!_registerWarning)
				{
					_registerWarning = true;
					ModuleLog.ShipSystems.LogWarning((object)("[ShipSystems.ShipCameras] LethalCCTV Register failed: " + ex.Message));
				}
				return false;
			}
		}

		internal static bool Unregister(Component cameraRoot)
		{
			if ((Object)(object)cameraRoot == (Object)null)
			{
				return false;
			}
			Resolve();
			if (_unregister == null)
			{
				return false;
			}
			try
			{
				return _unregister(cameraRoot);
			}
			catch (Exception ex)
			{
				if (!_unregisterWarning)
				{
					_unregisterWarning = true;
					ModuleLog.ShipSystems.LogWarning((object)("[ShipSystems.ShipCameras] LethalCCTV Unregister failed: " + ex.Message));
				}
				return false;
			}
		}

		private static void Resolve()
		{
			if (_resolved)
			{
				return;
			}
			_resolved = true;
			if (!ShipUpgradeCatalog.TryGet(ShipUpgradeId.ShipCameras, out var definition) || !RefitModPresence.IsPluginLoaded(definition.RequiredModGuid))
			{
				return;
			}
			try
			{
				Type type = Type.GetType("LethalCCTV.Api.ShipCameraFeeds, LethalCCTV", throwOnError: false);
				MethodInfo methodInfo = type?.GetMethod("Register", BindingFlags.Static | BindingFlags.Public, null, new Type[2]
				{
					typeof(Component),
					typeof(string)
				}, null);
				MethodInfo methodInfo2 = type?.GetMethod("Unregister", BindingFlags.Static | BindingFlags.Public, null, new Type[1] { typeof(Component) }, null);
				if (methodInfo == null || methodInfo2 == null || methodInfo.ReturnType != typeof(bool) || methodInfo2.ReturnType != typeof(bool) || methodInfo.ContainsGenericParameters || methodInfo2.ContainsGenericParameters)
				{
					WarnUnavailable(definition.RequiredModGuid, "the required ShipCameraFeeds API is missing");
					return;
				}
				Func<Component, string, bool> register = (Func<Component, string, bool>)Delegate.CreateDelegate(typeof(Func<Component, string, bool>), methodInfo);
				Func<Component, bool> unregister = (Func<Component, bool>)Delegate.CreateDelegate(typeof(Func<Component, bool>), methodInfo2);
				_register = register;
				_unregister = unregister;
			}
			catch (Exception ex)
			{
				WarnUnavailable(definition.RequiredModGuid, ex.Message);
			}
		}

		private static void WarnUnavailable(string pluginGuid, string reason)
		{
			string text = "unknown";
			try
			{
				if (Chainloader.PluginInfos.TryGetValue(pluginGuid, out var value) && value.Metadata != null && value.Metadata.Version != null)
				{
					text = value.Metadata.Version.ToString();
				}
			}
			catch
			{
			}
			ModuleLog.ShipSystems.LogWarning((object)("[ShipSystems.ShipCameras] LethalCCTV " + text + ": " + reason + "; hull camera feeds are unavailable."));
		}
	}
}
namespace Y4NGZCompany.ShipSystems.Upgrades.ReserveCell
{
	internal sealed class ReserveCellEffect : IRefitEffect
	{
		private static bool _teardownRegistered;

		public ShipUpgradeId Id => ShipUpgradeId.ReserveCell;

		public void Apply(int level, RefitEffectContext context)
		{
			int num = (InActiveSession() ? level : 0);
			if (num >= 1 && !_teardownRegistered)
			{
				_teardownRegistered = true;
				ShipLayoutBootstrap.Registrations.Add("reserve cell", Teardown);
			}
			ReserveCellHost.Apply(num, context.IsHost);
		}

		private static bool InActiveSession()
		{
			NetworkManager singleton = NetworkManager.Singleton;
			if ((Object)(object)StartOfRound.Instance != (Object)null && (Object)(object)singleton != (Object)null)
			{
				return singleton.IsListening;
			}
			return false;
		}

		private static void Teardown()
		{
			_teardownRegistered = false;
			ReserveCellHost.Apply(0, isHost: false);
		}
	}
	internal static class ReserveCellHost
	{
		internal static bool Installed { get; private set; }

		internal static void Apply(int level, bool isHost)
		{
			bool flag = isHost && level >= 1;
			if (Installed != flag)
			{
				Installed = flag;
				if (Installed)
				{
					ModuleLog.ShipSystems.LogInfo((object)$"[ShipSystems.ReserveCell] Host reserve cell installed (level {level}).");
				}
				else
				{
					ModuleLog.ShipSystems.LogInfo((object)"[ShipSystems.ReserveCell] Host reserve cell removed.");
				}
			}
		}
	}
}
namespace Y4NGZCompany.ShipSystems.Upgrades.PaintJobs
{
	internal enum PaintMaterialFamily
	{
		None = -1,
		Vinyl,
		Metal,
		Grate
	}
	internal sealed class PaintJobMaterials
	{
		private const string BundleName = "y4ngz-ship-paint.bundle";

		private static readonly string[] Schemes = new string[7] { "hazard-orange", "deep-navy", "matte-black", "forest-green", "arctic-white", "crimson-red", "safety-yellow" };

		private static readonly string[] Suffixes = new string[3] { "", "-metal", "-grate" };

		private readonly Material[,] _donors = new Material[Schemes.Length, Suffixes.Length];

		private readonly bool[] _attempted = new bool[Schemes.Length];

		internal static readonly int BaseMap = Shader.PropertyToID("_BaseColorMap");

		internal static readonly int MaskMap = Shader.PropertyToID("_MaskMap");

		private static readonly int BaseColor = Shader.PropertyToID("_BaseColor");

		private static readonly int Metallic = Shader.PropertyToID("_Metallic");

		private static readonly int Smoothness = Shader.PropertyToID("_Smoothness");

		private static readonly int[] RemapMin = new int[3]
		{
			Shader.PropertyToID("_MetallicRemapMin"),
			Shader.PropertyToID("_AORemapMin"),
			Shader.PropertyToID("_SmoothnessRemapMin")
		};

		private static readonly int[] RemapMax = new int[3]
		{
			Shader.PropertyToID("_MetallicRemapMax"),
			Shader.PropertyToID("_AORemapMax"),
			Shader.PropertyToID("_SmoothnessRemapMax")
		};

		internal Material Get(int level, PaintMaterialFamily family)
		{
			int num = level - 2;
			if (!_attempted[num])
			{
				_attempted[num] = true;
				if (!SidecarBundle.TryLoad("y4ngz-ship-paint.bundle", out var bundle))
				{
					return null;
				}
				for (int i = 0; i < Suffixes.Length; i++)
				{
					string text = "assets/y4ngz/shipsystems/paint/" + Schemes[num] + Suffixes[i] + ".mat";
					Material val = bundle.LoadAsset<Material>(text);
					if (!SupportsMaps(val) || (Object)(object)val.GetTexture(BaseMap) == (Object)null || (Object)(object)val.GetTexture(MaskMap) == (Object)null)
					{
						for (int j = 0; j < Suffixes.Length; j++)
						{
							_donors[num, j] = null;
						}
						RefitEffects.WarningSink?.Invoke("[ShipSystems.PaintJobs] Missing HDRP paint maps: " + text);
						return null;
					}
					_donors[num, i] = val;
				}
			}
			return _donors[num, (int)family];
		}

		internal static bool SupportsMaps(Material material)
		{
			if ((Object)(object)material != (Object)null && (Object)(object)material.shader != (Object)null && ((Object)material.shader).name == "HDRP/Lit" && material.HasProperty(BaseMap))
			{
				return material.HasProperty(MaskMap);
			}
			return false;
		}

		internal static Material Clone(Material original, Material donor, int level)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Expected O, but got Unknown
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			Material val = new Material(original)
			{
				name = $"Y4NGZ.PaintJobs.{level}.{((Object)original).name}"
			};
			val.SetTexture(BaseMap, donor.GetTexture(BaseMap));
			val.SetTexture(MaskMap, donor.GetTexture(MaskMap));
			if (val.HasProperty(BaseColor))
			{
				val.SetColor(BaseColor, Color.white);
			}
			if (val.HasProperty(Metallic))
			{
				val.SetFloat(Metallic, 1f);
			}
			if (val.HasProperty(Smoothness))
			{
				val.SetFloat(Smoothness, 1f);
			}
			for (int i = 0; i < RemapMin.Length; i++)
			{
				if (val.HasProperty(RemapMin[i]))
				{
					val.SetFloat(RemapMin[i], 0f);
				}
				if (val.HasProperty(RemapMax[i]))
				{
					val.SetFloat(RemapMax[i], 1f);
				}
			}
			val.EnableKeyword("_MASKMAP");
			return val;
		}

		internal static PaintMaterialFamily FamilyOf(Material material)
		{
			if (!SupportsMaps(material))
			{
				return PaintMaterialFamily.None;
			}
			string name = ((Object)material).name;
			int num = name.Length;
			while (EndsWith(name, num, " (Instance)") || EndsWith(name, num, " (Clone)"))
			{
				num -= (EndsWith(name, num, " (Instance)") ? 11 : 8);
			}
			if (EqualsName(name, num, "HangarShipHull") || EqualsName(name, num, "HangarShipHull.002"))
			{
				return PaintMaterialFamily.Vinyl;
			}
			if (EqualsName(name, num, "HangarShipRoomMetal") || EqualsName(name, num, "HangarShipFloor"))
			{
				return PaintMaterialFamily.Metal;
			}
			if (EqualsName(name, num, "CatwalkGrate"))
			{
				return PaintMaterialFamily.Grate;
			}
			if ((EqualsName(name, num, "CatwalkRail") || EqualsName(name, num, "CatwalkRailB") || EqualsName(name, num, "CatwalkRailBase") || EqualsName(name, num, "Rail")) && (Object)(object)material.GetTexture(BaseMap) == (Object)null)
			{
				return PaintMaterialFamily.Vinyl;
			}
			return PaintMaterialFamily.None;
		}

		private static bool EqualsName(string name, int length, string expected)
		{
			if (length == expected.Length)
			{
				return string.CompareOrdinal(name, 0, expected, 0, length) == 0;
			}
			return false;
		}

		private static bool EndsWith(string name, int length, string suffix)
		{
			if (length >= suffix.Length)
			{
				return string.CompareOrdinal(name, length - suffix.Length, suffix, 0, suffix.Length) == 0;
			}
			return false;
		}
	}
	internal sealed class PaintJobsEffect : IRefitEffect
	{
		private sealed class Snapshot
		{
			internal Material[] Applied;

			internal bool Seen;

			internal Snapshot(int count)
			{
				Applied = (Material[])(object)new Material[count];
			}
		}

		private static readonly string[] VanillaTargets = new string[7] { "ShipInside", "ShipHull", "ShipRails", "ShipRailPosts", "CatwalkShip", "CatwalkRailLining", "CatwalkRailLiningB" };

		private static readonly string[] LayoutRoots = new string[4] { "ShipBoth_LGU", "MelanieShip_LGU", "wall_left", "wall_right" };

		private readonly PaintMaterialCache _materials = new PaintMaterialCache();

		private readonly Dictionary<Renderer, Snapshot> _snapshots = new Dictionary<Renderer, Snapshot>();

		private readonly List<Renderer> _removed = new List<Renderer>();

		private readonly List<MeshRenderer> _layoutRenderers = new List<MeshRenderer>();

		private readonly List<Material> _live = new List<Material>();

		public ShipUpgradeId Id => ShipUpgradeId.PaintJobs;

		public void Apply(int level, RefitEffectContext context)
		{
			Transform shipRoot = context.ShipRoot;
			ShipPaintScheme.NotifyApplied((!((Object)(object)shipRoot == (Object)null)) ? level : 0);
			if (level < 2 || level > 8 || (Object)(object)shipRoot == (Object)null)
			{
				Remove();
				return;
			}
			_materials.BeginReconcile();
			foreach (Snapshot value in _snapshots.Values)
			{
				value.Seen = false;
			}
			for (int i = 0; i < VanillaTargets.Length; i++)
			{
				Transform val = shipRoot.Find(VanillaTargets[i]);
				if ((Object)(object)val != (Object)null)
				{
					Reconcile((Renderer)(object)((Component)val).GetComponent<MeshRenderer>(), level);
				}
			}
			for (int j = 0; j < shipRoot.childCount; j++)
			{
				Transform child = shipRoot.GetChild(j);
				string name = ((Object)child).name;
				bool flag = false;
				for (int k = 0; k < LayoutRoots.Length; k++)
				{
					if (!(name != LayoutRoots[k]))
					{
						flag = true;
						break;
					}
				}
				if (flag)
				{
					_layoutRenderers.Clear();
					((Component)child).GetComponentsInChildren<MeshRenderer>(true, _layoutRenderers);
					for (int l = 0; l < _layoutRenderers.Count; l++)
					{
						Reconcile((Renderer)(object)_layoutRenderers[l], level);
					}
				}
			}
			_layoutRenderers.Clear();
			_removed.Clear();
			foreach (KeyValuePair<Renderer, Snapshot> snapshot in _snapshots)
			{
				if ((Object)(object)snapshot.Key == (Object)null || !snapshot.Value.Seen)
				{
					RestoreOwnedMaterials(snapshot.Key, snapshot.Value);
					_removed.Add(snapshot.Key);
				}
			}
			for (int m = 0; m < _removed.Count; m++)
			{
				_snapshots.Remove(_removed[m]);
			}
			_removed.Clear();
			_materials.EndReconcile();
		}

		private void Reconcile(Renderer renderer, int level)
		{
			if ((Object)(object)renderer == (Object)null)
			{
				return;
			}
			_live.Clear();
			renderer.GetSharedMaterials(_live);
			bool flag = false;
			for (int i = 0; i < _live.Count; i++)
			{
				if (PaintJobMaterials.FamilyOf(_materials.OriginalOf(_live[i])) != PaintMaterialFamily.None)
				{
					flag = true;
					break;
				}
			}
			if (!flag)
			{
				if (_snapshots.TryGetValue(renderer, out var value))
				{
					RestoreOwnedMaterials(renderer, value);
				}
				_snapshots.Remove(renderer);
				_live.Clear();
				return;
			}
			if (!_snapshots.TryGetValue(renderer, out var value2))
			{
				value2 = new Snapshot(_live.Count);
				_snapshots.Add(renderer, value2);
			}
			else if (value2.Applied.Length != _live.Count)
			{
				value2.Applied = (Material[])(object)new Material[_live.Count];
			}
			value2.Seen = true;
			bool flag2 = false;
			for (int j = 0; j < _live.Count; j++)
			{
				Material original = _materials.OriginalOf(_live[j]);
				Material val = _materials.Paint(original, level);
				value2.Applied[j] = val;
				if (_live[j] != val)
				{
					flag2 = true;
				}
			}
			if (flag2)
			{
				renderer.sharedMaterials = value2.Applied;
			}
			_live.Clear();
		}

		private void RestoreOwnedMaterials(Renderer renderer, Snapshot snapshot)
		{
			if ((Object)(object)renderer == (Object)null)
			{
				return;
			}
			_live.Clear();
			renderer.GetSharedMaterials(_live);
			bool flag = false;
			for (int i = 0; i < _live.Count; i++)
			{
				Material val = _materials.OriginalOf(_live[i]);
				if (val != _live[i])
				{
					_live[i] = val;
					flag = true;
				}
			}
			if (flag)
			{
				if (snapshot.Applied.Length != _live.Count)
				{
					snapshot.Applied = (Material[])(object)new Material[_live.Count];
				}
				_live.CopyTo(snapshot.Applied);
				renderer.sharedMaterials = snapshot.Applied;
			}
			_live.Clear();
		}

		private void Remove()
		{
			foreach (KeyValuePair<Renderer, Snapshot> snapshot in _snapshots)
			{
				RestoreOwnedMaterials(snapshot.Key, snapshot.Value);
			}
			_snapshots.Clear();
			_materials.Clear();
			_removed.Clear();
			_layoutRenderers.Clear();
			_live.Clear();
		}
	}
	internal sealed class PaintMaterialCache
	{
		private sealed class Source
		{
			internal readonly PaintMaterialFamily Family;

			internal readonly Material[] Schemes = (Material[])(object)new Material[7];

			internal bool Referenced;

			internal Source(PaintMaterialFamily family)
			{
				Family = family;
			}
		}

		private readonly PaintJobMaterials _donors = new PaintJobMaterials();

		private readonly Dictionary<Material, Source> _sources = new Dictionary<Material, Source>();

		private readonly Dictionary<Material, Material> _originals = new Dictionary<Material, Material>();

		private readonly List<Material> _unused = new List<Material>();

		internal Material OriginalOf(Material material)
		{
			if (material == null || !_originals.TryGetValue(material, out var value))
			{
				return material;
			}
			return value;
		}

		internal void BeginReconcile()
		{
			foreach (Source value in _sources.Values)
			{
				value.Referenced = false;
			}
		}

		internal Material Paint(Material original, int level)
		{
			if ((Object)(object)original == (Object)null)
			{
				return original;
			}
			if (!_sources.TryGetValue(original, out var value))
			{
				PaintMaterialFamily paintMaterialFamily = PaintJobMaterials.FamilyOf(original);
				if (paintMaterialFamily == PaintMaterialFamily.None)
				{
					return original;
				}
				value = new Source(paintMaterialFamily);
				_sources.Add(original, value);
			}
			value.Referenced = true;
			int num = level - 2;
			Material val = value.Schemes[num];
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
			Material val2 = _donors.Get(level, value.Family);
			if ((Object)(object)val2 == (Object)null)
			{
				return original;
			}
			if (val != null)
			{
				_originals.Remove(val);
			}
			val = PaintJobMaterials.Clone(original, val2, level);
			value.Schemes[num] = val;
			_originals.Add(val, original);
			return val;
		}

		internal void EndReconcile()
		{
			_unused.Clear();
			foreach (KeyValuePair<Material, Source> source in _sources)
			{
				if ((Object)(object)source.Key == (Object)null || !source.Value.Referenced)
				{
					_unused.Add(source.Key);
				}
			}
			for (int i = 0; i < _unused.Count; i++)
			{
				Material key = _unused[i];
				DestroyClones(_sources[key]);
				_sources.Remove(key);
			}
			_unused.Clear();
		}

		internal void Clear()
		{
			foreach (Source value in _sources.Values)
			{
				DestroyClones(value);
			}
			_sources.Clear();
			_originals.Clear();
			_unused.Clear();
		}

		private void DestroyClones(Source source)
		{
			for (int i = 0; i < source.Schemes.Length; i++)
			{
				Material val = source.Schemes[i];
				if (val != null)
				{
					_originals.Remove(val);
					if ((Object)(object)val != (Object)null)
					{
						Object.Destroy((Object)(object)val);
					}
				}
			}
		}
	}
	internal static class ShipPaintScheme
	{
		internal readonly struct Rgb
		{
			internal readonly byte R;

			internal readonly byte G;

			internal readonly byte B;

			internal Rgb(byte r, byte g, byte b)
			{
				R = r;
				G = g;
				B = b;
			}
		}

		internal static readonly Rgb HazardOrange = new Rgb(180, 87, 30);

		internal static readonly Rgb DeepNavy = new Rgb(36, 57, 86);

		internal static readonly Rgb MatteBlack = new Rgb(37, 40, 43);

		internal static readonly Rgb ForestGreen = new Rgb(50, 84, 44);

		internal static readonly Rgb ArcticWhite = new Rgb(184, 192, 198);

		internal static readonly Rgb CrimsonRed = new Rgb(150, 30, 40);

		internal static readonly Rgb SafetyYellow = new Rgb(194, 164, 30);

		internal const int FirstPaintedLevel = 2;

		internal const int MaxLevel = 8;

		internal const int PaintedSchemeCount = 7;

		internal static int AppliedLevel { get; private set; }

		internal static event Action<int> AppliedLevelChanged;

		internal static bool TryGetTint(int level, out Rgb tint)
		{
			switch (level)
			{
			case 2:
				tint = HazardOrange;
				return true;
			case 3:
				tint = DeepNavy;
				return true;
			case 4:
				tint = MatteBlack;
				return true;
			case 5:
				tint = ForestGreen;
				return true;
			case 6:
				tint = ArcticWhite;
				return true;
			case 7:
				tint = CrimsonRed;
				return true;
			case 8:
				tint = SafetyYellow;
				return true;
			default:
				tint = default(Rgb);
				return false;
			}
		}

		internal static void NotifyApplied(int level)
		{
			if (level != AppliedLevel)
			{
				AppliedLevel = level;
				ShipPaintScheme.AppliedLevelChanged?.Invoke(level);
			}
		}
	}
}
namespace Y4NGZCompany.ShipSystems.Upgrades.FuelEfficiency
{
	internal sealed class FuelEfficiencyEffect : IRefitEffect, IFuelCostModifier
	{
		internal const string BundleFileName = "y4ngz-ship-fuel-efficiency.bundle";

		internal const string PrefabAddress = "assets/y4ngz/shipsystems/fuel-efficiency/auxtank.prefab";

		internal static readonly Vector3 MountPosition = new Vector3(2.9951f, 1f, -3.29513f);

		internal static readonly Vector3 MountEuler = new Vector3(0f, -19.06749f, 0f);

		private static FuelEfficiencyEffect _instance;

		private ShipSystemsController _controller;

		private GameObject _visual;

		private Transform _visualParent;

		private Transform _gauge;

		private int _visualLevel;

		private int _effectiveLevel;

		private int _cut;

		private bool _visualUnavailable;

		private bool _disposed;

		public ShipUpgradeId Id => ShipUpgradeId.FuelEfficiency;

		internal FuelEfficiencyEffect()
		{
			_instance = this;
			ShipLayoutBootstrap.Registrations.Add("fuel efficiency effect", Dispose);
		}

		public void Apply(int level, RefitEffectContext context)
		{
			if (!_disposed)
			{
				_effectiveLevel = (context.HostEnabled ? Math.Max(0, Math.Min(3, level)) : 0);
				ReconcileModifier(ShipSystemsController.Instance, _effectiveLevel);
				ReconcileVisual(context.ShipRoot, _effectiveLevel);
			}
		}

		public void ModifyFuelCosts(ref float entryCost, ref float moonCost)
		{
			entryCost = FuelEfficiencyRules.ApplyCut(entryCost, _cut);
			moonCost = FuelEfficiencyRules.ApplyCut(moonCost, _cut);
		}

		internal static void PrepareForQuote(ShipSystemsController controller)
		{
			FuelEfficiencyEffect instance = _instance;
			if (instance != null && !instance._disposed)
			{
				instance.ReconcileModifier(controller, instance._effectiveLevel);
			}
		}

		private void ReconcileModifier(ShipSystemsController controller, int level)
		{
			if ((Object)(object)_controller != (Object)null && ((Object)(object)_controller != (Object)(object)controller || level <= 0))
			{
				RemoveModifier();
			}
			if ((Object)(object)controller == (Object)null || level <= 0)
			{
				_cut = 0;
				return;
			}
			_controller = controller;
			_cut = FuelEfficiencyRules.CutForLevel(level);
			controller.FuelCostModifier = this;
		}

		private void RemoveModifier()
		{
			if ((Object)(object)_controller != (Object)null && _controller.FuelCostModifier == this)
			{
				_controller.FuelCostModifier = null;
			}
			_controller = null;
			_cut = 0;
		}

		private void ReconcileVisual(Transform parent, int level)
		{
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: 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)
			if (level <= 0 || (Object)(object)parent == (Object)null || ((Object)(object)_visual != (Object)null && (Object)(object)_visualParent != (Object)(object)parent))
			{
				RemoveVisual();
			}
			if (level <= 0 || (Object)(object)parent == (Object)null || _visualUnavailable)
			{
				return;
			}
			if ((Object)(object)_visual == (Object)null)
			{
				if (!SidecarBundle.TryLoad("y4ngz-ship-fuel-efficiency.bundle", out var bundle) || !SidecarBundle.TryInstantiate(bundle, "assets/y4ngz/shipsystems/fuel-efficiency/auxtank.prefab", parent, out _visual))
				{
					_visualUnavailable = true;
					ManualLogSource log = ShipSystemsBootstrap.Log;
					if (log != null)
					{
						log.LogWarning((object)"[ShipSystems.FuelEfficiency] Auxiliary tank prefab unavailable; fuel reduction remains active.");
					}
					return;
				}
				_visualParent = parent;
				Transform transform = _visual.transform;
				transform.localPosition = MountPosition;
				transform.localRotation = Quaternion.Euler(MountEuler);
				transform.localScale = Vector3.one;
				_gauge = transform.Find("GaugeFill");
				_visualLevel = 0;
				if ((Object)(object)_gauge == (Object)null)
				{
					ManualLogSource log2 = ShipSystemsBootstrap.Log;
					if (log2 != null)
					{
						log2.LogWarning((object)"[ShipSystems.FuelEfficiency] Auxiliary tank prefab has no GaugeFill child.");
					}
				}
			}
			if ((Object)(object)_gauge != (Object)null && _visualLevel != level)
			{
				Vector3 localScale = _gauge.localScale;
				localScale.y = (float)level / 3f;
				_gauge.localScale = localScale;
			}
			_visualLevel = level;
		}

		private void RemoveVisual()
		{
			if ((Object)(object)_visual != (Object)null)
			{
				_visual.SetActive(false);
				Object.Destroy((Object)(object)_visual);
			}
			_visual = null;
			_visualParent = null;
			_gauge = null;
			_visualLevel = 0;
		}

		private void Dispose()
		{
			_disposed = true;
			_effectiveLevel = 0;
			RemoveModifier();
			RemoveVisual();
			if (_instance == this)
			{
				_instance = null;
			}
		}
	}
	internal static class FuelEfficiencyRules
	{
		internal const int MaxLevel = 3;

		internal static int CutForLevel(int level)
		{
			return Math.Max(0, Math.Min(3, level)) * 10;
		}

		internal static float ApplyCut(float baseCost, int percent)
		{
			if (baseCost <= 0f || percent <= 0)
			{
				return baseCost;
			}
			int num = Math.Min(90, percent);
			float num2 = (float)Math.Round((double)baseCost * (double)(100 - num) / 100.0, MidpointRounding.AwayFromZero);
			if (!(baseCost >= 1f))
			{
				return num2;
			}
			return Math.Max(1f, num2);
		}
	}
	internal interface IFuelCostModifier
	{
		void ModifyFuelCosts(ref float entryCost, ref float moonCost);
	}
}
namespace Y4NGZCompany.ShipSystems.Upgrades.FlashlightShelf
{
	internal static class FlashlightShelfConfig
	{
		private const string Section = "Ship Upgrades: Flashlight Shelf";

		private static ConfigEntry<bool> _refill;

		internal static bool HostRefillEnabled => _refill?.Value ?? true;

		internal static void Bind(ConfigFile config)
		{
			_refill = config.Bind<bool>("Ship Upgrades: Flashlight Shelf", "Refill", true, "Host: replace lost shelf flashlights while the refit is owned and enabled; never replace flashlights carried by any player. When false, missing slots stay empty after loading an owned shelf; a new purchase still supplies four basic flashlights.");
		}
	}
	internal sealed class FlashlightShelfEffect : IRefitEffect
	{
		private readonly NetworkObjectReference[] _slots = (NetworkObjectReference[])(object)new NetworkObjectReference[4];

		private readonly bool[] _bound = new bool[4];

		private readonly bool[] _restore = new bool[4];

		private readonly int[] _restoreCharge = new int[4];

		private readonly FlashlightShelfPresentation _presentation = new FlashlightShelfPresentation();

		private StartOfRound _round;

		private Transform _shipRoot;

		private bool _hostContext;

		private bool _enabled;

		private bool _startupInProgress;

		private bool _itemsLoaded;

		private bool _activated;

		private bool _initialPending;

		private bool _freshPurchase;

		private bool _disposed;

		private Item _basicItem;

		public ShipUpgradeId Id => ShipUpgradeId.FlashlightShelf;

		internal FlashlightShelfEffect()
		{
			FlashlightShelfPatches.Install(this);
			ShipLayoutBootstrap.Registrations.Add("flashlight shelf", Dispose);
		}

		public void Apply(int level, RefitEffectContext context)
		{
			if (_disposed)
			{
				return;
			}
			EnsureSession(StartOfRound.Instance, context.ShipRoot);
			_hostContext = context.IsHost;
			if (level <= 0 || !context.HostEnabled || !InSession() || !((Object)(object)_shipRoot != (Object)null))
			{
				RemoveRackItems();
				_enabled = false;
				_presentation.Remove();
				return;
			}
			_enabled = true;
			if (!_activated)
			{
				_activated = true;
				_initialPending = true;
				_freshPurchase = _itemsLoaded && !_startupInProgress;
			}
			if (_presentation.Ensure(_shipRoot, context.LayoutType, this))
			{
				if (IsHost() && _itemsLoaded)
				{
					InitializeSlots();
					RestoreRemovedSlots();
				}
				_presentation.Refresh();
			}
		}

		internal void OnRoundStarting(StartOfRound round)
		{
			if (!_disposed && !((Object)(object)round == (Object)null) && !((Object)(object)round != (Object)(object)StartOfRound.Instance))
			{
				EnsureSession(round, round.elevatorTransform);
				_startupInProgress = true;
			}
		}

		internal void OnRoundStarted(StartOfRound round)
		{
			if ((Object)(object)round == (Object)(object)_round)
			{
				_startupInProgress = false;
			}
		}

		internal void OnItemsLoaded(StartOfRound round)
		{
			if (!_disposed && !((Object)(object)round == (Object)null) && !((Object)(object)round != (Object)(object)StartOfRound.Instance))
			{
				EnsureSession(round, round.elevatorTransform);
				if (!_itemsLoaded)
				{
					_itemsLoaded = true;
					_presentation.CollectCandidates(round.elevatorTransform);
				}
				if (_enabled && IsHost() && _presentation.IsReady)
				{
					InitializeSlots();
					RestoreRemovedSlots();
				}
			}
		}

		internal void OnShipReady(StartOfRound round)
		{
			if (_disposed || (Object)(object)round != (Object)(object)_round || !_enabled || !_itemsLoaded || !IsHost() || !_presentation.IsReady)
			{
				return;
			}
			InitializeSlots();
			RestoreRemovedSlots();
			if (!FlashlightShelfConfig.HostRefillEnabled)
			{
				return;
			}
			for (int i = 0; i < _slots.Length; i++)
			{
				GrabbableObject val = ResolveSlot(i);
				bool playerHeld = (Object)(object)val != (Object)null && !IsUnheld(val);
				if (FlashlightShelfRules.ShouldReplace((Object)(object)val != (Object)null, playerHeld, IsInsideShip(val)) && (!((Object)(object)val != (Object)null) || TryDespawn(val)))
				{
					ClearSlot(i);
					TrySpawnSlot(i, 100);
				}
			}
		}

		internal void OnItemStarted(GrabbableObject item)
		{
			if (!_disposed && InSession() && IsBasicFlashlight(item))
			{
				StartOfRound instance = StartOfRound.Instance;
				if (!((Object)(object)instance.elevatorTransform == (Object)null))
				{
					EnsureSession(instance, instance.elevatorTransform);
					_presentation.ObserveStartup(item, instance.elevatorTransform);
				}
			}
		}

		internal void RefreshPresentation()
		{
			if (!_disposed && _enabled)
			{
				if (!InSession() || (Object)(object)_round != (Object)(object)StartOfRound.Instance || (Object)(object)_shipRoot == (Object)null)
				{
					ResetSession();
				}
				else
				{
					_presentation.Tick();
				}
			}
		}

		internal void OnCrewFired()
		{
			if (IsHost())
			{
				RemoveRackItems();
				ClearOwnership();
			}
		}

		internal void ResetSession()
		{
			RemoveRackItems();
			ClearOwnership();
			_basicItem = null;
			_itemsLoaded = false;
			_startupInProgress = false;
			_hostContext = false;
			_shipRoot = null;
			_round = null;
		}

		private void EnsureSession(StartOfRound round, Transform root)
		{
			if (!((Object)(object)_round == (Object)(object)round) || !((Object)(object)_shipRoot == (Object)(object)root))
			{
				bool startupInProgress = (Object)(object)round != (Object)null && (Object)(object)_round == (Object)(object)round && _startupInProgress;
				ResetSession();
				_round = round;
				_shipRoot = root;
				_startupInProgress = startupInProgress;
			}
		}

		private void ClearOwnership()
		{
			_enabled = false;
			_activated = false;
			_initialPending = false;
			_freshPurchase = false;
			for (int i = 0; i < _slots.Length; i++)
			{
				ClearSlot(i);
				_restore[i] = false;
				_restoreCharge[i] = 0;
			}
			_presentation.Remove();
			_presentation.ClearStartupObservations();
		}

		private static bool InSession()
		{
			NetworkManager singleton = NetworkManager.Singleton;
			if ((Object)(object)StartOfRound.Instance != (Object)null && (Object)(object)singleton != (Object)null)
			{
				return singleton.IsListening;
			}
			return false;
		}

		private bool IsHost()
		{
			NetworkManager singleton = NetworkManager.Singleton;
			if (_hostContext && InSession() && singleton.IsServer)
			{
				return (Object)(object)_round == (Object)(object)StartOfRound.Instance;
			}
			return false;
		}

		private void Dispose()
		{
			if (!_disposed)
			{
				ResetSession();
				_disposed = true;
				FlashlightShelfPatches.Uninstall(this);
			}
		}

		private void InitializeSlots()
		{
			if (!_initialPending)
			{
				return;
			}
			_initialPending = false;
			for (int i = 0; i < _slots.Length; i++)
			{
				if (!((Object)(object)ResolveSlot(i) != (Object)null))
				{
					GrabbableObject val = FindCandidate(i, atSocketOnly: true);
					if ((Object)(object)val != (Object)null)
					{
						BindSlot(i, val);
						_presentation.SettleAtSocket(val, i);
					}
				}
			}
			for (int j = 0; j < _slots.Length; j++)
			{
				if (!((Object)(object)ResolveSlot(j) != (Object)null))
				{
					GrabbableObject val2 = FindCandidate(j, atSocketOnly: false);
					if ((Object)(object)val2 != (Object)null)
					{
						BindSlot(j, val2);
					}
					else if (_freshPurchase || FlashlightShelfConfig.HostRefillEnabled)
					{
						TrySpawnSlot(j, 100);
					}
				}
			}
		}

		private GrabbableObject FindCandidate(int slot, bool atSocketOnly)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			List<GrabbableObject> candidates = _presentation.Candidates;
			GrabbableObject result = null;
			float num = float.MaxValue;
			Vector3 position = _presentation.Socket(slot).position;
			for (int i = 0; i < candidates.Count; i++)
			{
				GrabbableObject val = candidates[i];
				if (IsBasicFlashlight(val) && IsUnheld(val) && IsInsideShip(val) && !((Object)(object)((NetworkBehaviour)val).NetworkObject == (Object)null) && ((NetworkBehaviour)val).NetworkObject.IsSpawned && !IsBound(val))
				{
					Vector3 val2 = ((Component)val).transform.position - position;
					float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude;
					if ((!atSocketOnly || FlashlightShelfRules.IsRackHeld(unheld: true, sqrMagnitude)) && sqrMagnitude < num)
					{
						result = val;
						num = sqrMagnitude;
					}
				}
			}
			return result;
		}

		private void RestoreRemovedSlots()
		{
			for (int i = 0; i < _restore.Length; i++)
			{
				if (_restore[i] && ((Object)(object)ResolveSlot(i) != (Object)null || TrySpawnSlot(i, _restoreCharge[i])))
				{
					_restore[i] = false;
				}
			}
		}

		private void RemoveRackItems()
		{
			//IL_003d: 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_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			if (!_enabled || !IsHost() || !_presentation.IsReady)
			{
				return;
			}
			List<GrabbableObject> candidates = _presentation.Candidates;
			for (int i = 0; i < _slots.Length; i++)
			{
				Vector3 position = _presentation.Socket(i).position;
				for (int j = 0; j < candidates.Count; j++)
				{
					GrabbableObject val = candidates[j];
					if (!IsBasicFlashlight(val) || (Object)(object)((NetworkBehaviour)val).NetworkObject == (Object)null || !((Netw