Decompiled source of LC BetterMonitors v2.1.0

BepInEx/plugins/GoAwayModList.dll

Decompiled 7 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using LC_API;
using LC_API.GameInterfaceAPI.Features;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("Go Away ModList")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Go Away ModList")]
[assembly: AssemblyCopyright("Copyright © RTPoogle 2024")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("6e7bde11-075e-4589-8140-a0065ee617f8")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		internal IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}
namespace FacilityMeltdownPatch
{
	[BepInPlugin("xyz.poogle.goml", "Go Away ModList", "1.0.1")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class GOMLPlugin : BaseUnityPlugin
	{
		public const string GUID = "xyz.poogle.goml";

		public const string NAME = "Go Away ModList";

		public const string VER = "1.0.1";

		public readonly Harmony harmony = new Harmony("xyz.poogle.goml");

		public ManualLogSource LogSrc;

		public static GOMLPlugin Instance;

		private void Awake()
		{
			if ((Object)(object)Instance == (Object)null)
			{
				Instance = this;
			}
			LogSrc = Logger.CreateLogSource("xyz.poogle.goml");
			Patches.InitPatches();
			LogSrc.LogInfo((object)"Initialized!");
		}
	}
	internal class Patches
	{
		[HarmonyPatch]
		public static class CheatDatabase_OtherPlayerCheatDetector_Patch
		{
			private static readonly MethodInfo QueueTip = AccessTools.Method(typeof(Player), "QueueTip", (Type[])null, (Type[])null);

			private static readonly MethodInfo LocalPlayer = AccessTools.PropertyGetter(typeof(Player), "LocalPlayer");

			private static readonly MethodInfo Nop_With_Params = CreateDynamicNop();

			private static readonly int LookAhead = ((MethodBase)QueueTip).GetParameterTypes().Length + 1;

			private static MethodInfo CreateDynamicNop()
			{
				DynamicMethod dynamicMethod = new DynamicMethod("Nop", null, ((MethodBase)QueueTip).GetParameterTypes(), typeof(Player));
				dynamicMethod.GetILGenerator().Emit(OpCodes.Ret);
				return dynamicMethod;
			}

			public static IEnumerable<MethodBase> TargetMethods()
			{
				return AccessTools.GetDeclaredMethods(typeof(CheatDatabase)).Cast<MethodBase>();
			}

			private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase original)
			{
				//IL_005e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0068: Expected O, but got Unknown
				//IL_007a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0084: Expected O, but got Unknown
				GOMLPlugin.Instance.LogSrc.LogInfo((object)("Patching " + original.Name));
				List<CodeInstruction> list = new List<CodeInstruction>(instructions);
				for (int i = 0; i < list.Count - LookAhead; i++)
				{
					if (CodeInstructionExtensions.Calls(list[i], LocalPlayer) && CodeInstructionExtensions.Calls(list[i + LookAhead], QueueTip))
					{
						list[i] = new CodeInstruction(OpCodes.Nop, (object)null);
						list[i + LookAhead] = new CodeInstruction(OpCodes.Callvirt, (object)Nop_With_Params);
					}
				}
				GOMLPlugin.Instance.LogSrc.LogInfo((object)("Patched " + original.Name));
				return list;
			}
		}

		internal static void InitPatches()
		{
			GOMLPlugin.Instance.harmony.PatchAll();
		}
	}
}

BepInEx/plugins/MeteoMultiplier.dll

Decompiled 7 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Microsoft.CodeAnalysis;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("MeteoMultiplier")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Multiplies loot value according to meteorigical conditions. An improved version of the other mod with a similar name")]
[assembly: AssemblyFileVersion("1.1.3.0")]
[assembly: AssemblyInformationalVersion("1.1.3+9ac6c74c13fd163aad4e01cf6c11e4dd7c3de1d8")]
[assembly: AssemblyProduct("MeteoMultiplier")]
[assembly: AssemblyTitle("MeteoMultiplier")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.1.3.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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 MeteoMultiplier
{
	[BepInPlugin("com.github.fredolx.meteomultiplier", "MeteoMultiplier", "1.1.3")]
	public class Plugin : BaseUnityPlugin
	{
		public static Dictionary<LevelWeatherType, ConfigEntry<float>> Multipliers = new Dictionary<LevelWeatherType, ConfigEntry<float>>();

		public static Dictionary<LevelWeatherType, ConfigEntry<float>> SpawnMultipliers = new Dictionary<LevelWeatherType, ConfigEntry<float>>();

		public static ConfigEntry<bool> MultipliersEnabled;

		public static ConfigEntry<bool> SpawnMultipliersEnabled;

		public static ConfigEntry<bool> MultiplyApparatusEnabled;

		public const LevelWeatherType DEFAULT_WEATHER = -1;

		private void Awake()
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Plugin MeteoMultiplier is loaded!");
			Harmony val = new Harmony("MeteoMultiplier");
			SetConfig();
			((BaseUnityPlugin)this).Logger.LogInfo((object)$"MultipliersEnabled: {MultipliersEnabled.Value}");
			((BaseUnityPlugin)this).Logger.LogInfo((object)$"MultiplyApparatusEnabled: {MultiplyApparatusEnabled.Value}");
			((BaseUnityPlugin)this).Logger.LogInfo((object)("Multipliers:\n" + string.Join("\n", Multipliers.Select((KeyValuePair<LevelWeatherType, ConfigEntry<float>> x) => $"{x.Key}:{x.Value.Value}"))));
			((BaseUnityPlugin)this).Logger.LogInfo((object)$"SpawnMultipliersEnabled: {SpawnMultipliersEnabled.Value}");
			((BaseUnityPlugin)this).Logger.LogInfo((object)("SpawnMultipliers:\n" + string.Join("\n", SpawnMultipliers.Select((KeyValuePair<LevelWeatherType, ConfigEntry<float>> x) => $"{x.Key}:{x.Value.Value}"))));
			val.PatchAll();
		}

		private void SetConfig()
		{
			MultipliersEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Multipliers", "Enabled", true, "Enables multipliers (scrap value according to meteo)");
			MultiplyApparatusEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Multipliers", "MultiplyApparatusEnabled", true, "Also multiply the value of the apparatus (power module) according to meteo");
			SetMultipliers();
			SpawnMultipliersEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Spawn Multipliers", "Enabled", false, "Enables spawn multipliers (amount of scrap in the map)");
			SetSpawnMultipliers();
		}

		private void SetMultipliers()
		{
			Multipliers.Add((LevelWeatherType)(-1), ((BaseUnityPlugin)this).Config.Bind<float>("Multipliers", "None", 0.4f, "No weather event"));
			Multipliers.Add((LevelWeatherType)0, ((BaseUnityPlugin)this).Config.Bind<float>("Multipliers", "DustClouds", 0.44f, "Dust Clouds"));
			Multipliers.Add((LevelWeatherType)3, ((BaseUnityPlugin)this).Config.Bind<float>("Multipliers", "Foggy", 0.44f, "Foggy"));
			Multipliers.Add((LevelWeatherType)1, ((BaseUnityPlugin)this).Config.Bind<float>("Multipliers", "Rainy", 0.44f, "Rainy"));
			Multipliers.Add((LevelWeatherType)2, ((BaseUnityPlugin)this).Config.Bind<float>("Multipliers", "Stormy", 0.52f, "Stormy"));
			Multipliers.Add((LevelWeatherType)4, ((BaseUnityPlugin)this).Config.Bind<float>("Multipliers", "Flooded", 0.56f, "Flooded"));
			Multipliers.Add((LevelWeatherType)5, ((BaseUnityPlugin)this).Config.Bind<float>("Multipliers", "Eclipsed", 0.6f, "Eclipsed"));
		}

		private void SetSpawnMultipliers()
		{
			SpawnMultipliers.Add((LevelWeatherType)(-1), ((BaseUnityPlugin)this).Config.Bind<float>("Spawn Multipliers", "None", 1f, "No weather event"));
			SpawnMultipliers.Add((LevelWeatherType)0, ((BaseUnityPlugin)this).Config.Bind<float>("Spawn Multipliers", "DustClouds", 1.25f, "Dust Clouds"));
			SpawnMultipliers.Add((LevelWeatherType)3, ((BaseUnityPlugin)this).Config.Bind<float>("Spawn Multipliers", "Foggy", 1.25f, "Foggy"));
			SpawnMultipliers.Add((LevelWeatherType)1, ((BaseUnityPlugin)this).Config.Bind<float>("Spawn Multipliers", "Rainy", 1.25f, "Rainy"));
			SpawnMultipliers.Add((LevelWeatherType)2, ((BaseUnityPlugin)this).Config.Bind<float>("Spawn Multipliers", "Stormy", 1.5f, "Stormy"));
			SpawnMultipliers.Add((LevelWeatherType)4, ((BaseUnityPlugin)this).Config.Bind<float>("Spawn Multipliers", "Flooded", 1.5f, "Flooded"));
			SpawnMultipliers.Add((LevelWeatherType)5, ((BaseUnityPlugin)this).Config.Bind<float>("Spawn Multipliers", "Eclipsed", 1.5f, "Eclipsed"));
		}
	}
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "MeteoMultiplier";

		public const string PLUGIN_NAME = "MeteoMultiplier";

		public const string PLUGIN_VERSION = "1.1.3";
	}
}
namespace MeteoMultiplier.Patches
{
	[HarmonyPatch(typeof(LungProp), "DisconnectFromMachinery")]
	public class MultiplyApparatus
	{
		private static void Prefix(LungProp __instance)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			LevelWeatherType currentWeather = __instance.roundManager.currentLevel.currentWeather;
			if (Plugin.MultiplyApparatusEnabled.Value && Plugin.Multipliers.ContainsKey(currentWeather))
			{
				((GrabbableObject)__instance).SetScrapValue((int)((float)((GrabbableObject)__instance).scrapValue * (Plugin.Multipliers[currentWeather].Value + 1f)));
			}
		}
	}
	[HarmonyPatch(typeof(RoundManager), "SpawnScrapInLevel")]
	public class SpawnScrapInLevelPatches
	{
		private static void Prefix(RoundManager __instance)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			LevelWeatherType currentWeather = __instance.currentLevel.currentWeather;
			if (Plugin.MultipliersEnabled.Value)
			{
				if (Plugin.Multipliers.ContainsKey(currentWeather))
				{
					__instance.scrapValueMultiplier = Plugin.Multipliers[currentWeather].Value;
				}
				else
				{
					__instance.scrapValueMultiplier = Plugin.Multipliers[(LevelWeatherType)(-1)].Value;
				}
			}
			if (Plugin.SpawnMultipliersEnabled.Value)
			{
				if (Plugin.SpawnMultipliers.ContainsKey(currentWeather))
				{
					__instance.scrapAmountMultiplier = Plugin.SpawnMultipliers[currentWeather].Value;
				}
				else
				{
					__instance.scrapAmountMultiplier = Plugin.SpawnMultipliers[(LevelWeatherType)(-1)].Value;
				}
			}
		}
	}
}

BepInEx/plugins/OpenBodyCams.dll

