Decompiled source of SpikeTrapFixes v1.2.0

SpikeTrapFixes.dll

Decompiled 2 weeks ago
using System;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using STFixes.Patches;
using Unity.Collections;
using Unity.Netcode;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("Fixes Spike Traps")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("SpikeTrapFixes")]
[assembly: AssemblyCopyright("Spookybuddy 2024")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("28f2f16b-6471-4c7e-b0a4-007e3a2450d4")]
[assembly: AssemblyFileVersion("1.1.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.1.0.0")]
namespace STFixes
{
	internal class ConfigControl : SyncedInstance<ConfigControl>
	{
		public ConfigEntry<bool> cfgModEnabled;

		public ConfigEntry<bool> cfgSTEnabled;

		public ConfigEntry<STFixModBase.EnumOptions> cfgTypes;

		public ConfigEntry<bool> cfgClamp;

		public ConfigEntry<float> cfgMin;

		public ConfigEntry<float> cfgMax;

		public ConfigEntry<bool> cfgScan;

		public ConfigEntry<bool> cfgMove;

		public ConfigEntry<int> cfgRange;

		internal bool Mod
		{
			get
			{
				if (cfgModEnabled.Value)
				{
					return true;
				}
				return false;
			}
			set
			{
				cfgModEnabled.Value = value;
			}
		}

		internal bool Traps
		{
			get
			{
				if (cfgSTEnabled.Value)
				{
					return true;
				}
				return false;
			}
			set
			{
				cfgSTEnabled.Value = value;
			}
		}

		internal STFixModBase.EnumOptions Types
		{
			get
			{
				if (cfgTypes == null)
				{
					return (STFixModBase.EnumOptions)((ConfigEntryBase)cfgTypes).DefaultValue;
				}
				return cfgTypes.Value;
			}
			set
			{
				cfgTypes.Value = value;
			}
		}

		internal bool Clamp
		{
			get
			{
				if (cfgClamp.Value)
				{
					return true;
				}
				return false;
			}
			set
			{
				cfgClamp.Value = value;
			}
		}

		internal float Minimum
		{
			get
			{
				if (cfgMin.Value > 0.7f)
				{
					return cfgMin.Value;
				}
				return (float)((ConfigEntryBase)cfgMin).DefaultValue;
			}
			set
			{
				cfgMin.Value = value;
			}
		}

		internal float Maximum
		{
			get
			{
				if (cfgMax.Value > cfgMin.Value)
				{
					return cfgMax.Value;
				}
				return (float)((ConfigEntryBase)cfgMax).DefaultValue;
			}
			set
			{
				cfgMax.Value = value;
			}
		}

		internal bool Scans
		{
			get
			{
				if (cfgScan.Value)
				{
					return true;
				}
				return false;
			}
			set
			{
				cfgScan.Value = value;
			}
		}

		internal bool Move
		{
			get
			{
				if (cfgMove.Value)
				{
					return true;
				}
				return false;
			}
			set
			{
				cfgMove.Value = value;
			}
		}

		internal int ScanRange
		{
			get
			{
				if (cfgRange.Value > 1)
				{
					return cfgRange.Value;
				}
				return (int)((ConfigEntryBase)cfgRange).DefaultValue;
			}
			set
			{
				cfgRange.Value = value;
			}
		}

