Decompiled source of Keep Camera After Death v1.1.0

alexandria-p.KeepCameraAfterDeath.dll

Decompiled 2 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Logging;
using ContentSettings.API.Attributes;
using ContentSettings.API.Settings;
using KeepCameraAfterDeath.Patches;
using Microsoft.CodeAnalysis;
using MonoMod.RuntimeDetour.HookGen;
using MyceliumNetworking;
using On;
using Photon.Pun;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("alexandria-p.KeepCameraAfterDeath")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.1.0.0")]
[assembly: AssemblyInformationalVersion("1.1.0+323788f981155e72f22e241f2e1e23ad6706b9b5")]
[assembly: AssemblyProduct("KeepCameraAfterDeath")]
[assembly: AssemblyTitle("alexandria-p.KeepCameraAfterDeath")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.1.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

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

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace BepInEx
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	internal sealed class BepInAutoPluginAttribute : Attribute
	{
		public BepInAutoPluginAttribute(string id = null, string name = null, string version = null)
		{
		}
	}
}
namespace BepInEx.Preloader.Core.Patching
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	internal sealed class PatcherAutoPluginAttribute : Attribute
	{
		public PatcherAutoPluginAttribute(string id = null, string name = null, string version = null)
		{
		}
	}
}
namespace KeepCameraAfterDeath
{
	[ContentWarningPlugin("alexandria-p.KeepCameraAfterDeath", "1.1.0", false)]
	[BepInPlugin("alexandria-p.KeepCameraAfterDeath", "KeepCameraAfterDeath", "1.1.0")]
	public class KeepCameraAfterDeath : BaseUnityPlugin
	{
		[SettingRegister("KeepCameraAfterDeath Mod Settings", null)]
		public class EnableRewardForCameraReturnSetting : BoolSetting, ICustomSetting, IExposedSetting
		{
			public override void ApplyValue()
			{
				Instance.SetPlayerSettingEnableRewardForCameraReturn(((BoolSetting)this).Value);
			}

			public string GetDisplayName()
			{
				return "Turn on incentives for bringing the camera back to the surface (uses the host's game settings)";
			}

			protected override bool GetDefaultValue()
			{
				return true;
			}
		}

		[SettingRegister("KeepCameraAfterDeath Mod Settings", null)]
		public class SetMetaCoinRewardForCameraReturnSetting : IntSetting, ICustomSetting, IExposedSetting
		{
			public override void ApplyValue()
			{
				Instance.SetPlayerSettingMetaCoinReward(((IntSetting)this).Value);
			}

			public string GetDisplayName()
			{
				return "Meta Coin (MC) reward for camera return (uses the host's game settings)";
			}

			protected override int GetDefaultValue()
			{
				return 10;
			}

			protected override (int, int) GetMinMaxValue()
			{
				return (0, 100);
			}
		}

		[SettingRegister("KeepCameraAfterDeath Mod Settings", null)]
		public class SetCashRewardForCameraReturnSetting : IntSetting, ICustomSetting, IExposedSetting
		{
			public override void ApplyValue()
			{
				Instance.SetPlayerSettingCashReward(((IntSetting)this).Value);
			}

			public string GetDisplayName()
			{
				return "Cash reward for camera return (uses the host's game settings)";
			}

			protected override int GetDefaultValue()
			{
				return 0;
			}

			protected override (int, int) GetMinMaxValue()
			{
				return (0, 1000);
			}
		}

		[SettingRegister("KeepCameraAfterDeath Mod Settings", null)]
		public class EnableAllowCrewToWatchFootageEvenIfQuotaNotMetSetting : BoolSetting, ICustomSetting, IExposedSetting
		{
			public override void ApplyValue()
			{
				Instance.SetAllowCrewToWatchFootageEvenIfQuotaNotMet(((BoolSetting)this).Value);
			}