Decompiled 7 months ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using AdvancedCompany.Game;
using AdvancedCompany.Objects;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using LethalVRM;
using Microsoft.CodeAnalysis;
using ModelReplacement;
using MoreCompany;
using MoreCompany.Cosmetics;
using OpenBodyCams.Compatibility;
using OpenBodyCams.Patches;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.HighDefinition;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("OpenBodyCams")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("OpenBodyCams")]
[assembly: AssemblyCopyright("Copyright ©  2024")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("3d49e5ff-443d-44f6-90aa-a870ecfeb2d5")]
[assembly: AssemblyFileVersion("1.3.0")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.3.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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 OpenBodyCams
{
	public class BodyCamComponent : MonoBehaviour
	{
		[Flags]
		private enum TargetDirtyStatus
		{
			None = 0,
			Immediate = 1,
			UntilRender = 2
		}

		private enum Perspective
		{
			FirstPerson,
			ThirdPerson
		}

		public const int DEFAULT_LAYER = 0;

		public const int ENEMIES_LAYER = 19;

		public const int ENEMIES_NOT_RENDERED_LAYER = 23;

		private const float RADAR_BOOSTER_INITIAL_PAN = 270f;

		private static readonly Vector3 BODY_CAM_OFFSET = new Vector3(0.07f, 0f, 0.15f);

		private static readonly Vector3 CAMERA_CONTAINER_OFFSET = new Vector3(0.07f, 0f, 0.125f);

		private static BodyCamComponent[] AllBodyCams = Array.Empty<BodyCamComponent>();

		private static BodyCamComponent lastBodyCamRendered;

		private static int bodyCamCullingMask;

		private static FrameSettings mainCameraCustomFrameSettings;

		private static FrameSettingsOverrideMask mainCameraCustomFrameSettingsMask;

		private static Material fogShaderMaterial;

		private static GameObject nightVisionPrefab;

		private static bool hasFinishedStaticSetup = false;

		private static bool disableCameraWhileTargetIsOnShip = false;

		private static Color screenEmissiveColor;

		private static float radarBoosterPanSpeed;

		private static bool bruteForcePreventNullModels;

		internal GameObject CameraObject;

		internal Camera Camera;

		internal Renderer MonitorRenderer;

		internal int MonitorMaterialIndex = -1;

		internal Material MonitorOnMaterial;

		internal Material MonitorOffMaterial;

		internal bool MonitorIsOn = true;

		private bool keepCameraOn;

		private bool enableCamera = true;

		private bool wasBlanked;

		private GameObject[] localPlayerCosmetics = Array.Empty<GameObject>();

		private PlayerModelState localPlayerModelState;

		private PlayerControllerB currentPlayer;

		private GameObject[] currentPlayerCosmetics = Array.Empty<GameObject>();

		private PlayerModelState currentPlayerModelState;

		private Transform currentActualTarget;

		internal Renderer[] currentlyViewedMeshes = Array.Empty<Renderer>();

		private TargetDirtyStatus targetDirtyStatus;

		private float elapsedSinceLastFrame;

		private float timePerFrame;

		private bool panCamera;

		private float panAngle = 270f;

		private Light nightVisionLight;

		private MeshRenderer greenFlashRenderer;

		private Animator greenFlashAnimator;

		private MeshRenderer fogShaderPlaneRenderer;

		public bool ForceEnableCamera
		{
			get
			{
				return keepCameraOn;
			}
			set
			{
				keepCameraOn = value;
			}
		}

		public bool IsBlanked => wasBlanked;

		public event Action<Camera> OnCameraCreated;

		public event Action<RenderTexture> OnRenderTextureCreated;

		public event Action<bool> OnBlankedSet;

		public static BodyCamComponent[] GetAllBodyCams()
		{
			BodyCamComponent[] allBodyCams = AllBodyCams;
			int num = 0;
			BodyCamComponent[] array = new BodyCamComponent[allBodyCams.Length];
			BodyCamComponent[] array2 = allBodyCams;
			foreach (BodyCamComponent bodyCamComponent in array2)
			{
				array[num] = bodyCamComponent;
				num++;
			}
			return array;
		}

		public Camera GetCamera()
		{
			return Camera;
		}

		internal static void InitializeStatic()
		{
			RenderPipelineManager.beginCameraRendering += BeginAnyCameraRendering;
			RenderPipelineManager.endCameraRendering += EndAnyCameraRendering;
		}

		internal static void InitializeAtStartOfGame()
		{
			//IL_00f3: 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_008b: 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)
			PlayerControllerB val = StartOfRound.Instance.allPlayerScripts[0];
			bodyCamCullingMask = val.gameplayCamera.cullingMask & ~LayerMask.GetMask(new string[3] { "Ignore Raycast", "UI", "HelmetVisor" });
			HDAdditionalCameraData component = ((Component)val.gameplayCamera).GetComponent<HDAdditionalCameraData>();
			if (component.customRenderingSettings)
			{
				Plugin.Instance.Logger.LogInfo((object)("Using custom camera settings from " + ((Object)component).name + "."));
				mainCameraCustomFrameSettings = component.renderingPathCustomFrameSettings;
				mainCameraCustomFrameSettingsMask = component.renderingPathCustomFrameSettingsOverrideMask;
			}
			fogShaderMaterial = ((Renderer)((Component)((Component)val.localVisor).transform.Find("ScavengerHelmet/Plane")).GetComponent<MeshRenderer>()).sharedMaterial;
			nightVisionPrefab = Object.Instantiate<GameObject>(((Component)val.nightVision).gameObject);
			((Object)nightVisionPrefab).hideFlags = (HideFlags)61;
			((Object)nightVisionPrefab).name = "NightVision";
			nightVisionPrefab.transform.localPosition = Vector3.zero;
			nightVisionPrefab.SetActive(false);
			Light mapCameraLight = StartOfRound.Instance.mapScreen.mapCameraLight;
			mapCameraLight.cullingMask = 1 << ((Component)mapCameraLight).gameObject.layer;
			UpdateAllCameraSettings();
			hasFinishedStaticSetup = true;
		}

		public static void UpdateAllCameraSettings()
		{
			UpdateStaticSettings();
			BodyCamComponent[] allBodyCams = AllBodyCams;
			for (int i = 0; i < allBodyCams.Length; i++)
			{
				allBodyCams[i].UpdateSettings();
			}
		}

		private static Color ParseColor(string str)
		{
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			float[] array = (from x in str.Split(new char[2] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries)
				select float.Parse(x.Trim(), CultureInfo.InvariantCulture)).ToArray();
			if (array.Length < 0 || array.Length > 4)
			{
				throw new ArgumentException("Too many color components");
			}
			return new Color(array[0], array[1], array[2], (array.Length == 4) ? array[3] : 0f);
		}

		private static Color GetEmissiveColor()
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				return ParseColor(Plugin.MonitorEmissiveColor.Value);
			}
			catch (Exception arg)
			{
				Plugin.Instance.Logger.LogWarning((object)$"Failed to parse emissive color: {arg}");
				return ParseColor((string)((ConfigEntryBase)Plugin.MonitorEmissiveColor).DefaultValue);
			}
		}

		internal static void UpdateStaticSettings()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			screenEmissiveColor = GetEmissiveColor();
			disableCameraWhileTargetIsOnShip = Plugin.DisableCameraWhileTargetIsOnShip.Value;
			radarBoosterPanSpeed = Plugin.RadarBoosterPanRPM.Value * 360f / 60f;
			bruteForcePreventNullModels = Plugin.BruteForcePreventFreezes.Value;
		}

		public static void MarkTargetDirtyUntilRenderForAllBodyCams(Transform target)
		{
			BodyCamComponent[] allBodyCams = AllBodyCams;
			for (int i = 0; i < allBodyCams.Length; i++)
			{
				allBodyCams[i].MarkTargetDirtyUntilRender(target);
			}
		}

		public static void MarkTargetDirtyUntilRenderForAllBodyCams()
		{
			BodyCamComponent[] allBodyCams = AllBodyCams;
			for (int i = 0; i < allBodyCams.Length; i++)
			{
				allBodyCams[i].MarkTargetDirtyUntilRender();
			}
		}

		public static void MarkTargetStatusChangedForAllBodyCams(Transform target)
		{
			BodyCamComponent[] allBodyCams = AllBodyCams;
			for (int i = 0; i < allBodyCams.Length; i++)
			{
				allBodyCams[i].MarkTargetStatusChanged(target);
			}
		}

		public static void MarkTargetStatusChangedForAllBodyCams()
		{
			BodyCamComponent[] allBodyCams = AllBodyCams;
			for (int i = 0; i < allBodyCams.Length; i++)
			{
				allBodyCams[i].MarkTargetStatusChanged();
			}
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private static void ResetLastRenderedBodyCam()
		{
			if ((Object)(object)lastBodyCamRendered != (Object)null)
			{
				lastBodyCamRendered.ResetCameraRendering();
				lastBodyCamRendered = null;
			}
		}

		private static void BeginAnyCameraRendering(ScriptableRenderContext context, Camera camera)
		{
			ResetLastRenderedBodyCam();
			int num = AllBodyCams.Length;
			for (int i = 0; i < num; i++)
			{
				BodyCamComponent bodyCamComponent = AllBodyCams[i];
				if (bodyCamComponent.Camera == camera)
				{
					lastBodyCamRendered = bodyCamComponent;
					bodyCamComponent.BeginCameraRendering();
					break;
				}
			}
		}

		private static void EndAnyCameraRendering(ScriptableRenderContext context, Camera camera)
		{
			ResetLastRenderedBodyCam();
		}

		private void Awake()
		{
			if (!hasFinishedStaticSetup)
			{
				Plugin.Instance.Logger.LogError((object)"Attempted to create a body cam before static initialization has been completed.");
				Plugin.Instance.Logger.LogError((object)"This may occur if the save is corrupted, or if a mod caused an error during the start of the game.");
				Object.Destroy((Object)(object)this);
				return;
			}
			BodyCamComponent[] allBodyCams = AllBodyCams;
			int num = 0;
			BodyCamComponent[] array = new BodyCamComponent[1 + allBodyCams.Length];
			BodyCamComponent[] array2 = allBodyCams;
			foreach (BodyCamComponent bodyCamComponent in array2)
			{
				array[num] = bodyCamComponent;
				num++;
			}
			array[num] = this;
			num++;
			AllBodyCams = array;
			((Behaviour)nightVisionPrefab.GetComponent<Light>()).enabled = false;
		}

		private void Start()
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Expected O, but got Unknown
			if ((Object)(object)MonitorRenderer != (Object)null)
			{
				MonitorOnMaterial = new Material(Shader.Find("HDRP/Unlit"))
				{
					name = "BodyCamMaterial"
				};
				MonitorOnMaterial.SetFloat("_AlbedoAffectEmissive", 1f);
				MonitorOffMaterial = ShipObjects.blackScreenMaterial;
				SetMaterial(MonitorRenderer, MonitorMaterialIndex, MonitorOnMaterial);
			}
			EnsureCameraExists();
			SyncBodyCamToRadarMap.UpdateBodyCamTarget(this);
		}

		private static void SetMaterial(Renderer renderer, int index, Material material)
		{
			Material[] sharedMaterials = renderer.sharedMaterials;
			sharedMaterials[index] = material;
			renderer.sharedMaterials = sharedMaterials;
		}

		public void EnsureCameraExists()
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Expected O, but got Unknown
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Expected O, but got Unknown
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_0214: Unknown result type (might be due to invalid IL or missing references)
			//IL_0234: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)CameraObject != (Object)null))
			{
				Plugin.Instance.Logger.LogInfo((object)"Camera has been destroyed, recreating it.");
				CameraObject = new GameObject("BodyCam");
				Camera = CameraObject.AddComponent<Camera>();
				Camera.nearClipPlane = 0.05f;
				Camera.cullingMask = bodyCamCullingMask;
				HDAdditionalCameraData val = CameraObject.AddComponent<HDAdditionalCameraData>();
				val.volumeLayerMask = LayerMask.op_Implicit(1);
				_ = mainCameraCustomFrameSettings;
				val.customRenderingSettings = true;
				val.renderingPathCustomFrameSettings = mainCameraCustomFrameSettings;
				val.renderingPathCustomFrameSettingsOverrideMask = mainCameraCustomFrameSettingsMask;
				GameObject val2 = Object.Instantiate<GameObject>(nightVisionPrefab);
				val2.transform.SetParent(CameraObject.transform, false);
				val2.SetActive(true);
				nightVisionLight = val2.GetComponent<Light>();
				UpdateSettings();
				GameObject val3 = new GameObject("CameraGreenTransitionScaler");
				val3.transform.SetParent(CameraObject.transform, false);
				val3.transform.localScale = new Vector3(1f, 0.004f, 1f);
				GameObject val4 = Object.Instantiate<GameObject>(((Component)StartOfRound.Instance.mapScreen.mapCameraAnimator).gameObject);
				val4.transform.SetParent(val3.transform, false);
				val4.transform.localPosition = new Vector3(0f, 0f, 0.1f);
				val4.layer = 0;
				greenFlashRenderer = val4.GetComponent<MeshRenderer>();
				((Renderer)greenFlashRenderer).forceRenderingOff = true;
				greenFlashAnimator = val4.GetComponent<Animator>() ?? throw new Exception("Green flash object copied from the map screen has no Animator.");
				greenFlashAnimator.Play("MapTransitionGreen", 0, 1f);
				greenFlashAnimator.WriteDefaultValues();
				GameObject val5 = GameObject.CreatePrimitive((PrimitiveType)5);
				Object.Destroy((Object)(object)val5.GetComponent<MeshCollider>());
				val5.transform.SetParent(CameraObject.transform, false);
				val5.transform.localPosition = new Vector3(0f, 0f, Camera.nearClipPlane * 2f);
				val5.transform.localRotation = Quaternion.Euler(0f, 0f, 0f);
				fogShaderPlaneRenderer = val5.GetComponent<MeshRenderer>();
				((Renderer)fogShaderPlaneRenderer).sharedMaterial = fogShaderMaterial;
				((Renderer)fogShaderPlaneRenderer).shadowCastingMode = (ShadowCastingMode)0;
				((Renderer)fogShaderPlaneRenderer).receiveShadows = false;
				((Renderer)fogShaderPlaneRenderer).forceRenderingOff = true;
				this.OnCameraCreated?.Invoke(Camera);
			}
		}

		public void UpdateSettings()
		{
			//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_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Expected O, but got Unknown
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			Camera.targetTexture = new RenderTexture(Plugin.HorizontalResolution.Value, Plugin.HorizontalResolution.Value * 3 / 4, 32)
			{
				name = ((Object)this).name + ".RenderTexture",
				filterMode = Plugin.MonitorTextureFiltering.Value
			};
			Camera.fieldOfView = Plugin.FieldOfView.Value;
			if ((Object)(object)MonitorOnMaterial != (Object)null)
			{
				MonitorOnMaterial.mainTexture = (Texture)(object)Camera.targetTexture;
				MonitorOnMaterial.SetColor("_EmissiveColor", screenEmissiveColor);
			}
			Camera.farClipPlane = Plugin.RenderDistance.Value;
			if (Plugin.Framerate.Value != 0f)
			{
				timePerFrame = 1f / Plugin.Framerate.Value;
				((Behaviour)Camera).enabled = false;
			}
			else
			{
				timePerFrame = 0f;
				((Behaviour)Camera).enabled = false;
			}
			nightVisionLight.intensity = 367f * Plugin.NightVisionBrightness.Value;
			nightVisionLight.range = 12f * Plugin.NightVisionBrightness.Value;
			enableCamera = Plugin.EnableCamera.Value;
			this.OnRenderTextureCreated?.Invoke(Camera.targetTexture);
		}

		public void StartTargetTransition()
		{
			if (Plugin.UseTargetTransitionAnimation.Value)
			{
				Animator obj = greenFlashAnimator;
				if (obj != null)
				{
					obj.SetTrigger("Transition");
				}
			}
		}

		private static void SetCosmeticHidden(GameObject cosmetic, bool hidden)
		{
			cosmetic.layer = (hidden ? 23 : 0);
		}

		public void SetScreenPowered(bool powered)
		{
			if (!((Object)(object)MonitorRenderer == (Object)null) && powered != MonitorIsOn)
			{
				if (powered)
				{
					StartTargetTransition();
					SetMaterial(MonitorRenderer, MonitorMaterialIndex, MonitorOnMaterial);
					MonitorIsOn = true;
				}
				else
				{
					SetMaterial(MonitorRenderer, MonitorMaterialIndex, MonitorOffMaterial);
					MonitorIsOn = false;
				}
			}
		}

		public bool IsScreenPowered()
		{
			return MonitorIsOn;
		}

		private void SetScreenBlanked(bool blanked)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			if (blanked != wasBlanked)
			{
				if ((Object)(object)MonitorOnMaterial != (Object)null)
				{
					MonitorOnMaterial.color = (blanked ? Color.black : Color.white);
				}
				this.OnBlankedSet?.Invoke(blanked);
			}
			wasBlanked = blanked;
		}

		private bool ShouldHideOutput()
		{
			if (!enableCamera)
			{
				return true;
			}
			if ((Object)(object)currentActualTarget == (Object)null)
			{
				return true;
			}
			if (currentPlayer != null)
			{
				if (currentPlayer.isPlayerControlled)
				{
					if (disableCameraWhileTargetIsOnShip)
					{
						return currentPlayer.isInHangarShipRoom;
					}
					return false;
				}
				if (!currentPlayer.isPlayerDead)
				{
					return false;
				}
				if ((Object)(object)currentPlayer.redirectToEnemy != (Object)null)
				{
					if (disableCameraWhileTargetIsOnShip)
					{
						return currentPlayer.redirectToEnemy.isInsidePlayerShip;
					}
					return false;
				}
				if ((Object)(object)currentPlayer.deadBody != (Object)null)
				{
					if (disableCameraWhileTargetIsOnShip)
					{
						return currentPlayer.deadBody.isInShip;
					}
					return false;
				}
			}
			RadarBoosterItem component = ((Component)currentActualTarget).GetComponent<RadarBoosterItem>();
			if (component != null)
			{
				if (disableCameraWhileTargetIsOnShip)
				{
					return ((GrabbableObject)component).isInShipRoom;
				}
				return false;
			}
			return true;
		}

		private static void CollectDescendentModelsToHide(Transform parent, List<Renderer> list)
		{
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Expected O, but got Unknown
			BodyCamComponent[] allBodyCams = AllBodyCams;
			foreach (BodyCamComponent bodyCamComponent in allBodyCams)
			{
				if ((Object)(object)parent == (Object)(object)bodyCamComponent.CameraObject.transform)
				{
					return;
				}
			}
			Renderer component = ((Component)parent).GetComponent<Renderer>();
			if ((Object)(object)component != (Object)null && ((1 << ((Component)component).gameObject.layer) & bodyCamCullingMask) != 0)
			{
				list.Add(component);
			}
			foreach (Transform item in parent)
			{
				CollectDescendentModelsToHide(item, list);
			}
		}

		private static Renderer[] CollectModelsToHide(Transform parent)
		{
			List<Renderer> list = new List<Renderer>(20);
			CollectDescendentModelsToHide(parent, list);
			int num = 0;
			Renderer[] array = (Renderer[])(object)new Renderer[list.Count];
			foreach (Renderer item in list)
			{
				array[num] = item;
				num++;
			}
			return array;
		}

		private bool TargetWouldRequireUpdate(Transform target)
		{
			if (target == null)
			{
				return true;
			}
			if (currentActualTarget == target)
			{
				return true;
			}
			if (((Component)StartOfRound.Instance.localPlayerController).transform == target)
			{
				return true;
			}
			return false;
		}

		public void MarkTargetStatusChanged(Transform transform)
		{
			if (!targetDirtyStatus.HasFlag(TargetDirtyStatus.Immediate) && TargetWouldRequireUpdate(transform))
			{
				targetDirtyStatus |= TargetDirtyStatus.Immediate;
			}
		}

		public void MarkTargetStatusChanged()
		{
			MarkTargetStatusChanged(null);
		}

		public void MarkTargetDirtyUntilRender(Transform transform)
		{
			if (!targetDirtyStatus.HasFlag(TargetDirtyStatus.UntilRender) && TargetWouldRequireUpdate(transform))
			{
				targetDirtyStatus |= TargetDirtyStatus.UntilRender;
			}
		}

		public void MarkTargetDirtyUntilRender()
		{
			MarkTargetDirtyUntilRender(null);
		}

		private void ClearTargetDirtyImmediate()
		{
			targetDirtyStatus &= ~TargetDirtyStatus.Immediate;
		}

		public void SetTargetToNone()
		{
			//IL_004b: 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)
			ClearTargetDirtyImmediate();
			currentPlayer = null;
			currentActualTarget = null;
			currentlyViewedMeshes = Array.Empty<Renderer>();
			if (!((Object)(object)CameraObject == (Object)null))
			{
				CameraObject.transform.SetParent((Transform)null, false);
				CameraObject.transform.localPosition = Vector3.zero;
				CameraObject.transform.localRotation = Quaternion.identity;
			}
		}

		public void SetTargetToPlayer(PlayerControllerB player)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0223: Unknown result type (might be due to invalid IL or missing references)
			//IL_0234: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)player == (Object)null)
			{
				SetTargetToNone();
				return;
			}
			EnsureCameraExists();
			ClearTargetDirtyImmediate();
			currentPlayer = player;
			UpdateModelReferences();
			panCamera = false;
			Vector3 localPosition = Vector3.zero;
			currentActualTarget = null;
			Transform val = null;
			if (!currentPlayer.isPlayerDead)
			{
				if (Plugin.CameraMode.Value == CameraModeOptions.Head)
				{
					val = ((Component)currentPlayer.gameplayCamera).transform;
					localPosition = CAMERA_CONTAINER_OFFSET;
				}
				else
				{
					val = ((Component)currentPlayer.playerGlobalHead).transform.parent;
					localPosition = BODY_CAM_OFFSET;
				}
				currentActualTarget = ((Component)currentPlayer).transform;
				currentlyViewedMeshes = Array.Empty<Renderer>();
			}
			else if ((Object)(object)currentPlayer.redirectToEnemy != (Object)null)
			{
				EnemyAI redirectToEnemy = currentPlayer.redirectToEnemy;
				MaskedPlayerEnemy val2 = (MaskedPlayerEnemy)(object)((redirectToEnemy is MaskedPlayerEnemy) ? redirectToEnemy : null);
				if (val2 != null)
				{
					if (Plugin.CameraMode.Value == CameraModeOptions.Head)
					{
						val = val2.headTiltTarget;
						localPosition = CAMERA_CONTAINER_OFFSET;
					}
					else
					{
						val = val2.animationContainer.Find("metarig/spine/spine.001/spine.002/spine.003");
						localPosition = BODY_CAM_OFFSET;
					}
				}
				else
				{
					val = currentPlayer.redirectToEnemy.eye;
				}
				currentActualTarget = ((Component)currentPlayer.redirectToEnemy).transform;
				currentlyViewedMeshes = CollectModelsToHide(currentActualTarget);
			}
			else if ((Object)(object)currentPlayer.deadBody != (Object)null)
			{
				Transform parent;
				if (Plugin.CameraMode.Value == CameraModeOptions.Head)
				{
					val = ((Component)currentPlayer.deadBody).transform.Find("spine.001/spine.002/spine.003/spine.004/spine.004_end");
					parent = val.parent;
					localPosition = CAMERA_CONTAINER_OFFSET - new Vector3(0f, 0.15f, 0f);
				}
				else
				{
					val = ((Component)currentPlayer.deadBody).transform.Find("spine.001/spine.002/spine.003");
					parent = val;
					localPosition = BODY_CAM_OFFSET;
				}
				currentActualTarget = ((Component)currentPlayer.deadBody).transform;
				currentlyViewedMeshes = CollectModelsToHide(parent);
			}
			if ((Object)(object)val == (Object)null)
			{
				SetTargetToNone();
				return;
			}
			CameraObject.transform.SetParent(val, false);
			CameraObject.transform.localPosition = localPosition;
			CameraObject.transform.localRotation = Quaternion.identity;
		}

		public void SetTargetToTransform(Transform transform)
		{
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)transform == (Object)null || (Object)(object)((Component)transform).gameObject == (Object)null)
			{
				SetTargetToNone();
				return;
			}
			EnsureCameraExists();
			ClearTargetDirtyImmediate();
			currentPlayer = null;
			currentActualTarget = transform;
			UpdateModelReferences();
			panCamera = false;
			Vector3 zero = Vector3.zero;
			if ((Object)(object)((Component)currentActualTarget).GetComponent<RadarBoosterItem>() != (Object)null)
			{
				currentlyViewedMeshes = (Renderer[])(object)new Renderer[1] { ((Component)((Component)currentActualTarget).transform.Find("AnimContainer/Rod")).GetComponent<Renderer>() };
				((Vector3)(ref zero))..ctor(0f, 1.5f, 0f);
				panCamera = true;
			}
			CameraObject.transform.SetParent(((Component)currentActualTarget).transform, false);
			CameraObject.transform.localPosition = zero;
			CameraObject.transform.localRotation = Quaternion.identity;
		}

		private void UpdateTargetStatus()
		{
			if ((Object)(object)currentPlayer != (Object)null)
			{
				SetTargetToPlayer(currentPlayer);
			}
			else
			{
				SetTargetToTransform(currentActualTarget);
			}
		}

		private void UpdateModelReferences()
		{
			currentPlayerCosmetics = CosmeticsCompatibility.CollectCosmetics(currentPlayer);
			currentPlayerModelState.cosmeticsLayers = new int[currentPlayerCosmetics.Length];
			if ((Object)(object)currentPlayer != (Object)(object)StartOfRound.Instance.localPlayerController)
			{
				localPlayerCosmetics = CosmeticsCompatibility.CollectCosmetics(StartOfRound.Instance.localPlayerController);
				localPlayerModelState.cosmeticsLayers = new int[localPlayerCosmetics.Length];
			}
			else
			{
				localPlayerCosmetics = Array.Empty<GameObject>();
				localPlayerModelState.cosmeticsLayers = Array.Empty<int>();
			}
		}

		private static void SaveStateAndApplyPerspective(PlayerControllerB player, ref GameObject[] cosmetics, ref PlayerModelState state, Perspective perspective)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			if (player == null)
			{
				return;
			}
			state.bodyShadowMode = ((Renderer)player.thisPlayerModel).shadowCastingMode;
			state.bodyLayer = ((Component)player.thisPlayerModel).gameObject.layer;
			state.armsEnabled = ((Renderer)player.thisPlayerModelArms).enabled;
			state.armsLayer = ((Component)player.thisPlayerModelArms).gameObject.layer;
			if ((Object)(object)player.currentlyHeldObjectServer != (Object)null)
			{
				state.heldItemPosition = ((Component)player.currentlyHeldObjectServer).transform.position;
				state.heldItemRotation = ((Component)player.currentlyHeldObjectServer).transform.rotation;
			}
			for (int i = 0; i < cosmetics.Length; i++)
			{
				state.cosmeticsLayers[i] = cosmetics[i].layer;
			}
			switch (perspective)
			{
			case Perspective.FirstPerson:
			{
				((Renderer)player.thisPlayerModel).shadowCastingMode = (ShadowCastingMode)3;
				((Component)player.thisPlayerModel).gameObject.layer = 23;
				((Renderer)player.thisPlayerModelArms).enabled = true;
				((Component)player.thisPlayerModelArms).gameObject.layer = 0;
				if ((Object)(object)player.currentlyHeldObjectServer != (Object)null)
				{
					AttachItem(player.currentlyHeldObjectServer, player.localItemHolder);
				}
				GameObject[] array = cosmetics;
				for (int j = 0; j < array.Length; j++)
				{
					SetCosmeticHidden(array[j], hidden: true);
				}
				break;
			}
			case Perspective.ThirdPerson:
			{
				((Renderer)player.thisPlayerModel).shadowCastingMode = (ShadowCastingMode)1;
				((Component)player.thisPlayerModel).gameObject.layer = 0;
				((Renderer)player.thisPlayerModelArms).enabled = false;
				((Component)player.thisPlayerModelArms).gameObject.layer = 23;
				if ((Object)(object)player.currentlyHeldObjectServer != (Object)null)
				{
					AttachItem(player.currentlyHeldObjectServer, player.serverItemHolder);
				}
				GameObject[] array = cosmetics;
				for (int j = 0; j < array.Length; j++)
				{
					SetCosmeticHidden(array[j], hidden: false);
				}
				break;
			}
			}
			static void AttachItem(GrabbableObject item, Transform holder)
			{
				//IL_0007: Unknown result type (might be due to invalid IL or missing references)
				//IL_001d: Unknown result type (might be due to invalid IL or missing references)
				//IL_002e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0034: Unknown result type (might be due to invalid IL or missing references)
				//IL_003f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0044: Unknown result type (might be due to invalid IL or missing references)
				//IL_0049: Unknown result type (might be due to invalid IL or missing references)
				((Component)item).transform.rotation = holder.rotation;
				((Component)item).transform.Rotate(item.itemProperties.rotationOffset);
				((Component)item).transform.position = holder.position + holder.rotation * item.itemProperties.positionOffset;
			}
		}

		private static void RestoreState(PlayerControllerB player, GameObject[] cosmetics, PlayerModelState state)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			if (player != null)
			{
				((Renderer)player.thisPlayerModel).shadowCastingMode = state.bodyShadowMode;
				((Component)player.thisPlayerModel).gameObject.layer = state.bodyLayer;
				((Renderer)player.thisPlayerModelArms).enabled = state.armsEnabled;
				((Component)player.thisPlayerModelArms).gameObject.layer = state.armsLayer;
				for (int i = 0; i < cosmetics.Length; i++)
				{
					cosmetics[i].layer = state.cosmeticsLayers[i];
				}
				if ((Object)(object)player.currentlyHeldObjectServer != (Object)null)
				{
					((Component)player.currentlyHeldObjectServer).transform.position = state.heldItemPosition;
					((Component)player.currentlyHeldObjectServer).transform.rotation = state.heldItemRotation;
				}
			}
		}

		private void UpdateTargetStatusBeforeRender()
		{
			if (targetDirtyStatus.HasFlag(TargetDirtyStatus.UntilRender))
			{
				UpdateTargetStatus();
				targetDirtyStatus ^= TargetDirtyStatus.UntilRender;
			}
		}

		private void BeginCameraRendering()
		{
			UpdateTargetStatusBeforeRender();
			((Behaviour)nightVisionLight).enabled = true;
			((Renderer)greenFlashRenderer).forceRenderingOff = false;
			((Renderer)fogShaderPlaneRenderer).forceRenderingOff = false;
			PlayerControllerB localPlayerController = StartOfRound.Instance.localPlayerController;
			SaveStateAndApplyPerspective(currentPlayer, ref currentPlayerCosmetics, ref currentPlayerModelState, Perspective.FirstPerson);
			if (currentPlayer != localPlayerController)
			{
				SaveStateAndApplyPerspective(localPlayerController, ref localPlayerCosmetics, ref localPlayerModelState, Perspective.ThirdPerson);
			}
			Renderer[] array = currentlyViewedMeshes;
			foreach (Renderer val in array)
			{
				if (!((Object)(object)val == (Object)null))
				{
					val.forceRenderingOff = true;
				}
			}
		}

		private void ResetCameraRendering()
		{
			((Behaviour)nightVisionLight).enabled = false;
			((Renderer)greenFlashRenderer).forceRenderingOff = true;
			((Renderer)fogShaderPlaneRenderer).forceRenderingOff = true;
			PlayerControllerB localPlayerController = StartOfRound.Instance.localPlayerController;
			RestoreState(currentPlayer, currentPlayerCosmetics, currentPlayerModelState);
			if (currentPlayer != localPlayerController)
			{
				RestoreState(localPlayerController, localPlayerCosmetics, localPlayerModelState);
			}
			if (currentlyViewedMeshes.Length == 0 || !((Object)(object)currentlyViewedMeshes[0] == (Object)null))
			{
				Renderer[] array = currentlyViewedMeshes;
				for (int i = 0; i < array.Length; i++)
				{
					array[i].forceRenderingOff = false;
				}
			}
		}

		private bool AllCosmeticsExist(PlayerControllerB player, GameObject[] cosmetics)
		{
			for (int i = 0; i < cosmetics.Length; i++)
			{
				if ((Object)(object)cosmetics[i] == (Object)null)
				{
					Plugin.Instance.Logger.LogError((object)("A cosmetic attached to " + player.playerUsername + " has been destroyed, re-collecting cosmetics."));
					return false;
				}
			}
			return true;
		}

		private void UpdateTargetStatusDuringUpdate()
		{
			if (targetDirtyStatus.HasFlag(TargetDirtyStatus.Immediate))
			{
				UpdateTargetStatus();
			}
		}

		private void LateUpdate()
		{
			//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
			EnsureCameraExists();
			UpdateTargetStatusDuringUpdate();
			PlayerControllerB val = StartOfRound.Instance.localPlayerController;
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			if ((Object)(object)val.spectatedPlayerScript != (Object)null)
			{
				val = val.spectatedPlayerScript;
			}
			bool flag = keepCameraOn || ((Object)(object)MonitorRenderer != (Object)null && MonitorRenderer.isVisible && val.isInHangarShipRoom && IsScreenPowered());
			if (flag)
			{
				bool flag2 = ShouldHideOutput();
				flag = !flag2;
				if (flag2 != wasBlanked)
				{
					SetScreenBlanked(flag2);
					wasBlanked = flag2;
				}
			}
			if (flag && bruteForcePreventNullModels)
			{
				bool flag3 = false;
				if ((Object)(object)currentPlayer != (Object)null && !AllCosmeticsExist(currentPlayer, currentPlayerCosmetics))
				{
					flag3 = true;
				}
				PlayerControllerB localPlayerController = StartOfRound.Instance.localPlayerController;
				if (currentPlayer != localPlayerController && !AllCosmeticsExist(localPlayerController, localPlayerCosmetics))
				{
					flag3 = true;
				}
				Renderer[] array = currentlyViewedMeshes;
				for (int i = 0; i < array.Length; i++)
				{
					if ((Object)(object)array[i] == (Object)null)
					{
						Plugin.Instance.Logger.LogError((object)("A mesh attached to non-player target " + ((Object)currentActualTarget).name + " is null, marking dirty."));
						flag3 = true;
						break;
					}
				}
				if (flag3)
				{
					UpdateTargetStatus();
				}
			}
			if (!flag)
			{
				((Behaviour)Camera).enabled = false;
				return;
			}
			if (radarBoosterPanSpeed != 0f)
			{
				panAngle = (panAngle + Time.deltaTime * radarBoosterPanSpeed) % 360f;
			}
			else
			{
				panAngle = 270f;
			}
			if (panCamera)
			{
				CameraObject.transform.localRotation = Quaternion.Euler(0f, panAngle, 0f);
			}
			if (timePerFrame > 0f)
			{
				elapsedSinceLastFrame += Time.deltaTime;
				if (elapsedSinceLastFrame >= timePerFrame)
				{
					Camera.Render();
					elapsedSinceLastFrame %= timePerFrame;
				}
			}
			else
			{
				((Behaviour)Camera).enabled = true;
			}
		}

		private void OnDestroy()
		{
			AllBodyCams = AllBodyCams.Where((BodyCamComponent bodyCam) => bodyCam != this).ToArray();
			SyncBodyCamToRadarMap.OnBodyCamDestroyed(this);
		}

		private static bool PlayerContainsRenderer(PlayerControllerB player, Renderer renderer)
		{
			if ((Object)(object)player == (Object)null)
			{
				return false;
			}
			if ((Object)(object)player.thisPlayerModelArms == (Object)(object)renderer)
			{
				return true;
			}
			if ((Object)(object)player.thisPlayerModel == (Object)(object)renderer)
			{
				return true;
			}
			return false;
		}

		public bool HasReference(Renderer renderer)
		{
			if (targetDirtyStatus.HasFlag(TargetDirtyStatus.UntilRender))
			{
				return false;
			}
			if (targetDirtyStatus.HasFlag(TargetDirtyStatus.Immediate))
			{
				UpdateTargetStatus();
			}
			if (PlayerContainsRenderer(currentPlayer, renderer))
			{
				return true;
			}
			if (PlayerContainsRenderer(StartOfRound.Instance?.localPlayerController, renderer))
			{
				return true;
			}
			if (Array.IndexOf(currentlyViewedMeshes, renderer) != -1)
			{
				return true;
			}
			return false;
		}

		public bool HasReference(GameObject gameObject)
		{
			if (targetDirtyStatus.HasFlag(TargetDirtyStatus.UntilRender))
			{
				return false;
			}
			if (targetDirtyStatus.HasFlag(TargetDirtyStatus.Immediate))
			{
				UpdateTargetStatus();
			}
			if (Array.IndexOf(currentPlayerCosmetics, gameObject) != -1)
			{
				return true;
			}
			return Array.IndexOf(localPlayerCosmetics, gameObject) != -1;
		}

		public static bool AnyBodyCamHasReference(Renderer renderer)
		{
			BodyCamComponent[] allBodyCams = AllBodyCams;
			for (int i = 0; i < allBodyCams.Length; i++)
			{
				if (allBodyCams[i].HasReference(renderer))
				{
					return true;
				}
			}
			return false;
		}

		public static bool AnyBodyCamHasReference(GameObject gameObject)
		{
			BodyCamComponent[] allBodyCams = AllBodyCams;
			for (int i = 0; i < allBodyCams.Length; i++)
			{
				if (allBodyCams[i].HasReference(gameObject))
				{
					return true;
				}
			}
			return false;
		}
	}
	internal struct PlayerModelState
	{
		public ShadowCastingMode bodyShadowMode;

		public int bodyLayer;

		public bool armsEnabled;

		public int armsLayer;

		public int[] cosmeticsLayers;

		public Vector3 heldItemPosition;

		public Quaternion heldItemRotation;
	}
	internal static class CosmeticsCompatibility
	{
		[Flags]
		private enum CompatibilityMode
		{
			None = 0,
			MoreCompany = 1,
			AdvancedCompany = 2,
			ModelReplacementAPI = 4,
			LethalVRM = 8
		}

		internal static bool PrintDebugInfo;

		private static CompatibilityMode compatibilityMode;

		public static void Initialize(Harmony harmony)
		{
			bool flag = Chainloader.PluginInfos.ContainsKey("com.potatoepet.AdvancedCompany");
			if (Plugin.EnableAdvancedCompanyCosmeticsCompatibility.Value && flag)
			{
				if (AdvancedCompanyCompatibility.Initialize(harmony))
				{
					compatibilityMode |= CompatibilityMode.AdvancedCompany;
					Plugin.Instance.Logger.LogInfo((object)"AdvancedCompany compatibility mode is enabled.");
				}
				else
				{
					Plugin.Instance.Logger.LogWarning((object)"AdvancedCompany is installed, but the compatibility feature failed to initialize.");
				}
			}
			if (Plugin.EnableMoreCompanyCosmeticsCompatibility.Value && !flag && Chainloader.PluginInfos.ContainsKey("me.swipez.melonloader.morecompany"))
			{
				if (MoreCompanyCompatibility.Initialize(harmony))
				{
					compatibilityMode |= CompatibilityMode.MoreCompany;
					Plugin.Instance.Logger.LogInfo((object)"MoreCompany compatibility mode is enabled.");
				}
				else
				{
					Plugin.Instance.Logger.LogWarning((object)"MoreCompany is installed, but the compatibility feature failed to initialize.");
				}
			}
			if (Plugin.EnableModelReplacementAPICompatibility.Value && Chainloader.PluginInfos.ContainsKey("meow.ModelReplacementAPI"))
			{
				if (ModelReplacementAPICompatibility.Initialize(harmony))
				{
					compatibilityMode |= CompatibilityMode.ModelReplacementAPI;
					Plugin.Instance.Logger.LogInfo((object)"ModelReplacementAPI compatibility mode is enabled.");
				}
				else
				{
					Plugin.Instance.Logger.LogWarning((object)"ModelReplacementAPI is installed, but the compatibility feature failed to initialize.");
				}
			}
			if (Plugin.EnableLethalVRMCompatibility.Value && Chainloader.PluginInfos.ContainsKey("Ooseykins.LethalVRM"))
			{
				if (LethalVRMCompatibility.Initialize(harmony))
				{
					compatibilityMode |= CompatibilityMode.LethalVRM;
					Plugin.Instance.Logger.LogInfo((object)"LethalVRM compatibility mode is enabled.");
				}
				else
				{
					Plugin.Instance.Logger.LogWarning((object)"LethalVRM is installed, but the compatibility feature failed to initialize.");
				}
			}
		}

		private static void DebugLog(object data)
		{
			if (PrintDebugInfo)
			{
				Plugin.Instance.Logger.LogInfo(data);
			}
		}

		private static GameObject[] DoCollectCosmetics(PlayerControllerB player)
		{
			if ((Object)(object)player == (Object)null)
			{
				return (GameObject[])(object)new GameObject[0];
			}
			List<GameObject> list = new List<GameObject>();
			DebugLog("Collecting cosmetics for " + player.playerUsername + ".");
			if (compatibilityMode.HasFlag(CompatibilityMode.MoreCompany))
			{
				GameObject[] array = MoreCompanyCompatibility.CollectCosmetics(player);
				list.AddRange(array);
				DebugLog($"Collected {array.Length} MoreCompany cosmetics objects.");
			}
			if (compatibilityMode.HasFlag(CompatibilityMode.AdvancedCompany))
			{
				GameObject[] array2 = AdvancedCompanyCompatibility.CollectCosmetics(player);
				list.AddRange(array2);
				DebugLog($"Collected {array2.Length} AdvancedCompany cosmetics objects.");
			}
			if (compatibilityMode.HasFlag(CompatibilityMode.ModelReplacementAPI))
			{
				GameObject[] array3 = ModelReplacementAPICompatibility.CollectCosmetics(player);
				list.AddRange(array3);
				DebugLog($"Collected {array3.Length} ModelReplacementAPI cosmetics objects.");
			}
			if (compatibilityMode.HasFlag(CompatibilityMode.LethalVRM))
			{
				GameObject[] array4 = LethalVRMCompatibility.CollectCosmetics(player);
				list.AddRange(array4);
				DebugLog($"Collected {array4.Length} LethalVRM cosmetics objects.");
			}
			Plugin.Instance.Logger.LogInfo((object)$"Collected {list.Count} cosmetics objects for {player.playerUsername}.");
			if (PrintDebugInfo)
			{
				Plugin.Instance.Logger.LogInfo((object)"Called from:");
				StackFrame[] frames = new StackTrace().GetFrames();
				for (int i = 1; i < frames.Length; i++)
				{
					StackFrame stackFrame = frames[i];
					Plugin.Instance.Logger.LogInfo((object)("  " + stackFrame.GetMethod().DeclaringType.Name + "." + stackFrame.GetMethod().Name + "()"));
				}
			}
			int num = 0;
			GameObject[] array5 = (GameObject[])(object)new GameObject[list.Count];
			foreach (GameObject item in list)
			{
				array5[num] = item;
				num++;
			}
			return array5;
		}

		public static GameObject[] CollectCosmetics(PlayerControllerB player)
		{
			try
			{
				return DoCollectCosmetics(player);
			}
			catch (Exception ex)
			{
				Plugin.Instance.Logger.LogError((object)("Failed to get cosmetics for player " + player.playerUsername + ":"));
				Plugin.Instance.Logger.LogError((object)ex);
				return Array.Empty<GameObject>();
			}
		}
	}
	public enum CameraModeOptions
	{
		Body,
		Head
	}
	[BepInPlugin("Zaggy1024.OpenBodyCams", "OpenBodyCams", "1.3.0")]
	[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 class Plugin : BaseUnityPlugin
	{
		public const string MOD_NAME = "OpenBodyCams";

		public const string MOD_UNIQUE_NAME = "Zaggy1024.OpenBodyCams";

		public const string MOD_VERSION = "1.3.0";

		private readonly Harmony harmony = new Harmony("Zaggy1024.OpenBodyCams");

		public static ConfigEntry<CameraModeOptions> CameraMode;

		public static ConfigEntry<int> HorizontalResolution;

		public static ConfigEntry<float> FieldOfView;

		public static ConfigEntry<float> RenderDistance;

		public static ConfigEntry<float> Framerate;

		public const float NightVisionIntensityBase = 367f;

		public const float NightVisionRangeBase = 12f;

		public static ConfigEntry<float> NightVisionBrightness;

		public static ConfigEntry<string> MonitorEmissiveColor;

		public static ConfigEntry<FilterMode> MonitorTextureFiltering;

		public static ConfigEntry<float> RadarBoosterPanRPM;

		public static ConfigEntry<bool> UseTargetTransitionAnimation;

		public static ConfigEntry<bool> DisableCameraWhileTargetIsOnShip;

		public static ConfigEntry<bool> EnableCamera;

		public static ConfigEntry<bool> TerminalPiPBodyCamEnabled;

		public static ConfigEntry<PiPPosition> TerminalPiPPosition;

		public static ConfigEntry<int> TerminalPiPWidth;

		public static ConfigEntry<int> GeneralImprovementsBetterMonitorIndex;

		public static ConfigEntry<bool> EnableMoreCompanyCosmeticsCompatibility;

		public static ConfigEntry<bool> EnableAdvancedCompanyCosmeticsCompatibility;

		public static ConfigEntry<bool> EnableModelReplacementAPICompatibility;

		public static ConfigEntry<bool> EnableLethalVRMCompatibility;

		public static ConfigEntry<bool> DisableInternalShipCamera;

		public static ConfigEntry<bool> FixDroppedItemRotation;

		public static ConfigEntry<bool> PrintCosmeticsDebugInfo;

		public static ConfigEntry<bool> BruteForcePreventFreezes;

		public static ConfigEntry<bool> ReferencedObjectDestructionDetectionEnabled;

		private static readonly Harmony DestructionDetectionPatch = new Harmony("Zaggy1024.OpenBodyCams.DestructionDetectionPatch");

		public static Plugin Instance { get; private set; }

		public ManualLogSource Logger => ((BaseUnityPlugin)this).Logger;

		private void Awake()
		{
			//IL_04e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ef: Expected O, but got Unknown
			Instance = this;
			harmony.PatchAll(typeof(PatchStartOfRound));
			harmony.PatchAll(typeof(PatchManualCameraRenderer));
			harmony.PatchAll(typeof(PatchPlayerControllerB));
			harmony.PatchAll(typeof(PatchHauntedMaskItem));
			harmony.PatchAll(typeof(PatchMaskedPlayerEnemy));
			CameraMode = ((BaseUnityPlugin)this).Config.Bind<CameraModeOptions>("Camera", "Mode", CameraModeOptions.Head, "Choose where to attach the camera. 'Head' will attach the camera to the right side of the head, 'Body' will attach it to the chest.");
			HorizontalResolution = ((BaseUnityPlugin)this).Config.Bind<int>("Camera", "HorizontalResolution", 160, "The horizontal resolution of the rendering. The vertical resolution is calculated based on the aspect ratio of the monitor.");
			FieldOfView = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "FieldOfView", 65f, "The vertical FOV of the camera in degrees.");
			RenderDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "RenderDistance", 25f, "The far clip plane for the body cam. Lowering may improve framerates.");
			Framerate = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "Framerate", 0f, "The number of frames to render per second. A value of 0 will render at the game's framerate and results in best performance. Higher framerates will negatively affect performance, values between 0 and 30 are recommended.");
			NightVisionBrightness = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "NightVisionBrightness", 1f, "A multiplier for the intensity of the area light used to brighten dark areas. A value of 1 is identical to the player's actual vision.");
			MonitorEmissiveColor = ((BaseUnityPlugin)this).Config.Bind<string>("Camera", "MonitorEmissiveColor", "0.05, 0.13, 0.05", "Adjust the color that is emitted from the body cam monitor.");
			MonitorTextureFiltering = ((BaseUnityPlugin)this).Config.Bind<FilterMode>("Camera", "MonitorTextureFiltering", (FilterMode)1, "The texture filtering to use for the body cam on the monitor. Bilinear and Trilinear will result in a smooth image, while Point will result in sharp square edges. If Point is used, a fairly high resolution is recommended.");
			RadarBoosterPanRPM = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "RadarBoosterPanRPM", 9f, "The rotations per minute to turn the camera when a radar booster is selected. If the value is set to 0, the radar booster camera will face in the direction player faces when it is placed.");
			UseTargetTransitionAnimation = ((BaseUnityPlugin)this).Config.Bind<bool>("Camera", "UseTargetTransitionAnimation", true, "Enables a green flash animation on the body cam screen mirroring the one that the radar map shows when switching targets.");
			DisableCameraWhileTargetIsOnShip = ((BaseUnityPlugin)this).Config.Bind<bool>("Camera", "DisableCameraWhileTargetIsOnShip", false, "With this option enabled, the camera will stop rendering when the target is onboard the ship to reduce the performance hit of rendering a large number of items on the ship twice.");
			EnableCamera = ((BaseUnityPlugin)this).Config.Bind<bool>("Camera", "EnableCamera", true, "Enables/disables rendering of the body cam, and can be enabled/disabled during a game with LethalConfig.");
			CameraMode.SettingChanged += delegate
			{
				BodyCamComponent.MarkTargetStatusChangedForAllBodyCams();
			};
			HorizontalResolution.SettingChanged += delegate
			{
				BodyCamComponent.UpdateAllCameraSettings();
			};
			FieldOfView.SettingChanged += delegate
			{
				BodyCamComponent.UpdateAllCameraSettings();
			};
			RenderDistance.SettingChanged += delegate
			{
				BodyCamComponent.UpdateAllCameraSettings();
			};
			Framerate.SettingChanged += delegate
			{
				BodyCamComponent.UpdateAllCameraSettings();
			};
			NightVisionBrightness.SettingChanged += delegate
			{
				BodyCamComponent.UpdateAllCameraSettings();
			};
			MonitorEmissiveColor.SettingChanged += delegate
			{
				BodyCamComponent.UpdateAllCameraSettings();
			};
			MonitorTextureFiltering.SettingChanged += delegate
			{
				BodyCamComponent.UpdateAllCameraSettings();
			};
			RadarBoosterPanRPM.SettingChanged += delegate
			{
				BodyCamComponent.UpdateAllCameraSettings();
			};
			DisableCameraWhileTargetIsOnShip.SettingChanged += delegate
			{
				BodyCamComponent.UpdateAllCameraSettings();
			};
			EnableCamera.SettingChanged += delegate
			{
				BodyCamComponent.UpdateAllCameraSettings();
			};
			TerminalPiPBodyCamEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Terminal", "EnablePiPBodyCam", false, "Adds a 'view bodycam' command to the terminal that places a picture-in-picture view of the bodycam in front of the radar map.");
			TerminalPiPPosition = ((BaseUnityPlugin)this).Config.Bind<PiPPosition>("Terminal", "PiPPosition", PiPPosition.BottomRight, "The corner inside the terminal's radar map to align the body cam to.");
			TerminalPiPWidth = ((BaseUnityPlugin)this).Config.Bind<int>("Terminal", "PiPWidth", 150, "The width of the picture-in-picture in pixels.");
			TerminalPiPBodyCamEnabled.SettingChanged += delegate
			{
				TerminalCommands.Initialize();
			};
			TerminalPiPPosition.SettingChanged += delegate
			{
				TerminalCommands.Initialize();
			};
			TerminalPiPWidth.SettingChanged += delegate
			{
				TerminalCommands.Initialize();
			};
			harmony.PatchAll(typeof(TerminalCommands));
			GeneralImprovementsBetterMonitorIndex = ((BaseUnityPlugin)this).Config.Bind<int>("Compatibility", "GeneralImprovementsBetterMonitorIndex", 0, new ConfigDescription("Choose which of GeneralImprovements' extended monitor set to display the body cam on. A value of 0 will place it on the large monitor on the right, 1-14 goes left to right, top to bottom, skipping the large center monitor.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 14), Array.Empty<object>()));
			EnableMoreCompanyCosmeticsCompatibility = ((BaseUnityPlugin)this).Config.Bind<bool>("Compatibility", "EnableMoreCompanyCosmeticsCompatibility", true, "If this is enabled, a patch will be applied to MoreCompany to spawn cosmetics for the local player, and all cosmetics will be shown and hidden based on the camera's perspective.");
			EnableAdvancedCompanyCosmeticsCompatibility = ((BaseUnityPlugin)this).Config.Bind<bool>("Compatibility", "EnableAdvancedCompanyCosmeticsCompatibility", true, "When this is enabled and AdvancedCompany is installed, all cosmetics will be shown and hidden based on the camera's perspective.");
			EnableModelReplacementAPICompatibility = ((BaseUnityPlugin)this).Config.Bind<bool>("Compatibility", "EnableModelReplacementAPICompatibility", true, "When enabled, this will get the third person model replacement and hide/show it based on the camera's perspective.");
			EnableLethalVRMCompatibility = ((BaseUnityPlugin)this).Config.Bind<bool>("Compatibility", "EnableLethalVRMCompatibility", true, "When enabled, any VRM model will be hidden/shown based on the camera's perspective.");
			DisableInternalShipCamera = ((BaseUnityPlugin)this).Config.Bind<bool>("Misc", "DisableInternalShipCamera", false, "Whether to disable the internal ship camera displayed above the bodycam monitor.");
			FixDroppedItemRotation = ((BaseUnityPlugin)this).Config.Bind<bool>("Misc", "FixDroppedItemRotation", true, "If enabled, the mod will patch a bug that causes the rotation of dropped items to be desynced between clients.");
			PrintCosmeticsDebugInfo = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "PrintCosmeticsDebugInfo", false, "Prints extra information about the cosmetics being collected for each player, as well as the code that is causing the collection.");
			BruteForcePreventFreezes = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "BruteForcePreventFreezes", false, "Enable a brute force approach to preventing errors in the camera setup callback that can cause the screen to freeze.");
			ReferencedObjectDestructionDetectionEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "ModelDestructionDebuggingPatchEnabled", false, "Enable this option when reproducing a camera freeze. This will cause a debug message to be printed when a model that a body cam is tracking is destroyed.");
			PrintCosmeticsDebugInfo.SettingChanged += delegate
			{
				CosmeticsCompatibility.PrintDebugInfo = PrintCosmeticsDebugInfo.Value;
			};
			CosmeticsCompatibility.PrintDebugInfo = PrintCosmeticsDebugInfo.Value;
			BruteForcePreventFreezes.SettingChanged += delegate
			{
				BodyCamComponent.UpdateStaticSettings();
			};
			ReferencedObjectDestructionDetectionEnabled.SettingChanged += delegate
			{
				UpdateReferencedObjectDestructionDetectionEnabled();
			};
			UpdateReferencedObjectDestructionDetectionEnabled();
			CosmeticsCompatibility.Initialize(harmony);
			harmony.PatchAll(typeof(PatchFixItemDropping));
			BodyCamComponent.InitializeStatic();
		}

		private void UpdateReferencedObjectDestructionDetectionEnabled()
		{
			if (ReferencedObjectDestructionDetectionEnabled.Value)
			{
				DestructionDetectionPatch.PatchAll(typeof(PatchModelDestructionDebugging));
			}
			else
			{
				DestructionDetectionPatch.UnpatchSelf();
			}
		}
	}
	public static class ShipObjects
	{
		public static Material blackScreenMaterial;

		public static ManualCameraRenderer ShipCameraRenderer;

		public static Terminal TerminalScript;

		public static bool TwoRadarCamsPresent;

		public static BodyCamComponent MainBodyCam;

		public static ManualCameraRenderer ExternalCameraRenderer;

		public static MeshRenderer DoorScreenRenderer;

		public static bool DoorScreenUsesExternalCamera;

		public static void EarlyInitialization()
		{
			blackScreenMaterial = StartOfRound.Instance.mapScreen.offScreenMat;
			GameObject obj = GameObject.Find("Environment/HangarShip/Cameras/FrontDoorSecurityCam/SecurityCamera");
			ExternalCameraRenderer = ((obj != null) ? obj.GetComponent<ManualCameraRenderer>() : null);
			GameObject obj2 = GameObject.Find("Environment/HangarShip/ShipModels2b/MonitorWall/SingleScreen");
			DoorScreenRenderer = ((obj2 != null) ? obj2.GetComponent<MeshRenderer>() : null);
			GetAndMaybeDisableShipCamera();
			BodyCamComponent.InitializeAtStartOfGame();
		}

		private static void GetAndMaybeDisableShipCamera()
		{
			GameObject val = GameObject.Find("Environment/HangarShip/Cameras/ShipCamera");
			if ((Object)(object)val == (Object)null)
			{
				Plugin.Instance.Logger.LogError((object)"Could not find the internal ship camera object.");
				return;
			}
			ShipCameraRenderer = val.GetComponent<ManualCameraRenderer>();
			if ((Object)(object)ShipCameraRenderer?.mesh == (Object)null)
			{
				Plugin.Instance.Logger.LogError((object)"Internal ship camera does not have a camera renderer.");
			}
			else if (Plugin.DisableInternalShipCamera.Value)
			{
				int num = Array.FindIndex(((Renderer)ShipCameraRenderer.mesh).sharedMaterials, (Material material) => ((Object)material).name.StartsWith("ShipScreen1Mat"));
				if ((Object)(object)blackScreenMaterial == (Object)null || num == -1)
				{
					Plugin.Instance.Logger.LogError((object)"Internal ship camera monitor does not have the expected materials.");
					return;
				}
				val.SetActive(false);
				Material[] sharedMaterials = ((Renderer)ShipCameraRenderer.mesh).sharedMaterials;
				sharedMaterials[num] = blackScreenMaterial;
				((Renderer)ShipCameraRenderer.mesh).sharedMaterials = sharedMaterials;
			}
		}

		public static void LateInitialization()
		{
			TerminalScript = Object.FindObjectOfType<Terminal>();
			TwoRadarCamsPresent = (Object)(object)((Component)TerminalScript).GetComponent<ManualCameraRenderer>() != (Object)null;
			if ((Object)(object)DoorScreenRenderer != (Object)null)
			{
				DoorScreenUsesExternalCamera = ((Renderer)DoorScreenRenderer).sharedMaterials.Any((Material mat) => (Object)(object)mat.mainTexture == (Object)(object)ExternalCameraRenderer.cam.targetTexture);
			}
			InitializeBodyCam();
			TerminalCommands.Initialize();
			if (!TwoRadarCamsPresent && ((NetworkBehaviour)StartOfRound.Instance).IsServer)
			{
				ManualCameraRenderer mapScreen = StartOfRound.Instance.mapScreen;
				mapScreen.SwitchRadarTargetAndSync(Math.Min(mapScreen.targetTransformIndex, mapScreen.radarTargets.Count - 1));
			}
		}

		private static void InitializeBodyCam()
		{
			GameObject val = GameObject.Find("Environment/HangarShip/ShipModels2b/MonitorWall/Cube.001");
			if ((Object)(object)val == (Object)null)
			{
				Plugin.Instance.Logger.LogError((object)"Could not find the bottom monitors' game object.");
			}
			else if ((Object)(object)val.GetComponent<BodyCamComponent>() == (Object)null)
			{
				MainBodyCam = val.AddComponent<BodyCamComponent>();
				val.AddComponent<SyncBodyCamToRadarMap>();
				MeshRenderer val2 = val.GetComponent<MeshRenderer>();
				int monitorMaterialIndex = 2;
				int num = Plugin.GeneralImprovementsBetterMonitorIndex.Value - 1;
				if (num < 0)
				{
					num = 13;
				}
				MeshRenderer monitorForID = GeneralImprovementsCompatibility.GetMonitorForID(num);
				if (monitorForID != null)
				{
					val2 = monitorForID;
					monitorMaterialIndex = 0;
				}
				if ((Object)(object)val2 == (Object)null)
				{
					Plugin.Instance.Logger.LogError((object)"Failed to find the monitor renderer.");
					return;
				}
				MainBodyCam.MonitorRenderer = (Renderer)(object)val2;
				MainBodyCam.MonitorMaterialIndex = monitorMaterialIndex;
			}
		}
	}
	public class SyncBodyCamToRadarMap : MonoBehaviour
	{
		private static SyncBodyCamToRadarMap[] AllSynchronizedCams = new SyncBodyCamToRadarMap[0];

		public static readonly FieldInfo f_ManualCameraRenderer_isScreenOn = AccessTools.Field(typeof(ManualCameraRenderer), "isScreenOn");

		internal ManualCameraRenderer MapRenderer;

		internal BodyCamComponent BodyCam;

		public static SyncBodyCamToRadarMap[] GetAllSynchronizedCams()
		{
			return AllSynchronizedCams;
		}

		public ManualCameraRenderer GetMapRenderer()
		{
			return MapRenderer;
		}

		public BodyCamComponent GetBodyCam()
		{
			return BodyCam;
		}

		private static void DoForMap(ManualCameraRenderer mapRenderer, Action<SyncBodyCamToRadarMap> action)
		{
			SyncBodyCamToRadarMap[] allSynchronizedCams = AllSynchronizedCams;
			foreach (SyncBodyCamToRadarMap syncBodyCamToRadarMap in allSynchronizedCams)
			{
				if (syncBodyCamToRadarMap.MapRenderer == mapRenderer)
				{
					action(syncBodyCamToRadarMap);
				}
			}
		}

		public static void UpdateBodyCamTargetForMap(ManualCameraRenderer mapRenderer)
		{
			DoForMap(mapRenderer, delegate(SyncBodyCamToRadarMap syncedCam)
			{
				syncedCam.UpdateBodyCamTarget();
			});
		}

		public static void StartTargetTransitionForMap(ManualCameraRenderer mapRenderer)
		{
			DoForMap(mapRenderer, delegate(SyncBodyCamToRadarMap syncedCam)
			{
				syncedCam.StartTargetTransition();
			});
		}

		private static void DoForCam(BodyCamComponent bodyCam, Action<SyncBodyCamToRadarMap> action)
		{
			SyncBodyCamToRadarMap[] allSynchronizedCams = AllSynchronizedCams;
			foreach (SyncBodyCamToRadarMap syncBodyCamToRadarMap in allSynchronizedCams)
			{
				if (syncBodyCamToRadarMap.BodyCam == bodyCam)
				{
					action(syncBodyCamToRadarMap);
				}
			}
		}

		public static void UpdateBodyCamTarget(BodyCamComponent bodyCam)
		{
			DoForCam(bodyCam, delegate(SyncBodyCamToRadarMap syncedCam)
			{
				syncedCam.UpdateBodyCamTarget();
			});
		}

		private void Awake()
		{
			AllSynchronizedCams = AllSynchronizedCams.Append(this).ToArray();
			if ((Object)(object)MapRenderer == (Object)null)
			{
				MapRenderer = ((Component)this).GetComponentsInChildren<ManualCameraRenderer>()?.FirstOrDefault((Func<ManualCameraRenderer, bool>)((ManualCameraRenderer renderer) => (Object)(object)renderer.cam == (Object)(object)renderer.mapCamera));
			}
			if ((Object)(object)BodyCam == (Object)null)
			{
				BodyCam = ((Component)this).GetComponent<BodyCamComponent>();
			}
		}

		private void Start()
		{
			UpdateBodyCamTarget();
		}

		public void UpdateBodyCamTarget()
		{
			if ((Object)(object)MapRenderer.targetedPlayer != (Object)null)
			{
				BodyCam.SetTargetToPlayer(MapRenderer.targetedPlayer);
			}
			else
			{
				BodyCam.SetTargetToTransform(MapRenderer.radarTargets[MapRenderer.targetTransformIndex].transform);
			}
			BodyCam.SetScreenPowered((bool)f_ManualCameraRenderer_isScreenOn.GetValue(MapRenderer));
		}

		public void StartTargetTransition()
		{
			BodyCam.StartTargetTransition();
		}

		internal static void OnBodyCamDestroyed(BodyCamComponent bodyCam)
		{
			DoForCam(bodyCam, (Action<SyncBodyCamToRadarMap>)Object.Destroy);
		}

		private void OnDestroy()
		{
			AllSynchronizedCams = AllSynchronizedCams.Where((SyncBodyCamToRadarMap syncedCam) => syncedCam != this).ToArray();
		}
	}
	public static class TerminalCommands
	{
		public static TerminalNode ViewMonitorNode;

		public static TerminalNode ViewBodyCamNode;

		public static TerminalKeyword BodyCamKeyword;

		public static RawImage PiPImage;

		private static readonly List<TerminalKeyword> newTerminalKeywords = new List<TerminalKeyword>();

		private static readonly List<TerminalKeyword> modifiedTerminalKeywords = new List<TerminalKeyword>();

		public static void Initialize()
		{
			//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_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01da: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dc: 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_01f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f3: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)ShipObjects.TerminalScript == (Object)null || (Object)(object)ShipObjects.MainBodyCam == (Object)null)
			{
				return;
			}
			if ((Object)(object)PiPImage != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)PiPImage).gameObject);
			}
			PiPImage = null;
			ShipObjects.MainBodyCam.OnRenderTextureCreated -= SetRenderTexture;
			if (Plugin.TerminalPiPBodyCamEnabled.Value)
			{
				GameObject val = new GameObject("PictureInPictureImage");
				val.transform.SetParent(((Component)ShipObjects.TerminalScript.terminalImageMask).transform, false);
				PiPImage = val.AddComponent<RawImage>();
				val.AddComponent<TerminalBodyCamVisibilityTracker>().BodyCamToActivate = ShipObjects.MainBodyCam;
				RectTransform rectTransform = ((Graphic)ShipObjects.TerminalScript.terminalImage).rectTransform;
				Vector2 val2 = default(Vector2);
				((Vector2)(ref val2))..ctor(0f, 0f);
				Vector2 val3 = default(Vector2);
				((Vector2)(ref val3))..ctor(1f, 1f);
				int value = (int)Plugin.TerminalPiPPosition.Value;
				ref float x = ref val2.x;
				ref float x2 = ref val3.x;
				(float, int) tuple = ((((uint)value & (true ? 1u : 0u)) != 0) ? (rectTransform.offsetMax.x, -1) : (rectTransform.offsetMin.x, 1));
				(float, int) tuple2 = tuple;
				float num = tuple2.Item2;
				x = tuple2.Item1;
				x2 = num;
				ref float y = ref val2.y;
				x2 = ref val3.y;
				(float, int) tuple3 = ((((uint)value & 2u) != 0) ? (rectTransform.offsetMax.y, -1) : (rectTransform.offsetMin.y, 1));
				(float, int) tuple4 = tuple3;
				num = tuple4.Item2;
				y = tuple4.Item1;
				x2 = num;
				Vector2 val4 = val2 + new Vector2(1f, 0.75f) * val3 * (float)Plugin.TerminalPiPWidth.Value;
				((Graphic)PiPImage).rectTransform.offsetMin = Vector2.Min(val2, val4);
				((Graphic)PiPImage).rectTransform.offsetMax = Vector2.Max(val2, val4);
				if ((Object)(object)ShipObjects.MainBodyCam.Camera != (Object)null)
				{
					PiPImage.texture = (Texture)(object)ShipObjects.MainBodyCam.Camera.targetTexture;
				}
				ShipObjects.MainBodyCam.OnRenderTextureCreated += SetRenderTexture;
				ShipObjects.MainBodyCam.OnBlankedSet += SetBodyCamBlanked;
				val.SetActive(false);
			}
			InitializeCommands();
		}

		public static void SetRenderTexture(RenderTexture texture)
		{
			PiPImage.texture = (Texture)(object)texture;
		}

		public static void SetBodyCamBlanked(bool blanked)
		{
			//IL_000f: 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)
			((Graphic)PiPImage).color = (blanked ? Color.black : Color.white);
		}

		private static void InitializeCommands()
		{
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Expected O, but got Unknown
			RemoveAddedKeywords();
			ViewBodyCamNode = null;
			BodyCamKeyword = null;
			if (Plugin.TerminalPiPBodyCamEnabled.Value)
			{
				ViewBodyCamNode = ScriptableObject.CreateInstance<TerminalNode>();
				((Object)ViewBodyCamNode).name = "ViewBodyCam";
				ViewBodyCamNode.displayText = "Toggling body cam\n\n";
				ViewBodyCamNode.clearPreviousText = true;
				BodyCamKeyword = FindOrCreateKeyword("BodyCam", "bodycam", verb: false);
				ViewMonitorNode = FindOrCreateKeyword("View", "view", verb: true, (CompatibleNoun[])(object)new CompatibleNoun[1]
				{
					new CompatibleNoun
					{
						noun = BodyCamKeyword,
						result = ViewBodyCamNode
					}
				}).FindCompatibleNoun("monitor").result;
			}
			AddNewlyCreatedCommands();
		}

		private static bool TerminalIsDisplayingMap()
		{
			return (Object)(object)ShipObjects.TerminalScript.displayingPersistentImage == (Object)(object)ViewMonitorNode.displayTexture;
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(Terminal), "RunTerminalEvents")]
		private static bool RunTerminalEventsPrefix(TerminalNode node)
		{
			if ((Object)(object)node == (Object)(object)ViewBodyCamNode)
			{
				if (((Component)PiPImage).gameObject.activeSelf)
				{
					((Component)PiPImage).gameObject.SetActive(false);
					return false;
				}
				if (!TerminalIsDisplayingMap())
				{
					ShipObjects.TerminalScript.LoadTerminalImage(ViewMonitorNode);
				}
				if (TerminalIsDisplayingMap())
				{
					((Component)PiPImage).gameObject.SetActive(true);
				}
				return false;
			}
			return true;
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Terminal), "LoadNewNode")]
		private static void LoadNewNodePostfix(TerminalNode node)
		{
			if (!((Object)(object)PiPImage == (Object)null) && !((Object)(object)node != (Object)(object)ViewMonitorNode) && !TerminalIsDisplayingMap())
			{
				((Component)PiPImage).gameObject.SetActive(false);
			}
		}

		private static void RemoveAddedKeywords()
		{
			foreach (TerminalKeyword modifiedTerminalKeyword in modifiedTerminalKeywords)
			{
				if (modifiedTerminalKeyword.compatibleNouns == null)
				{
					continue;
				}
				TerminalKeyword val = modifiedTerminalKeyword;
				List<CompatibleNoun> list = new List<CompatibleNoun>();
				foreach (CompatibleNoun item in modifiedTerminalKeyword.compatibleNouns.Where((CompatibleNoun compatible) => !newTerminalKeywords.Contains(compatible.noun)))
				{
					list.Add(item);
				}
				val.compatibleNouns = list.ToArray();
			}
			modifiedTerminalKeywords.Clear();
			foreach (TerminalKeyword newTerminalKeyword in newTerminalKeywords)
			{
				Object.Destroy((Object)(object)newTerminalKeyword);
			}
			TerminalNodesList terminalNodes;
			TerminalNodesList obj = (terminalNodes = ShipObjects.TerminalScript.terminalNodes);
			List<TerminalKeyword> list2 = new List<TerminalKeyword>();
			foreach (TerminalKeyword item2 in obj.allKeywords.Where((TerminalKeyword keyword) => !newTerminalKeywords.Contains(keyword)))
			{
				list2.Add(item2);
			}
			terminalNodes.allKeywords = list2.ToArray();
			newTerminalKeywords.Clear();
		}

		private static TerminalKeyword FindKeyword(string word, bool verb)
		{
			return ((IEnumerable<TerminalKeyword>)ShipObjects.TerminalScript.terminalNodes.allKeywords).FirstOrDefault((Func<TerminalKeyword, bool>)((TerminalKeyword keyword) => keyword.word == word && keyword.isVerb == verb));
		}

		private static CompatibleNoun FindCompatibleNoun(this TerminalKeyword keyword, string noun)
		{
			return ((IEnumerable<CompatibleNoun>)keyword.compatibleNouns).FirstOrDefault((Func<CompatibleNoun, bool>)((CompatibleNoun compatible) => compatible.noun.word == noun));
		}

		private static TerminalKeyword FindOrCreateKeyword(string name, string word, bool verb, CompatibleNoun[] compatibleNouns = null)
		{
			Plugin.Instance.Logger.LogInfo((object)("Creating terminal " + (verb ? "verb" : "noun") + " '" + word + "' (" + name + ")."));
			TerminalKeyword val = FindKeyword(word, verb);
			if ((Object)(object)val == (Object)null)
			{
				val = ScriptableObject.CreateInstance<TerminalKeyword>();
				((Object)val).name = name;
				val.isVerb = verb;
				val.word = word;
				val.compatibleNouns = compatibleNouns;
				newTerminalKeywords.Add(val);
				Plugin.Instance.Logger.LogInfo((object)"  Keyword was not found, created a new one.");
			}
			else
			{
				TerminalKeyword val2 = val;
				CompatibleNoun[] obj = val.compatibleNouns ?? Array.Empty<CompatibleNoun>();
				CompatibleNoun[] array = compatibleNouns ?? Array.Empty<CompatibleNoun>();
				int num = 0;
				CompatibleNoun[] array2 = (CompatibleNoun[])(object)new CompatibleNoun[obj.Length + array.Length];
				CompatibleNoun[] array3 = obj;
				foreach (CompatibleNoun val3 in array3)
				{
					array2[num] = val3;
					num++;
				}
				array3 = array;
				foreach (CompatibleNoun val3 in array3)
				{
					array2[num] = val3;
					num++;
				}
				val2.compatibleNouns = array2;
				Plugin.Instance.Logger.LogInfo((object)"  Keyword existed, appended nouns.");
			}
			modifiedTerminalKeywords.Add(val);
			return val;
		}

		private static void AddNewlyCreatedCommands()
		{
			TerminalNodesList terminalNodes;
			TerminalKeyword[] allKeywords = (terminalNodes = ShipObjects.TerminalScript.terminalNodes).allKeywords;
			List<TerminalKeyword> list = newTerminalKeywords;
			int num = 0;
			TerminalKeyword[] array = (TerminalKeyword[])(object)new TerminalKeyword[allKeywords.Length + list.Count];
			TerminalKeyword[] array2 = allKeywords;
			foreach (TerminalKeyword val in array2)
			{
				array[num] = val;
				num++;
			}
			foreach (TerminalKeyword item in list)
			{
				array[num] = item;
				num++;
			}
			terminalNodes.allKeywords = array;
		}
	}
	public enum PiPPosition : uint
	{
		BottomLeft,
		BottomRight,
		TopLeft,
		TopRight
	}
	public class TerminalBodyCamVisibilityTracker : MonoBehaviour
	{
		public BodyCamComponent BodyCamToActivate;

		private void OnEnable()
		{
			if ((Object)(object)BodyCamToActivate != (Object)null)
			{
				BodyCamToActivate.ForceEnableCamera = true;
			}
		}

		private void OnDisable()
		{
			if ((Object)(object)BodyCamToActivate != (Object)null)
			{
				BodyCamToActivate.ForceEnableCamera = false;
			}
		}
	}
	public static class Utilities
	{
		private static Camera[] allCameras = Array.Empty<Camera>();

		private static readonly Plane[] frustumPlanes = (Plane[])(object)new Plane[6];

		public static bool IsVisibleToAnyCameraExcept(this Renderer renderer, Camera cameraToSkip, bool debug = false)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			if (allCameras.Length != Camera.allCamerasCount)
			{
				allCameras = (Camera[])(object)new Camera[Camera.allCamerasCount];
			}
			Camera.GetAllCameras(allCameras);
			Bounds bounds = renderer.bounds;
			int layer = ((Component)renderer).gameObject.layer;
			Camera[] array = allCameras;
			foreach (Camera val in array)
			{
				if ((val == null || val != cameraToSkip) && (val.cullingMask & (1 << layer)) != 0)
				{
					GeometryUtility.CalculateFrustumPlanes(val, frustumPlanes);
					if (GeometryUtility.TestPlanesAABB(frustumPlanes, bounds))
					{
						return true;
					}
				}
			}
			return false;
		}
	}
}
namespace OpenBodyCams.Patches
{
	public class SequenceMatch
	{
		public int Start;