		public ConfigControl(ConfigFile cfg)
		{
			InitInstance(this);
			cfgModEnabled = cfg.Bind<bool>("Enabled", "Mod Enabled", true, "Turn the mod on.");
			cfgSTEnabled = cfg.Bind<bool>("Enabled", "Traps Enabled", true, "When disabled turns the spike traps into harmless decor.");
			cfgTypes = cfg.Bind<STFixModBase.EnumOptions>("Enabled", "Trap types", STFixModBase.EnumOptions.Both, "What types of traps should spawn.");
			cfgClamp = cfg.Bind<bool>("Clamp", "Enabled", true, "Enable the slam rate limits listed below. \n\nWhen disabled the spike traps will use the values they spawned with.");
			cfgMin = cfg.Bind<float>("Clamp", "Minimum", 1.5f, "The fastest slam interval. \n\nBase game's quickest possible is 0.71 sec.");
			cfgMax = cfg.Bind<float>("Clamp", "Maximum", 25f, "The slowest slam interval. \n\nBase game's slowest possible is 26.15 sec.");
			cfgScan = cfg.Bind<bool>("Scan Node", "Enabled", true, "Add a scanable node to the spike traps, similar to landmines and turrets. \n\nBase game does not have a scan node.");
			cfgMove = cfg.Bind<bool>("Scan Node", "Move with spikes", true, "The scan node will move with the spikes. Otherwise it will remain in a fixed position.");
			cfgRange = cfg.Bind<int>("Scan Node", "Range", 9, "The max distance the scan node can be scanned.");
		}
	}
	[BepInPlugin("SpikeTrapFixes", "SpikeTrapFixes", "1.2.0")]
	public class STFixModBase : BaseUnityPlugin
	{
		internal enum EnumOptions
		{
			IntervalOnly,
			DetectionOnly,
			Both
		}

		public const string modGUID = "SpikeTrapFixes";

		private const string modName = "SpikeTrapFixes";

		private const string modVersion = "1.2.0";

		private readonly Harmony harmony = new Harmony("SpikeTrapFixes");

		internal ConfigControl Configuration;

		internal static STFixModBase Instance;

		internal static ManualLogSource mls;

		internal static AudioClip soundFix;

