Decompiled source of OpenBodyCams v3.0.3

OpenBodyCams.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
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 System.Text;
using AdvancedCompany.Game;
using AdvancedCompany.Objects;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using GeneralImprovements.API;
using HarmonyLib;
using LethalLib.Modules;
using LethalVRM;
using Microsoft.CodeAnalysis;
using ModelReplacement;
using ModelReplacement.Monobehaviors;
using MoreCompany.Cosmetics;
using OpenBodyCams.API;
using OpenBodyCams.Compatibility;
using OpenBodyCams.Components;
using OpenBodyCams.Overlay;
using OpenBodyCams.Patches;
using OpenBodyCams.Utilities;
using OpenBodyCams.Utilities.IL;
using ReservedItemSlotCore.Data;
using ReservedItemSlotCore.Patches;
using TMPro;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.Experimental.Rendering;
using UnityEngine.Rendering;
using UnityEngine.Rendering.HighDefinition;
using UnityEngine.SceneManagement;
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("3.0.3")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("3.0.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.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 OpenBodyCams
{
	public class BodyCamComponent : MonoBehaviour
	{
		public delegate bool TargetChangedToTransform(MonoBehaviour bodyCam, Transform target, ref Transform attachmentPoint, ref Vector3 offset, ref Quaternion angle, ref Renderer[] renderersToHide);

		public delegate void RenderersToHideTransformer(MonoBehaviour bodyCam, ref Renderer[] renderers);

		[Flags]
		private enum TargetDirtyStatus
		{
			None = 0,
			Immediate = 1,
			UntilRender = 2
		}

		private const float RADAR_BOOSTER_INITIAL_PAN = 270f;

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

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

		private static readonly Vector3 CORPSE_HEAD_CAM_OFFSET = new Vector3(0.07f, -0.1f, 0.125f);

		private static readonly Vector3 MASKED_HEAD_CAM_OFFSET = new Vector3(0.07f, 0.1f, 0.031f);

		private static readonly int CullModeProperty = Shader.PropertyToID("_CullMode");

		private static int bodyCamCullingMask;

		private static FrameSettings mainCameraCustomFrameSettings;

		private static FrameSettingsOverrideMask mainCameraCustomFrameSettingsMask;

		private static Material fogShaderMaterial;

		private static GameObject nightVisionPrefab;

		private static Light vanillaMapNightVisionLight;

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

		private static BodyCamComponent lastBodyCamCulled;

		private static BodyCamComponent lastBodyCamRendered;

		private static Transform sunRootTransform = null;

		private static MatchLocalPlayerPosition[] matchLocalPlayerPositions = Array.Empty<MatchLocalPlayerPosition>();

		internal static WeatherEffectComponents[] weatherEffects = Array.Empty<WeatherEffectComponents>();

		private static bool disableCameraWhileTargetIsOnShip = false;

		private static float radarBoosterPanSpeed;

		private Transform CameraContainer;

		internal Transform CameraTransform;

		internal Camera Camera;

		internal Renderer MonitorRenderer;

		internal int MonitorMaterialIndex = -1;

		internal Material MonitorOnMaterial;

		internal Material MonitorNoTargetMaterial;

		internal Material MonitorOffMaterial;

		internal Material MonitorDisabledMaterial;

		internal bool MonitorIsOn = true;

		internal bool EnableCamera = true;

		private bool keepCameraOn;

		private static readonly Vector2Int DefaultResolution = new Vector2Int(160, 120);

		private Vector2Int resolution = DefaultResolution;

		private bool isRemoteCamera = true;

		private bool vanillaMapNightVisionLightWasEnabled;

		private PlayerModelState localPlayerModelState;

		private PlayerControllerB currentPlayer;

		private PlayerModelState currentPlayerModelState;

		private Transform currentActualTarget;

		private Transform currentAttachmentPoint;

		private Renderer[] currentRenderersToHide = Array.Empty<Renderer>();

		private Material currentObstructingMaterial;

		private float currentObstructingMaterialCullMode;

		private bool originalDirectSunlightEnabled;

		private bool originalIndirectSunlightEnabled;

		private bool targetSunlightEnabled = true;

		private float originalBlackSkyVolumeWeight;

		private float targetBlackSkyVolumeWeight;

		private float originalIndirectSunlightDimmer;

		private float targetIndirectSunlightDimmer;

		private Vector3 originalSunRootScale = Vector3.one;

		private Transform targetWeatherParent;

		private WeatherEffectComponents[] targetWeatherComponents;

		private Light nightVisionLight;

		private MeshRenderer greenFlashRenderer;

		private Animator greenFlashAnimator;

		private MeshRenderer fogShaderPlaneRenderer;

		private TargetDirtyStatus targetDirtyStatus;

		private float elapsedSinceLastFrame;

		private float timePerFrame;

		private bool panCamera;

		private float panAngle = 270f;

		private CameraRenderingStatus cameraStatus;

		public bool IsRemoteCamera
		{
			get
			{
				return isRemoteCamera;
			}
			set
			{
				if (isRemoteCamera != value)
				{
					isRemoteCamera = value;
					TargetHasChanged();
				}
			}
		}

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

		public Vector2Int Resolution
		{
			get
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				return resolution;
			}
			set
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0002: Unknown result type (might be due to invalid IL or missing references)
				resolution = value;
				UpdateSettings();
			}
		}

		public bool IsBlanked => !CameraShouldRender(cameraStatus);

		public CameraRenderingStatus CameraStatus => cameraStatus;

		public float Framerate
		{
			get
			{
				return 1f / timePerFrame;
			}
			set
			{
				if (value != 0f)
				{
					timePerFrame = 1f / value;
				}
				else
				{
					timePerFrame = 0f;
				}
			}
		}

		public PlayerControllerB? CurrentPlayerTarget => currentPlayer;

		public Transform? CurrentTarget => currentActualTarget;

		public static event TargetChangedToTransform? BeforeTargetChangedToTransform;

		public static event RenderersToHideTransformer? RenderersToHideTransformers;

		public event Action<Camera>? OnCameraCreated;

		public event Action<RenderTexture>? OnRenderTextureCreated;

		public event Action<bool>? OnBlankedSet;

		public event Action<CameraRenderingStatus>? OnCameraStatusChanged;

		public event Action<bool>? OnScreenPowerChanged;

		public event BodyCam.BodyCamStatusUpdate? OnTargetChanged;

		public static BodyCamComponent[] GetAllBodyCams()
		{
			return new ReadOnlySpan<BodyCamComponent>(AllBodyCams).ToArray();
		}

		public Camera? GetCamera()
		{
			CreateCameraIfNotCreated();
			return Camera;
		}

		internal static void InitializeStatic()
		{
			SceneManager.sceneLoaded += delegate
			{
				UpdateSceneStaticObjects();
			};
			SceneManager.sceneUnloaded += delegate
			{
				UpdateSceneStaticObjects();
			};
		}

		private static void UpdateSceneStaticObjects()
		{
			animatedSun obj = Object.FindAnyObjectByType<animatedSun>();
			object obj2;
			if (obj == null)
			{
				obj2 = null;
			}
			else
			{
				MatchLocalPlayerPosition componentInParent = ((Component)obj).GetComponentInParent<MatchLocalPlayerPosition>();
				obj2 = ((componentInParent != null) ? ((Component)componentInParent).transform : null);
			}
			sunRootTransform = (Transform)obj2;
			matchLocalPlayerPositions = Object.FindObjectsByType<MatchLocalPlayerPosition>((FindObjectsSortMode)0);
		}

		internal static void UpdateWeathers()
		{
			if ((Object)(object)TimeOfDay.Instance != (Object)null)
			{
				int num = TimeOfDay.Instance.effects.Length;
				weatherEffects = new WeatherEffectComponents[num];
				for (int i = 0; i < num; i++)
				{
					weatherEffects[i] = new WeatherEffectComponents((LevelWeatherType)i);
				}
			}
			else
			{
				weatherEffects = Array.Empty<WeatherEffectComponents>();
			}
			CreateTargetWeatherEffectsForAllCams();
		}

		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);
			((Behaviour)nightVisionPrefab.GetComponent<Light>()).enabled = false;
			vanillaMapNightVisionLight = StartOfRound.Instance.mapScreen.mapCameraLight;
			UpdateAllCameraSettings();
		}

		internal static bool HasFinishedGameStartSetup()
		{
			return (Object)(object)vanillaMapNightVisionLight != (Object)null;
		}

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

		internal static void UpdateStaticSettings()
		{
			disableCameraWhileTargetIsOnShip = Plugin.DisableCameraWhileTargetIsOnShip.Value;
			radarBoosterPanSpeed = Plugin.RadarBoosterPanRPM.Value * 360f / 60f;
		}

		internal static void CreateTargetWeatherEffectsForAllCams()
		{
			BodyCamComponent[] allBodyCams = AllBodyCams;
			for (int i = 0; i < allBodyCams.Length; i++)
			{
				allBodyCams[i].CreateTargetWeatherEffects();
			}
		}

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

		public static void MarkAnyParentDirtyUntilRenderForAllBodyCams(Transform target)
		{
			while ((Object)(object)target != (Object)null)
			{
				MarkTargetDirtyUntilRenderForAllBodyCams(target);
				target = target.parent;
			}
		}

		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();
			}
		}

		private static void RevertLastOverrides()
		{
			if ((Object)(object)lastBodyCamCulled != (Object)null)
			{
				lastBodyCamCulled.RevertCullingOverrides();
				lastBodyCamCulled = null;
			}
			if ((Object)(object)lastBodyCamRendered != (Object)null)
			{
				lastBodyCamRendered.RevertRenderingOverrides();
				lastBodyCamRendered = null;
			}
		}

		internal static void BeforeCullingAnyCamera(Camera camera)
		{
			RevertLastOverrides();
			int num = AllBodyCams.Length;
			for (int i = 0; i < num; i++)
			{
				BodyCamComponent bodyCamComponent = AllBodyCams[i];
				if (bodyCamComponent.Camera == camera)
				{
					lastBodyCamCulled = bodyCamComponent;
					bodyCamComponent.ApplyCullingOverrides();
					break;
				}
			}
		}

		internal static void BeforeRenderingAnyCamera(Camera camera)
		{
			RevertLastOverrides();
			int num = AllBodyCams.Length;
			for (int i = 0; i < num; i++)
			{
				BodyCamComponent bodyCamComponent = AllBodyCams[i];
				if (bodyCamComponent.Camera == camera)
				{
					lastBodyCamRendered = bodyCamComponent;
					bodyCamComponent.ApplyRenderingOverrides();
					break;
				}
			}
		}

		internal static void AfterRenderingAnyCamera(Camera camera)
		{
			RevertLastOverrides();
		}

		private void Awake()
		{
			if (!HasFinishedGameStartSetup())
			{
				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];
			ReadOnlySpan<BodyCamComponent> readOnlySpan = new ReadOnlySpan<BodyCamComponent>(allBodyCams);
			readOnlySpan.CopyTo(new Span<BodyCamComponent>(array).Slice(num, readOnlySpan.Length));
			num += readOnlySpan.Length;
			array[num] = this;
			num++;
			AllBodyCams = array;
			BodyCam.BodyCamInstantiated(this);
		}

		private void Start()
		{
			if (HasFinishedGameStartSetup())
			{
				CreateCameraIfNotCreated();
				CreateTargetWeatherEffects();
				SyncBodyCamToRadarMap.UpdateBodyCamTarget(this);
			}
		}

		private void SetMonitorMaterial(Material material)
		{
			if (!((Object)(object)MonitorRenderer == (Object)null))
			{
				MonitorRenderer.SetMaterial(MonitorMaterialIndex, material);
			}
		}

		private void EnsureMaterialsExist()
		{
			//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
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)MonitorOnMaterial == (Object)null)
			{
				MonitorOnMaterial = new Material(Shader.Find("HDRP/Unlit"))
				{
					name = "BodyCamMaterial"
				};
				MonitorOnMaterial.SetFloat("_AlbedoAffectEmissive", 1f);
				MonitorOnMaterial.SetColor("_EmissiveColor", Color.white);
			}
			if ((Object)(object)MonitorOffMaterial == (Object)null)
			{
				MonitorOffMaterial = ShipObjects.BlackScreenMaterial;
			}
		}

		private void CreateCameraIfNotCreated()
		{
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Expected O, but got Unknown
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Expected O, but got Unknown
			//IL_0196: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0295: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b5: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)Camera != (Object)null))
			{
				Plugin.Instance.Logger.LogInfo((object)("Creating a new camera for " + ((Object)this).name + "."));
				UpdateScreenMaterial();
				CameraContainer = new GameObject("BodyCam_" + ((Object)this).name + "_Container").transform;
				GameObject val = new GameObject("BodyCam");
				CameraTransform = val.transform;
				CameraTransform.SetParent(CameraContainer, false);
				Camera = val.AddComponent<Camera>();
				Camera.nearClipPlane = 0.01f;
				Camera.cullingMask = bodyCamCullingMask;
				HDAdditionalCameraData val2 = val.AddComponent<HDAdditionalCameraData>();
				val2.volumeLayerMask = LayerMask.op_Implicit(1);
				_ = mainCameraCustomFrameSettings;
				val2.customRenderingSettings = true;
				ref FrameSettings renderingPathCustomFrameSettings = ref val2.renderingPathCustomFrameSettings;
				ref FrameSettingsOverrideMask renderingPathCustomFrameSettingsOverrideMask = ref val2.renderingPathCustomFrameSettingsOverrideMask;
				renderingPathCustomFrameSettings = mainCameraCustomFrameSettings;
				renderingPathCustomFrameSettingsOverrideMask = mainCameraCustomFrameSettingsMask;
				((FrameSettings)(ref renderingPathCustomFrameSettings)).SetEnabled((FrameSettingsField)93, false);
				((BitArray128)(ref renderingPathCustomFrameSettingsOverrideMask.mask))[93u] = true;
				((FrameSettings)(ref renderingPathCustomFrameSettings)).SetEnabled((FrameSettingsField)88, false);
				((BitArray128)(ref renderingPathCustomFrameSettingsOverrideMask.mask))[88u] = true;
				val2.hasPersistentHistory = true;
				GameObject val3 = Object.Instantiate<GameObject>(nightVisionPrefab);
				val3.transform.SetParent(CameraTransform, false);
				val3.SetActive(true);
				nightVisionLight = val3.GetComponent<Light>();
				UpdateSettings();
				GameObject val4 = new GameObject("CameraGreenTransitionScaler");
				val4.transform.SetParent(CameraTransform, false);
				val4.transform.localScale = new Vector3(1f, 0.004f, 1f);
				GameObject val5 = Object.Instantiate<GameObject>(((Component)StartOfRound.Instance.mapScreen.mapCameraAnimator).gameObject);
				val5.transform.SetParent(val4.transform, false);
				val5.transform.localPosition = new Vector3(0f, 0f, 0.1f);
				val5.layer = 0;
				greenFlashRenderer = val5.GetComponent<MeshRenderer>();
				((Renderer)greenFlashRenderer).forceRenderingOff = true;
				greenFlashAnimator = val5.GetComponent<Animator>() ?? throw new Exception("Green flash object copied from the map screen has no Animator.");
				greenFlashAnimator.Play("MapTransitionGreen", 0, 1f);
				greenFlashAnimator.WriteDefaultValues();
				GameObject val6 = GameObject.CreatePrimitive((PrimitiveType)5);
				Object.Destroy((Object)(object)val6.GetComponent<MeshCollider>());
				val6.transform.SetParent(CameraTransform, false);
				val6.transform.localPosition = new Vector3(0f, 0f, Camera.nearClipPlane * 2f);
				val6.transform.localRotation = Quaternion.Euler(0f, 0f, 0f);
				fogShaderPlaneRenderer = val6.GetComponent<MeshRenderer>();
				((Renderer)fogShaderPlaneRenderer).sharedMaterial = fogShaderMaterial;
				((Renderer)fogShaderPlaneRenderer).shadowCastingMode = (ShadowCastingMode)0;
				((Renderer)fogShaderPlaneRenderer).receiveShadows = false;
				((Renderer)fogShaderPlaneRenderer).forceRenderingOff = true;
				this.OnCameraCreated?.Invoke(Camera);
			}
		}

		private bool PositionIsInInterior(Vector3 position)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			return position.y < -80f;
		}

		private void CreateTargetWeatherEffects()
		{
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Invalid comparison between Unknown and I4
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			DestroyTargetWeatherEffects();
			if (Plugin.DisplayWeatherBasedOnPerspective.Value != BoolWithDefault.True)
			{
				return;
			}
			targetWeatherComponents = new WeatherEffectComponents[weatherEffects.Length];
			targetWeatherParent = new GameObject("BodyCam_" + ((Object)this).name + "_TargetWeathers").transform;
			TimeOfDay instance = TimeOfDay.Instance;
			LevelWeatherType val = (LevelWeatherType)((instance == null) ? (-1) : ((int)instance.currentLevelWeather));
			Dictionary<GameObject, GameObject> dictionary = new Dictionary<GameObject, GameObject>();
			for (int i = 0; i < targetWeatherComponents.Length; i++)
			{
				WeatherEffectComponents weatherEffectComponents = weatherEffects[i];
				GameObject value = null;
				if ((Object)(object)weatherEffectComponents.effectObject != (Object)null && !dictionary.TryGetValue(weatherEffectComponents.effectObject, out value))
				{
					value = Object.Instantiate<GameObject>(weatherEffectComponents.effectObject);
					value.transform.SetParent(targetWeatherParent, false);
					OccludeAudio[] componentsInChildren = value.GetComponentsInChildren<OccludeAudio>();
					for (int j = 0; j < componentsInChildren.Length; j++)
					{
						Object.Destroy((Object)(object)componentsInChildren[j]);
					}
					AudioLowPassFilter[] componentsInChildren2 = value.GetComponentsInChildren<AudioLowPassFilter>();
					for (int j = 0; j < componentsInChildren2.Length; j++)
					{
						Object.Destroy((Object)(object)componentsInChildren2[j]);
					}
					AudioSource[] componentsInChildren3 = value.GetComponentsInChildren<AudioSource>();
					for (int j = 0; j < componentsInChildren3.Length; j++)
					{
						Object.Destroy((Object)(object)componentsInChildren3[j]);
					}
					dictionary.Add(weatherEffectComponents.effectObject, value);
				}
				WeatherEffectComponents weatherEffectComponents2 = new WeatherEffectComponents(weatherEffectComponents.weatherType, value);
				weatherEffectComponents2.SetVisibility(show: false);
				if ((int)val == i && !PositionIsInInterior(CameraTransform.position))
				{
					weatherEffectComponents2.enabled = true;
				}
				targetWeatherComponents[i] = weatherEffectComponents2;
			}
		}

		private void DestroyTargetWeatherEffects()
		{
			targetWeatherComponents = Array.Empty<WeatherEffectComponents>();
			if ((Object)(object)targetWeatherParent != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)targetWeatherParent).gameObject);
			}
			targetWeatherParent = null;
		}

		public void UpdateSettings()
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Expected O, but got Unknown
			if (!((Object)(object)Camera == (Object)null))
			{
				int x = ((Vector2Int)(ref resolution)).x;
				int y = ((Vector2Int)(ref resolution)).y;
				Camera.targetTexture = new RenderTexture(x, y, 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;
				}
				Camera.farClipPlane = Plugin.RenderDistance.Value;
				nightVisionLight.intensity = 367f * Plugin.NightVisionBrightness.Value;
				nightVisionLight.range = 12f * Plugin.NightVisionBrightness.Value;
				this.OnRenderTextureCreated?.Invoke(Camera.targetTexture);
				CreateTargetWeatherEffects();
			}
		}

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

		public void UpdateScreenMaterial()
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			if (!HasFinishedGameStartSetup())
			{
				return;
			}
			EnsureMaterialsExist();
			if (!MonitorIsOn)
			{
				if ((Object)(object)MonitorOffMaterial != (Object)null)
				{
					SetMonitorMaterial(MonitorOffMaterial);
				}
				return;
			}
			bool enabled = ((Behaviour)this).enabled;
			if (IsBlanked || !enabled)
			{
				MonitorOnMaterial.color = Color.black;
				if (!enabled && (Object)(object)MonitorDisabledMaterial != (Object)null)
				{
					SetMonitorMaterial(MonitorDisabledMaterial);
					return;
				}
				if ((Object)(object)MonitorNoTargetMaterial != (Object)null)
				{
					SetMonitorMaterial(MonitorNoTargetMaterial);
					return;
				}
			}
			else
			{
				MonitorOnMaterial.color = Color.white;
			}
			SetMonitorMaterial(MonitorOnMaterial);
		}

		public void SetScreenPowered(bool powered)
		{
			if (!((Object)(object)MonitorRenderer == (Object)null) && powered != MonitorIsOn)
			{
				if (powered)
				{
					StartTargetTransition();
				}
				MonitorIsOn = powered;
				UpdateScreenMaterial();
				this.OnScreenPowerChanged?.Invoke(MonitorIsOn);
			}
		}

		public bool IsScreenPowered()
		{
			return MonitorIsOn;
		}

		private bool CameraShouldRender(CameraRenderingStatus status)
		{
			return status == CameraRenderingStatus.Rendering;
		}

		private void SetStatus(CameraRenderingStatus newStatus)
		{
			if (newStatus != cameraStatus)
			{
				bool num = CameraShouldRender(cameraStatus) != CameraShouldRender(newStatus);
				cameraStatus = newStatus;
				UpdateScreenMaterial();
				if (num)
				{
					this.OnBlankedSet?.Invoke(IsBlanked);
				}
				this.OnCameraStatusChanged?.Invoke(cameraStatus);
			}
		}

		private CameraRenderingStatus GetUpdatedCameraStatus()
		{
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			if (!EnableCamera)
			{
				return CameraRenderingStatus.Disabled;
			}
			if ((Object)(object)currentActualTarget == (Object)null)
			{
				return CameraRenderingStatus.TargetInvalid;
			}
			if (currentPlayer != null)
			{
				if (currentPlayer.isPlayerControlled)
				{
					if (currentPlayer.isInHangarShipRoom)
					{
						return CameraRenderingStatus.TargetDisabledOnShip;
					}
					return CameraRenderingStatus.Rendering;
				}
				if (!currentPlayer.isPlayerDead)
				{
					return CameraRenderingStatus.Rendering;
				}
				if ((Object)(object)currentPlayer.redirectToEnemy != (Object)null)
				{
					if (currentPlayer.redirectToEnemy.isInsidePlayerShip)
					{
						return CameraRenderingStatus.TargetDisabledOnShip;
					}
					return CameraRenderingStatus.Rendering;
				}
				if ((Object)(object)currentPlayer.deadBody != (Object)null)
				{
					if (currentPlayer.deadBody.isInShip)
					{
						return CameraRenderingStatus.TargetDisabledOnShip;
					}
					return CameraRenderingStatus.Rendering;
				}
			}
			RadarBoosterItem component = ((Component)currentActualTarget).GetComponent<RadarBoosterItem>();
			if (component != null)
			{
				Vector3 val = default(Vector3);
				((Vector3)(ref val))..ctor(3000f, -400f, 3000f);
				if (((Vector3)(ref ((GrabbableObject)component).targetFloorPosition)).Equals(val))
				{
					return CameraRenderingStatus.TargetInvalid;
				}
				if (((GrabbableObject)component).isInShipRoom)
				{
					return CameraRenderingStatus.TargetDisabledOnShip;
				}
				return CameraRenderingStatus.Rendering;
			}
			return CameraRenderingStatus.Rendering;
		}

		private static void CollectDescendentModelsToHide(Transform parent, List<Renderer> list)
		{
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Expected O, but got Unknown
			BodyCamComponent[] allBodyCams = AllBodyCams;
			foreach (BodyCamComponent bodyCamComponent in allBodyCams)
			{
				if ((Object)(object)parent == (Object)(object)bodyCamComponent.CameraTransform)
				{
					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);
			return list.ToArray();
		}

		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;
		}

		private void SetRenderersToHide(Renderer[] renderers)
		{
			BodyCamComponent.RenderersToHideTransformers?.Invoke((MonoBehaviour)(object)this, ref renderers);
			currentRenderersToHide = renderers;
		}

		private void TargetHasChanged()
		{
			UpdateOverrides(float.PositiveInfinity);
			this.OnTargetChanged?.Invoke((MonoBehaviour)(object)this);
		}

		public void SetTargetToNone()
		{
			//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)
			CreateCameraIfNotCreated();
			ClearTargetDirtyImmediate();
			currentPlayer = null;
			currentActualTarget = null;
			currentAttachmentPoint = null;
			SetRenderersToHide(Array.Empty<Renderer>());
			UpdateModelReferences();
			currentObstructingMaterial = null;
			CameraTransform.SetLocalPositionAndRotation(Vector3.zero, Quaternion.identity);
			TargetHasChanged();
		}

		public void SetTargetToPlayer(PlayerControllerB player)
		{
			//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_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0253: Unknown result type (might be due to invalid IL or missing references)
			//IL_0254: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			CreateCameraIfNotCreated();
			if ((Object)(object)player == (Object)null)
			{
				SetTargetToNone();
				return;
			}
			ClearTargetDirtyImmediate();
			currentPlayer = player;
			currentActualTarget = null;
			currentAttachmentPoint = null;
			UpdateModelReferences();
			panCamera = false;
			currentObstructingMaterial = null;
			Vector3 val = Vector3.zero;
			if (!currentPlayer.isPlayerDead)
			{
				if (Plugin.CameraMode.Value == CameraModeOptions.Head)
				{
					currentAttachmentPoint = ((Component)currentPlayer.gameplayCamera).transform;
					val = PLAYER_HEAD_CAM_OFFSET;
				}
				else
				{
					currentAttachmentPoint = ((Component)currentPlayer.playerGlobalHead).transform.parent;
					val = BODY_CAM_OFFSET;
				}
				currentActualTarget = ((Component)currentPlayer).transform;
				SetRenderersToHide(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)
					{
						currentAttachmentPoint = ((EnemyAI)val2).eye;
						val = MASKED_HEAD_CAM_OFFSET;
					}
					else
					{
						currentAttachmentPoint = val2.animationContainer.Find("metarig/spine/spine.001/spine.002/spine.003");
						val = BODY_CAM_OFFSET;
					}
				}
				else
				{
					currentAttachmentPoint = currentPlayer.redirectToEnemy.eye;
				}
				currentActualTarget = ((Component)currentPlayer.redirectToEnemy).transform;
				SetRenderersToHide(CollectModelsToHide(currentActualTarget));
			}
			else if ((Object)(object)currentPlayer.deadBody != (Object)null)
			{
				Transform parent;
				if (Plugin.CameraMode.Value == CameraModeOptions.Head)
				{
					currentAttachmentPoint = ((Component)currentPlayer.deadBody).transform.Find("spine.001/spine.002/spine.003/spine.004/spine.004_end");
					parent = currentAttachmentPoint.parent;
					val = CORPSE_HEAD_CAM_OFFSET;
				}
				else
				{
					currentAttachmentPoint = ((Component)currentPlayer.deadBody).transform.Find("spine.001/spine.002/spine.003");
					parent = currentAttachmentPoint;
					val = BODY_CAM_OFFSET;
				}
				currentActualTarget = ((Component)currentPlayer.deadBody).transform;
				SetRenderersToHide(CollectModelsToHide(parent));
				Renderer component = ((Component)currentActualTarget).GetComponent<Renderer>();
				currentObstructingMaterial = ((component != null) ? component.sharedMaterial : null);
			}
			if ((Object)(object)currentAttachmentPoint == (Object)null)
			{
				currentAttachmentPoint = currentActualTarget;
			}
			CameraTransform.SetLocalPositionAndRotation(val, Quaternion.identity);
			TargetHasChanged();
		}

		public void SetTargetToTransform(Transform transform)
		{
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			CreateCameraIfNotCreated();
			if ((Object)(object)transform == (Object)null || (Object)(object)((Component)transform).gameObject == (Object)null)
			{
				SetTargetToNone();
				return;
			}
			ClearTargetDirtyImmediate();
			currentPlayer = null;
			currentActualTarget = transform;
			currentAttachmentPoint = null;
			UpdateModelReferences();
			panCamera = false;
			Vector3 offset = Vector3.zero;
			Quaternion angle = Quaternion.identity;
			currentRenderersToHide = Array.Empty<Renderer>();
			if (((Component)currentActualTarget).GetComponent<RadarBoosterItem>() != null)
			{
				SetRenderersToHide((Renderer[])(object)new Renderer[1] { ((Component)((Component)currentActualTarget).transform.Find("AnimContainer/Rod")).GetComponent<Renderer>() });
				currentAttachmentPoint = currentActualTarget;
				((Vector3)(ref offset))..ctor(0f, 1.5f, 0f);
				panCamera = true;
			}
			else
			{
				currentAttachmentPoint = currentActualTarget;
				if (BodyCamComponent.BeforeTargetChangedToTransform != null)
				{
					Delegate[] invocationList = BodyCamComponent.BeforeTargetChangedToTransform.GetInvocationList();
					for (int i = 0; i < invocationList.Length; i++)
					{
						if (((TargetChangedToTransform)invocationList[i])((MonoBehaviour)(object)this, currentActualTarget, ref currentAttachmentPoint, ref offset, ref angle, ref currentRenderersToHide))
						{
							SetRenderersToHide(currentRenderersToHide);
							break;
						}
					}
				}
			}
			CameraTransform.SetLocalPositionAndRotation(offset, angle);
			TargetHasChanged();
		}

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

		private void UpdateModelReferences()
		{
			ViewPerspective.PrepareModelState(currentPlayer, ref currentPlayerModelState);
			if ((Object)(object)currentPlayer != (Object)(object)StartOfRound.Instance.localPlayerController)
			{
				ViewPerspective.PrepareModelState(StartOfRound.Instance.localPlayerController, ref localPlayerModelState);
			}
		}

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

		private void SetTargetWeathersVisible(bool visible)
		{
			for (int i = 0; i < targetWeatherComponents.Length; i++)
			{
				WeatherEffectComponents weatherEffectComponents = weatherEffects[i];
				WeatherEffectComponents weatherEffectComponents2 = targetWeatherComponents[i];
				if (weatherEffectComponents != null && weatherEffectComponents2 != null)
				{
					weatherEffectComponents.SetVisibility(!visible);
					weatherEffectComponents2.SetVisibility(visible);
				}
			}
		}

		private static void SetMatchLocalPlayerPositions(Vector3 position)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			MatchLocalPlayerPosition[] array = matchLocalPlayerPositions;
			foreach (MatchLocalPlayerPosition val in array)
			{
				if (!((Object)(object)val == (Object)null))
				{
					((Component)val).transform.position = position;
				}
			}
		}

		private void ApplyCullingOverrides()
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0208: 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_01d3: 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)
			UpdateTargetStatusBeforeRender();
			if ((Object)(object)currentAttachmentPoint == (Object)null)
			{
				return;
			}
			CameraContainer.SetPositionAndRotation(currentAttachmentPoint.position, currentAttachmentPoint.rotation);
			vanillaMapNightVisionLightWasEnabled = ((Behaviour)vanillaMapNightVisionLight).enabled;
			((Behaviour)vanillaMapNightVisionLight).enabled = false;
			((Behaviour)nightVisionLight).enabled = true;
			((Renderer)greenFlashRenderer).forceRenderingOff = false;
			((Renderer)fogShaderPlaneRenderer).forceRenderingOff = false;
			PlayerControllerB localPlayerController = StartOfRound.Instance.localPlayerController;
			ViewPerspective.Apply(ref currentPlayerModelState, Perspective.FirstPerson);
			if (currentPlayer != localPlayerController)
			{
				ViewPerspective.Apply(ref localPlayerModelState, Perspective.ThirdPerson);
			}
			bool flag = false;
			Renderer[] array = currentRenderersToHide;
			foreach (Renderer val in array)
			{
				if ((Object)(object)val == (Object)null)
				{
					if (!flag)
					{
						Plugin.Instance.Logger.LogError((object)("Mesh obstructing the body cam on " + ((Object)this).name + " which should be hidden was unexpectedly null."));
					}
					flag = true;
				}
				else
				{
					val.forceRenderingOff = true;
				}
			}
			if ((Object)(object)currentObstructingMaterial != (Object)null)
			{
				currentObstructingMaterialCullMode = currentObstructingMaterial.GetFloat(CullModeProperty);
				currentObstructingMaterial.SetFloat(CullModeProperty, 2f);
			}
			Light sunDirect = TimeOfDay.Instance.sunDirect;
			if ((Object)(object)sunDirect != (Object)null)
			{
				Light sunIndirect = TimeOfDay.Instance.sunIndirect;
				originalDirectSunlightEnabled = ((Behaviour)sunDirect).enabled;
				originalIndirectSunlightEnabled = ((Behaviour)sunIndirect).enabled;
				((Behaviour)sunDirect).enabled = targetSunlightEnabled;
				((Behaviour)sunIndirect).enabled = targetSunlightEnabled;
			}
			Volume blackSkyVolume = StartOfRound.Instance.blackSkyVolume;
			originalBlackSkyVolumeWeight = blackSkyVolume.weight;
			blackSkyVolume.weight = targetBlackSkyVolumeWeight;
			if ((Object)(object)sunRootTransform != (Object)null)
			{
				originalSunRootScale = sunRootTransform.localScale;
				Transform obj = sunRootTransform;
				obj.localScale *= Math.Min(Camera.farClipPlane * 0.005f, 1f);
			}
			SetMatchLocalPlayerPositions(((Component)Camera).transform.position);
			SetTargetWeathersVisible(visible: true);
		}

		private void RevertCullingOverrides()
		{
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)currentAttachmentPoint == (Object)null)
			{
				return;
			}
			((Behaviour)vanillaMapNightVisionLight).enabled = vanillaMapNightVisionLightWasEnabled;
			((Behaviour)nightVisionLight).enabled = false;
			((Renderer)greenFlashRenderer).forceRenderingOff = true;
			((Renderer)fogShaderPlaneRenderer).forceRenderingOff = true;
			PlayerControllerB localPlayerController = StartOfRound.Instance.localPlayerController;
			ViewPerspective.Restore(ref currentPlayerModelState);
			if (currentPlayer != localPlayerController)
			{
				ViewPerspective.Restore(ref localPlayerModelState);
			}
			Renderer[] array = currentRenderersToHide;
			foreach (Renderer val in array)
			{
				if (!((Object)(object)val == (Object)null))
				{
					val.forceRenderingOff = false;
				}
			}
			Material obj = currentObstructingMaterial;
			if (obj != null)
			{
				obj.SetFloat(CullModeProperty, currentObstructingMaterialCullMode);
			}
			Light sunDirect = TimeOfDay.Instance.sunDirect;
			if ((Object)(object)sunDirect != (Object)null)
			{
				Light sunIndirect = TimeOfDay.Instance.sunIndirect;
				((Behaviour)sunDirect).enabled = originalDirectSunlightEnabled;
				((Behaviour)sunIndirect).enabled = originalIndirectSunlightEnabled;
			}
			StartOfRound.Instance.blackSkyVolume.weight = originalBlackSkyVolumeWeight;
			if ((Object)(object)sunRootTransform != (Object)null)
			{
				sunRootTransform.localScale = originalSunRootScale;
			}
			SetMatchLocalPlayerPositions(((Component)GameNetworkManager.Instance.localPlayerController).transform.position);
			SetTargetWeathersVisible(visible: false);
		}

		private void ApplyRenderingOverrides()
		{
			if (!((Object)(object)currentAttachmentPoint == (Object)null))
			{
				HDAdditionalLightData indirectLightData = TimeOfDay.Instance.indirectLightData;
				if ((Object)(object)indirectLightData != (Object)null)
				{
					originalIndirectSunlightDimmer = indirectLightData.lightDimmer;
					indirectLightData.lightDimmer = targetIndirectSunlightDimmer;
					targetIndirectSunlightDimmer = indirectLightData.lightDimmer;
				}
				SetTargetWeathersVisible(visible: true);
			}
		}

		private void RevertRenderingOverrides()
		{
			if (!((Object)(object)currentAttachmentPoint == (Object)null))
			{
				HDAdditionalLightData indirectLightData = TimeOfDay.Instance.indirectLightData;
				if ((Object)(object)indirectLightData != (Object)null)
				{
					indirectLightData.lightDimmer = originalIndirectSunlightDimmer;
				}
				SetTargetWeathersVisible(visible: false);
			}
		}

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

		private void UpdateOverrides(float deltaTime)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)currentActualTarget == (Object)null)
			{
				return;
			}
			TargetTracker.TargetInfo currentInfo = TargetTracker.GetCurrentInfo(currentActualTarget);
			bool flag = PositionIsInInterior(CameraTransform.position);
			bool flag2 = false;
			if ((Object)(object)currentInfo?.lastTrigger != (Object)null)
			{
				flag2 = currentInfo.lastTrigger.insideLighting;
			}
			targetSunlightEnabled = !flag;
			targetBlackSkyVolumeWeight = (flag ? 1 : 0);
			targetIndirectSunlightDimmer = Mathf.Lerp(targetIndirectSunlightDimmer, (float)((!flag2) ? 1 : 0), Mathf.Clamp01(5f * deltaTime));
			for (int i = 0; i < targetWeatherComponents.Length; i++)
			{
				WeatherEffectComponents weatherEffectComponents = targetWeatherComponents[i];
				if (weatherEffectComponents != null)
				{
					if (flag)
					{
						weatherEffectComponents.enabled = false;
					}
					else if (currentInfo != null && i < currentInfo.enabledWeathers.Length)
					{
						weatherEffectComponents.enabled = currentInfo.enabledWeathers[i];
					}
					else
					{
						weatherEffectComponents.enabled = false;
					}
					weatherEffectComponents.Update(currentActualTarget, flag, deltaTime);
				}
			}
		}

		private void LateUpdate()
		{
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)Camera == (Object)null)
			{
				return;
			}
			UpdateTargetStatusDuringUpdate();
			PlayerControllerB val = StartOfRound.Instance.localPlayerController;
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			if ((Object)(object)val.spectatedPlayerScript != (Object)null)
			{
				val = val.spectatedPlayerScript;
			}
			UpdateOverrides(Time.deltaTime);
			bool flag = keepCameraOn || ((Object)(object)MonitorRenderer != (Object)null && MonitorRenderer.isVisible && val.isInHangarShipRoom && IsScreenPowered());
			CameraRenderingStatus cameraRenderingStatus = CameraRenderingStatus.Culled;
			if (flag)
			{
				cameraRenderingStatus = GetUpdatedCameraStatus();
				if (cameraRenderingStatus == CameraRenderingStatus.TargetDisabledOnShip && (!disableCameraWhileTargetIsOnShip || keepCameraOn))
				{
					cameraRenderingStatus = CameraRenderingStatus.Rendering;
				}
				flag = !IsBlanked;
			}
			SetStatus(cameraRenderingStatus);
			if (!flag)
			{
				((Behaviour)Camera).enabled = false;
				return;
			}
			if (radarBoosterPanSpeed != 0f)
			{
				panAngle = (panAngle + Time.deltaTime * radarBoosterPanSpeed) % 360f;
			}
			else
			{
				panAngle = 270f;
			}
			if (panCamera)
			{
				CameraTransform.localRotation = Quaternion.Euler(0f, panAngle, 0f);
			}
			if (timePerFrame > 0f)
			{
				elapsedSinceLastFrame += Time.deltaTime;
				((Behaviour)Camera).enabled = elapsedSinceLastFrame >= timePerFrame;
				elapsedSinceLastFrame %= timePerFrame;
			}
			else
			{
				((Behaviour)Camera).enabled = true;
			}
		}

		private void OnDisable()
		{
			SetStatus(CameraRenderingStatus.Disabled);
			UpdateScreenMaterial();
			if ((Object)(object)Camera != (Object)null)
			{
				((Behaviour)Camera).enabled = false;
			}
		}

		private void OnEnable()
		{
			UpdateScreenMaterial();
		}

		private void OnDestroy()
		{
			if ((Object)(object)CameraContainer != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)CameraContainer).gameObject);
			}
			AllBodyCams = AllBodyCams.Where((BodyCamComponent bodyCam) => bodyCam != this).ToArray();
			DestroyTargetWeatherEffects();
			SyncBodyCamToRadarMap.OnBodyCamDestroyed(this);
			BodyCam.BodyCamDestroyed(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(currentRenderersToHide, 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 (currentPlayerModelState.ReferencesObject(gameObject))
			{
				return true;
			}
			if (localPlayerModelState.ReferencesObject(gameObject))
			{
				return true;
			}
			return false;
		}

		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;
		}
	}
	public enum CameraRenderingStatus
	{
		Rendering,
		Disabled,
		TargetInvalid,
		TargetDisabledOnShip,
		Culled
	}
	public enum CameraModeOptions
	{
		Body,
		Head
	}
	public enum BoolWithDefault
	{
		False,
		True,
		Default
	}
	[BepInPlugin("Zaggy1024.OpenBodyCams", "OpenBodyCams", "3.0.3")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		public const string MOD_NAME = "OpenBodyCams";

		public const string MOD_UNIQUE_NAME = "Zaggy1024.OpenBodyCams";

		public const string MOD_VERSION = "3.0.3";

		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> DisplayOriginalScreenWhenDisabled;

		public static ConfigEntry<bool> OverlayEnabled;

		public static ConfigEntry<float> OverlayTextScale;

		public static ConfigEntry<string> DefaultText;

		public static ConfigEntry<string> BuyAntennaText;

		public static ConfigEntry<string> AntennaStoredText;

		public static ConfigEntry<string> TargetInvalidText;

		public static ConfigEntry<string> TargetOnShipText;

		public static ConfigEntry<bool> TerminalPiPBodyCamEnabled;

		public static ConfigEntry<PiPPosition> TerminalPiPPosition;

		public static ConfigEntry<int> TerminalPiPWidth;

		public static ConfigEntry<bool> ShipUpgradeEnabled;

		public static ConfigEntry<int> ShipUpgradePrice;

		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> EnableReservedItemSlotsCompatibility;

		public static ConfigEntry<bool> SwapInternalAndExternalShipCameras;

		public static ConfigEntry<bool> DisableCameraOnSmallMonitor;

		public static ConfigEntry<string> ExternalCameraEmissiveColor;

		public static ConfigEntry<bool> FixDroppedItemRotation;

		public static ConfigEntry<bool> FixMaskedConversionForClients;

		public static ConfigEntry<BoolWithDefault> DisplayWeatherBasedOnPerspective;

		public static ConfigEntry<bool> PrintCosmeticsDebugInfo;

		public static ConfigEntry<bool> ReferencedObjectDestructionDetectionEnabled;

		public static ConfigEntry<string> LastConfigVersion;

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

		internal static AssetBundle Assets;

		private const string OptionDisabledWithBetterMonitors = "This has no effect when GeneralImprovements's UseBetterMonitors option is enabled.";

		public static Plugin Instance { get; private set; }

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

		private void Awake()
		{
			//IL_0739: Unknown result type (might be due to invalid IL or missing references)
			//IL_0743: Expected O, but got Unknown
			Instance = this;
			Assets = AssetBundle.LoadFromFile(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "openbodycams"));
			if ((Object)(object)Assets != (Object)null)
			{
				Instance.Logger.LogInfo((object)"Successfully loaded OpenBodyCams assets.");
			}
			else
			{
				Instance.Logger.LogError((object)"Failed to load the asset bundle, some features may be missing.");
			}
			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. Setting this significantly below the average framerate on the ship will improve performance.");
			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, using comma-separated decimal numbers for red, green and blue.");
			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.");
			DisplayOriginalScreenWhenDisabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Camera", "DisplayOriginalScreenWhenDisabled", true, "When enabled, the screen that the body cam replaces will be displayed when it is disabled due to invalid targets.");
			CameraMode.SettingChanged += delegate
			{
				BodyCamComponent.MarkTargetStatusChangedForAllBodyCams();
			};
			FieldOfView.SettingChanged += delegate
			{
				BodyCamComponent.UpdateAllCameraSettings();
			};
			RenderDistance.SettingChanged += delegate
			{
				BodyCamComponent.UpdateAllCameraSettings();
			};
			NightVisionBrightness.SettingChanged += delegate
			{
				BodyCamComponent.UpdateAllCameraSettings();
			};
			MonitorTextureFiltering.SettingChanged += delegate
			{
				BodyCamComponent.UpdateAllCameraSettings();
			};
			RadarBoosterPanRPM.SettingChanged += delegate
			{
				BodyCamComponent.UpdateAllCameraSettings();
			};
			DisableCameraWhileTargetIsOnShip.SettingChanged += delegate
			{
				BodyCamComponent.UpdateAllCameraSettings();
			};
			DisplayOriginalScreenWhenDisabled.SettingChanged += delegate
			{
				ShipObjects.UpdateMainBodyCamNoTargetMaterial();
			};
			HorizontalResolution.SettingChanged += delegate
			{
				ShipObjects.UpdateMainBodyCamSettings();
			};
			Framerate.SettingChanged += delegate
			{
				ShipObjects.UpdateMainBodyCamSettings();
			};
			MonitorEmissiveColor.SettingChanged += delegate
			{
				ShipObjects.UpdateMainBodyCamSettings();
			};
			EnableCamera.SettingChanged += delegate
			{
				ShipObjects.UpdateMainBodyCamSettings();
			};
			OverlayEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Overlay", "Enabled", true, "Displays an overlay on the monitor that the body cam replaces to communicate the status of the body cam. This will only work if the screen is displaying a render texture connected to a camera. Restart the lobby to apply.");
			OverlayTextScale = ((BaseUnityPlugin)this).Config.Bind<float>("Overlay", "TextScale", 1f, "The factor by which to scale the text on the overlay screen.");
			DefaultText = ((BaseUnityPlugin)this).Config.Bind<string>("Overlay", "DefaultText", "", "The text displayed on the body cam monitor when it is operating normally.");
			BuyAntennaText = ((BaseUnityPlugin)this).Config.Bind<string>("Overlay", "BuyAntennaText", "<color=\"yellow\">Body cam ${price}", "The text displayed on the body cam monitor to prompt players to buy the antenna in the store to enable body cams.");
			AntennaStoredText = ((BaseUnityPlugin)this).Config.Bind<string>("Overlay", "AntennaStoredText", "<color=\"yellow\">Antenna stored", "The text displayed when the antenna is stored, preventing the body cams displaying on the monitor.");
			TargetInvalidText = ((BaseUnityPlugin)this).Config.Bind<string>("Overlay", "TargetInvalidText", "<color=\"red\">Signal lost", "The text displayed when the selected target is invalid (for example, the target is a player that has been eaten).");
			TargetOnShipText = ((BaseUnityPlugin)this).Config.Bind<string>("Overlay", "TargetOnShipText", "<color=\"green\">Target on ship", "The text displayed when the selected target is safe on the ship with DisableCameraWhileTargetIsOnShip enabled.");
			OverlayTextScale.SettingChanged += UpdateOverlayPrefs;
			DefaultText.SettingChanged += UpdateOverlayText;
			BuyAntennaText.SettingChanged += UpdateOverlayText;
			AntennaStoredText.SettingChanged += UpdateOverlayText;
			TargetInvalidText.SettingChanged += UpdateOverlayText;
			TargetOnShipText.SettingChanged += UpdateOverlayText;
			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));
			ShipUpgradeEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("ShipUpgrade", "Enabled", true, "Adds a ship upgrade that enables the body cam on the main monitors only after it is bought.\n\nNOTE: The upgrade will only be available if LethalLib is installed. Without it, the main body cam will always be enabled.");
			ShipUpgradePrice = ((BaseUnityPlugin)this).Config.Bind<int>("ShipUpgrade", "Price", 200, "The price at which the ship upgrade is sold in the store.");
			GeneralImprovementsBetterMonitorIndex = ((BaseUnityPlugin)this).Config.Bind<int>("Compatibility", "GeneralImprovementsBetterMonitorIndex", 0, new ConfigDescription("With GeneralImprovements's UseBetterMonitors enabled, choose which monitor to display the body cam on.\nA value of 0 will place it on the large monitor on the right.\nValues greater than 0 go left to right, top to bottom, skipping the large center monitor. Without AddMoreBetterMonitors, the maximum value is 9, rather than 14.", (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.");
			EnableReservedItemSlotsCompatibility = ((BaseUnityPlugin)this).Config.Bind<bool>("Compatibility", "EnableReservedItemSlotsCompatibility", true, "When enabled, items holstered in reserved item slots will be hidden/shown based on the perspective.");
			SwapInternalAndExternalShipCameras = ((BaseUnityPlugin)this).Config.Bind<bool>("Ship", "SwapInternalAndExternalShipCameras", false, "Causes the internal ship camera to be placed onto big monitor, and the external one to be placed onto the small monitor. This has no effect when GeneralImprovements's UseBetterMonitors option is enabled.");
			DisableCameraOnSmallMonitor = ((BaseUnityPlugin)this).Config.Bind<bool>("Ship", "DisableCameraOnSmallMonitor", false, "Disables whichever camera is placed onto the small camera monitor. This has no effect when GeneralImprovements's UseBetterMonitors option is enabled.");
			ExternalCameraEmissiveColor = ((BaseUnityPlugin)this).Config.Bind<string>("Ship", "ExternalCameraEmissiveColor", "", "Sets the color emitted by the external camera screen, using comma-separated decimal numbers for red, green and blue.");
			ExternalCameraEmissiveColor.SettingChanged += delegate
			{
				ShipObjects.SetExternalCameraEmissiveColor();
			};
			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.");
			FixMaskedConversionForClients = ((BaseUnityPlugin)this).Config.Bind<bool>("Misc", "FixMaskedConversionForClients", true, "If enabled, the mod will patch a bug that causes maps and body cams to be unable to target a player that was converted into a masked enemy.");
			DisplayWeatherBasedOnPerspective = ((BaseUnityPlugin)this).Config.Bind<BoolWithDefault>("Experimental", "DisplayWeatherBasedOnPerspective", BoolWithDefault.Default, "If enabled, a clone of each weather effect will be simulated on the body cam target. This allows rain and fog effects to be visible on body cams when far from the viewer. This may cause issues with some modded weathers.\n\nThe Default value will leave the feature disabled, but may be changed in future versions.");
			DisplayWeatherBasedOnPerspective.SettingChanged += delegate
			{
				BodyCamComponent.CreateTargetWeatherEffectsForAllCams();
			};
			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.");
			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.");
			LastConfigVersion = ((BaseUnityPlugin)this).Config.Bind<string>("Debug", "LastConfigVersion", "", "The last version of the mod that loaded/saved this config file. Used for setting migration.");
			PrintCosmeticsDebugInfo.SettingChanged += delegate
			{
				Cosmetics.PrintDebugInfo = PrintCosmeticsDebugInfo.Value;
			};
			Cosmetics.PrintDebugInfo = PrintCosmeticsDebugInfo.Value;
			ReferencedObjectDestructionDetectionEnabled.SettingChanged += delegate
			{
				UpdateReferencedObjectDestructionDetectionEnabled();
			};
			UpdateReferencedObjectDestructionDetectionEnabled();
			MigrateSettings();
			harmony.PatchAll(typeof(PatchTerminal));
			harmony.PatchAll(typeof(PatchStartOfRound));
			harmony.PatchAll(typeof(PatchManualCameraRenderer));
			harmony.PatchAll(typeof(PatchPlayerControllerB));
			harmony.PatchAll(typeof(PatchHauntedMaskItem));
			harmony.PatchAll(typeof(PatchMaskedPlayerEnemy));
			harmony.PatchAll(typeof(PatchUnlockableSuit));
			harmony.PatchAll(typeof(PatchCentipedeAI));
			harmony.PatchAll(typeof(PatchFlowerSnakeEnemy));
			harmony.PatchAll(typeof(PatchHDRenderPipeline));
			harmony.PatchAll(typeof(PatchRadarBoosterItem));
			harmony.PatchAll(typeof(PatchDeadBodyInfo));
			harmony.PatchAll(typeof(PatchTimeOfDay));
			harmony.PatchAll(typeof(PatchFixItemDropping));
			BodyCamComponent.InitializeStatic();
			SetUpCameraCallbacks();
			ShipUpgrades.Initialize();
			Cosmetics.Initialize(harmony);
			static void UpdateOverlayPrefs(object target, EventArgs args)
			{
				if ((Object)(object)ShipObjects.Overlay != (Object)null)
				{
					ShipObjects.Overlay.UpdatePreferences();
				}
			}
			static void UpdateOverlayText(object target, EventArgs args)
			{
				if ((Object)(object)ShipObjects.Overlay != (Object)null)
				{
					ShipObjects.Overlay.UpdateText();
				}
			}
		}

		private void UpdateReferencedObjectDestructionDetectionEnabled()
		{
			if (ReferencedObjectDestructionDetectionEnabled.Value)
			{
				DestructionDetectionPatch.PatchAll(typeof(PatchModelDestructionDebugging));
			}
			else
			{
				DestructionDetectionPatch.UnpatchSelf();
			}
		}

		private void MigrateSettings()
		{
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Expected O, but got Unknown
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Expected O, but got Unknown
			Dictionary<ConfigDefinition, string> orphanedEntries;
			try
			{
				orphanedEntries = ((BaseUnityPlugin)this).Config.OrphanedEntries;
			}
			catch (MissingFieldException)
			{
				Logger.LogError((object)"Failed to migrate config, orphaned entries property was not found.");
				return;
			}
			if (!Version.TryParse(LastConfigVersion.Value, out Version result))
			{
				result = new Version(2, 0, 0);
			}
			Logger.LogInfo((object)$"Last config version is {result}.");
			ConfigDefinition val = new ConfigDefinition("Misc", "DisableInternalShipCamera");
			if (orphanedEntries.TryGetValue(val, out var value))
			{
				Logger.LogInfo((object)$"{val} option was found set to '{value}' in the config, migrating it over to {((ConfigEntryBase)DisableCameraOnSmallMonitor).Definition}.");
				orphanedEntries.Remove(val);
				DisableCameraOnSmallMonitor.Value = TomlTypeConverter.ConvertToValue<bool>(value);
			}
			if (result < new Version(2, 0, 2) && !ShipUpgradeEnabled.Value)
			{
				Logger.LogInfo((object)$"{((ConfigEntryBase)ShipUpgradeEnabled).Definition} was set to its 2.0.0 default value 'false', resetting it to 'true'.");
				ShipUpgradeEnabled.Value = true;
			}
			if (result < new Version(3, 0, 0))
			{
				orphanedEntries.Remove(new ConfigDefinition("Debug", "BruteForcePreventFreezes"));
			}
			LastConfigVersion.Value = "3.0.3";
		}

		private static Color ParseColor(string str)
		{
			//IL_007c: 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 < 3)
			{
				throw new FormatException("Not enough color components");
			}
			if (array.Length > 4)
			{
				throw new FormatException("Too many color components");
			}
			return new Color(array[0], array[1], array[2], (array.Length == 4) ? array[3] : 0f);
		}

		internal static Color GetBodyCamEmissiveColor()
		{
			//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(MonitorEmissiveColor.Value);
			}
			catch (Exception arg)
			{
				Instance.Logger.LogWarning((object)$"Failed to parse the body cam screen's emissive color: {arg}");
				return ParseColor((string)((ConfigEntryBase)MonitorEmissiveColor).DefaultValue);
			}
		}

		internal static Color? GetExternalCameraEmissiveColor()
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			if (ExternalCameraEmissiveColor.Value == "")
			{
				return null;
			}
			try
			{
				return ParseColor(ExternalCameraEmissiveColor.Value);
			}
			catch (Exception arg)
			{
				Instance.Logger.LogWarning((object)$"Failed to parse the external camera screen's emissive color: {arg}");
				return null;
			}
		}

		private void SetUpCameraCallbacks()
		{
			PatchHDRenderPipeline.BeforeCameraCulling = (Action<ScriptableRenderContext, Camera>)Delegate.Combine(PatchHDRenderPipeline.BeforeCameraCulling, new Action<ScriptableRenderContext, Camera>(BeforeCullingAnyCamera));
			PatchHDRenderPipeline.BeforeCameraRendering = (Action<ScriptableRenderContext, Camera>)Delegate.Combine(PatchHDRenderPipeline.BeforeCameraRendering, new Action<ScriptableRenderContext, Camera>(BeforeRenderingAnyCamera));
			RenderPipelineManager.endCameraRendering += AfterRenderingAnyCamera;
		}

		private void BeforeCullingAnyCamera(ScriptableRenderContext context, Camera camera)
		{
			BodyCamComponent.BeforeCullingAnyCamera(camera);
		}

		private void BeforeRenderingAnyCamera(ScriptableRenderContext context, Camera camera)
		{
			BodyCamComponent.BeforeRenderingAnyCamera(camera);
			OverlayManager.BeforeRenderingAnyCamera(camera);
		}

		private void AfterRenderingAnyCamera(ScriptableRenderContext context, Camera camera)
		{
			BodyCamComponent.AfterRenderingAnyCamera(camera);
			OverlayManager.AfterRenderingAnyCamera(camera);
		}
	}
	public static class ShipObjects
	{
		internal static Material BlackScreenMaterial;

		internal static Terminal TerminalScript;

		internal static bool TwoRadarCamsPresent;

		internal static BodyCamComponent MainBodyCam;

		internal static OverlayManager Overlay;

		internal static ManualCameraRenderer InternalCameraRenderer;

		internal static ManualCameraRenderer ExternalCameraRenderer;

		internal static Material ExternalCameraMaterial;

		internal static Color OriginalExternalCameraEmissiveColor;

		internal static MeshRenderer DoorScreenRenderer;

		internal static bool DoorScreenUsesExternalCamera;

		internal static ManualCameraRenderer ShipCameraOnSmallMonitor;

		internal static ManualCameraRenderer CameraReplacedByBodyCam;

		public static void EarlyInitialization()
		{
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			if (HasFinishedEarlyInitialization())
			{
				return;
			}
			BlackScreenMaterial = StartOfRound.Instance.mapScreen.offScreenMat;
			GameObject obj = GameObject.Find("Environment/HangarShip/Cameras/ShipCamera");
			InternalCameraRenderer = ((obj != null) ? obj.GetComponent<ManualCameraRenderer>() : null);
			GameObject obj2 = GameObject.Find("Environment/HangarShip/Cameras/FrontDoorSecurityCam/SecurityCamera");
			ExternalCameraRenderer = ((obj2 != null) ? obj2.GetComponent<ManualCameraRenderer>() : null);
			GameObject obj3 = GameObject.Find("Environment/HangarShip/ShipModels2b/MonitorWall/SingleScreen");
			DoorScreenRenderer = ((obj3 != null) ? obj3.GetComponent<MeshRenderer>() : null);
			ShipCameraOnSmallMonitor = InternalCameraRenderer;
			BodyCamComponent.InitializeAtStartOfGame();
			if ((Object)(object)ExternalCameraRenderer != (Object)null)
			{
				int cameraMaterialIndex = GetCameraMaterialIndex(ExternalCameraRenderer);
				if (cameraMaterialIndex != -1)
				{
					ExternalCameraMaterial = ((Renderer)ExternalCameraRenderer.mesh).sharedMaterials[cameraMaterialIndex];
					OriginalExternalCameraEmissiveColor = ExternalCameraMaterial.GetColor("_EmissiveColor");
					SetExternalCameraEmissiveColor();
				}
			}
		}

		private static bool HasFinishedEarlyInitialization()
		{
			return (Object)(object)ShipCameraOnSmallMonitor != (Object)null;
		}

		internal static void SetExternalCameraEmissiveColor()
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: 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)
			Color valueOrDefault = Plugin.GetExternalCameraEmissiveColor().GetValueOrDefault(OriginalExternalCameraEmissiveColor);
			Material externalCameraMaterial = ExternalCameraMaterial;
			if (externalCameraMaterial != null)
			{
				externalCameraMaterial.SetColor("_EmissiveColor", valueOrDefault);
			}
		}

		public static void LateInitialization()
		{
			ManageShipCameras();
			TwoRadarCamsPresent = (Object)(object)((Component)TerminalScript).GetComponent<ManualCameraRenderer>() != (Object)null;
			if ((Object)(object)DoorScreenRenderer != (Object)null && (Object)(object)ExternalCameraRenderer?.cam != (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 ManageShipCameras()
		{
			if (!GeneralImprovementsCompatibility.BetterMonitorsEnabled)
			{
				if (Plugin.SwapInternalAndExternalShipCameras.Value)
				{
					SwapShipCameras();
				}
				if (Plugin.DisableCameraOnSmallMonitor.Value)
				{
					DisableCameraOnSmallMonitor();
				}
			}
		}

		private static int GetCameraMaterialIndex(ManualCameraRenderer shipCamera)
		{
			if ((Object)(object)shipCamera == (Object)null)
			{
				return -1;
			}
			if ((Object)(object)shipCamera.mesh == (Object)null)
			{
				return -1;
			}
			Camera val = shipCamera.cam;
			if ((Object)(object)val == (Object)null)
			{
				val = ((Component)shipCamera).GetComponent<Camera>();
			}
			RenderTexture texture = val.targetTexture;
			return Array.FindIndex(((Renderer)shipCamera.mesh).sharedMaterials, (Material material) => (Object)(object)material.mainTexture == (Object)(object)texture);
		}

		private static void SwapShipCameras()
		{
			int cameraMaterialIndex = GetCameraMaterialIndex(InternalCameraRenderer);
			int cameraMaterialIndex2 = GetCameraMaterialIndex(ExternalCameraRenderer);
			if (cameraMaterialIndex == -1 || cameraMaterialIndex2 == -1)
			{
				Plugin.Instance.Logger.LogError((object)$"{((ConfigEntryBase)Plugin.SwapInternalAndExternalShipCameras).Definition} is enabled, but one of the ship's cameras' materials was not found.");
				return;
			}
			Material material = ((Renderer)InternalCameraRenderer.mesh).sharedMaterials[cameraMaterialIndex];
			((Renderer)(object)InternalCameraRenderer.mesh).SetMaterial(cameraMaterialIndex, ((Renderer)ExternalCameraRenderer.mesh).sharedMaterials[cameraMaterialIndex2]);
			((Renderer)(object)ExternalCameraRenderer.mesh).SetMaterial(cameraMaterialIndex2, material);
			ManualCameraRenderer internalCameraRenderer = InternalCameraRenderer;
			ManualCameraRenderer externalCameraRenderer = ExternalCameraRenderer;
			MeshRenderer mesh = ExternalCameraRenderer.mesh;
			MeshRenderer mesh2 = InternalCameraRenderer.mesh;
			internalCameraRenderer.mesh = mesh;
			externalCameraRenderer.mesh = mesh2;
			ShipCameraOnSmallMonitor = ExternalCameraRenderer;
		}

		private static void DisableCameraOnSmallMonitor()
		{
			int cameraMaterialIndex = GetCameraMaterialIndex(ShipCameraOnSmallMonitor);
			if (cameraMaterialIndex == -1)
			{
				Plugin.Instance.Logger.LogError((object)$"{((ConfigEntryBase)Plugin.DisableCameraOnSmallMonitor).Definition} is enabled, but the small monitor's camera material was not found.");
				return;
			}
			((Renderer)(object)ShipCameraOnSmallMonitor.mesh).SetMaterial(cameraMaterialIndex, BlackScreenMaterial);
			((Behaviour)ShipCameraOnSmallMonitor.cam).enabled = false;
			((Behaviour)ShipCameraOnSmallMonitor).enabled = false;
		}

		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.");
				return;
			}
			if ((Object)(object)val.GetComponent<BodyCamComponent>() == (Object)null)
			{
				MainBodyCam = val.AddComponent<BodyCamComponent>();
				val.AddComponent<SyncBodyCamToRadarMap>();
				if (!GeneralImprovementsCompatibility.BetterMonitorsEnabled)
				{
					MainBodyCam.MonitorRenderer = (Renderer)(object)val.GetComponent<MeshRenderer>();
					MainBodyCam.MonitorMaterialIndex = 2;
					MainBodyCam.MonitorDisabledMaterial = MainBodyCam.MonitorRenderer.sharedMaterials[MainBodyCam.MonitorMaterialIndex];
				}
				else
				{
					GeneralImprovementsCompatibility.GeneralImprovementsMonitorSpecification? monitorForID = GeneralImprovementsCompatibility.GetMonitorForID(Plugin.GeneralImprovementsBetterMonitorIndex.Value - 1);
					if (monitorForID.HasValue)
					{
						MainBodyCam.MonitorRenderer = monitorForID.Value.Renderer;
						MainBodyCam.MonitorMaterialIndex = monitorForID.Value.MaterialIndex;
						MainBodyCam.MonitorDisabledMaterial = monitorForID.Value.OriginalMaterial;
					}
				}
				if ((Object)(object)MainBodyCam.MonitorRenderer == (Object)null)
				{
					Plugin.Instance.Logger.LogError((object)"Failed to find the monitor renderer.");
					Object.DestroyImmediate((Object)(object)MainBodyCam);
					return;
				}
				if ((Object)(object)MainBodyCam.MonitorDisabledMaterial == (Object)null)
				{
					MainBodyCam.MonitorDisabledMaterial = BlackScreenMaterial;
				}
				UpdateMainBodyCamNoTargetMaterial();
				if (ShipUpgrades.BodyCamUnlockable != null)
				{
					((Behaviour)MainBodyCam).enabled = ShipUpgrades.BodyCamUnlockableIsPlaced;
				}
				else
				{
					BodyCam.BodyCamReceiverBecameEnabled();
				}
				CameraReplacedByBodyCam = null;
				Texture mainTexture = MainBodyCam.MonitorDisabledMaterial.mainTexture;
				RenderTexture val2 = (RenderTexture)(object)((mainTexture is RenderTexture) ? mainTexture : null);
				if (val2 != null)
				{
					ManualCameraRenderer internalCameraRenderer = InternalCameraRenderer;
					object obj;
					if (internalCameraRenderer == null)
					{
						obj = null;
					}
					else
					{
						Camera cam = internalCameraRenderer.cam;
						obj = ((cam != null) ? cam.targetTexture : null);
					}
					if ((Object)(object)val2 == (Object)obj)
					{
						CameraReplacedByBodyCam = InternalCameraRenderer;
					}
					else
					{
						ManualCameraRenderer externalCameraRenderer = ExternalCameraRenderer;
						object obj2;
						if (externalCameraRenderer == null)
						{
							obj2 = null;
						}
						else
						{
							Camera cam2 = externalCameraRenderer.cam;
							obj2 = ((cam2 != null) ? cam2.targetTexture : null);
						}
						if ((Object)(object)val2 == (Object)obj2)
						{
							CameraReplacedByBodyCam = ExternalCameraRenderer;
						}
					}
				}
			}
			UpdateMainBodyCamSettings();
			InitializeMainBodyCamOverlay();
		}

		private static void InitializeMainBodyCamOverlay()
		{
			if (!((Object)(object)Plugin.Assets == (Object)null) && Plugin.OverlayEnabled.Value)
			{
				GameObject obj = Object.Instantiate<GameObject>(Plugin.Assets.LoadAsset<GameObject>("Assets/OpenBodyCams/Prefabs/BodyCamOverlayCanvas.prefab"));
				obj.transform.SetParent(GameObject.Find("Systems/UI").transform, false);
				Overlay = obj.AddComponent<OverlayManager>();
				Overlay.BodyCam = MainBodyCam;
			}
		}

		internal static void UpdateMainBodyCamNoTargetMaterial()
		{
			if (Plugin.DisplayOriginalScreenWhenDisabled.Value)
			{
				MainBodyCam.MonitorNoTargetMaterial = MainBodyCam.MonitorDisabledMaterial;
			}
			else
			{
				MainBodyCam.MonitorNoTargetMaterial = null;
			}
			MainBodyCam.UpdateScreenMaterial();
		}

		internal static void UpdateMainBodyCamSettings()
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)MainBodyCam == (Object)null))
			{
				MainBodyCam.Resolution = new Vector2Int(Plugin.HorizontalResolution.Value, Plugin.HorizontalResolution.Value * 3 / 4);
				MainBodyCam.Framerate = Plugin.Framerate.Value;
				MainBodyCam.EnableCamera = Plugin.EnableCamera.Value;
				MainBodyCam.UpdateScreenMaterial();
				MainBodyCam.MonitorOnMaterial.SetColor("_EmissiveColor", Plugin.GetBodyCamEmissiveColor());
			}
		}
	}
	internal static class ShipUpgrades
	{
		internal static UnlockableItem BodyCamUnlockable;

		internal static int BodyCamPrice;

		internal static bool BodyCamUnlockableIsPlaced;

		public static void Initialize()
		{
			if (!Chainloader.PluginInfos.ContainsKey("evaisa.lethallib"))
			{
				Plugin.Instance.Logger.LogInfo((object)"LethalLib is not present, body cam will be enabled by default.");
			}
			else
			{
				RegisterUnlockables();
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static void RegisterUnlockables()
		{
			RegisterBodyCamShipUpgrade();
		}

		private static void RegisterBodyCamShipUpgrade()
		{
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Expected O, but got Unknown
			//IL_00a8: Expected O, but got Unknown
			if (!((Object)(object)Plugin.Assets == (Object)null) && Plugin.ShipUpgradeEnabled.Value)
			{
				GameObject val = Plugin.Assets.LoadAsset<GameObject>("Assets/OpenBodyCams/Prefabs/BodyCamAntenna.prefab");
				if ((Object)(object)val == (Object)null)
				{
					Plugin.Instance.Logger.LogInfo((object)"Body cam antenna prop was not found within the asset bundle.");
					return;
				}
				val.AddComponent<EnableMainBodyCam>();
				UnlockableItem val2 = new UnlockableItem
				{
					unlockableName = "Bodycam",
					unlockableType = 1,
					prefabObject = val,
					IsPlaceable = true,
					alwaysInStock = true
				};
				BodyCamPrice = Plugin.ShipUpgradePrice.Value;
				Unlockables.RegisterUnlockable(val2, BodyCamPrice, (StoreType)1);
				NetworkPrefabs.RegisterNetworkPrefab(val);
				Utilities.FixMixerGroups(val);
				BodyCamUnlockable = val2;
				Plugin.Instance.Logger.LogInfo((object)$"Registered body cam unlockable for {BodyCamPrice} credits.");
			}
		}
	}
	internal class EnableMainBodyCam : MonoBehaviour
	{
		private void OnEnable()
		{
			ShipUpgrades.BodyCamUnlockableIsPlaced = true;
			BodyCam.BodyCamReceiverBecameEnabled();
			if (!((Object)(object)ShipObjects.MainBodyCam == (Object)null))
			{
				((Behaviour)ShipObjects.MainBodyCam).enabled = true;
			}
		}

		private void OnDisable()
		{
			ShipUpgrades.BodyCamUnlockableIsPlaced = false;
			BodyCam.BodyCamReceiverBecameDisabled();
			if (!((Object)(object)ShipObjects.MainBodyCam == (Object)null))
			{
				((Behaviour)ShipObjects.MainBodyCam).enabled = false;
			}
		}
	}
	public class SyncBodyCamToRadarMap : MonoBehaviour
	{
		private static SyncBodyCamToRadarMap[] AllSynchronizedCams = new SyncBodyCamToRadarMap[0];

		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()
		{
			SyncBodyCamToRadarMap[] allSynchronizedCams = AllSynchronizedCams;
			int num = 0;
			SyncBodyCamToRadarMap[] array = new SyncBodyCamToRadarMap[1 + allSynchronizedCams.Length];
			ReadOnlySpan<SyncBodyCamToRadarMap> readOnlySpan = new ReadOnlySpan<SyncBodyCamToRadarMap>(allSynchronizedCams);
			readOnlySpan.CopyTo(new Span<SyncBodyCamToRadarMap>(array).Slice(num, readOnlySpan.Length));
			num += readOnlySpan.Length;
			array[num] = this;
			num++;
			AllSynchronizedCams = array;
			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();
		}

		private void OnEnable()
		{
			if ((Object)(object)BodyCam != (Object)null && (Object)(object)MapRenderer != (Object)null)
			{
				UpdateBodyCamTarget();
			}
		}

		public void UpdateBodyCamTarget()
		{
			if (((Behaviour)this).isActiveAndEnabled)
			{
				if ((Object)(object)MapRenderer.targetedPlayer != (Object)null)
				{
					BodyCam.SetTargetToPlayer(MapRenderer.targetedPlayer);
				}
				else
				{
					BodyCam.SetTargetToTransform(MapRenderer.radarTargets[MapRenderer.targetTransformIndex].transform);
				}
				BodyCam.SetScreenPowered(MapRenderer.isScreenOn);
			}
		}

		public void StartTargetTransition()
		{
			if (((Behaviour)this).isActiveAndEnabled)
			{
				BodyCam.StartTargetTransition();
			}
		}

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

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

		private static TerminalNode ViewBodyCamNode;

		private static TerminalKeyword BodyCamKeyword;

		private static TerminalNode BodyCamFailedNode;

		private static TerminalNode BodyCamLockedNode;

		private static RawImage PiPImage;

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

		private static readonly Dictionary<TerminalKeyword, List<TerminalKeyword>> addedCompatibleNouns = new Dictionary<TerminalKeyword, List<TerminalKeyword>>();

		public static void Initialize()
		{
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: 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_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0208: Unknown result type (might be due to invalid IL or missing references)
			//IL_020d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0212: Unknown result type (might be due to invalid IL or missing references)
			//IL_021e: Unknown result type (might be due to invalid IL or missing references)
			//IL_021f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0221: Unknown result type (might be due to invalid IL or missing references)
			//IL_0235: Unknown result type (might be due to invalid IL or missing references)
			//IL_0236: Unknown result type (might be due to invalid IL or missing references)
			//IL_0238: 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;
			ShipObjects.MainBodyCam.OnBlankedSet -= SetBodyCamBlanked;
			BodyCam.OnBodyCamReceiverBecameDisabled -= DisablePiPImage;
			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;
				BodyCam.OnBodyCamReceiverBecameDisabled += DisablePiPImage;
				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 DisablePiPImage()
		{
			((Component)PiPImage).gameObject.SetActive(false);
		}

		private static void EnablePiPImage()
		{
			((Component)PiPImage).gameObject.SetActive(true);
		}

		private static void InitializeCommands()
		{
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Expected O, but got Unknown
			RemoveAddedKeywords();
			ViewBodyCamNode = null;
			BodyCamKeyword = null;
			TerminalKeyword val = FindKeyword("view", verb: true);
			ViewMonitorNode = ((val == null) ? null : val.FindCompatibleNoun("monitor")?.result);
			if (Plugin.TerminalPiPBodyCamEnabled.Value)
			{
				if ((Object)(object)ViewMonitorNode == (Object)null)
				{
					Plugin.Instance.Logger.LogWarning((object)"'view monitor' command does not exist, terminal PiP body cam view will be disabled.");
					return;
				}
				ViewBodyCamNode = ScriptableObject.CreateInstance<TerminalNode>();
				((Object)ViewBodyCamNode).name = "ViewBodyCam";
				ViewBodyCamNode.displayText = "Toggling picture-in-picture body cam.\n\n";
				ViewBodyCamNode.clearPreviousText = true;
				BodyCamKeyword = FindOrCreateKeyword("BodyCam", "bodycam", verb: false);
				AddCompatibleNoun(val, BodyCamKeyword, ViewBodyCamNode);
				CompatibleNoun[] array = val.compatibleNouns ?? Array.Empty<CompatibleNoun>();
				int num = 0;
				CompatibleNoun[] array2 = (CompatibleNoun[])(object)new CompatibleNoun[1 + array.Length];
				ReadOnlySpan<CompatibleNoun> readOnlySpan = new ReadOnlySpan<CompatibleNoun>(array);
				readOnlySpan.CopyTo(new Span<CompatibleNoun>(array2).Slice(num, readOnlySpan.Length));
				num += readOnlySpan.Length;
				array2[num] = new CompatibleNoun
				{
					noun = BodyCamKeyword,
					result = ViewBodyCamNode
				};
				num++;
				val.compatibl