		public int End;

		public int Size => End - Start;

		public SequenceMatch(int start, int end)
		{
			Start = start;
			End = end;
			base..ctor();
		}
	}
	public static class Common
	{
		public static IEnumerable<T> IndexRangeView<T>(this List<T> list, int start, int end)
		{
			for (int i = start; i < end; i++)
			{
				yield return list[i];
			}
		}

		public static IEnumerable<T> IndexRangeView<T>(this List<T> list, SequenceMatch range)
		{
			return list.IndexRangeView(range.Start, range.End);
		}

		public static SequenceMatch FindIndexOfSequence<T>(this List<T> list, int startIndex, IEnumerable<Predicate<T>> predicates)
		{
			int num;
			for (num = startIndex; num < list.Count(); num++)
			{
				IEnumerator<Predicate<T>> enumerator = predicates.GetEnumerator();
				if (!enumerator.MoveNext())
				{
					return null;
				}
				num = list.FindIndex(num, enumerator.Current);
				if (num < 0)
				{
					break;
				}
				bool flag = true;
				int num2 = 1;
				while (enumerator.MoveNext())
				{
					if (num2 >= list.Count() - num || !enumerator.Current(list[num + num2]))
					{
						flag = false;
						break;
					}
					num2++;
				}
				if (flag)
				{
					return new SequenceMatch(num, num + predicates.Count());
				}
			}
			return null;
		}