		private void Awake()
		{
			if ((Object)(object)Instance == (Object)null)
			{
				Instance = this;
			}
			mls = Logger.CreateLogSource("SpikeTrapFixes");
			string[] files = Directory.GetFiles(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location), "spiketrapfix.bundle");
			if (files != null && files.Length != 0 && files[0] != null)
			{
				AssetBundle val = AssetBundle.LoadFromFile(Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location), files[0]));
				if ((Object)(object)val != (Object)null)
				{
					soundFix = val.LoadAllAssets<AudioClip>()[0];
				}
				else
				{
					val.Unload(true);
				}
			}
			if ((Object)(object)soundFix != (Object)null)
			{
				mls.LogInfo((object)"Spike trap audio fix loaded.");
			}
			else
			{
				mls.LogWarning((object)"Spike trap audio fix not found.");
			}
			Configuration = new ConfigControl(((BaseUnityPlugin)this).Config);
			harmony.PatchAll(typeof(STFixModBase));
			harmony.PatchAll(typeof(SpikeRoofTrapPatch));
			harmony.PatchAll(typeof(ConfigControl));
			mls.LogInfo((object)"Spike Trap Fixes was loaded.");
		}
	}
	[Serializable]
	public class SyncedInstance<T>
	{
		[NonSerialized]
		protected static int IntSize = 4;

		internal static CustomMessagingManager MessageManager => NetworkManager.Singleton.CustomMessagingManager;

		internal static bool IsClient => NetworkManager.Singleton.IsClient;

		internal static bool IsHost => NetworkManager.Singleton.IsHost;

		public static T Default { get; private set; }

		public static T Instance { get; private set; }

		public static bool Synced { get; internal set; }

		protected void InitInstance(T instance)
		{
			Default = instance;
			Instance = instance;
			IntSize = 4;
		}

		internal static void SyncInstance(byte[] data)
		{
			Instance = DeserializeFromBytes(data);
			Synced = true;
		}

		internal static void RevertSync()
		{
			Instance = Default;
			Synced = false;
		}

		public static byte[] SerializeToBytes(T val)
		{
			BinaryFormatter binaryFormatter = new BinaryFormatter();
			MemoryStream memoryStream = new MemoryStream();
			try
			{
				binaryFormatter.Serialize(memoryStream, val);
				return memoryStream.ToArray();
			}
			catch (Exception arg)
			{
				STFixModBase.mls.LogError((object)$"Error serializing instance: {arg}");
				return null;
			}
		}

		public static T DeserializeFromBytes(byte[] data)
		{
			BinaryFormatter binaryFormatter = new BinaryFormatter();
			MemoryStream serializationStream = new MemoryStream(data);
			try
			{
				return (T)binaryFormatter.Deserialize(serializationStream);
			}
			catch (Exception arg)
			{
				STFixModBase.mls.LogError((object)$"Error deserializing instance: {arg}");
				return default(T);
			}
		}

		public static void RequestSync()
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			if (IsClient)
			{
				FastBufferWriter val = default(FastBufferWriter);
				((FastBufferWriter)(ref val))..ctor(IntSize, (Allocator)2, -1);
				MessageManager.SendNamedMessage("SpikeTrapFixes_OnRequestConfigSync", 0uL, val, (NetworkDelivery)3);
			}
		}

		public static void OnRequestSync(ulong clientId, FastBufferReader _)
		{
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			if (!IsHost)
			{
				return;
			}
			STFixModBase.mls.LogInfo((object)$"Config sync request received from client: {clientId}");
			byte[] array = SerializeToBytes(Instance);
			int num = array.Length;
			FastBufferWriter val = default(FastBufferWriter);
			((FastBufferWriter)(ref val))..ctor(num + IntSize, (Allocator)2, -1);
			try
			{
				((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref num, default(ForPrimitives));
				((FastBufferWriter)(ref val)).WriteBytesSafe(array, -1, 0);
				MessageManager.SendNamedMessage("SpikeTrapFixes_OnReceiveConfigSync", clientId, val, (NetworkDelivery)3);
			}
			catch (Exception arg)
			{
				STFixModBase.mls.LogInfo((object)$"Error occurred syncing config with client: {clientId}\n{arg}");
			}
		}

		public static void OnReceiveSync(ulong _, FastBufferReader reader)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			if (!((FastBufferReader)(ref reader)).TryBeginRead(IntSize))
			{
				STFixModBase.mls.LogError((object)"Config sync error: Could not begin reading buffer.");
				return;
			}
			int num = default(int);
			((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref num, default(ForPrimitives));
			if (!((FastBufferReader)(ref reader)).TryBeginRead(num))
			{
				STFixModBase.mls.LogError((object)"Config sync error: Host could not sync.");
				return;
			}
			byte[] data = new byte[num];
			((FastBufferReader)(ref reader)).ReadBytesSafe(ref data, num, 0);
			SyncInstance(data);
			STFixModBase.mls.LogInfo((object)"Successfully synced config with host.");
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(GameNetworkManager), "SteamMatchmaking_OnLobbyMemberJoined")]
		public static void InitializeLocalPlayer()
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Expected O, but got Unknown
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Expected O, but got Unknown
			if (IsHost)
			{
				MessageManager.RegisterNamedMessageHandler("SpikeTrapFixes_OnRequestConfigSync", new HandleNamedMessageDelegate(OnRequestSync));
				Synced = true;
			}
			else
			{
				Synced = false;
				MessageManager.RegisterNamedMessageHandler("SpikeTrapFixes_OnReceiveConfigSync", new HandleNamedMessageDelegate(OnReceiveSync));
				RequestSync();
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(GameNetworkManager), "StartDisconnect")]
		public static void PlayerLeave()
		{
			SyncedInstance<ConfigControl>.RevertSync();
		}
	}
}
namespace STFixes.Patches
{
	[HarmonyPatch(typeof(SpikeRoofTrap))]
	internal class SpikeRoofTrapPatch
	{
		internal static readonly Vector3 moving = new Vector3(-0.48f, 0f, -0.378f);

		internal static readonly Vector3 still = new Vector3(0f, 3f, 1.8f);

