Decompiled source of BetterLadders v1.4.3

BetterLadders.dll

Decompiled 4 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using BetterLadders;
using BetterLadders.Patches;
using GameNetcodeStuff;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using Unity.Collections;
using Unity.Netcode;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("AmazingAssets.TerrainToMesh")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp-firstpass")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: IgnoresAccessChecksTo("ClientNetworkTransform")]
[assembly: IgnoresAccessChecksTo("DissonanceVoip")]
[assembly: IgnoresAccessChecksTo("Facepunch Transport for Netcode for GameObjects")]
[assembly: IgnoresAccessChecksTo("Facepunch.Steamworks.Win64")]
[assembly: IgnoresAccessChecksTo("Unity.AI.Navigation")]
[assembly: IgnoresAccessChecksTo("Unity.Animation.Rigging")]
[assembly: IgnoresAccessChecksTo("Unity.Animation.Rigging.DocCodeExamples")]
[assembly: IgnoresAccessChecksTo("Unity.Burst")]
[assembly: IgnoresAccessChecksTo("Unity.Burst.Unsafe")]
[assembly: IgnoresAccessChecksTo("Unity.Collections")]
[assembly: IgnoresAccessChecksTo("Unity.Collections.LowLevel.ILSupport")]
[assembly: IgnoresAccessChecksTo("Unity.InputSystem")]
[assembly: IgnoresAccessChecksTo("Unity.InputSystem.ForUI")]
[assembly: IgnoresAccessChecksTo("Unity.Jobs")]
[assembly: IgnoresAccessChecksTo("Unity.Mathematics")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.Common")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.MetricTypes")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStats")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Component")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Configuration")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Implementation")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsReporting")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetworkProfiler.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetworkSolutionInterface")]
[assembly: IgnoresAccessChecksTo("Unity.Netcode.Components")]
[assembly: IgnoresAccessChecksTo("Unity.Netcode.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.Networking.Transport")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Csg")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder.KdTree")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Poly2Tri")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Stl")]
[assembly: IgnoresAccessChecksTo("Unity.Profiling.Core")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.ShaderLibrary")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.HighDefinition.Config.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.HighDefinition.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.ShaderGraph.ShaderGraphLibrary")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Authentication")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Analytics")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Configuration")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Device")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Environments")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Environments.Internal")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Internal")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Networking")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Registration")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Scheduler")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Telemetry")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Threading")]
[assembly: IgnoresAccessChecksTo("Unity.Services.QoS")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Relay")]
[assembly: IgnoresAccessChecksTo("Unity.TextMeshPro")]
[assembly: IgnoresAccessChecksTo("Unity.Timeline")]
[assembly: IgnoresAccessChecksTo("Unity.VisualEffectGraph.Runtime")]
[assembly: IgnoresAccessChecksTo("UnityEngine.ARModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.NVIDIAModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.UI")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("BetterLadders")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyDescription("Configurable climbing speed, extension ladder time, and climbing with two-handed items")]
[assembly: AssemblyFileVersion("1.4.3.0")]
[assembly: AssemblyInformationalVersion("1.4.3+ec9e47752cb829c5e645f0727a36b300d0a848f1")]
[assembly: AssemblyProduct("BetterLadders")]
[assembly: AssemblyTitle("BetterLadders")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.4.3.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
[Serializable]
public class SyncedInstance<T>
{
	[CompilerGenerated]
	private static class <>O
	{
		public static HandleNamedMessageDelegate <0>__OnRequestSync;

		public static HandleNamedMessageDelegate <1>__OnRequestHideItem;

		public static HandleNamedMessageDelegate <2>__OnReceiveHideItem;

		public static HandleNamedMessageDelegate <3>__OnReceiveSync;
	}

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

	internal static Harmony harmony => Plugin.Instance.harmony;

	public static T Default { get; private set; }

	public static T Instance { get; private set; }

	public static bool SyncedPatchesApplied { 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();
		using MemoryStream memoryStream = new MemoryStream();
		try
		{
			binaryFormatter.Serialize(memoryStream, val);
			return memoryStream.ToArray();
		}
		catch (Exception arg)
		{
			Plugin.Logger.LogError((object)$"Error serializing instance: {arg}");
			return null;
		}
	}

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

	public static void RequestSync()
	{
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		if (!IsClient)
		{
			return;
		}
		FastBufferWriter val = default(FastBufferWriter);
		((FastBufferWriter)(ref val))..ctor(IntSize, (Allocator)2, -1);
		try
		{
			MessageManager.SendNamedMessage("BetterLadders_OnRequestConfigSync", 0uL, val, (NetworkDelivery)3);
			Plugin.Logger.LogInfo((object)"Requested sync from server");
		}
		finally
		{
			((IDisposable)(FastBufferWriter)(ref val)).Dispose();
		}
	}

	public static void OnRequestSync(ulong clientId, FastBufferReader _)
	{
		//IL_0047: Unknown result type (might be due to invalid IL or missing references)
		//IL_004d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0068: Unknown result type (might be due to invalid IL or missing references)
		if (!IsHost)
		{
			return;
		}
		Plugin.Logger.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("BetterLadders_OnReceiveConfigSync", clientId, val, (NetworkDelivery)3);
		}
		catch (Exception arg)
		{
			Plugin.Logger.LogInfo((object)$"Error occurred syncing config with client: {clientId}\n{arg}");
		}
		finally
		{
			((IDisposable)(FastBufferWriter)(ref val)).Dispose();
		}
	}

	public static void OnReceiveSync(ulong _, FastBufferReader reader)
	{
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		//IL_002a: Unknown result type (might be due to invalid IL or missing references)
		if (!((FastBufferReader)(ref reader)).TryBeginRead(IntSize))
		{
			Plugin.Logger.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))
		{
			Plugin.Logger.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);
		Plugin.Logger.LogInfo((object)"Successfully synced config with host.");
	}

	public static void RequestHideItem(bool enabled)
	{
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		FastBufferWriter val = default(FastBufferWriter);
		((FastBufferWriter)(ref val))..ctor(1 + IntSize, (Allocator)2, -1);
		try
		{
			((FastBufferWriter)(ref val)).WriteValueSafe<bool>(ref enabled, default(ForPrimitives));
			MessageManager.SendNamedMessage("BetterLadders_OnRequestHideItem", 0uL, val, (NetworkDelivery)3);
			if (GameNetworkManager.Instance.localPlayerController.playerClientId != 0L)
			{
				Plugin.Logger.LogInfo((object)("Requested server to " + (enabled ? "show" : "hide") + " this client's held item"));
			}
		}
		finally
		{
			((IDisposable)(FastBufferWriter)(ref val)).Dispose();
		}
	}

	public static void OnRequestHideItem(ulong clientId, FastBufferReader reader)
	{
		//IL_0028: Unknown result type (might be due to invalid IL or missing references)
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0068: 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_007a: 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_0090: Unknown result type (might be due to invalid IL or missing references)
		if (!IsHost)
		{
			return;
		}
		if (!((FastBufferReader)(ref reader)).TryBeginRead(1))
		{
			Plugin.Logger.LogError((object)"Hide item error: Could not begin reading buffer.");
			return;
		}
		bool flag = default(bool);
		((FastBufferReader)(ref reader)).ReadValueSafe<bool>(ref flag, default(ForPrimitives));
		if (clientId != 0L)
		{
			Plugin.Logger.LogInfo((object)$"Hide item request received from client: {clientId}");
		}
		FastBufferWriter val = default(FastBufferWriter);
		((FastBufferWriter)(ref val))..ctor(9 + IntSize, (Allocator)2, -1);
		try
		{
			((FastBufferWriter)(ref val)).WriteValueSafe<ulong>(ref clientId, default(ForPrimitives));
			((FastBufferWriter)(ref val)).WriteValueSafe<bool>(ref flag, default(ForPrimitives));
			MessageManager.SendNamedMessageToAll("BetterLadders_OnReceiveHideItem", val, (NetworkDelivery)3);
		}
		finally
		{
			((IDisposable)(FastBufferWriter)(ref val)).Dispose();
		}
	}

	public static void OnReceiveHideItem(ulong _, FastBufferReader reader)
	{
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0031: Unknown result type (might be due to invalid IL or missing references)
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		if (!((FastBufferReader)(ref reader)).TryBeginRead(9))
		{
			Plugin.Logger.LogError((object)"Hide item error: Could not begin reading buffer.");
			return;
		}
		ulong requestingClientId = default(ulong);
		((FastBufferReader)(ref reader)).ReadValueSafe<ulong>(ref requestingClientId, default(ForPrimitives));
		bool flag = default(bool);
		((FastBufferReader)(ref reader)).ReadValueSafe<bool>(ref flag, default(ForPrimitives));
		if (GameNetworkManager.Instance.localPlayerController.playerClientId == requestingClientId)
		{
			return;
		}
		PlayerControllerB val = ((IEnumerable<PlayerControllerB>)Object.FindObjectsOfType<PlayerControllerB>()).FirstOrDefault((Func<PlayerControllerB, bool>)((PlayerControllerB player) => player.playerClientId == requestingClientId));
		if ((Object)(object)val != (Object)null)
		{
			if ((val.twoHanded && SyncedInstance<Config>.Default.hideTwoHanded) || (!val.twoHanded && SyncedInstance<Config>.Default.hideOneHanded))
			{
				val.currentlyHeldObjectServer.EnableItemMeshes(flag);
				Plugin.Logger.LogInfo((object)string.Format("Successfully {0} client {1}'s held item.", flag ? "showed" : "hid", requestingClientId));
			}
		}
		else
		{
			Plugin.Logger.LogError((object)$"Failed to find client with id {requestingClientId}.");
		}
	}

	[HarmonyPostfix]
	[HarmonyPatch(typeof(GameNetworkManager), "StartDisconnect")]
	public static void PlayerLeave()
	{
		SyncedInstance<Config>.RevertSync();
		if (SyncedPatchesApplied)
		{
			Plugin.Logger.LogInfo((object)"Unpatching transpilers");
			Plugin.Instance.UnpatchSyncedTranspilers();
			SyncedPatchesApplied = false;
		}
	}

	[HarmonyPostfix]
	[HarmonyPatch(typeof(PlayerControllerB), "ConnectClientToPlayerObject")]
	public static void InitializeLocalPlayer()
	{
		//IL_00af: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ba: Expected O, but got Unknown
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_002f: Expected O, but got Unknown
		//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00de: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e4: Expected O, but got Unknown
		//IL_004e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0053: Unknown result type (might be due to invalid IL or missing references)
		//IL_0059: Expected O, but got Unknown
		//IL_0078: Unknown result type (might be due to invalid IL or missing references)
		//IL_007d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0083: Expected O, but got Unknown
		if (IsHost)
		{
			CustomMessagingManager messageManager = SyncedInstance<Config>.MessageManager;
			object obj = <>O.<0>__OnRequestSync;
			if (obj == null)
			{
				HandleNamedMessageDelegate val = SyncedInstance<Config>.OnRequestSync;
				<>O.<0>__OnRequestSync = val;
				obj = (object)val;
			}
			messageManager.RegisterNamedMessageHandler("BetterLadders_OnRequestConfigSync", (HandleNamedMessageDelegate)obj);
			CustomMessagingManager messageManager2 = SyncedInstance<Config>.MessageManager;
			object obj2 = <>O.<1>__OnRequestHideItem;
			if (obj2 == null)
			{
				HandleNamedMessageDelegate val2 = SyncedInstance<Config>.OnRequestHideItem;
				<>O.<1>__OnRequestHideItem = val2;
				obj2 = (object)val2;
			}
			messageManager2.RegisterNamedMessageHandler("BetterLadders_OnRequestHideItem", (HandleNamedMessageDelegate)obj2);
			CustomMessagingManager messageManager3 = SyncedInstance<Config>.MessageManager;
			object obj3 = <>O.<2>__OnReceiveHideItem;
			if (obj3 == null)
			{
				HandleNamedMessageDelegate val3 = SyncedInstance<Config>.OnReceiveHideItem;
				<>O.<2>__OnReceiveHideItem = val3;
				obj3 = (object)val3;
			}
			messageManager3.RegisterNamedMessageHandler("BetterLadders_OnReceiveHideItem", (HandleNamedMessageDelegate)obj3);
			SyncedInstance<Config>.Synced = true;
		}
		else
		{
			SyncedInstance<Config>.Synced = false;
			CustomMessagingManager messageManager4 = SyncedInstance<Config>.MessageManager;
			object obj4 = <>O.<3>__OnReceiveSync;
			if (obj4 == null)
			{
				HandleNamedMessageDelegate val4 = SyncedInstance<Config>.OnReceiveSync;
				<>O.<3>__OnReceiveSync = val4;
				obj4 = (object)val4;
			}
			messageManager4.RegisterNamedMessageHandler("BetterLadders_OnReceiveConfigSync", (HandleNamedMessageDelegate)obj4);
			CustomMessagingManager messageManager5 = SyncedInstance<Config>.MessageManager;
			object obj5 = <>O.<2>__OnReceiveHideItem;
			if (obj5 == null)
			{
				HandleNamedMessageDelegate val5 = SyncedInstance<Config>.OnReceiveHideItem;
				<>O.<2>__OnReceiveHideItem = val5;
				obj5 = (object)val5;
			}
			messageManager5.RegisterNamedMessageHandler("BetterLadders_OnReceiveHideItem", (HandleNamedMessageDelegate)obj5);
			SyncedInstance<Config>.RequestSync();
		}
	}

	[HarmonyPostfix]
	[HarmonyPatch(typeof(StartMatchLever), "PullLeverAnim")]
	private static void PostSyncOrNoResponse()
	{
		if (!IsHost && !SyncedInstance<Config>.Synced && !SyncedInstance<Config>.Default.hostMissingMod)
		{
			Plugin.Logger.LogInfo((object)"Config wasn't synced with host (likely doesn't have mod), setting vanilla config defaults");
			SyncedInstance<Config>.Instance.SetVanillaDefaults();
		}
		Plugin.Logger.LogInfo((object)"All config syncing operations finished, starting synced patches");
		if (!SyncedPatchesApplied)
		{
			Plugin.Instance.PatchSyncedTranspilers();
			SyncedPatchesApplied = true;
		}
	}
}
namespace BetterLadders
{
	[Serializable]
	public class Config : SyncedInstance<Config>
	{
		public float climbSpeedMultiplier { get; internal set; }