		public static SequenceMatch FindIndexOfSequence<T>(this List<T> list, IEnumerable<Predicate<T>> predicates)
		{
			return list.FindIndexOfSequence(0, predicates);
		}

		public static int PopCount(this CodeInstruction instruction)
		{
			if (instruction.opcode == OpCodes.Call || instruction.opcode == OpCodes.Callvirt)
			{
				MethodInfo obj = (MethodInfo)instruction.operand;
				int num = obj.GetParameters().Length;
				if (!obj.IsStatic)
				{
					num++;
				}
				return num;
			}
			if (instruction.opcode == OpCodes.Ret)
			{
				return 1;
			}
			return instruction.opcode.StackBehaviourPop switch
			{
				StackBehaviour.Pop0 => 0, 
				StackBehaviour.Pop1 => 1, 
				StackBehaviour.Pop1_pop1 => 2, 
				StackBehaviour.Popi => 1, 
				StackBehaviour.Popi_pop1 => 2, 
				StackBehaviour.Popi_popi => 2, 
				StackBehaviour.Popi_popi8 => 2, 
				StackBehaviour.Popi_popi_popi => 3, 
				StackBehaviour.Popi_popr4 => 2, 
				StackBehaviour.Popi_popr8 => 2, 
				StackBehaviour.Popref => 1, 
				StackBehaviour.Popref_pop1 => 2, 
				StackBehaviour.Popref_popi => 2, 
				StackBehaviour.Popref_popi_popi => 3, 
				StackBehaviour.Popref_popi_popi8 => 3, 
				StackBehaviour.Popref_popi_popr4 => 3, 
				StackBehaviour.Popref_popi_popr8 => 3, 
				StackBehaviour.Popref_popi_popref => 3, 
				StackBehaviour.Varpop => throw new NotImplementedException("Variable pop on non-call instruction"), 
				StackBehaviour.Popref_popi_pop1 => 3, 
				_ => throw new NotSupportedException($"StackBehaviourPop of {instruction.opcode.StackBehaviourPop} was not a pop for instruction '{instruction}'"), 
			};
		}