		[HarmonyPatch("Start")]
		[HarmonyPrefix]
		private static void BeginningFix(SpikeRoofTrap __instance)
		{
			if (!SyncedInstance<ConfigControl>.Instance.Mod)
			{
				STFixModBase.mls.LogWarning((object)"Mod disabled.");
			}
			else if (!SyncedInstance<ConfigControl>.Instance.Traps)
			{
				Object.Destroy((Object)(object)__instance);
				STFixModBase.mls.LogInfo((object)"Removed script from spike trap.");
			}
			else if ((Object)(object)STFixModBase.soundFix != (Object)null)
			{
				__instance.spikeTrapAudio.loop = false;
				PlayAudioAnimationEvent componentInParent = ((Component)__instance).GetComponentInParent<PlayAudioAnimationEvent>();
				componentInParent.audioClip2 = STFixModBase.soundFix;
				componentInParent.audioClip3 = STFixModBase.soundFix;
			}
		}

		[HarmonyPatch("Start")]
		[HarmonyPostfix]
		private static void StartFix(SpikeRoofTrap __instance, ref float ___slamInterval, ref bool ___slamOnIntervals)
		{
			//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
			if (!SyncedInstance<ConfigControl>.Instance.Mod)
			{
				return;
			}
			if (!SyncedInstance<ConfigControl>.Instance.Traps)
			{
				Object.Destroy((Object)(object)__instance);
				return;
			}
			if (!SyncedInstance<ConfigControl>.Instance.Types.Equals(STFixModBase.EnumOptions.Both))
			{
				STFixModBase.mls.LogInfo((object)("Changing trap to " + SyncedInstance<ConfigControl>.Instance.Types));
				___slamOnIntervals = SyncedInstance<ConfigControl>.Instance.Types.Equals(STFixModBase.EnumOptions.IntervalOnly);
			}
			if (SyncedInstance<ConfigControl>.Instance.Clamp && !SyncedInstance<ConfigControl>.Instance.Types.Equals(STFixModBase.EnumOptions.DetectionOnly))
			{
				if (___slamInterval < SyncedInstance<ConfigControl>.Instance.Minimum)
				{
					STFixModBase.mls.LogInfo((object)$"Raised interval from {___slamInterval} sec to {SyncedInstance<ConfigControl>.Instance.Minimum} sec.");
				}
				if (___slamInterval > SyncedInstance<ConfigControl>.Instance.Maximum)
				{
					STFixModBase.mls.LogInfo((object)$"Lowered interval from {___slamInterval} sec to {SyncedInstance<ConfigControl>.Instance.Maximum} sec.");
				}
				___slamInterval = Mathf.Clamp(___slamInterval, SyncedInstance<ConfigControl>.Instance.Minimum, SyncedInstance<ConfigControl>.Instance.Maximum);
			}
			if (SyncedInstance<ConfigControl>.Instance.Scans)
			{
				GameObject val = GameObject.CreatePrimitive((PrimitiveType)3);
				if (SyncedInstance<ConfigControl>.Instance.Move)
				{
					val.transform.parent = __instance.stickingPointsContainer;
					val.transform.localPosition = moving;
				}
				else
				{
					val.transform.parent = __instance.laserEye;
					val.transform.localPosition = still;
				}
				val.tag = "DoNotSet";
				val.layer = 22;
				Object.Destroy((Object)(object)val.GetComponent<MeshFilter>());
				Object.Destroy((Object)(object)val.GetComponent<MeshRenderer>());
				ScanNodeProperties val2 = val.AddComponent<ScanNodeProperties>();
				val2.maxRange = SyncedInstance<ConfigControl>.Instance.ScanRange;
				val2.minRange = 1;
				val2.requiresLineOfSight = true;
				val2.headerText = "Spike Trap";
				val2.subText = "";
				val2.scrapValue = 0;
				val2.creatureScanID = -1;
				val2.nodeType = 1;
				STFixModBase.mls.LogInfo((object)"Added scan node to spike trap.");
			}
		}

		[HarmonyPatch("ToggleSpikesEnabledLocalClient")]
		[HarmonyPostfix]
		private static void EnableFix(SpikeRoofTrap __instance, bool enabled)
		{
			((Component)((Component)__instance).transform.parent.GetChild(3)).gameObject.SetActive(enabled);
		}
	}
}