		public float sprintingClimbSpeedMultiplier { get; internal set; }

		public float transitionSpeedMultiplier { get; internal set; }

		public bool allowTwoHanded { get; internal set; }

		public bool scaleAnimationSpeed { get; internal set; }

		public bool hideOneHanded { get; internal set; }

		public bool hideTwoHanded { get; internal set; }

		public float timeMultiplier { get; internal set; }

		public bool enableKillTrigger { get; internal set; }

		public bool holdToPickup { get; internal set; }

		public float holdTime { get; internal set; }

		public bool debugMode { get; internal set; }

		public bool hostMissingMod { get; internal set; }

		internal Config(ConfigFile cfg)
		{
			InitInstance(this);
			climbSpeedMultiplier = cfg.Bind<float>("General", "climbSpeedMultipler", 1f, "Ladder climb speed multiplier").Value;
			sprintingClimbSpeedMultiplier = cfg.Bind<float>("General", "sprintingClimbSpeedMultiplier", 1.5f, "Ladder climb speed multiplier while sprinting, stacks with climbSpeedMultiplier").Value;
			transitionSpeedMultiplier = cfg.Bind<float>("General", "transitionSpeedMultiplier", 1f, "Ladder entrance animation speed multiplier").Value;
			allowTwoHanded = cfg.Bind<bool>("General", "allowTwoHanded", true, "Whether to allow using ladders while carrying a two-handed object").Value;
			scaleAnimationSpeed = cfg.Bind<bool>("General", "scaleAnimationSpeed", true, "Whether to scale the speed of the climbing animation to the climbing speed").Value;
			hideOneHanded = cfg.Bind<bool>("General", "hideOneHanded", true, "Whether to hide one-handed items while climbing a ladder - false in vanilla").Value;
			hideTwoHanded = cfg.Bind<bool>("General", "hideTwoHanded", true, "Whether to hide two-handed items while climbing a ladder").Value;
			timeMultiplier = cfg.Bind<float>("Extension Ladders", "timeMultiplier", 0f, "Extension ladder time multiplier (0 for permanent) - lasts 20 seconds in vanilla").Value;
			enableKillTrigger = cfg.Bind<bool>("Extension Ladders", "enableKillTrigger", true, "Whether extension ladders should kill players they land on").Value;
			holdToPickup = cfg.Bind<bool>("Extension Ladders", "holdToPickup", true, "Whether the interact key needs to be held to pick up an activated extension ladder").Value;
			holdTime = cfg.Bind<float>("Extension Ladders", "holdTime", 0.5f, "How long, in seconds, the interact key must be held if holdToPickup is true").Value;
			debugMode = cfg.Bind<bool>("Debug", "debugMode", false, "Displays debug messages in the BepInEx console if true").Value;
			hostMissingMod = false;
		}