		public static int PushCount(this CodeInstruction instruction)
		{
			if (instruction.opcode == OpCodes.Call || instruction.opcode == OpCodes.Callvirt)
			{
				if (((MethodInfo)instruction.operand).ReturnType == typeof(void))
				{
					return 0;
				}
				return 1;
			}
			return instruction.opcode.StackBehaviourPush switch
			{
				StackBehaviour.Push0 => 0, 
				StackBehaviour.Push1 => 1, 
				StackBehaviour.Push1_push1 => 2, 
				StackBehaviour.Pushi => 1, 
				StackBehaviour.Pushi8 => 1, 
				StackBehaviour.Pushr4 => 1, 
				StackBehaviour.Pushr8 => 1, 
				StackBehaviour.Pushref => 1, 
				StackBehaviour.Varpush => throw new NotImplementedException("Variable push on non-call instruction"), 
				_ => throw new NotSupportedException($"StackBehaviourPush of {instruction.opcode.StackBehaviourPush} was not a push for instruction '{instruction}'"), 
			};
		}

		public static SequenceMatch InstructionRangeForStackItems(this List<CodeInstruction> instructions, int instructionIndex, int startIndex, int endIndex)
		{
			int num = -1;
			int num2 = -1;
			instructionIndex--;
			int num3 = 0;
			while (instructionIndex >= 0)
			{
				CodeInstruction instruction = instructions[instructionIndex];
				int num4 = instruction.PushCount();
				if (num2 == -1 && num3 == startIndex && num4 > 0)
				{
					num2 = instructionIndex + 1;
				}
				num3 += instruction.PushCount();
				num3 -= instruction.PopCount();
				if (num3 > endIndex)
				{
					num = instructionIndex;
					break;
				}
				instructionIndex--;
			}
			if (num == -1 || num2 == -1)
			{
				return null;
			}
			return new SequenceMatch(num, num2);
		}
	}
	internal class PatchFixItemDropping
	{
		private static readonly MethodInfo m_PlayerControllerB_SetObjectAsNoLongerHeld = typeof(PlayerControllerB).GetMethod("SetObjectAsNoLongerHeld", new Type[5]
		{
			typeof(bool),
			typeof(bool),
			typeof(Vector3),
			typeof(GrabbableObject),
			typeof(int)
		});

		[HarmonyTranspiler]
		[HarmonyPatch(typeof(PlayerControllerB), "ThrowObjectClientRpc")]
		private static IEnumerable<CodeInstruction> ThrowObjectClientRpcTranspiler(IEnumerable<CodeInstruction> instructions, MethodBase method)
		{
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Expected O, but got Unknown
			if (!Plugin.FixDroppedItemRotation.Value)
			{
				return instructions;
			}
			List<CodeInstruction> list = instructions.ToList();
			int num = Array.FindIndex(method.GetParameters(), (ParameterInfo p) => p.Name == "floorYRot") + 1;
			if (num < 1)
			{
				Plugin.Instance.Logger.LogWarning((object)"Dropped item patch transpiler failed to find the floorYRot argument.");
				return instructions;
			}
			int num2 = list.FindIndex((CodeInstruction insn) => CodeInstructionExtensions.Calls(insn, m_PlayerControllerB_SetObjectAsNoLongerHeld));
			if (num2 == -1)
			{
				Plugin.Instance.Logger.LogWarning((object)"Dropped item patch transpiler failed to find the call to SetObjectAsNoLongerHeld().");
				return instructions;
			}
			SequenceMatch sequenceMatch = list.InstructionRangeForStackItems(num2, 0, 0);
			if (sequenceMatch == null)
			{
				Plugin.Instance.Logger.LogWarning((object)"Dropped item patch transpiler failed to get the instructions pushing the floorYRot value.");
				return instructions;
			}
			list.RemoveRange(sequenceMatch.Start, sequenceMatch.Size);
			list.Insert(sequenceMatch.Start, new CodeInstruction(OpCodes.Ldarg, (object)num));
			return list;
		}
	}
	[HarmonyPatch(typeof(ManualCameraRenderer))]
	internal class PatchManualCameraRenderer
	{
		[HarmonyPostfix]
		[HarmonyPatch("updateMapTarget")]
		private static IEnumerator updateMapTargetPostfix(IEnumerator result, ManualCameraRenderer __instance)
		{
			SyncBodyCamToRadarMap.StartTargetTransitionForMap(__instance);
			while (result.MoveNext())
			{
				yield return result.Current;
			}
			SyncBodyCamToRadarMap.UpdateBodyCamTargetForMap(__instance);
		}