			public string GetDisplayName()
			{
				return "[BETA] Allow crew to view their camera footage on final day, even if the footage won't reach quota (uses the host's game settings) \nWithout this setting, the third day ends immediately.";
			}

			protected override bool GetDefaultValue()
			{
				return true;
			}
		}

		private const uint myceliumNetworkModId = 61812u;

		public bool Debug_InitSurfaceActive;

		public static KeepCameraAfterDeath Instance { get; private set; }

		internal static ManualLogSource Logger { get; private set; }

		public bool AllowCrewToWatchFootageEvenIfQuotaNotMet { get; private set; }

		public bool PlayerSettingEnableRewardForCameraReturn { get; private set; }

		public int PlayerSettingMetaCoinReward { get; private set; }

		public int PlayerSettingCashReward { get; private set; }

		public ItemInstanceData? PreservedCameraInstanceDataForHost { get; private set; }

		public (int cash, int mc)? PendingRewardForCameraReturn { get; private set; }

		private void Awake()
		{
			Logger = ((BaseUnityPlugin)this).Logger;
			Instance = this;
			HookAll();
			Logger.LogInfo((object)"KeepCameraAfterDeath v1.1.0 has loaded!");
		}

		private void Start()
		{
			MyceliumNetwork.RegisterNetworkObject((object)Instance, 61812u, 0);
		}

		private void OnDestroy()
		{
			MyceliumNetwork.DeregisterNetworkObject((object)Instance, 61812u, 0);
		}

		internal static void HookAll()
		{
			SurfaceNetworkHandlerPatch.Init();
			VideoCameraPatch.Init();
			PersistentObjectsHolderPatch.Init();
			PlayerPatch.Init();
			PhotonGameLobbyHandlerPatch.Init();
		}

		internal static void UnhookAll()
		{
			HookEndpointManager.RemoveAllOwnedBy((object)Assembly.GetExecutingAssembly());
		}

		public void SetAllowCrewToWatchFootageEvenIfQuotaNotMet(bool allowFinalDayIfQuotaNotMet)
		{
			AllowCrewToWatchFootageEvenIfQuotaNotMet = allowFinalDayIfQuotaNotMet;
		}

		public void SetPlayerSettingEnableRewardForCameraReturn(bool rewardEnabled)
		{
			PlayerSettingEnableRewardForCameraReturn = rewardEnabled;
		}

		public void SetPlayerSettingMetaCoinReward(int mcReward)
		{
			PlayerSettingMetaCoinReward = mcReward;
		}

		public void SetPlayerSettingCashReward(int cashReward)
		{
			PlayerSettingCashReward = cashReward;
		}

		public void SetPreservedCameraInstanceDataForHost(ItemInstanceData data)
		{
			if (MyceliumNetwork.IsHost)
			{
				PreservedCameraInstanceDataForHost = data;
			}
		}

		public void SetPendingRewardForAllPlayers()
		{
			if (MyceliumNetwork.IsHost)
			{
				MyceliumNetwork.RPC(61812u, "RPC_SetPendingRewardForCameraReturn", (ReliableType)1, new object[2] { PlayerSettingCashReward, PlayerSettingMetaCoinReward });
			}
		}

		[CustomRPC]
		public void RPC_SetPendingRewardForCameraReturn(int cash, int mc)
		{
			PendingRewardForCameraReturn = (cash, mc);
		}

		public void Command_ResetDataforDay()
		{
			if (MyceliumNetwork.IsHost)
			{
				MyceliumNetwork.RPC(61812u, "RPC_ResetDataforDay", (ReliableType)1, Array.Empty<object>());
			}
		}

		[CustomRPC]
		public void RPC_ResetDataforDay()
		{
			Instance.ClearData();
		}

		public void ClearData()
		{
			Instance.ClearPreservedCameraInstanceDataForHost();
			Instance.ClearPendingRewardForCameraReturn();
		}

		public void ClearPreservedCameraInstanceDataForHost()
		{
			if (MyceliumNetwork.IsHost)
			{
				PreservedCameraInstanceDataForHost = null;
			}
		}