		internal void SetVanillaDefaults()
		{
			SyncedInstance<Config>.Instance.climbSpeedMultiplier = 1f;
			SyncedInstance<Config>.Instance.sprintingClimbSpeedMultiplier = 1f;
			SyncedInstance<Config>.Instance.transitionSpeedMultiplier = 1f;
			SyncedInstance<Config>.Instance.allowTwoHanded = false;
			SyncedInstance<Config>.Instance.timeMultiplier = 1f;
			SyncedInstance<Config>.Instance.enableKillTrigger = true;
			hostMissingMod = true;
		}
	}
	[BepInPlugin("e3s1.BetterLadders", "BetterLadders", "1.4.3")]
	public class Plugin : BaseUnityPlugin
	{
		public static Plugin Instance;

		internal readonly Harmony harmony = new Harmony("e3s1.BetterLadders");

		public const string GUID = "e3s1.BetterLadders";

		public const string NAME = "BetterLadders";

		public const string VERSION = "1.4.3";

		internal static ManualLogSource Logger { get; private set; }

		public static Config Config { get; internal set; }

		private void Awake()
		{
			Instance = this;
			Logger = ((BaseUnityPlugin)this).Logger;
			Config = new Config(((BaseUnityPlugin)this).Config);
			harmony.PatchAll(typeof(SyncedInstance<Config>));
			harmony.PatchAll(typeof(AllowTwoHanded));
			harmony.PatchAll(typeof(ClimbSpeed));
			harmony.PatchAll(typeof(HideItems));
			harmony.PatchAll(typeof(HoverTip));
			if (SyncedInstance<Config>.Default.holdToPickup)
			{
				harmony.PatchAll(typeof(HoldToPickup));
			}
			Logger.LogInfo((object)"BetterLadders loaded");
		}