		[HarmonyPostfix]
		[HarmonyPatch("SwitchScreenOn")]
		[HarmonyAfter(new string[] { "ShaosilGaming.GeneralImprovements" })]
		private static void SwitchScreenOnPostfix(ManualCameraRenderer __instance)
		{
			SyncBodyCamToRadarMap.UpdateBodyCamTargetForMap(__instance);
		}

		[HarmonyPostfix]
		[HarmonyPatch("MeetsCameraEnabledConditions")]
		private static void MeetsCameraEnabledConditionsPostfix(ManualCameraRenderer __instance, ref bool __result, PlayerControllerB player)
		{
			if (__instance == StartOfRound.Instance.mapScreen)
			{
				if (!__result && !ShipObjects.TwoRadarCamsPresent && ((Behaviour)ShipObjects.TerminalScript.terminalUIScreen).isActiveAndEnabled)
				{
					__result = true;
				}
			}
			else if (__instance == ShipObjects.ShipCameraRenderer)
			{
				if (__result)
				{
					__result = ((Renderer)(object)__instance.mesh).IsVisibleToAnyCameraExcept(__instance.cam);
				}
			}
			else if (__instance == ShipObjects.ExternalCameraRenderer && ShipObjects.DoorScreenUsesExternalCamera && !__result && (player.isInHangarShipRoom || !StartOfRound.Instance.shipDoorsEnabled))
			{
				__result = ((Renderer)(object)ShipObjects.DoorScreenRenderer).IsVisibleToAnyCameraExcept(__instance.cam, debug: true);
			}
		}

		[HarmonyTranspiler]
		[HarmonyPatch("RemoveTargetFromRadar")]
		private static IEnumerable<CodeInstruction> RemoveTargetFromRadarTranspiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
		{
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Expected O, but got Unknown
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Expected O, but got Unknown
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Expected O, but got Unknown
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Expected O, but got Unknown
			MethodInfo m_ManualCameraRenderer_SwitchRadarTargetForward = typeof(ManualCameraRenderer).GetMethod("SwitchRadarTargetForward", new Type[1] { typeof(bool) });
			MethodInfo method = typeof(NetworkBehaviour).GetMethod("get_IsOwner");
			List<CodeInstruction> list = instructions.ToList();
			SequenceMatch sequenceMatch = list.FindIndexOfSequence(new <>z__ReadOnlyArray<Predicate<CodeInstruction>>(new Predicate<CodeInstruction>[3]
			{
				(CodeInstruction insn) => CodeInstructionExtensions.IsLdarg(insn, (int?)0),
				(CodeInstruction insn) => CodeInstructionExtensions.LoadsConstant(insn, 0L),
				(CodeInstruction insn) => CodeInstructionExtensions.Calls(insn, m_ManualCameraRenderer_SwitchRadarTargetForward)
			}));
			list[sequenceMatch.Start + 1] = new CodeInstruction(OpCodes.Ldc_I4_1, (object)null);
			Label label = generator.DefineLabel();
			list[sequenceMatch.End].labels.Add(label);
			list.InsertRange(sequenceMatch.Start, new <>z__ReadOnlyArray<CodeInstruction>((CodeInstruction[])(object)new CodeInstruction[3]
			{
				new CodeInstruction(OpCodes.Ldarg_0, (object)null),
				new CodeInstruction(OpCodes.Call, (object)method),
				new CodeInstruction(OpCodes.Brfalse_S, (object)label)
			}));
			return list;
		}
	}
	[HarmonyPatch(typeof(HauntedMaskItem))]
	internal class PatchHauntedMaskItem
	{
		[HarmonyPostfix]
		[HarmonyPatch("CreateMimicServerRpc")]
		private static void CreateMimicServerRpcPostfix()
		{
			BodyCamComponent.MarkTargetStatusChangedForAllBodyCams();
		}

		[HarmonyPostfix]
		[HarmonyPatch("waitForMimicEnemySpawn")]
		private static IEnumerator waitForMimicEnemySpawnPostfix(IEnumerator __result)
		{
			while (__result.MoveNext())
			{
				yield return __result.Current;
			}
			BodyCamComponent.MarkTargetStatusChangedForAllBodyCams();
		}
	}
	[HarmonyPatch(typeof(MaskedPlayerEnemy))]
	internal class PatchMaskedPlayerEnemy
	{
		[HarmonyPrefix]
		[HarmonyPatch("FinishKillAnimation")]
		private static void FinishKillAnimationPrefix(bool __0)
		{
			if (__0)
			{
				BodyCamComponent.MarkTargetStatusChangedForAllBodyCams();
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch("waitForMimicEnemySpawn")]
		private static IEnumerator waitForMimicEnemySpawnPostfix(IEnumerator __result)
		{
			while (__result.MoveNext())
			{
				yield return __result.Current;
			}
			BodyCamComponent.MarkTargetStatusChangedForAllBodyCams();
		}
	}
	internal static class PatchModelDestructionDebugging
	{
		private static bool IsChildReferenced(GameObject obj)
		{
			Transform[] componentsInChildren = obj.GetComponentsInChildren<Transform>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				if (BodyCamComponent.AnyBodyCamHasReference(((Component)componentsInChildren[i]).gameObject))
				{
					return true;
				}
			}
			Renderer[] componentsInChildren2 = obj.GetComponentsInChildren<Renderer>(true);
			for (int i = 0; i < componentsInChildren2.Length; i++)
			{
				if (BodyCamComponent.AnyBodyCamHasReference(componentsInChildren2[i]))
				{
					return true;
				}
			}
			return false;
		}

		private static bool IsReferencedObject(Object obj)
		{
			if (obj == (Object)null)
			{
				return false;
			}
			Renderer val = (Renderer)(object)((obj is Renderer) ? obj : null);
			if (val != null)
			{
				return BodyCamComponent.AnyBodyCamHasReference(val);
			}
			GameObject val2 = (GameObject)(object)((obj is GameObject) ? obj : null);
			if (val2 != null)
			{
				return IsChildReferenced(val2);
			}
			return false;
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(Object), "Destroy", new Type[]
		{
			typeof(Object),
			typeof(float)
		})]
		private static void DestroyingObject(Object obj, float t)
		{
			if (IsReferencedObject(obj))
			{
				Plugin.Instance.Logger.LogWarning((object)$"In {t} seconds, {obj.name} will be destroyed while it is referenced by a body cam.");
				Plugin.Instance.Logger.LogWarning((object)new StackTrace());
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(Object), "DestroyImmediate", new Type[]
		{
			typeof(Object),
			typeof(bool)
		})]
		private static void DestroyingObjectImmediately(Object obj)
		{
			if (IsReferencedObject(obj))
			{
				Plugin.Instance.Logger.LogWarning((object)("Immediately destroying " + obj.name + " which is referenced by a body cam."));
				Plugin.Instance.Logger.LogWarning((object)new StackTrace());
			}
		}
	}
	[HarmonyPatch(typeof(PlayerControllerB))]
	internal class PatchPlayerControllerB
	{
		[HarmonyFinalizer]
		[HarmonyPatch("ConnectClientToPlayerObject")]
		[HarmonyAfter(new string[] { "ShaosilGaming.GeneralImprovements" })]
		private static void ConnectClientToPlayerObjectFinalizer()
		{
			ShipObjects.LateInitialization();
		}

		[HarmonyPostfix]
		[HarmonyPatch("KillPlayer")]
		private static void KillPlayerPostfix(PlayerControllerB __instance)
		{
			if (((NetworkBehaviour)__instance).IsOwner)
			{
				BodyCamComponent.MarkTargetStatusChangedForAllBodyCams(((Component)__instance).transform);
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch("KillPlayerClientRpc")]
		private static void KillPlayerClientRpcPostfix(PlayerControllerB __instance)
		{
			if (!((NetworkBehaviour)__instance).IsOwner)
			{
				BodyCamComponent.MarkTargetStatusChangedForAllBodyCams(((Component)__instance).transform);
			}
		}
	}
	[HarmonyPatch(typeof(StartOfRound))]
	internal class PatchStartOfRound
	{
		[HarmonyPostfix]
		[HarmonyPatch("Start")]
		[HarmonyPriority(700)]
		private static void StartPostfix()
		{
			ShipObjects.EarlyInitialization();
		}

		[HarmonyPostfix]
		[HarmonyPatch("ReviveDeadPlayers")]
		private static void ReviveDeadPlayersPostfix()
		{
			BodyCamComponent.MarkTargetStatusChangedForAllBodyCams();
		}
	}
	public static class Reflection
	{
		public static readonly MethodInfo m_StartOfRound_get_Instance = typeof(StartOfRound).GetMethod("get_Instance", Array.Empty<Type>());

		public static readonly FieldInfo f_StartOfRound_thisClientPlayerId = typeof(StartOfRound).GetField("thisClientPlayerId");
	}
}
namespace OpenBodyCams.Compatibility
{
	public static class AdvancedCompanyCompatibility
	{
		private static int cosmeticChangesInProgress;

		public static bool Initialize(Harmony harmony)
		{
			Type typeFromHandle = typeof(Player);
			(string, Type[])[] obj = new(string, Type[])[6]
			{
				("SetCosmetics", new Type[2]
				{
					typeof(string[]),
					typeof(bool)
				}),
				("AddCosmetic", new Type[1] { typeof(string) }),
				("ReequipHead", Array.Empty<Type>()),
				("ReequipBody", Array.Empty<Type>()),
				("ReequipFeet", Array.Empty<Type>()),
				("UnequipAll", Array.Empty<Type>())
			};
			MethodInfo method = typeof(AdvancedCompanyCompatibility).GetMethod("AfterEquipmentChange", BindingFlags.Static | BindingFlags.NonPublic);
			(string, Type[])[] array = obj;
			for (int i = 0; i < array.Length; i++)
			{
				(string, Type[]) tuple = array[i];
				string item = tuple.Item1;
				Type[] item2 = tuple.Item2;
				MethodInfo method2 = typeFromHandle.GetMethod(item, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, item2, null);
				if ((object)method2 == null)
				{
					Plugin.Instance.Logger.LogWarning((object)("Failed to find " + typeFromHandle.Name + "." + item + " to apply postfix."));
					return false;
				}
				harmony.CreateProcessor((MethodBase)method2).AddPostfix(method).Patch();
			}
			harmony.CreateProcessor((MethodBase)typeof(LightShoeRGB).GetMethod("LiftCurse", BindingFlags.Instance | BindingFlags.NonPublic)).AddPostfix(typeof(AdvancedCompanyCompatibility).GetMethod("UpdateCosmeticsAfterCoroutine", BindingFlags.Static | BindingFlags.NonPublic)).Patch();
			return true;
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		public static GameObject[] CollectCosmetics(PlayerControllerB player)
		{
			Player player2 = Player.GetPlayer(player);
			IEnumerable<GameObject> enumerable = player2.AppliedCosmetics.Values;
			GameObject[] equipmentItemsHead = player2.EquipmentItemsHead;
			if (equipmentItemsHead != null)
			{
				enumerable = enumerable.Concat(equipmentItemsHead);
			}
			GameObject[] equipmentItemsBody = player2.EquipmentItemsBody;
			if (equipmentItemsBody != null)
			{
				enumerable = enumerable.Concat(equipmentItemsBody);
			}
			GameObject[] equipmentItemsFeet = player2.EquipmentItemsFeet;
			if (equipmentItemsFeet != null)
			{
				enumerable = enumerable.Concat(equipmentItemsFeet);
			}
			IEnumerable<GameObject> first = from transform in enumerable.Where((GameObject cosmetic) => (Object)(object)cosmetic != (Object)null).SelectMany((GameObject cosmetic) => cosmetic.GetComponentsInChildren<Transform>())
				select ((Component)transform).gameObject;
			IEnumerable<GameObject> second;
			if (!((Object)(object)player2.HeadMount == (Object)null))
			{
				IEnumerable<GameObject> enumerable2 = new <>z__ReadOnlyArray<GameObject>((GameObject[])(object)new GameObject[1] { player2.HeadMount });
				second = enumerable2;
			}
			else
			{
				IEnumerable<GameObject> enumerable2 = Array.Empty<GameObject>();
				second = enumerable2;
			}
			return first.Concat(second).ToArray();
		}

		private static void AfterEquipmentChange()
		{
			BodyCamComponent.MarkTargetDirtyUntilRenderForAllBodyCams();
		}

		private static IEnumerator UpdateCosmeticsAfterCoroutine(IEnumerator __result)
		{
			while (true)
			{
				try
				{
					if (!__result.MoveNext())
					{
						break;
					}
				}
				catch (Exception ex)
				{
					Plugin.Instance.Logger.LogError((object)"AdvancedCompany encountered an error in a coroutine:");
					Plugin.Instance.Logger.LogError((object)ex);
					break;
				}
				yield return __result.Current;
			}
			BodyCamComponent.MarkTargetDirtyUntilRenderForAllBodyCams();
		}
	}
	public static class GeneralImprovementsCompatibility
	{
		private static string getMonitorPath(int id)
		{
			return id switch
			{
				0 => "Monitors/TopGroupL/Screen1", 
				1 => "Monitors/TopGroupL/Screen2", 
				2 => "Monitors/TopGroupM/Screen3", 
				3 => "Monitors/TopGroupM/Screen4", 
				4 => "Monitors/TopGroupR/Screen5", 
				5 => "Monitors/TopGroupR/Screen6", 
				6 => "Monitors/TopGroupL/Screen7", 
				7 => "Monitors/TopGroupL/Screen8", 
				8 => "Monitors/TopGroupM/Screen9", 
				9 => "Monitors/TopGroupM/Screen10", 
				10 => "Monitors/TopGroupR/Screen11", 
				11 => "Monitors/TopGroupR/Screen12", 
				12 => "Monitors/BigLeft/LScreen", 
				13 => "Monitors/BigRight/RScreen", 
				_ => null, 
			};
		}

		public static MeshRenderer GetMonitorForID(int id)
		{
			GameObject obj = GameObject.Find("Environment/HangarShip/ShipModels2b/MonitorWall/MonitorGroup(Clone)/" + getMonitorPath(id));
			if (obj == null)
			{
				return null;
			}
			return obj.GetComponent<MeshRenderer>();
		}
	}
	public static class LethalVRMCompatibility
	{
		private static IEnumerable vrmInstances;

		[MethodImpl(MethodImplOptions.NoInlining)]
		public static bool Initialize(Harmony harmony)
		{
			GameObject obj = GameObject.Find("LethalVRM Manager");
			LethalVRMManager val = ((obj != null) ? obj.GetComponent<LethalVRMManager>() : null);
			if (val == null)
			{
				Plugin.Instance.Logger.LogWarning((object)"Failed to find the LethalVRMManager instance.");
				return false;
			}
			vrmInstances = val.instances;
			if (vrmInstances == null)
			{
				Plugin.Instance.Logger.LogWarning((object)"Failed to get the value of the LethalVRMManager.instances field.");
				return false;
			}
			MethodInfo method = typeof(LethalVRMManager).GetMethod("LoadModelToPlayer", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).GetCustomAttribute<AsyncStateMachineAttribute>().StateMachineType.GetMethod("MoveNext", BindingFlags.Instance | BindingFlags.NonPublic);
			harmony.CreateProcessor((MethodBase)method).AddTranspiler(typeof(LethalVRMCompatibility).GetMethod("LoadModelToPlayerTranspiler", BindingFlags.Static | BindingFlags.NonPublic)).Patch();
			return true;
		}

		private static IEnumerable<CodeInstruction> LoadModelToPlayerTranspiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			List<CodeInstruction> list = instructions.ToList();
			MethodInfo method = typeof(BodyCamComponent).GetMethod("MarkTargetDirtyUntilRenderForAllBodyCams", Array.Empty<Type>());
			list.Insert(list.Count() - 2, new CodeInstruction(OpCodes.Call, (object)method));
			return list;
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		public static GameObject[] CollectCosmetics(PlayerControllerB player)
		{
			foreach (LethalVRMInstance item in (ICollection<LethalVRMInstance>)vrmInstances)
			{
				if (item != null && item.PlayerControllerB == player)
				{
					return item.renderers.Select((Renderer renderer) => ((Component)renderer).gameObject).ToArray();
				}
			}
			return (GameObject[])(object)new GameObject[0];
		}
	}
	public static class ModelReplacementAPICompatibility
	{
		public static MethodInfo m_UpdateModelReplacement;