		public void ClearPendingRewardForCameraReturn()
		{
			PendingRewardForCameraReturn = null;
		}

		public bool IsFinalDayAndQuotaNotMet()
		{
			if (SurfaceNetworkHandler.RoomStats != null && SurfaceNetworkHandler.RoomStats.IsQuotaDay)
			{
				return !SurfaceNetworkHandler.RoomStats.CalculateIfReachedQuota();
			}
			return false;
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "alexandria-p.KeepCameraAfterDeath";

		public const string PLUGIN_NAME = "KeepCameraAfterDeath";

		public const string PLUGIN_VERSION = "1.1.0";
	}
}
namespace KeepCameraAfterDeath.Patches
{
	public class PersistentObjectsHolderPatch
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static hook_FindPersistantObjects <0>__PersistentObjectsHolder_FindPersistantObjects;
		}

		internal static void Init()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			object obj = <>O.<0>__PersistentObjectsHolder_FindPersistantObjects;
			if (obj == null)
			{
				hook_FindPersistantObjects val = PersistentObjectsHolder_FindPersistantObjects;
				<>O.<0>__PersistentObjectsHolder_FindPersistantObjects = val;
				obj = (object)val;
			}
			PersistentObjectsHolder.FindPersistantObjects += (hook_FindPersistantObjects)obj;
		}

		private static void PersistentObjectsHolder_FindPersistantObjects(orig_FindPersistantObjects orig, PersistentObjectsHolder self)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			List<VideoCamera> list = FindVideoCamerasInSet(self.m_PersistentObjects);
			orig.Invoke(self);
			if (!MyceliumNetwork.IsHost)
			{
				return;
			}
			int count = self.m_PersistentObjects.Count;
			VideoCamera item2 = default(VideoCamera);
			for (int num = count - 1; num >= 0; num--)
			{
				PersistentObjectInfo item = self.m_PersistentObjects[num];
				ItemInstanceData instanceData = ((PersistentObjectInfo)(ref item)).InstanceData;
				Guid guid = instanceData.m_guid;
				if (CameraHandler.TryGetCamera(guid, ref item2) && !list.Contains(item2))
				{
					KeepCameraAfterDeath.Instance.SetPreservedCameraInstanceDataForHost(instanceData);
					if (self.m_PersistentObjectDic.ContainsKey(((PersistentObjectInfo)(ref item)).Pickup))
					{
						self.m_PersistentObjectDic.Remove(((PersistentObjectInfo)(ref item)).Pickup);
					}
					self.m_PersistentObjects.Remove(item);
					break;
				}
			}
		}

		private static List<VideoCamera> FindVideoCamerasInSet(List<PersistentObjectInfo> persistantObjects)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			List<VideoCamera> list = new List<VideoCamera>();
			VideoCamera item = default(VideoCamera);
			foreach (PersistentObjectInfo persistantObject in persistantObjects)
			{
				PersistentObjectInfo current = persistantObject;
				ItemInstanceData instanceData = ((PersistentObjectInfo)(ref current)).InstanceData;
				Guid guid = instanceData.m_guid;
				if (CameraHandler.TryGetCamera(guid, ref item))
				{
					list.Add(item);
				}
			}
			return list;
		}
	}
	public class PhotonGameLobbyHandlerPatch
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static hook_SetCurrentObjective <0>__PhotonGameLobbyHandler_SetCurrentObjective;
		}

		internal static void Init()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			object obj = <>O.<0>__PhotonGameLobbyHandler_SetCurrentObjective;
			if (obj == null)
			{
				hook_SetCurrentObjective val = PhotonGameLobbyHandler_SetCurrentObjective;
				<>O.<0>__PhotonGameLobbyHandler_SetCurrentObjective = val;
				obj = (object)val;
			}
			PhotonGameLobbyHandler.SetCurrentObjective += (hook_SetCurrentObjective)obj;
		}

		private static void PhotonGameLobbyHandler_SetCurrentObjective(orig_SetCurrentObjective orig, PhotonGameLobbyHandler self, Objective objective)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Expected O, but got Unknown
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Expected O, but got Unknown
			if (MyceliumNetwork.IsHost && KeepCameraAfterDeath.Instance.AllowCrewToWatchFootageEvenIfQuotaNotMet && KeepCameraAfterDeath.Instance.IsFinalDayAndQuotaNotMet())
			{
				if (KeepCameraAfterDeath.Instance.Debug_InitSurfaceActive)
				{
					objective = (Objective)new ExtractVideoObjective();
				}
				if (objective is GoToBedSuccessObjective)
				{
					objective = (Objective)new GoToBedFailedObjective();
				}
			}
			orig.Invoke(self, objective);
		}
	}
	public class PlayerPatch
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static hook_Update <0>__Player_Update;
		}

		internal static void Init()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			object obj = <>O.<0>__Player_Update;
			if (obj == null)
			{
				hook_Update val = Player_Update;
				<>O.<0>__Player_Update = val;
				obj = (object)val;
			}
			Player.Update += (hook_Update)obj;
		}

		private static void Player_Update(orig_Update orig, Player self)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Invalid comparison between Unknown and I4
			if (KeepCameraAfterDeath.Instance.PendingRewardForCameraReturn.HasValue && self.IsLocal && self.data.playerSetUpAndReady && SurfaceNetworkHandler.RoomStats != null && (int)TimeOfDayHandler.TimeOfDay == 10)
			{
				AddCashToRoom();
				AddMCToPlayers();
				KeepCameraAfterDeath.Instance.ClearPendingRewardForCameraReturn();
			}
			orig.Invoke(self);
			static void AddCashToRoom()
			{
				int item2 = KeepCameraAfterDeath.Instance.PendingRewardForCameraReturn.Value.cash;
				if (item2 > 0)
				{
					UserInterface.ShowMoneyNotification("Cash Received", $"${item2}", (MoneyCellType)1);
					if (MyceliumNetwork.IsHost)
					{
						SurfaceNetworkHandler.RoomStats.AddMoney(item2);
					}
				}
			}
			static void AddMCToPlayers()
			{
				int item = KeepCameraAfterDeath.Instance.PendingRewardForCameraReturn.Value.mc;
				if (item > 0)
				{
					MetaProgressionHandler.AddMetaCoins(item);
				}
			}
		}
	}
	public class SurfaceNetworkHandlerPatch
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static hook_InitSurface <0>__SurfaceNetworkHandler_InitSurface;

			public static hook_NextDay <1>__SurfaceNetworkHandler_NextDay;
		}

		internal static void Init()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Expected O, but got Unknown
			object obj = <>O.<0>__SurfaceNetworkHandler_InitSurface;
			if (obj == null)
			{
				hook_InitSurface val = SurfaceNetworkHandler_InitSurface;
				<>O.<0>__SurfaceNetworkHandler_InitSurface = val;
				obj = (object)val;
			}
			SurfaceNetworkHandler.InitSurface += (hook_InitSurface)obj;
			object obj2 = <>O.<1>__SurfaceNetworkHandler_NextDay;
			if (obj2 == null)
			{
				hook_NextDay val2 = SurfaceNetworkHandler_NextDay;
				<>O.<1>__SurfaceNetworkHandler_NextDay = val2;
				obj2 = (object)val2;
			}
			SurfaceNetworkHandler.NextDay += (hook_NextDay)obj2;
		}

		private static void SurfaceNetworkHandler_InitSurface(orig_InitSurface orig, SurfaceNetworkHandler self)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Invalid comparison between Unknown and I4
			if (SurfaceNetworkHandler.RoomStats == null)
			{
				KeepCameraAfterDeath.Instance.ClearData();
			}
			KeepCameraAfterDeath.Instance.Debug_InitSurfaceActive = true;
			if (MyceliumNetwork.IsHost && (int)TimeOfDayHandler.TimeOfDay == 10)
			{
				if (KeepCameraAfterDeath.Instance.PreservedCameraInstanceDataForHost != null)
				{
					KeepCameraAfterDeath.Logger.LogInfo((object)"KeepCameraAfterDeath: Found backed-up camera footage");
					self.m_VideoCameraSpawner.SpawnMe(true);
				}
				else
				{
					KeepCameraAfterDeath.Logger.LogInfo((object)"KeepCameraAfterDeath: Could not find camera footage to restore");
					if (KeepCameraAfterDeath.Instance.PlayerSettingEnableRewardForCameraReturn)
					{
						KeepCameraAfterDeath.Instance.SetPendingRewardForAllPlayers();
					}
				}
			}
			orig.Invoke(self);
			if (MyceliumNetwork.IsHost && KeepCameraAfterDeath.Instance.AllowCrewToWatchFootageEvenIfQuotaNotMet && KeepCameraAfterDeath.Instance.IsFinalDayAndQuotaNotMet() && !Player.justDied)
			{
				SpawnHandler.Instance.SpawnLocalPlayer((Spawns)3);
			}
			KeepCameraAfterDeath.Instance.Debug_InitSurfaceActive = false;
		}

		private static void SurfaceNetworkHandler_NextDay(orig_NextDay orig, SurfaceNetworkHandler self)
		{
			if (MyceliumNetwork.IsHost && KeepCameraAfterDeath.Instance.AllowCrewToWatchFootageEvenIfQuotaNotMet && KeepCameraAfterDeath.Instance.IsFinalDayAndQuotaNotMet() && KeepCameraAfterDeath.Instance.Debug_InitSurfaceActive)
			{
				KeepCameraAfterDeath.Logger.LogInfo((object)"KeepCameraAfterDeath: Allow players to watch their video on the final day when they didn't meet quota");
				return;
			}
			KeepCameraAfterDeath.Instance.Command_ResetDataforDay();
			orig.Invoke(self);
		}
	}
	public class VideoCameraPatch
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static hook_ConfigItem <0>__VideoCamera_ConfigItem;
		}

		internal static void Init()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			object obj = <>O.<0>__VideoCamera_ConfigItem;
			if (obj == null)
			{
				hook_ConfigItem val = VideoCamera_ConfigItem;
				<>O.<0>__VideoCamera_ConfigItem = val;
				obj = (object)val;
			}
			VideoCamera.ConfigItem += (hook_ConfigItem)obj;
		}

		private static void VideoCamera_ConfigItem(orig_ConfigItem orig, VideoCamera self, ItemInstanceData data, PhotonView playerView)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Invalid comparison between Unknown and I4
			bool flag = (int)TimeOfDayHandler.TimeOfDay == 10;
			VideoInfoEntry val = default(VideoInfoEntry);
			bool flag2 = !data.TryGetEntry<VideoInfoEntry>(ref val) || val.videoID.id == Guid.Empty;
			bool flag3 = KeepCameraAfterDeath.Instance.PreservedCameraInstanceDataForHost != null;
			VideoInfoEntry val2 = default(VideoInfoEntry);
			if (MyceliumNetwork.IsHost && flag3 && flag && flag2 && KeepCameraAfterDeath.Instance.PreservedCameraInstanceDataForHost.TryGetEntry<VideoInfoEntry>(ref val2) && val2.videoID.id != Guid.Empty)
			{
				ManualLogSource logger = KeepCameraAfterDeath.Logger;
				Guid id = val2.videoID.id;
				logger.LogInfo((object)("KeepCameraAfterDeath: Restore camera footage: " + id));
				data.AddDataEntry((ItemDataEntry)(object)val2);
				KeepCameraAfterDeath.Instance.ClearPreservedCameraInstanceDataForHost();
			}
			orig.Invoke(self, data, playerView);
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}