		internal void PatchSyncedTranspilers()
		{
			harmony.PatchAll(typeof(ExtLadderTime));
			harmony.PatchAll(typeof(KillTrigger));
			harmony.PatchAll(typeof(TransitionSpeed));
		}

		internal void UnpatchSyncedTranspilers()
		{
			harmony.Unpatch((MethodBase)AccessTools.Method(typeof(ExtensionLadderItem), "Update", (Type[])null, (Type[])null), (HarmonyPatchType)3, harmony.Id);
			harmony.Unpatch((MethodBase)AccessTools.Method(typeof(ExtensionLadderItem), "LadderAnimation", (Type[])null, (Type[])null), (HarmonyPatchType)3, harmony.Id);
			harmony.Unpatch((MethodBase)AccessTools.Method(typeof(InteractTrigger), "ladderClimbAnimation", (Type[])null, (Type[])null), (HarmonyPatchType)3, harmony.Id);
		}

		internal void TranspilerLogger(List<CodeInstruction> code, int i, int startRelative, int endRelative, string name)
		{
			if (SyncedInstance<Config>.Instance.debugMode)
			{
				Logger.LogInfo((object)("Found code match in " + name));
				for (int j = startRelative; j < endRelative; j++)
				{
					Logger.LogInfo((object)code[i + j]);
				}
				Logger.LogInfo((object)"============================================================");
			}
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "BetterLadders";

		public const string PLUGIN_NAME = "BetterLadders";

		public const string PLUGIN_VERSION = "1.4.3";
	}
}
namespace BetterLadders.Patches
{
	internal class AllowTwoHanded
	{
		[HarmonyPrefix]
		[HarmonyPatch(typeof(PlayerControllerB), "Interact_performed")]
		private static void LadderTwoHandedAccessPatch(ref InteractTrigger ___hoveringOverTrigger, ref bool ___twoHanded)
		{
			if ((SyncedInstance<Config>.Instance.allowTwoHanded && (Object)(object)___hoveringOverTrigger != (Object)null && ___hoveringOverTrigger.isLadder) & ___twoHanded)
			{
				___hoveringOverTrigger.twoHandedItemAllowed = true;
				___hoveringOverTrigger.specialCharacterAnimation = false;
			}
		}
	}
	internal class ClimbSpeed
	{
		[HarmonyPostfix]
		[HarmonyPatch(typeof(PlayerControllerB), "Update")]
		private static void LadderClimbSpeedPatch(ref bool ___isSprinting, ref float ___climbSpeed, ref bool ___isClimbingLadder, ref PlayerControllerB __instance)
		{
			if (!___isClimbingLadder)
			{
				return;
			}
			float num = (___climbSpeed = 4f * SyncedInstance<Config>.Instance.climbSpeedMultiplier * (___isSprinting ? SyncedInstance<Config>.Instance.sprintingClimbSpeedMultiplier : 1f));
			if (__instance.moveInputVector.y != 0f && SyncedInstance<Config>.Instance.scaleAnimationSpeed)
			{
				float num2 = num / 4f * ((__instance.moveInputVector.y > 0f) ? 1f : (-1f));
				if (__instance.currentAnimationSpeed != num2)
				{
					__instance.previousAnimationSpeed = num2;
					__instance.currentAnimationSpeed = num2;
					Plugin.Logger.LogInfo((object)$"Setting animationSpeed to {num2}");
					__instance.playerBodyAnimator.SetFloat("animationSpeed", num2);
				}
			}
			else if (__instance.moveInputVector.y == 0f && __instance.currentAnimationSpeed != 0f)
			{
				__instance.previousAnimationSpeed = 0f;
				__instance.currentAnimationSpeed = 0f;
				Plugin.Logger.LogInfo((object)"Setting animationSpeed to 0");
				__instance.playerBodyAnimator.SetFloat("animationSpeed", 0f);
			}
		}
	}
	internal class ExtLadderTime
	{
		[HarmonyTranspiler]
		[HarmonyPatch(typeof(ExtensionLadderItem), "Update")]
		private static IEnumerable<CodeInstruction> ExtLadderTimeTranspiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Expected O, but got Unknown
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Expected O, but got Unknown
			//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b7: Expected O, but got Unknown
			Plugin.Logger.LogInfo((object)"Starting ExtLadderTimeTranspiler");
			List<CodeInstruction> list = new List<CodeInstruction>(instructions);
			if (SyncedInstance<Config>.Instance.timeMultiplier < 0f)
			{
				Plugin.Logger.LogWarning((object)"timeMultiplier is set to a negative value, not changing extension ladder time");
				return list;
			}
			if (SyncedInstance<Config>.Instance.timeMultiplier > 0f)
			{
				for (int i = 0; i < list.Count - 1; i++)
				{
					if (list[i].opcode == OpCodes.Ldfld && list[i].operand is FieldInfo fieldInfo && fieldInfo.Name == "ladderTimer" && list[i + 1].opcode == OpCodes.Ldc_R4)
					{
						list.Insert(i + 2, new CodeInstruction(OpCodes.Ldc_R4, (object)SyncedInstance<Config>.Instance.timeMultiplier));
						list.Insert(i + 3, new CodeInstruction(OpCodes.Mul, (object)null));
						Plugin.Instance.TranspilerLogger(list, i, -2, 5, "ExtLadderTime");
					}
				}
				return list;
			}
			if (SyncedInstance<Config>.Instance.timeMultiplier == 0f)
			{
				for (int j = 0; j < list.Count - 5; j++)
				{
					if (list[j].opcode == OpCodes.Ret && list[j + 2].opcode == OpCodes.Ldfld && list[j + 2].operand is FieldInfo fieldInfo2 && fieldInfo2.Name == "ladderAnimationBegun" && list[j + 5].opcode == OpCodes.Ldarg_0)
					{
						list.Insert(j + 4, new CodeInstruction(OpCodes.Ret, (object)null));
						Plugin.Instance.TranspilerLogger(list, j, -2, 6, "ExtLadderTime");
						return list;
					}
				}
				return list;
			}
			return list;
		}
	}
	internal class HideItems
	{
		private static bool hasUsedLadder;