		public static bool Initialize(Harmony harmony)
		{
			MethodInfo method = typeof(ViewStateManager).GetMethod("ReportBodyReplacementAddition", new Type[1] { typeof(BodyReplacementBase) });
			if ((object)method == null)
			{
				Plugin.Instance.Logger.LogInfo((object)"ModelReplacementAPI is installed, but the `ViewStateManager.ReportBodyReplacementAddition()` method was not found.");
				return false;
			}
			MethodInfo method2 = typeof(ModelReplacementAPI).GetMethod("RemovePlayerModelReplacement", new Type[1] { typeof(PlayerControllerB) });
			if ((object)method2 == null)
			{
				Plugin.Instance.Logger.LogInfo((object)"ModelReplacementAPI is installed, but the `ModelReplacementAPI.RemovePlayerModelReplacement()` method was not found.");
				return false;
			}
			m_UpdateModelReplacement = typeof(ModelReplacementAPICompatibility).GetMethod("UpdateModelReplacement", new Type[1] { typeof(ViewStateManager) });
			harmony.CreateProcessor((MethodBase)method).AddPostfix(m_UpdateModelReplacement).Patch();
			MethodInfo method3 = typeof(ModelReplacementAPICompatibility).GetMethod("RemoveModelReplacementTranspiler");
			harmony.CreateProcessor((MethodBase)method2).AddTranspiler(method3).Patch();
			m_UpdateModelReplacement = null;
			return true;
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		public static GameObject[] CollectCosmetics(PlayerControllerB player)
		{
			BodyReplacementBase val = ((Component)player).GetComponent<ViewStateManager>()?.bodyReplacement;
			if ((Object)(object)val?.replacementModel == (Object)null)
			{
				return Array.Empty<GameObject>();
			}
			return (from cosmeticObject in val.replacementModel.GetComponentsInChildren<Transform>()
				select ((Component)cosmeticObject).gameObject).ToArray();
		}

		public static void UpdateModelReplacement(ViewStateManager __instance)
		{
			BodyCamComponent.MarkTargetDirtyUntilRenderForAllBodyCams(((Com

BepInEx/plugins/OpenMonitors.dll

Decompiled 7 months ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using DunGen;
using GameNetcodeStuff;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using OpenMonitors.Monitors;
using TMPro;
using Unity.Netcode;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("OpenMonitors")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("OpenMonitors")]
[assembly: AssemblyCopyright("Copyright ©  2024")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("1203C15A-FDA7-419A-9D8B-0312A7C308AC")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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]
	[Microsoft.CodeAnalysis.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]
	[Microsoft.CodeAnalysis.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 OpenMonitors
{
	public static class ModInfo
	{
		public const string Name = "OpenMonitors";

		public const string Guid = "xxxstoner420bongmasterxxx.open_monitors";

		public const string Version = "1.1.1";
	}
	[BepInPlugin("xxxstoner420bongmasterxxx.open_monitors", "OpenMonitors", "1.1.1")]
	public class Plugin : BaseUnityPlugin
	{
		public static ConfigFile ModConfig;

		private static Plugin? _instance;

		public static ManualLogSource ModLogger;

		private readonly Harmony _harmony = new Harmony("xxxstoner420bongmasterxxx.open_monitors");

		private void Awake()
		{
			ModLogger = ((BaseUnityPlugin)this).Logger;
			if (!Object.op_Implicit((Object)(object)_instance))
			{
				ModLogger.LogInfo((object)"OpenMonitors -> loading");
				_instance = this;
				ModConfig = ((BaseUnityPlugin)this).Config;
				Config.Initialize();
				_harmony.PatchAll(Assembly.GetExecutingAssembly());
				ModLogger.LogInfo((object)"OpenMonitors -> complete");
			}
		}
	}
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "OpenMonitors";

		public const string PLUGIN_NAME = "OpenMonitors";

		public const string PLUGIN_VERSION = "1.0.0";
	}
}
namespace OpenMonitors.Patch
{
	[HarmonyPatch(typeof(DepositItemsDesk))]
	public class DepositItemsDesk
	{
		[HarmonyPostfix]
		[HarmonyPatch("SellAndDisplayItemProfits")]
		private static void UpdateCreditsAfterSellingLoot()
		{
			Plugin.ModLogger.LogDebug((object)"DepositItemsDesk.UpdateCreditsAfterSellingLoot");
			CreditsMonitor.Instance.UpdateMonitor();
		}
	}
	[HarmonyPatch(typeof(HUDManager))]
	public class HUDManager
	{
		[HarmonyPostfix]
		[HarmonyPatch("ApplyPenalty")]
		private static void UpdateCreditsAfterDeadPlayersPenalty()
		{
			Plugin.ModLogger.LogDebug((object)"HUDManager.UpdateCreditsAfterDeadPlayersPenalty");
			CreditsMonitor.Instance.UpdateMonitor();
		}
	}
	[HarmonyPatch(typeof(PlayerControllerB))]
	public class PlayerControllerB
	{
		[HarmonyPostfix]
		[HarmonyPatch("ConnectClientToPlayerObject")]
		private static void OnPlayerConnect()
		{
			((MonoBehaviour)CoroutineHelper.Instance).StartCoroutine(WaitOnPlayerConnectForMonitorsToBeCreated());
		}

		private static IEnumerator WaitOnPlayerConnectForMonitorsToBeCreated()
		{
			Plugin.ModLogger.LogDebug((object)"WaitOnPlayerConnectForMonitorsToBeCreated");
			yield return (object)new WaitUntil((Func<bool>)(() => Object.op_Implicit((Object)(object)CreditsMonitor.Instance) && Object.op_Implicit((Object)(object)LifeSupportMonitor.Instance)));
			CreditsMonitor.Instance.UpdateMonitor();
			LifeSupportMonitor.Instance.UpdateMonitor();
			PlayersLifeSupportMonitor.Instance.UpdateMonitor();
		}

		[HarmonyPostfix]
		[HarmonyPatch("GrabObjectClientRpc")]
		private static void RefreshLootOnPickupClient(bool grabValidated, ref NetworkObjectReference grabbedObject)
		{
			NetworkObject val = default(NetworkObject);
			if (((NetworkObjectReference)(ref grabbedObject)).TryGet(ref val, (NetworkManager)null))
			{
				GrabbableObject componentInChildren = ((Component)val).gameObject.GetComponentInChildren<GrabbableObject>();
				if (componentInChildren.isInShipRoom || componentInChildren.isInElevator)
				{
					Plugin.ModLogger.LogDebug((object)"PlayerControllerB.RefreshLootOnPickupClient");
					LootMonitor.Instance.UpdateMonitor();
				}
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch("ThrowObjectClientRpc")]
		private static void RefreshLootOnThrowClient(bool droppedInElevator, bool droppedInShipRoom, Vector3 targetFloorPosition, NetworkObjectReference grabbedObject)
		{
			if (droppedInShipRoom || droppedInElevator)
			{
				Plugin.ModLogger.LogDebug((object)"PlayerControllerB.RefreshLootOnThrowClient");
				LootMonitor.Instance.UpdateMonitor();
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch("KillPlayer")]
		private static void UpdateLifeSupportMonitorOnPlayerDeath(Vector3 bodyVelocity, bool spawnBody, CauseOfDeath causeOfDeath, int deathAnimation)
		{
			Plugin.ModLogger.LogDebug((object)"PlayerControllerB.UpdateLifeSupportMonitorOnPlayerDeath");
			LifeSupportMonitor.Instance.UpdateMonitor();
			PlayersLifeSupportMonitor.Instance.UpdateMonitor();
		}

		[HarmonyPostfix]
		[HarmonyPatch("KillPlayerClientRpc")]
		private static void UpdateLifeSupportMonitorOnPlayerDeathClientRpc(int playerId, bool spawnBody, Vector3 bodyVelocity, int causeOfDeath, int deathAnimation)
		{
			Plugin.ModLogger.LogDebug((object)"PlayerControllerB.UpdateLifeSupportMonitorOnPlayerDeathClientRpc");
			LifeSupportMonitor.Instance.UpdateMonitor();
			PlayersLifeSupportMonitor.Instance.UpdateMonitor();
		}

		[HarmonyPostfix]
		[HarmonyPatch("DamagePlayer")]
		private static void UpdateLifeSupportMonitorOnPlayerDamage(int damageNumber, bool hasDamageSFX, bool callRPC, CauseOfDeath causeOfDeath, int deathAnimation, bool fallDamage, Vector3 force)
		{
			Plugin.ModLogger.LogDebug((object)"PlayerControllerB.UpdateLifeSupportMonitorOnPlayerDamage");
			PlayersLifeSupportMonitor.Instance.UpdateMonitor();
		}

		[HarmonyPostfix]
		[HarmonyPatch("DamageOnOtherClients")]
		private static void UpdateLifeSupportMonitorForPlayerDamageOnOtherClients(int damageNumber, int newHealthAmount)
		{
			Plugin.ModLogger.LogDebug((object)"PlayerControllerB.UpdateLifeSupportMonitorForPlayerDamageOnOtherClients");
			PlayersLifeSupportMonitor.Instance.UpdateMonitor();
		}

		[HarmonyPostfix]
		[HarmonyPatch("DamagePlayerClientRpc")]
		private static void UpdateLifeSupportMonitorOnPlayerDamageClientRpc(int damageNumber, int newHealthAmount)
		{
			Plugin.ModLogger.LogDebug((object)"PlayerControllerB.UpdateLifeSupportMonitorOnPlayerDamageClientRpc");
			PlayersLifeSupportMonitor.Instance.UpdateMonitor();
		}

		[HarmonyPostfix]
		[HarmonyPatch("DamagePlayerFromOtherClientClientRpc")]
		private static void UpdateLifeSupportMonitorOnOtherClientPlayerDamageClientRpc(int damageAmount, Vector3 hitDirection, int playerWhoHit, int newHealthAmount)
		{
			Plugin.ModLogger.LogDebug((object)"PlayerControllerB.UpdateLifeSupportMonitorOnOtherClientPlayerDamageClientRpc");
			PlayersLifeSupportMonitor.Instance.UpdateMonitor();
		}
	}
	[HarmonyPatch(typeof(StartOfRound))]
	public class StartOfRound
	{
		[HarmonyPostfix]
		[HarmonyPatch("Start")]
		private static void Initialize()
		{
			Plugin.ModLogger.LogDebug((object)"StartOfRound.Initialize");
			Setup.Initialize();
		}

		[HarmonyPostfix]
		[HarmonyPatch("ReviveDeadPlayers")]
		private static void RefreshMonitorsWhenPlayerRevives()
		{
			Plugin.ModLogger.LogDebug((object)"StartOfRound.RefreshMonitorsWhenPlayerRevives");
			CreditsMonitor.Instance.UpdateMonitor();
			DayMonitor.Instance.UpdateMonitor();
			LifeSupportMonitor.Instance.UpdateMonitor();
			LootMonitor.Instance.UpdateMonitor();
			PlayersLifeSupportMonitor.Instance.UpdateMonitor();
		}

		[HarmonyPostfix]
		[HarmonyPatch("SyncShipUnlockablesClientRpc")]
		private static void RefreshLootForClientOnStart()
		{
			Plugin.ModLogger.LogDebug((object)"StartOfRound.RefreshLootForClientOnStart");
			LootMonitor.Instance.UpdateMonitor();
		}

		[HarmonyPostfix]
		[HarmonyPatch("ChangeLevelClientRpc")]
		private static void UpdateCreditsWhenSwitchingMoons()
		{
			Plugin.ModLogger.LogDebug((object)"StartOfRound.UpdateCreditsWhenSwitchingMoons");
			CreditsMonitor.Instance.UpdateMonitor();
		}

		[HarmonyPostfix]
		[HarmonyPatch("EndOfGameClientRpc")]
		private static void RefreshDayWhenShipHasLeft()
		{
			Plugin.ModLogger.LogDebug((object)"StartOfRound.RefreshDayWhenShipHasLeft");
			DayMonitor.Instance.UpdateMonitor();
		}

		[HarmonyPostfix]
		[HarmonyPatch("StartGame")]
		private static void UpdateDayAtStartOfGame()
		{
			Plugin.ModLogger.LogDebug((object)"StartOfRound.UpdateDayAtStartOfGame");
			DayMonitor.Instance.UpdateMonitor();
		}

		[HarmonyPostfix]
		[HarmonyPatch("OnClientConnect")]
		private static void UpdateMonitorsWhenPlayerConnectsClient(ulong clientId)
		{
			Plugin.ModLogger.LogDebug((object)"StartOfRound.UpdateMonitorsWhenPlayerConnectsClient");
			CreditsMonitor.Instance.UpdateMonitor();
			LifeSupportMonitor.Instance.UpdateMonitor();
			PlayersLifeSupportMonitor.Instance.UpdateMonitor();
			LootMonitor.Instance.UpdateMonitor();
		}

		[HarmonyPostfix]
		[HarmonyPatch("OnPlayerConnectedClientRpc")]
		private static void UpdateMonitorsWhenPlayerConnectsClientRpc(ulong clientId, int connectedPlayers, ulong[] connectedPlayerIdsOrdered, int assignedPlayerObjectId, int serverMoneyAmount, int levelID, int profitQuota, int timeUntilDeadline, int quotaFulfilled, int randomSeed)
		{
			Plugin.ModLogger.LogDebug((object)"StartOfRound.UpdateMonitorsWhenPlayerConnectsClientRpc");
			CreditsMonitor.Instance.UpdateMonitor();
			LifeSupportMonitor.Instance.UpdateMonitor();
			LootMonitor.Instance.UpdateMonitor();
			PlayersLifeSupportMonitor.Instance.UpdateMonitor();
		}

		[HarmonyPostfix]
		[HarmonyPatch("OnPlayerDC")]
		private static void UpdateMonitorsWhenPlayerDisconnects(int playerObjectNumber, ulong clientId)
		{
			Plugin.ModLogger.LogDebug((object)"StartOfRound.UpdateMonitorsWhenPlayerDisconnects");
			CreditsMonitor.Instance.UpdateMonitor();
			LifeSupportMonitor.Instance.UpdateMonitor();
			LootMonitor.Instance.UpdateMonitor();
			PlayersLifeSupportMonitor.Instance.UpdateMonitor();
		}

		[HarmonyPostfix]
		[HarmonyPatch("SetMapScreenInfoToCurrentLevel")]
		private static void ColorWeather(ref TextMeshProUGUI ___screenLevelDescription, ref SelectableLevel ___currentLevel)
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			StringBuilder stringBuilder = new StringBuilder("Orbiting: ").AppendLine(___currentLevel.PlanetName);
			if (!Config.HideWeather.Value)
			{
				stringBuilder.Append("Weather: ").AppendLine(FormatWeather(___currentLevel.currentWeather));
			}
			stringBuilder.Append(___currentLevel.LevelDescription ?? string.Empty);
			((TMP_Text)___screenLevelDescription).text = stringBuilder.ToString();
		}

		private static string FormatWeather(LevelWeatherType currentWeather)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Expected I4, but got Unknown
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			Plugin.ModLogger.LogDebug((object)$"Weather: {currentWeather}");
			if (1 == 0)
			{
			}
			string text = (currentWeather - -1) switch
			{
				1 => ParseColorInput(Config.DustCloudsWeatherColor), 
				6 => ParseColorInput(Config.EclipsedWeatherColor), 
				5 => ParseColorInput(Config.FloodedWeatherColor), 
				4 => ParseColorInput(Config.FoggyWeatherColor), 
				0 => ParseColorInput(Config.NoneWeatherColor), 
				2 => ParseColorInput(Config.RainyWeatherColor), 
				3 => ParseColorInput(Config.StormyWeatherColor), 
				_ => ((ConfigEntryBase)Config.NoneWeatherColor).DefaultValue.ToString(), 
			};
			if (1 == 0)
			{
			}
			string arg = text;
			return $"<color=#{arg}>{currentWeather}</color>";
		}

		private static string ParseColorInput(ConfigEntry<string> entry)
		{
			string text = entry.Value.Replace("#", "");
			Regex regex = new Regex("(?i)[0-9a-f]{6}");
			return regex.IsMatch(text) ? text : ((ConfigEntryBase)entry).DefaultValue.ToString();
		}
	}
	[HarmonyPatch(typeof(Terminal))]
	public class Terminal
	{
		[HarmonyPostfix]
		[HarmonyPatch("SyncGroupCreditsClientRpc")]
		private static void RefreshMoney()
		{
			Plugin.ModLogger.LogDebug((object)"Terminal.RefreshMoney");
			CreditsMonitor.Instance.UpdateMonitor();
		}

		[HarmonyPostfix]
		[HarmonyPatch("TextPostProcess")]
		private static string WeatherConditions(string __result)
		{
			if (Config.HideWeather.Value)
			{
				__result = Enum.GetValues(typeof(LevelWeatherType)).Cast<LevelWeatherType>().Aggregate(__result, (string current, LevelWeatherType value) => current.Replace($"({value})", string.Empty));
			}
			return __result;
		}
	}
	[HarmonyPatch(typeof(TimeOfDay))]
	public class TimeOfDay
	{
		[HarmonyPostfix]
		[HarmonyPatch("SyncNewProfitQuotaClientRpc")]
		private static void UpdateCreditsAfterReachingQuota()
		{
			Plugin.ModLogger.LogDebug((object)"TimeOfDay.UpdateCreditsAfterReachingQuota");
			CreditsMonitor.Instance.UpdateMonitor();
		}

		[HarmonyPostfix]
		[HarmonyPatch("MoveTimeOfDay")]
		private static void UpdateClockTime()
		{
			TimeMonitor.Instance.UpdateMonitor();
		}
	}
}
namespace OpenMonitors.Monitors
{
	public static class Config
	{
		private const string MonitorSection = "Monitors";

		private const string MonitorWeatherColors = "MonitorWeatherColors";

		private const string AllowableSlotValues = "Possible Slots: 1, 2, 4, 5, 6, 7, 8";

		public static ConfigEntry<bool> HideWeather { get; private set; }

		public static ConfigEntry<int> ProfitQuotaMonitorSlot { get; private set; }

		public static ConfigEntry<int> DeadlineMonitorSlot { get; private set; }

		public static ConfigEntry<bool> HideLifeSupport { get; private set; }

		public static ConfigEntry<int> LifeSupportMonitorSlot { get; private set; }

		public static ConfigEntry<bool> HidePlayersLifeSupport { get; private set; }

		public static ConfigEntry<bool> HideLoot { get; private set; }

		public static ConfigEntry<int> LootMonitorSlot { get; private set; }

		public static ConfigEntry<bool> HideCredits { get; private set; }

		public static ConfigEntry<int> CreditsMonitorSlot { get; private set; }

		public static ConfigEntry<bool> HideDay { get; private set; }

		public static ConfigEntry<int> DayMonitorSlot { get; private set; }

		public static ConfigEntry<bool> HideTime { get; private set; }

		public static ConfigEntry<int> TimeMonitorSlot { get; private set; }

		public static ConfigEntry<bool> KeepBlueBackground1 { get; private set; }

		public static ConfigEntry<bool> KeepBlueBackground2 { get; private set; }

		public static ConfigEntry<string> NoneWeatherColor { get; private set; }

		public static ConfigEntry<string> RainyWeatherColor { get; private set; }

		public static ConfigEntry<string> FoggyWeatherColor { get; private set; }

		public static ConfigEntry<string> StormyWeatherColor { get; private set; }

		public static ConfigEntry<string> FloodedWeatherColor { get; private set; }

		public static ConfigEntry<string> EclipsedWeatherColor { get; private set; }

		public static ConfigEntry<string> DustCloudsWeatherColor { get; private set; }

		public static void Initialize()
		{
			HideWeather = Plugin.ModConfig.Bind<bool>("General", "HideWeather", false, "Disables Weather from the navigation screen, and Terminal");
			ProfitQuotaMonitorSlot = Plugin.ModConfig.Bind<int>("Monitors", "ProfitQuotaMonitorSlot", 1, "Slot for the Profit Quota Monitor. Possible Slots: 1, 2, 4, 5, 6, 7, 8");
			DeadlineMonitorSlot = Plugin.ModConfig.Bind<int>("Monitors", "DeadlineMonitorSlot", 2, "Slot for the Deadline Monitor. Possible Slots: 1, 2, 4, 5, 6, 7, 8");
			HideLifeSupport = Plugin.ModConfig.Bind<bool>("Monitors", "HideLifeSupport", false, "Disables the Life Support Monitor.");
			LifeSupportMonitorSlot = Plugin.ModConfig.Bind<int>("Monitors", "LifeSupportMonitorSlot", 4, "Slot for the Life Support Monitor. Possible Slots: 1, 2, 4, 5, 6, 7, 8");
			HidePlayersLifeSupport = Plugin.ModConfig.Bind<bool>("Monitors", "HidePlayersLifeSupport", true, "Disables the Players Life Support Monitor.");
			HideLoot = Plugin.ModConfig.Bind<bool>("Monitors", "HideLoot", false, "Disables the Loot Monitor");
			LootMonitorSlot = Plugin.ModConfig.Bind<int>("Monitors", "LootMonitorSlot", 5, "Slot for the Loot Monitor. Possible Slots: 1, 2, 4, 5, 6, 7, 8");
			HideCredits = Plugin.ModConfig.Bind<bool>("Monitors", "HideCredits", false, "Disables the Credits Monitor");
			TimeMonitorSlot = Plugin.ModConfig.Bind<int>("Monitors", "TimeMonitorSlot", 6, "Slot for the Time Monitor. Possible Slots: 1, 2, 4, 5, 6, 7, 8");
			HideDay = Plugin.ModConfig.Bind<bool>("Monitors", "HideDay", false, "Disables the Day Monitor");
			DayMonitorSlot = Plugin.ModConfig.Bind<int>("Monitors", "DayMonitorSlot", 7, "Slot for the Day Monitor. Possible Slots: 1, 2, 4, 5, 6, 7, 8");
			HideTime = Plugin.ModConfig.Bind<bool>("Monitors", "HideTime", false, "Disables the Time Monitor");
			CreditsMonitorSlot = Plugin.ModConfig.Bind<int>("Monitors", "CreditsMonitorSlot", 8, "Slot for the Credits Monitor. Possible Slots: 1, 2, 4, 5, 6, 7, 8");
			KeepBlueBackground1 = Plugin.ModConfig.Bind<bool>("Monitors", "KeepBlueBackground - Monitor 1", false, "Keeps the blue background on Monitor 1 (Quota)");
			KeepBlueBackground2 = Plugin.ModConfig.Bind<bool>("Monitors", "KeepBlueBackground - Monitor 2", false, "Keeps the blue background on Monitor 2 (Deadline)");
			NoneWeatherColor = Plugin.ModConfig.Bind<string>("MonitorWeatherColors", "No weather:", "69FF69", "Input 6 character hex code for weather coloring");
			RainyWeatherColor = Plugin.ModConfig.Bind<string>("MonitorWeatherColors", "Rainy:", "FFF01C", "Input 6 character hex code for weather coloring");
			FoggyWeatherColor = Plugin.ModConfig.Bind<string>("MonitorWeatherColors", "Foggy:", "FFF01C", "Input 6 character hex code for weather coloring");
			StormyWeatherColor = Plugin.ModConfig.Bind<string>("MonitorWeatherColors", "Stormy:", "FF9B00", "Input 6 character hex code for weather coloring");
			FloodedWeatherColor = Plugin.ModConfig.Bind<string>("MonitorWeatherColors", "Flooded:", "FF9B00", "Input 6 character hex code for weather coloring");
			EclipsedWeatherColor = Plugin.ModConfig.Bind<string>("MonitorWeatherColors", "Eclipsed:", "FF0000", "Input 6 character hex code for weather coloring");
			DustCloudsWeatherColor = Plugin.ModConfig.Bind<string>("MonitorWeatherColors", "Dust Clouds:", "69FF69", "Input 6 character color hex code for weather coloring");
			if (ProfitQuotaMonitorSlot.Value == 3)
			{
				ProfitQuotaMonitorSlot.Value = (int)((ConfigEntryBase)ProfitQuotaMonitorSlot).DefaultValue;
			}
			if (DeadlineMonitorSlot.Value == 3)
			{
				DeadlineMonitorSlot.Value = (int)((ConfigEntryBase)DeadlineMonitorSlot).DefaultValue;
			}
			if (LifeSupportMonitorSlot.Value == 3)
			{
				LifeSupportMonitorSlot.Value = (int)((ConfigEntryBase)LifeSupportMonitorSlot).DefaultValue;
			}
			if (LootMonitorSlot.Value == 3)
			{
				LootMonitorSlot.Value = (int)((ConfigEntryBase)LootMonitorSlot).DefaultValue;
			}
			if (TimeMonitorSlot.Value == 3)
			{
				TimeMonitorSlot.Value = (int)((ConfigEntryBase)TimeMonitorSlot).DefaultValue;
			}
			if (DayMonitorSlot.Value == 3)
			{
				DayMonitorSlot.Value = (int)((ConfigEntryBase)DayMonitorSlot).DefaultValue;
			}
		}
	}
	public class CreditsMonitor : MonoBehaviour
	{
		public static CreditsMonitor Instance;

		private Terminal _terminal = null;

		private TextMeshProUGUI _textMesh = null;

		public void Start()
		{
			Plugin.ModLogger.LogDebug((object)(((Object)this).name + " -> Start()"));
			if (!Object.op_Implicit((Object)(object)Instance))
			{
				Instance = this;
			}
			_textMesh = ((Component)this).GetComponent<TextMeshProUGUI>();
			_terminal = Object.FindObjectOfType<Terminal>();
			Plugin.ModLogger.LogDebug((object)(((Object)this).name + " -> Start() -> UpdateMonitor()"));
			UpdateMonitor();
		}

		public void UpdateMonitor()
		{
			Plugin.ModLogger.LogDebug((object)(((Object)this).name + " -> UpdateMonitor()"));
			((TMP_Text)_textMesh).text = (Config.HideCredits.Value ? string.Empty : $"CREDITS:\n${_terminal.groupCredits}");
		}
	}
	public class DayMonitor : MonoBehaviour
	{
		public static DayMonitor Instance;

		public TextMeshProUGUI textMesh = null;

		public void Start()
		{
			Plugin.ModLogger.LogDebug((object)(((Object)this).name + " -> Start()"));
			if (!Object.op_Implicit((Object)(object)Instance))
			{
				Instance = this;
			}
			textMesh = ((Component)this).GetComponent<TextMeshProUGUI>();
			((TMP_Text)textMesh).text = (Config.HideDay.Value ? string.Empty : "DAY:\n?");
			if (((NetworkBehaviour)StartOfRound.Instance).IsHost)
			{
				Plugin.ModLogger.LogDebug((object)(((Object)this).name + " -> Start() -> IsHost"));
				UpdateMonitor();
			}
			else
			{
				Plugin.ModLogger.LogDebug((object)(((Object)this).name + " -> Start() -> NOT IsHost"));
			}
		}

		public void UpdateMonitor()
		{
			Plugin.ModLogger.LogDebug((object)(((Object)this).name + " -> UpdateMonitor()"));
			((TMP_Text)textMesh).text = (Config.HideDay.Value ? string.Empty : $"DAY:\n{StartOfRound.Instance.gameStats.daysSpent}");
		}
	}
	public class LifeSupportMonitor : MonoBehaviour
	{
		public static LifeSupportMonitor Instance;

		private TextMeshProUGUI _textMesh = null;

		public void Start()
		{
			Plugin.ModLogger.LogDebug((object)(((Object)this).name + " -> Start()"));
			if (!Object.op_Implicit((Object)(object)Instance))
			{
				Instance = this;
			}
			_textMesh = ((Component)this).GetComponent<TextMeshProUGUI>();
			Plugin.ModLogger.LogDebug((object)(((Object)this).name + " -> Start() -> UpdateMonitor()"));
			UpdateMonitor();
		}

		public void UpdateMonitor()
		{
			Plugin.ModLogger.LogDebug((object)(((Object)this).name + " -> UpdateMonitor()"));
			((TMP_Text)_textMesh).text = (Config.HideLifeSupport.Value ? string.Empty : $"ALIVE:\n{StartOfRound.Instance.livingPlayers} / {StartOfRound.Instance.connectedPlayersAmount + 1}");
		}
	}
	public class LootMonitor : MonoBehaviour
	{
		public static LootMonitor Instance;

		public TextMeshProUGUI textMesh = null;

		private GameObject _ship = null;

		public void Start()
		{
			Plugin.ModLogger.LogDebug((object)(((Object)this).name + " -> Start()"));
			if (!Object.op_Implicit((Object)(object)Instance))
			{
				Instance = this;
			}
			textMesh = ((Component)this).GetComponent<TextMeshProUGUI>();
			((TMP_Text)textMesh).text = "LOOT:\n$NaN";
			_ship = GameObject.Find("/Environment/HangarShip");
			Plugin.ModLogger.LogDebug((object)(((Object)this).name + " -> Start() -> UpdateMonitor()"));
			UpdateMonitor();
		}

		public void UpdateMonitor()
		{
			Plugin.ModLogger.LogDebug((object)(((Object)this).name + " -> UpdateMonitor()"));
			((TMP_Text)textMesh).text = (Config.HideLoot.Value ? string.Empty : $"LOOT:\n${Calculate()}");
		}

		private float Calculate()
		{
			Plugin.ModLogger.LogDebug((object)(((Object)this).name + " -> Calculate()"));
			return (from grabbable in _ship.GetComponentsInChildren<GrabbableObject>()
				where CheckIfItemIsScrapAndOnShipFloor(grabbable)
				select grabbable).Sum((GrabbableObject x) => x.scrapValue);
			static bool CheckIfItemIsScrapAndOnShipFloor(GrabbableObject item)
			{
				return item.itemProperties.isScrap && item != null && !item.isPocketed && !item.isHeld;
			}
		}
	}
	public class PlayersLifeSupportMonitor : MonoBehaviour
	{
		public static PlayersLifeSupportMonitor Instance;

		public TextMeshProUGUI textMesh = null;

		public void Start()
		{
			Plugin.ModLogger.LogDebug((object)(((Object)this).name + " -> Start()"));
			if (!Object.op_Implicit((Object)(object)Instance))
			{
				Instance = this;
			}
			textMesh = ((Component)this).GetComponent<TextMeshProUGUI>();
			((TMP_Text)textMesh).fontSize = 42f;
			((TMP_Text)textMesh).enableWordWrapping = false;
			((TMP_Text)textMesh).text = (Config.HidePlayersLifeSupport.Value ? string.Empty : "LIFE SUPPORT:\n?");
			Plugin.ModLogger.LogDebug((object)(((Object)this).name + " -> Start() end"));
		}

		public void UpdateMonitor()
		{
			Plugin.ModLogger.LogDebug((object)(((Object)this).name + " -> UpdateMonitor()"));
			if (!Config.HidePlayersLifeSupport.Value)
			{
				((MonoBehaviour)CoroutineHelper.Instance).StartCoroutine(UpdateMonitorCoroutine());
			}
		}

		private IEnumerator UpdateMonitorCoroutine()
		{
			Plugin.ModLogger.LogDebug((object)(((Object)this).name + " -> UpdateCoroutine(), waiting 2 seconds before updating due to slow player loading"));
			yield return (object)new WaitForSeconds(2f);
			StringBuilder builder = new StringBuilder().AppendLine("LIFE SUPPORT:").AppendLine();
			foreach (PlayerControllerB player in StartOfRound.Instance.ClientPlayerList.Keys.Select((ulong playerId) => StartOfRound.Instance.allPlayerScripts[playerId]))
			{
				builder.Append((player.playerUsername.Length > 15) ? ("- " + player.playerUsername.Substring(0, 15) + "... ") : ("- " + player.playerUsername + " "));
				if (player.isPlayerDead)
				{
					Plugin.ModLogger.LogDebug((object)("-> " + player.playerUsername + " is dead"));
					builder.AppendLine("<color=#FF0000>(DEAD)</color>");
				}
				else if (player.health <= 50)
				{
					Plugin.ModLogger.LogDebug((object)$"-> {player.playerUsername} is injured! {player.health}");
					builder.AppendLine("<color=#FFF01C>(HURT)</color>");
				}
				else
				{
					Plugin.ModLogger.LogDebug((object)("-> " + player.playerUsername + " is still alive!"));
					builder.AppendLine();
				}
			}
			((TMP_Text)textMesh).text = builder.ToString();
		}
	}
	internal static class Setup
	{
		private const string MonitorContainerPath = "Environment/HangarShip/ShipModels2b/MonitorWall/Cube/Canvas (1)/MainContainer";

		private static GameObject _mainContainer = null;

		private static GameObject _quotaMonitorText = null;

		private static GameObject _deadlineMonitorText = null;

		private static readonly Vector3 TopRowLocalRotation = new Vector3(351.5f, 0f);

		private static readonly Vector3 LeftMonitorGroupBottomRowLocalRotation = new Vector3(9.5577f, 0f);

		private static readonly Vector3 RightMonitorGroupLocalRotation = new Vector3(0f, 24.9f, 5.4f);

		private static readonly Dictionary<int, Tuple<Vector3, Vector3>> MonitorPositionsBySlots = new Dictionary<int, Tuple<Vector3, Vector3>>
		{
			{
				1,
				new Tuple<Vector3, Vector3>(new Vector3(-233f, 24f, 21f), LeftMonitorGroupBottomRowLocalRotation)
			},
			{
				2,
				new Tuple<Vector3, Vector3>(new Vector3(240f, 24f, 21f), LeftMonitorGroupBottomRowLocalRotation)
			},
			{
				3,
				new Tuple<Vector3, Vector3>(new Vector3(797f, 29f, -101f), new Vector3(8.4566f, 26.5f, RightMonitorGroupLocalRotation.z))
			},
			{
				4,
				new Tuple<Vector3, Vector3>(new Vector3(1220f, 80f, -304f), new Vector3(8.4566f, RightMonitorGroupLocalRotation.y, RightMonitorGroupLocalRotation.z))
			},
			{
				5,
				new Tuple<Vector3, Vector3>(new Vector3(-233f, 480f), TopRowLocalRotation)
			},
			{
				6,
				new Tuple<Vector3, Vector3>(new Vector3(240f, 480f), TopRowLocalRotation)
			},
			{
				7,
				new Tuple<Vector3, Vector3>(new Vector3(748f, 500f, -110f), TopRowLocalRotation + RightMonitorGroupLocalRotation)
			},
			{
				8,
				new Tuple<Vector3, Vector3>(new Vector3(1170f, 540f, -310.3f), TopRowLocalRotation + RightMonitorGroupLocalRotation)
			},
			{
				9,
				new Tuple<Vector3, Vector3>(new Vector3(905f, -545f, -235f), new Vector3(10.5f, 26.2f, 5.2f))
			}
		};

		public static void Initialize()
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: 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_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: 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_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			_mainContainer = GameObject.Find("Environment/HangarShip/ShipModels2b/MonitorWall/Cube/Canvas (1)/MainContainer");
			_quotaMonitorText = GameObject.Find("Environment/HangarShip/ShipModels2b/MonitorWall/Cube/Canvas (1)/MainContainer/HeaderText");
			MonitorPositionsBySlots[Config.ProfitQuotaMonitorSlot.Value].Deconstruct(out var item, out var item2);
			Vector3 localPosition = item;
			Vector3 val = item2;
			_quotaMonitorText.transform.localPosition = localPosition;
			_quotaMonitorText.transform.localRotation = Quaternion.Euler(val);
			if (!Config.KeepBlueBackground1.Value)
			{
				Plugin.ModLogger.LogDebug((object)"Destroying Quota BG");
				Object.Destroy((Object)(object)GameObject.Find("Environment/HangarShip/ShipModels2b/MonitorWall/Cube/Canvas (1)/MainContainer/BG"));
			}
			if (!Config.KeepBlueBackground2.Value)
			{
				Plugin.ModLogger.LogDebug((object)"Destroying Deadline BG");
				Object.Destroy((Object)(object)GameObject.Find("Environment/HangarShip/ShipModels2b/MonitorWall/Cube/Canvas (1)/MainContainer/BG (1)"));
			}
			_deadlineMonitorText = GameObject.Find("Environment/HangarShip/ShipModels2b/MonitorWall/Cube/Canvas (1)/MainContainer/HeaderText (1)");
			MonitorPositionsBySlots[Config.DeadlineMonitorSlot.Value].Deconstruct(out item2, out item);
			Vector3 localPosition2 = item2;
			Vector3 val2 = item;
			_deadlineMonitorText.transform.localPosition = localPosition2;
			_deadlineMonitorText.transform.localRotation = Quaternion.Euler(val2);
			LifeSupportMonitor.Instance = CreateMonitor<LifeSupportMonitor>(Config.LifeSupportMonitorSlot.Value);
			LootMonitor.Instance = CreateMonitor<LootMonitor>(Config.LootMonitorSlot.Value);
			TimeMonitor.Instance = CreateMonitor<TimeMonitor>(Config.TimeMonitorSlot.Value);
			CreditsMonitor.Instance = CreateMonitor<CreditsMonitor>(Config.CreditsMonitorSlot.Value);
			DayMonitor.Instance = CreateMonitor<DayMonitor>(Config.DayMonitorSlot.Value);
			PlayersLifeSupportMonitor.Instance = CreateMonitor<PlayersLifeSupportMonitor>(9);
		}

		private static T CreateMonitor<T>(int targetSlot) where T : MonoBehaviour
		{
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			string text = typeof(T).Name.Replace("Monitor", "");
			Plugin.ModLogger.LogDebug((object)("Creating Monitor " + text));
			GameObject val = Object.Instantiate<GameObject>(_quotaMonitorText, _mainContainer.transform);
			((Object)val).name = text;
			TextMeshProUGUI component = val.GetComponent<TextMeshProUGUI>();
			var (localPosition, val4) = MonitorPositionsBySlots[targetSlot];
			((TMP_Text)component).transform.localPosition = localPosition;
			((TMP_Text)component).transform.localRotation = Quaternion.Euler(val4);
			Plugin.ModLogger.LogDebug((object)("Monitor " + text + " created"));
			return val.AddComponent<T>();
		}
	}
	public class TimeMonitor : MonoBehaviour
	{
		public static TimeMonitor Instance;

		public TextMeshProUGUI textMesh = null;

		public void Start()
		{
			Plugin.ModLogger.LogDebug((object)(((Object)this).name + " -> Start()"));
			if (!Object.op_Implicit((Object)(object)Instance))
			{
				Instance = this;
			}
			textMesh = ((Component)this).GetComponent<TextMeshProUGUI>();
			((TMP_Text)textMesh).text = (Config.HideTime.Value ? string.Empty : "TIME:\n7:30\nAM");
			Plugin.ModLogger.LogDebug((object)(((Object)this).name + " -> Start() end"));
		}

		public void UpdateMonitor()
		{
			((TMP_Text)textMesh).text = (Config.HideTime.Value ? string.Empty : ("TIME:\n" + ((TMP_Text)HUDManager.Instance.clockNumber).text));
		}
	}
}