		[HarmonyPostfix]
		[HarmonyPatch(typeof(PlayerControllerB), "SwitchToItemSlot")]
		private static void SetVisibilityOnItemSwitch(ref PlayerControllerB __instance)
		{
			SetVisibility(ref __instance.isClimbingLadder);
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(InteractTrigger), "SetUsingLadderOnLocalClient")]
		private static void SetVisibilityOnStartClimb(ref bool ___usingLadder)
		{
			hasUsedLadder = true;
			SetVisibility(ref ___usingLadder);
		}

		internal static void SetVisibility(ref bool ___usingLadder)
		{
			if (!hasUsedLadder)
			{
				return;
			}
			PlayerControllerB localPlayerController = GameNetworkManager.Instance.localPlayerController;
			if ((Object)(object)localPlayerController.currentlyHeldObjectServer != (Object)null && ((SyncedInstance<Config>.Instance.allowTwoHanded && localPlayerController.twoHanded) || !localPlayerController.twoHanded))
			{
				SyncedInstance<Config>.RequestHideItem(!___usingLadder);
				Plugin.Logger.LogInfo((object)"Sending request to other clients to hide held item");
				if ((localPlayerController.twoHanded && SyncedInstance<Config>.Default.hideTwoHanded) || (!localPlayerController.twoHanded && SyncedInstance<Config>.Default.hideOneHanded))
				{
					Plugin.Logger.LogInfo((object)"Hiding held item");
					localPlayerController.currentlyHeldObjectServer.EnableItemMeshes(!___usingLadder);
					hasUsedLadder = false;
				}
			}
		}
	}
	internal class HoldToPickup
	{
		private static bool canPickupLadder;

		[HarmonyPrefix]
		[HarmonyPatch(typeof(PlayerControllerB), "BeginGrabObject")]
		private static bool ControlExtLadderPickup(ref PlayerControllerB __instance)
		{
			if (LookingAtGrabbableExtLadder(ref __instance, out var _, out var extLadderObj) && (Object)(object)extLadderObj != (Object)null && extLadderObj.ladderActivated)
			{
				if (canPickupLadder)
				{
					canPickupLadder = false;
					return true;
				}
				return false;
			}
			return true;
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(PlayerControllerB), "ClickHoldInteraction")]
		private static void ShowHoldInteractHUD(ref PlayerControllerB __instance)
		{
			if (!Object.op_Implicit((Object)(object)__instance.hoveringOverTrigger))
			{
				RaycastHit hit;
				ExtensionLadderItem extLadderObj;
				if (!IngamePlayerSettings.Instance.playerInput.actions.FindAction("Interact", false).IsPressed())
				{
					HUDManager.Instance.holdFillAmount = 0f;
				}
				else if (LookingAtGrabbableExtLadder(ref __instance, out hit, out extLadderObj) && (Object)(object)extLadderObj != (Object)null && extLadderObj.ladderActivated && HUDManager.Instance.HoldInteractionFill(SyncedInstance<Config>.Default.holdTime, 1f))
				{
					canPickupLadder = true;
					__instance.BeginGrabObject();
				}
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(PlayerControllerB), "StopHoldInteractionOnTrigger")]
		private static bool StopHoldInteractionOnTrigger(ref PlayerControllerB __instance)
		{
			if (LookingAtGrabbableExtLadder(ref __instance, out var _, out var extLadderObj))
			{
				if ((Object)(object)extLadderObj != (Object)null && extLadderObj.ladderActivated)
				{
					if (IngamePlayerSettings.Instance.playerInput.actions.FindAction("Interact", false).IsPressed())
					{
						return false;
					}
					HUDManager.Instance.holdFillAmount = 0f;
				}
				else
				{
					HUDManager.Instance.holdFillAmount = 0f;
				}
			}
			else
			{
				HUDManager.Instance.holdFillAmount = 0f;
			}
			if ((Object)(object)__instance.previousHoveringOverTrigger != (Object)null)
			{
				__instance.previousHoveringOverTrigger.StopInteraction();
			}
			if ((Object)(object)__instance.hoveringOverTrigger != (Object)null)
			{
				__instance.hoveringOverTrigger.StopInteraction();
			}
			return false;
		}

		private static bool LookingAtGrabbableExtLadder(ref PlayerControllerB __instance, out RaycastHit hit, out ExtensionLadderItem extLadderObj)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			Ray val = default(Ray);
			((Ray)(ref val))..ctor(((Component)__instance.gameplayCamera).transform.position, ((Component)__instance.gameplayCamera).transform.forward);
			bool flag = Physics.Raycast(val, ref hit, __instance.grabDistance, __instance.interactableObjectsMask) && ((Component)((RaycastHit)(ref hit)).collider).gameObject.layer != 8;
			if (flag)
			{
				extLadderObj = ((Component)((RaycastHit)(ref hit)).collider).gameObject.GetComponent<ExtensionLadderItem>();
				if (__instance.twoHanded || ((Object)(object)extLadderObj != (Object)null && !((GrabbableObject)extLadderObj).grabbable))
				{
					return false;
				}
			}
			else
			{
				extLadderObj = null;
			}
			return flag;
		}
	}
	internal class HoverTip
	{
		[HarmonyPostfix]
		[HarmonyPatch(typeof(PlayerControllerB), "SetHoverTipAndCurrentInteractTrigger")]
		private static void LadderHandsFullTipPatch(ref PlayerControllerB __instance, ref InteractTrigger ___hoveringOverTrigger, ref bool ___isHoldingInteract, ref bool ___twoHanded)
		{
			if (((SyncedInstance<Config>.Instance.allowTwoHanded && (Object)(object)___hoveringOverTrigger != (Object)null) & ___isHoldingInteract & ___twoHanded) && ___hoveringOverTrigger.isLadder)
			{
				((TMP_Text)__instance.cursorTip).text = ___hoveringOverTrigger.hoverTip.Replace("[LMB]", "[E]");
			}
		}
	}
	internal class KillTrigger
	{
		[HarmonyTranspiler]
		[HarmonyPatch(/*Could not decode attribute arguments.*/)]
		internal static IEnumerable<CodeInstruction> KillTriggerTranspiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Expected O, but got Unknown
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Expected O, but got Unknown
			Plugin.Logger.LogInfo((object)"Starting KillTrigger transpiler");
			List<CodeInstruction> list = new List<CodeInstruction>(instructions);
			for (int i = 0; i < list.Count - 1; i++)
			{
				if (list[i].opcode == OpCodes.Ldfld && list[i].operand is FieldInfo fieldInfo && fieldInfo.Name == "killTrigger" && list[i + 1].opcode == OpCodes.Ldc_I4_1)
				{
					list.Insert(i + 2, new CodeInstruction(OpCodes.Pop, (object)null));
					list.Insert(i + 3, new CodeInstruction(SyncedInstance<Config>.Instance.enableKillTrigger ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0, (object)null));
					Plugin.Instance.TranspilerLogger(list, i, -2, 6, "KillTrigger");
				}
			}
			return list;
		}
	}
	internal class TransitionSpeed
	{
		[HarmonyTranspiler]
		[HarmonyPatch(/*Could not decode attribute arguments.*/)]
		internal static IEnumerable<CodeInstruction> TransitionSpeedTranspiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Expected O, but got Unknown
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Expected O, but got Unknown
			Plugin.Logger.LogInfo((object)"Starting TransitionSpeed transpiler");
			List<CodeInstruction> list = new List<CodeInstruction>(instructions);
			if (SyncedInstance<Config>.Instance.transitionSpeedMultiplier <= 0f)
			{
				Plugin.Logger.LogError((object)$"transitionSpeedMultiplier ({SyncedInstance<Config>.Instance.transitionSpeedMultiplier}) is an invalid value");
				return list;
			}
			for (int i = 0; i < list.Count; i++)
			{
				if (list[i].opcode == OpCodes.Call && list[i].operand is MethodInfo methodInfo && methodInfo.Name == "get_deltaTime")
				{
					list.Insert(i + 1, new CodeInstruction(OpCodes.Ldc_R4, (object)SyncedInstance<Config>.Instance.transitionSpeedMultiplier));
					list.Insert(i + 2, new CodeInstruction(OpCodes.Mul, (object)null));
					Plugin.Instance.TranspilerLogger(list, i, -2, 4, "TransitionSpeed");
				}
			}
			return list;
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}