Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of BetterLadders v1.5.0
e3s1.BetterLadders.dll
Decompiled 3 months agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using BetterLadders.Compatibility; using BetterLadders.Config; using BetterLadders.Patches; using GameNetcodeStuff; using HarmonyLib; using LethalConfig; using LethalConfig.ConfigItems; using LethalConfig.ConfigItems.Options; using LobbyCompatibility.Enums; using LobbyCompatibility.Features; using Microsoft.CodeAnalysis; using Unity.Netcode; using UnityEngine; using UnityEngine.InputSystem.Utilities; using UnityEngine.SceneManagement; using e3s1.BetterLadders.NetcodePatcher; [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("BMX.LobbyCompatibility")] [assembly: IgnoresAccessChecksTo("ClientNetworkTransform")] [assembly: IgnoresAccessChecksTo("com.olegknyazev.softmask")] [assembly: IgnoresAccessChecksTo("DissonanceVoip")] [assembly: IgnoresAccessChecksTo("EasyTextEffects")] [assembly: IgnoresAccessChecksTo("Facepunch Transport for Netcode for GameObjects")] [assembly: IgnoresAccessChecksTo("Facepunch.Steamworks.Win64")] [assembly: IgnoresAccessChecksTo("LethalConfig")] [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.Components")] [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("e3s1.BetterLadders")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("[v73] Configurable climbing speed, extension ladder time, climbing with two-handed items, and more")] [assembly: AssemblyFileVersion("1.5.0.0")] [assembly: AssemblyInformationalVersion("1.5.0+3378133b8109028859a5c07511c02330c0462007")] [assembly: AssemblyProduct("BetterLadders")] [assembly: AssemblyTitle("e3s1.BetterLadders")] [assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/e3s1/BetterLadders")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.5.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] [module: NetcodePatchedAssembly] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace BetterLadders { [BepInPlugin("e3s1.BetterLadders", "BetterLadders", "1.5.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public class BetterLaddersPlugin : BaseUnityPlugin { private const string LethalConfigGuid = "ainavt.lc.lethalconfig"; private const string LobbyCompatibilityGuid = "BMX.LobbyCompatibility"; private readonly Harmony _harmony = new Harmony("e3s1.BetterLadders"); internal static ManualLogSource Logger { get; private set; } private void Awake() { Logger = ((BaseUnityPlugin)this).Logger; NetcodePatcher(); if (Chainloader.PluginInfos.ContainsKey("ainavt.lc.lethalconfig")) { Logger.LogInfo((object)"LethalConfig detected"); LethalConfig.Init(); } if (Chainloader.PluginInfos.ContainsKey("BMX.LobbyCompatibility")) { Logger.LogInfo((object)"LobbyCompatibility detected, registering plugin..."); LobbyCompatibility.Init(((BaseUnityPlugin)this).Info.Metadata); } new LocalConfig(((BaseUnityPlugin)this).Config); SceneManager.sceneLoaded += SyncedConfig.Initialize; _harmony.PatchAll(typeof(AllowTwoHanded)); _harmony.PatchAll(typeof(ClimbSpeed)); _harmony.PatchAll(typeof(ExtensionLadderTime)); _harmony.PatchAll(typeof(HideItems)); _harmony.PatchAll(typeof(HoldToPickup)); _harmony.PatchAll(typeof(HoverTip)); _harmony.PatchAll(typeof(KillTrigger)); Logger.LogInfo((object)"Running transpilers..."); if (!LocalConfig.Instance.DebugMode.Value) { Logger.LogInfo((object)"Not logging IL code, DebugMode is disabled"); } _harmony.PatchAll(typeof(ExtensionLadderDelay)); _harmony.PatchAll(typeof(ExtensionLadderSpeed)); _harmony.PatchAll(typeof(TransitionSpeed)); Logger.LogInfo((object)"Finished loading"); } private static void NetcodePatcher() { foreach (Type item in Assembly.GetExecutingAssembly().GetTypes().Where(delegate(Type t) { string? @namespace = t.Namespace; return @namespace == null || !@namespace.StartsWith("BetterLadders.Compatibility"); })) { MethodInfo[] methods = item.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic); foreach (MethodInfo methodInfo in methods) { if (methodInfo.GetCustomAttributes(typeof(RuntimeInitializeOnLoadMethodAttribute), inherit: false).Length != 0) { methodInfo.Invoke(null, null); } } } } } public static class TranspilerHelper { public static IEnumerable<CodeInstruction> Patch(IEnumerable<CodeInstruction> instructions, Func<List<CodeInstruction>, List<(int logStartIndex, int logEndIndex)>, bool>[] patches, [CallerMemberName] string memberName = "") { BetterLaddersPlugin.Logger.LogInfo((object)("Starting " + memberName)); List<CodeInstruction> code = new List<CodeInstruction>(instructions); for (int i = 0; i < patches.Length; i++) { try { List<(int, int)> list = new List<(int, int)>(); if (!patches[i](code, list)) { BetterLaddersPlugin.Logger.LogError((object)$"No IL match found for patch #{i} in {memberName}"); continue; } BetterLaddersPlugin.Logger.LogInfo((object)$"Completed applying patch #{i} in {memberName}"); if (!LocalConfig.Instance.DebugMode.Value) { continue; } int num = list.Select<(int, int), List<CodeInstruction>>(((int logStartIndex, int logEndIndex) s) => code.GetRange(s.logStartIndex, s.logEndIndex - s.logStartIndex)).Max((List<CodeInstruction> codes) => codes.Max((CodeInstruction c) => ((object)c).ToString().Length)); int count = num + 2; for (int j = 0; j < list.Count; j++) { (int, int) tuple = list[j]; int item = tuple.Item1; int item2 = tuple.Item2; string text = "╞═╡"; if (j == 0) { text = "┌─┐"; } BetterLaddersPlugin.Logger.LogInfo((object)(text[0] + new string(text[1], count) + text[2])); for (int k = item; k < item2; k++) { string text2 = ((code[k].operand == null) ? code[k].opcode.ToString() : ((object)code[k]).ToString()); BetterLaddersPlugin.Logger.LogInfo((object)("│ " + text2.PadRight(num) + " │")); } if (j == list.Count - 1) { BetterLaddersPlugin.Logger.LogInfo((object)("└" + new string('─', count) + "┘")); } } } catch (Exception arg) { BetterLaddersPlugin.Logger.LogError((object)$"Error running patch #{i} in {memberName}: {arg}"); } } BetterLaddersPlugin.Logger.LogInfo((object)("Finished all patches in " + memberName)); BetterLaddersPlugin.Logger.LogInfo((object)""); return code; } } public static class MyPluginInfo { public const string PLUGIN_GUID = "e3s1.BetterLadders"; public const string PLUGIN_NAME = "BetterLadders"; public const string PLUGIN_VERSION = "1.5.0"; } } namespace BetterLadders.Patches { internal static class AllowTwoHanded { [HarmonyPrefix] [HarmonyPatch(typeof(PlayerControllerB), "Interact_performed")] private static void LadderTwoHandedAccessPrefix(PlayerControllerB __instance) { InteractTrigger hoveringOverTrigger = __instance.hoveringOverTrigger; if (!((Object)(object)hoveringOverTrigger == (Object)null) && hoveringOverTrigger.isLadder) { hoveringOverTrigger.specialCharacterAnimation = !(hoveringOverTrigger.twoHandedItemAllowed = LocalConfig.Instance.AllowTwoHanded.Value || __instance.isClimbingLadder); } } } internal static class ClimbSpeed { private class TimeoutResult { public bool TimedOut; } [CompilerGenerated] private sealed class <>c__DisplayClass7_0 { public PlayerControllerB player; internal bool <SetClimbSpeed>b__0() { player.climbSpeed = _vanillaClimbSpeed * LocalConfig.Instance.ClimbSpeedMultiplier.Value; if (player.isSprinting) { PlayerControllerB obj = player; obj.climbSpeed *= LocalConfig.Instance.SprintingClimbSpeedMultiplier.Value; } return player.isClimbingLadder; } } [CompilerGenerated] private sealed class <>c__DisplayClass8_0 { public PlayerControllerB player; internal bool <SetAnimationSpeed>b__0() { //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) float @float = player.playerBodyAnimator.GetFloat(AnimationSpeed); if (@float == 0f) { return player.isClimbingLadder; } bool flag = (Object)(object)player == (Object)(object)GameNetworkManager.Instance.localPlayerController; if (flag && player.moveInputVector.y == 0f) { player.playerBodyAnimator.SetFloat(AnimationSpeed, 0f); return player.isClimbingLadder; } bool num; if (!flag) { AnimatorStateInfo currentAnimatorStateInfo = player.playerBodyAnimator.GetCurrentAnimatorStateInfo(0); num = ((AnimatorStateInfo)(ref currentAnimatorStateInfo)).IsTag("Sprinting"); } else { num = player.isSprinting; } float num2 = LocalConfig.Instance.ClimbSpeedMultiplier.Value; if (num) { num2 *= LocalConfig.Instance.SprintingClimbSpeedMultiplier.Value; } int num3 = ((@float > 0f) ? 1 : ((@float < 0f) ? (-1) : 0)); int num4 = num3; player.playerBodyAnimator.SetFloat(AnimationSpeed, num2 * (float)num4); return player.isClimbingLadder; } } [CompilerGenerated] private sealed class <SetAnimationSpeed>d__8 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public PlayerControllerB player; private <>c__DisplayClass8_0 <>8__1; private TimeoutResult <timeoutResult>5__2; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <SetAnimationSpeed>d__8(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>8__1 = null; <timeoutResult>5__2 = null; <>1__state = -2; } private bool MoveNext() { //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>8__1 = new <>c__DisplayClass8_0(); <>8__1.player = player; BetterLaddersPlugin.Logger.LogInfo((object)("Starting SetAnimationSpeed coroutine for " + <>8__1.player.playerUsername)); <timeoutResult>5__2 = new TimeoutResult(); <>2__current = Timeout(<>8__1.player, <timeoutResult>5__2); <>1__state = 1; return true; case 1: <>1__state = -1; if (<timeoutResult>5__2.TimedOut) { return false; } <>2__current = (object)new WaitWhile((Func<bool>)delegate { //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) float @float = <>8__1.player.playerBodyAnimator.GetFloat(AnimationSpeed); if (@float == 0f) { return <>8__1.player.isClimbingLadder; } bool flag = (Object)(object)<>8__1.player == (Object)(object)GameNetworkManager.Instance.localPlayerController; if (flag && <>8__1.player.moveInputVector.y == 0f) { <>8__1.player.playerBodyAnimator.SetFloat(AnimationSpeed, 0f); return <>8__1.player.isClimbingLadder; } bool num; if (!flag) { AnimatorStateInfo currentAnimatorStateInfo = <>8__1.player.playerBodyAnimator.GetCurrentAnimatorStateInfo(0); num = ((AnimatorStateInfo)(ref currentAnimatorStateInfo)).IsTag("Sprinting"); } else { num = <>8__1.player.isSprinting; } float num2 = LocalConfig.Instance.ClimbSpeedMultiplier.Value; if (num) { num2 *= LocalConfig.Instance.SprintingClimbSpeedMultiplier.Value; } int num3 = ((@float > 0f) ? 1 : ((@float < 0f) ? (-1) : 0)); int num4 = num3; <>8__1.player.playerBodyAnimator.SetFloat(AnimationSpeed, num2 * (float)num4); return <>8__1.player.isClimbingLadder; }); <>1__state = 2; return true; case 2: <>1__state = -1; BetterLaddersPlugin.Logger.LogInfo((object)("Finished SetAnimationSpeed coroutine for " + <>8__1.player.playerUsername)); return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <SetClimbSpeed>d__7 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public PlayerControllerB player; private <>c__DisplayClass7_0 <>8__1; private TimeoutResult <timeoutResult>5__2; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <SetClimbSpeed>d__7(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>8__1 = null; <timeoutResult>5__2 = null; <>1__state = -2; } private bool MoveNext() { //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>8__1 = new <>c__DisplayClass7_0(); <>8__1.player = player; BetterLaddersPlugin.Logger.LogInfo((object)("Starting SetClimbSpeed coroutine for " + <>8__1.player.playerUsername)); <timeoutResult>5__2 = new TimeoutResult(); <>2__current = Timeout(<>8__1.player, <timeoutResult>5__2); <>1__state = 1; return true; case 1: <>1__state = -1; if (<timeoutResult>5__2.TimedOut) { return false; } <>2__current = (object)new WaitWhile((Func<bool>)delegate { <>8__1.player.climbSpeed = _vanillaClimbSpeed * LocalConfig.Instance.ClimbSpeedMultiplier.Value; if (<>8__1.player.isSprinting) { PlayerControllerB obj = <>8__1.player; obj.climbSpeed *= LocalConfig.Instance.SprintingClimbSpeedMultiplier.Value; } return <>8__1.player.isClimbingLadder; }); <>1__state = 2; return true; case 2: <>1__state = -1; BetterLaddersPlugin.Logger.LogInfo((object)("Finished SetClimbSpeed coroutine for " + <>8__1.player.playerUsername)); return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <Timeout>d__6 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public PlayerControllerB player; public TimeoutResult timeoutResult; private float <timeWaiting>5__2; private float <timeout>5__3; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <Timeout>d__6(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <timeWaiting>5__2 = 0f; <timeout>5__3 = 1f / LocalConfig.Instance.TransitionSpeedMultiplier.Value; break; case 1: <>1__state = -1; break; } if (!player.isClimbingLadder) { <timeWaiting>5__2 += Time.deltaTime; if (!(<timeWaiting>5__2 > <timeout>5__3)) { <>2__current = null; <>1__state = 1; return true; } BetterLaddersPlugin.Logger.LogInfo((object)$"Coroutine timed out for {player.playerUsername} after {<timeWaiting>5__2}s (max {<timeout>5__3}s)"); timeoutResult.TimedOut = true; } BetterLaddersPlugin.Logger.LogInfo((object)$"Waited {<timeWaiting>5__2}s for {player.playerUsername} to start climbing ladder"); return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private static float _vanillaClimbSpeed = float.NaN; private static readonly int AnimationSpeed = Animator.StringToHash("animationSpeed"); [HarmonyPostfix] [HarmonyPatch(typeof(PlayerControllerB), "Awake")] private static void GetVanillaClimbSpeedPatch(PlayerControllerB __instance) { if (float.IsNaN(_vanillaClimbSpeed)) { _vanillaClimbSpeed = __instance.climbSpeed; BetterLaddersPlugin.Logger.LogInfo((object)$"Vanilla climb speed: {_vanillaClimbSpeed}"); } } [HarmonyPostfix] [HarmonyPatch(typeof(InteractTrigger), "SetUsingLadderOnLocalClient")] private static void LadderAnimationSpeedPatch(bool isUsing) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) if (isUsing) { PlayerControllerB localPlayerController = GameNetworkManager.Instance.localPlayerController; ((MonoBehaviour)localPlayerController).StartCoroutine(SetAnimationSpeed(localPlayerController)); if (((NetworkBehaviour)SyncedConfig.Instance).IsSpawned) { SyncedConfig.Instance.RequestStartChangeAnimationSpeedRpc(NetworkBehaviourReference.op_Implicit((NetworkBehaviour)(object)localPlayerController)); } } } [HarmonyPostfix] [HarmonyPatch(typeof(InteractTrigger), "SetUsingLadderOnLocalClient")] private static void LadderClimbSpeedPatch(bool isUsing) { if (isUsing) { PlayerControllerB localPlayerController = GameNetworkManager.Instance.localPlayerController; ((MonoBehaviour)localPlayerController).StartCoroutine(SetClimbSpeed(localPlayerController)); } } [IteratorStateMachine(typeof(<Timeout>d__6))] private static IEnumerator Timeout(PlayerControllerB player, TimeoutResult timeoutResult) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <Timeout>d__6(0) { player = player, timeoutResult = timeoutResult }; } [IteratorStateMachine(typeof(<SetClimbSpeed>d__7))] private static IEnumerator SetClimbSpeed(PlayerControllerB player) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <SetClimbSpeed>d__7(0) { player = player }; } [IteratorStateMachine(typeof(<SetAnimationSpeed>d__8))] internal static IEnumerator SetAnimationSpeed(PlayerControllerB player) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <SetAnimationSpeed>d__8(0) { player = player }; } } public static class ExtensionLadderDelay { private static readonly ConstructorInfo WaitForSecondsConstructor = AccessTools.Constructor(typeof(WaitForSeconds), new Type[1] { typeof(float) }, false); private static readonly MethodInfo ExtensionDelayGetter = AccessTools.PropertyGetter(typeof(ExtensionLadderDelay), "ExtensionDelay"); private static readonly MethodInfo FallDelayGetter = AccessTools.PropertyGetter(typeof(ExtensionLadderDelay), "FallDelay"); private static float ExtensionDelay => LocalConfig.Instance.ExtensionDelay.Value; private static float FallDelay => LocalConfig.Instance.FallDelay.Value; [HarmonyTranspiler] [HarmonyPatch(/*Could not decode attribute arguments.*/)] internal static IEnumerable<CodeInstruction> ExtensionDelayTranspiler(IEnumerable<CodeInstruction> instructions) { return CommonTranspiler(instructions, LocalConfig.Instance.ExtensionDelay.VanillaValue, ExtensionDelayGetter, "ExtensionDelayTranspiler"); } [HarmonyTranspiler] [HarmonyPatch(/*Could not decode attribute arguments.*/)] internal static IEnumerable<CodeInstruction> FallDelayTranspiler(IEnumerable<CodeInstruction> instructions) { return CommonTranspiler(instructions, LocalConfig.Instance.FallDelay.VanillaValue, FallDelayGetter, "FallDelayTranspiler"); } private static IEnumerable<CodeInstruction> CommonTranspiler(IEnumerable<CodeInstruction> instructions, float vanillaValue, MethodInfo getter, [CallerMemberName] string memberName = "") { return TranspilerHelper.Patch(instructions, new Func<List<CodeInstruction>, List<(int, int)>, bool>[1] { delegate(List<CodeInstruction> code, List<(int logStartIndex, int logEndIndex)> logIndices) { //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Expected O, but got Unknown //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Expected O, but got Unknown for (int i = 0; i < code.Count; i++) { if (code[i].opcode == OpCodes.Ldc_R4 && code[i].operand is float num && num == vanillaValue && code[i + 1].opcode == OpCodes.Newobj && code[i + 1].operand is ConstructorInfo constructorInfo && constructorInfo == WaitForSecondsConstructor) { code.InsertRange(i + 1, new <>z__ReadOnlyArray<CodeInstruction>((CodeInstruction[])(object)new CodeInstruction[2] { new CodeInstruction(OpCodes.Pop, (object)null), new CodeInstruction(OpCodes.Call, (object)getter) })); logIndices.Add((i, i + 3)); return true; } } return false; } }, memberName); } } public static class ExtensionLadderSpeed { private static readonly MethodInfo ExtensionSpeedMultiplierGetter = AccessTools.PropertyGetter(typeof(ExtensionLadderSpeed), "ExtensionSpeedMultiplier"); private static readonly MethodInfo FallSpeedMultiplierGetter = AccessTools.PropertyGetter(typeof(ExtensionLadderSpeed), "FallSpeedMultiplier"); private static float ExtensionSpeedMultiplier => LocalConfig.Instance.ExtensionSpeedMultiplier.Value; private static float FallSpeedMultiplier => LocalConfig.Instance.FallSpeedMultiplier.Value; [HarmonyTranspiler] [HarmonyPatch(/*Could not decode attribute arguments.*/)] internal static IEnumerable<CodeInstruction> ExtensionSpeedTranspiler(IEnumerable<CodeInstruction> instructions) { return CommonTranspiler(instructions, ExtensionSpeedMultiplierGetter, "ExtensionSpeedTranspiler"); } [HarmonyTranspiler] [HarmonyPatch(/*Could not decode attribute arguments.*/)] internal static IEnumerable<CodeInstruction> FallSpeedTranspiler(IEnumerable<CodeInstruction> instructions) { return CommonTranspiler(instructions, FallSpeedMultiplierGetter, "FallSpeedTranspiler"); } private static IEnumerable<CodeInstruction> CommonTranspiler(IEnumerable<CodeInstruction> instructions, MethodInfo getter, [CallerMemberName] string memberName = "") { return TranspilerHelper.Patch(instructions, new Func<List<CodeInstruction>, List<(int, int)>, bool>[1] { delegate(List<CodeInstruction> code, List<(int logStartIndex, int logEndIndex)> logIndices) { //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Expected O, but got Unknown //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Expected O, but got Unknown for (int i = 0; i < code.Count; i++) { if (code[i].opcode == OpCodes.Ldfld && code[i].operand is FieldInfo fieldInfo && fieldInfo.Name.Contains("speedMultiplier")) { for (int j = i; j < i + 10 && j < code.Count; j++) { if (code[j - 1].opcode != OpCodes.Call && code[j].opcode == OpCodes.Mul && code[j + 1].opcode == OpCodes.Add && code[j + 2].opcode == OpCodes.Stfld && code[j + 2].operand is FieldInfo fieldInfo2 && fieldInfo2.Name.Contains("speedMultiplier")) { code.InsertRange(j + 1, new <>z__ReadOnlyArray<CodeInstruction>((CodeInstruction[])(object)new CodeInstruction[2] { new CodeInstruction(OpCodes.Call, (object)getter), new CodeInstruction(OpCodes.Mul, (object)null) })); logIndices.Add((i, j + 5)); return true; } } } } return false; } }, memberName); } } internal static class ExtensionLadderTime { [HarmonyPrefix] [HarmonyPatch(typeof(ExtensionLadderItem), "StartLadderAnimation")] private static void ExtensionTimePatch(ref float ___ladderTimer) { float num = ((!(LocalConfig.Instance.ExtensionTime.Value <= 0f)) ? (LocalConfig.Instance.ExtensionTime.VanillaValue - LocalConfig.Instance.ExtensionTime.Value) : float.MinValue); ___ladderTimer = num; } } internal static class HideItems { [HarmonyPostfix] [HarmonyPatch(typeof(InteractTrigger), "SetUsingLadderOnLocalClient")] private static void SetVisibilityOnStartClimb(InteractTrigger __instance, bool isUsing) { //IL_0083: Unknown result type (might be due to invalid IL or missing references) PlayerControllerB localPlayerController = GameNetworkManager.Instance.localPlayerController; if (!((Object)(object)localPlayerController.currentlyHeldObjectServer == (Object)null)) { bool flag = !isUsing; BetterLaddersPlugin.Logger.LogInfo((object)"Toggling visibility for held item"); if ((LocalConfig.Instance.HideOneHanded.Value && !localPlayerController.twoHanded) || (LocalConfig.Instance.HideTwoHanded.Value && localPlayerController.twoHanded)) { localPlayerController.currentlyHeldObjectServer.EnableItemMeshes(flag); } if (((NetworkBehaviour)SyncedConfig.Instance).IsSpawned) { SyncedConfig.Instance.RequestChangeItemVisibilityRpc(NetworkBehaviourReference.op_Implicit((NetworkBehaviour)(object)localPlayerController.currentlyHeldObjectServer), flag); } } } } internal static class HoldToPickup { private static bool _canPickupLadder; [HarmonyPrefix] [HarmonyPatch(typeof(PlayerControllerB), "BeginGrabObject")] private static bool ControlExtLadderPickup(PlayerControllerB __instance) { if (!LocalConfig.Instance.HoldToPickup.Value) { return true; } if (!LookingAtGrabbableExtLadder(__instance, out var extLadderObj)) { return true; } if ((Object)(object)extLadderObj == (Object)null || !extLadderObj.ladderActivated) { return true; } if (!_canPickupLadder) { return false; } _canPickupLadder = false; return true; } [HarmonyPostfix] [HarmonyPatch(typeof(PlayerControllerB), "ClickHoldInteraction")] private static void ShowHoldInteractHUD(PlayerControllerB __instance) { if (LocalConfig.Instance.HoldToPickup.Value && !Object.op_Implicit((Object)(object)__instance.hoveringOverTrigger)) { ExtensionLadderItem extLadderObj; if (!IngamePlayerSettings.Instance.playerInput.actions.FindAction("Interact", false).IsPressed()) { HUDManager.Instance.holdFillAmount = 0f; } else if (LookingAtGrabbableExtLadder(__instance, out extLadderObj) && (Object)(object)extLadderObj != (Object)null && extLadderObj.ladderActivated && HUDManager.Instance.HoldInteractionFill(LocalConfig.Instance.HoldTime.Value, 1f)) { _canPickupLadder = true; __instance.BeginGrabObject(); } } } [HarmonyPrefix] [HarmonyPatch(typeof(PlayerControllerB), "StopHoldInteractionOnTrigger")] private static bool StopHoldInteractionOnTrigger(PlayerControllerB __instance) { if (!LocalConfig.Instance.HoldToPickup.Value) { return true; } if (LookingAtGrabbableExtLadder(__instance, 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; } 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(PlayerControllerB player, out ExtensionLadderItem extLadderObj) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) RaycastHit val = default(RaycastHit); bool flag = Physics.Raycast(player.interactRay, ref val, player.grabDistance, player.interactableObjectsMask) && ((Component)((RaycastHit)(ref val)).collider).gameObject.layer != 8; if (flag) { extLadderObj = ((Component)((RaycastHit)(ref val)).collider).gameObject.GetComponent<ExtensionLadderItem>(); if (player.twoHanded || ((Object)(object)extLadderObj != (Object)null && !((GrabbableObject)extLadderObj).grabbable)) { return false; } } else { extLadderObj = null; } return flag; } } internal static class HoverTip { private static bool? _wasTwoHanded; [HarmonyPrefix] [HarmonyPatch(typeof(PlayerControllerB), "SetHoverTipAndCurrentInteractTrigger")] private static void LadderHoverTipPrefix(PlayerControllerB __instance) { if (!((Object)(object)__instance.hoveringOverTrigger == (Object)null) && __instance.hoveringOverTrigger.isLadder && __instance.isHoldingInteract && LocalConfig.Instance.AllowTwoHanded.Value && __instance.twoHanded) { _wasTwoHanded = true; __instance.twoHanded = false; } } [HarmonyPostfix] [HarmonyPatch(typeof(PlayerControllerB), "SetHoverTipAndCurrentInteractTrigger")] private static void LadderHoverTipPostfix(PlayerControllerB __instance) { if (_wasTwoHanded.HasValue) { __instance.twoHanded = _wasTwoHanded.Value; _wasTwoHanded = null; } } } internal static class KillTrigger { [HarmonyPrefix] [HarmonyPatch(typeof(ExtensionLadderItem), "StartLadderAnimation")] private static void KillTriggerPatch(ref Collider ___killTrigger) { ((Component)___killTrigger).gameObject.SetActive(LocalConfig.Instance.EnableKillTrigger.Value); } } internal static class TransitionSpeed { private static readonly MethodInfo DeltaTimeGetter = AccessTools.PropertyGetter(typeof(Time), "deltaTime"); private static readonly MethodInfo MultiplierGetter = AccessTools.PropertyGetter(typeof(TransitionSpeed), "Multiplier"); public static float Multiplier => LocalConfig.Instance.TransitionSpeedMultiplier.Value; [HarmonyTranspiler] [HarmonyPatch(/*Could not decode attribute arguments.*/)] internal static IEnumerable<CodeInstruction> TransitionSpeedTranspiler(IEnumerable<CodeInstruction> instructions) { return TranspilerHelper.Patch(instructions, new Func<List<CodeInstruction>, List<(int, int)>, bool>[1] { delegate(List<CodeInstruction> code, List<(int logStartIndex, int logEndIndex)> logIndices) { //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Expected O, but got Unknown //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Expected O, but got Unknown int num = 0; for (int i = 0; i < code.Count; i++) { if (code[i].opcode == OpCodes.Call && code[i].operand is MethodInfo methodInfo && methodInfo == DeltaTimeGetter) { code.Insert(i + 1, new CodeInstruction(OpCodes.Call, (object)MultiplierGetter)); code.Insert(i + 2, new CodeInstruction(OpCodes.Mul, (object)null)); num++; logIndices.Add((i, i + 3)); } } return num > 0; } }, "TransitionSpeedTranspiler"); } } } namespace BetterLadders.Config { [AttributeUsage(AttributeTargets.Class, Inherited = false)] public sealed class SourceGenAttribute : Attribute { public SourceGenAttribute(Type targetFieldType, Type targetClassType) { } } public abstract class CustomConfigEntry<T> { public ConfigEntry<T> ConfigEntry; public virtual T Value { get; } protected CustomConfigEntry(ConfigFile configFile, string section, string key, T defaultValue, ConfigDescription configDescription) { ConfigEntry = configFile.Bind<T>(section, key, defaultValue, configDescription); } protected abstract void LethalConfigCompat(); protected void Init() { if (LethalConfig.IsInstalled) { LethalConfigCompat(); } } } [SourceGen(typeof(SyncedConfigEntry<>), typeof(SyncedConfig))] public class LocalConfig { public readonly SyncedConfigEntry<float> ClimbSpeedMultiplier; public readonly SyncedConfigEntry<float> SprintingClimbSpeedMultiplier; public readonly SyncedConfigEntry<float> TransitionSpeedMultiplier; public readonly SyncedConfigEntry<bool> AllowTwoHanded; public readonly LocalConfigEntry<bool> ScaleAnimationSpeed; public readonly LocalConfigEntry<bool> HideOneHanded; public readonly LocalConfigEntry<bool> HideTwoHanded; public readonly SyncedConfigEntry<float> ExtensionTime; public readonly SyncedConfigEntry<float> ExtensionSpeedMultiplier; public readonly SyncedConfigEntry<float> ExtensionDelay; public readonly SyncedConfigEntry<float> FallSpeedMultiplier; public readonly SyncedConfigEntry<float> FallDelay; public readonly SyncedConfigEntry<bool> EnableKillTrigger; public readonly LocalConfigEntry<bool> HoldToPickup; public readonly LocalConfigEntry<float> HoldTime; public readonly LocalConfigEntry<bool> DebugMode; public static LocalConfig Instance { get; private set; } internal LocalConfig(ConfigFile configFile) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Expected O, but got Unknown //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Expected O, but got Unknown //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Expected O, but got Unknown //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Expected O, but got Unknown //IL_01a6: Unknown result type (might be due to invalid IL or missing references) //IL_01b5: Expected O, but got Unknown //IL_01e4: Unknown result type (might be due to invalid IL or missing references) //IL_01f3: Expected O, but got Unknown //IL_0222: Unknown result type (might be due to invalid IL or missing references) //IL_0231: Expected O, but got Unknown //IL_0260: Unknown result type (might be due to invalid IL or missing references) //IL_026f: Expected O, but got Unknown //IL_02d7: Unknown result type (might be due to invalid IL or missing references) //IL_02e1: Expected O, but got Unknown Instance = this; configFile.SaveOnConfigSet = false; ClimbSpeedMultiplier = new SyncedConfigEntry<float>(configFile, "General", "ClimbSpeedMultiplier", 1f, new ConfigDescription("Ladder climb speed multiplier (1 in vanilla)", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 10f), Array.Empty<object>()), 1f); SprintingClimbSpeedMultiplier = new SyncedConfigEntry<float>(configFile, "General", "SprintingClimbSpeedMultiplier", 1.5f, new ConfigDescription("Additional climb speed multiplier while sprinting (1 in vanilla)", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 10f), Array.Empty<object>()), 1f); TransitionSpeedMultiplier = new SyncedConfigEntry<float>(configFile, "General", "TransitionSpeedMultiplier", 1f, new ConfigDescription("Ladder enter/exit animation speed multiplier (1 in vanilla)", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 10f), Array.Empty<object>()), 1f); AllowTwoHanded = new SyncedConfigEntry<bool>(configFile, "General", "AllowTwoHanded", defaultValue: true, "Whether ladders can be climbed while carrying a two-handed object (false in vanilla)", vanillaValue: false); ScaleAnimationSpeed = new LocalConfigEntry<bool>(configFile, "General", "ScaleAnimationSpeed", defaultValue: true, "Whether the climbing animation is scaled to the climbing speed (false in vanilla)"); HideOneHanded = new LocalConfigEntry<bool>(configFile, "General", "HideOneHanded", defaultValue: true, "Whether one-handed items should be hidden while climbing a ladder (false in vanilla)"); HideTwoHanded = new LocalConfigEntry<bool>(configFile, "General", "HideTwoHanded", defaultValue: true, "Whether two-handed items should be hidden while climbing a ladder (false in vanilla)"); ExtensionTime = new SyncedConfigEntry<float>(configFile, "Extension Ladders", "ExtensionTime", 0f, new ConfigDescription("How long extension ladders should stay extended, in seconds (0 for permanent) (20 in vanilla)", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 3600f), Array.Empty<object>()), 20f); ExtensionSpeedMultiplier = new SyncedConfigEntry<float>(configFile, "Extension Ladders", "ExtensionSpeedMultiplier", 1f, new ConfigDescription("Multiplies how fast the ladder extends once activated (1 in vanilla)", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 100f), Array.Empty<object>()), 1f); ExtensionDelay = new SyncedConfigEntry<float>(configFile, "Extension Ladders", "ExtensionDelay", 1f, new ConfigDescription("How long before the ladder begins to extend once activated, in seconds (1 in vanilla)", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 15f), Array.Empty<object>()), 1f); FallSpeedMultiplier = new SyncedConfigEntry<float>(configFile, "Extension Ladders", "FallSpeedMultiplier", 1f, new ConfigDescription("Multiplies how fast the ladder falls once fully extended (1 in vanilla)", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 10f), Array.Empty<object>()), 1f); FallDelay = new SyncedConfigEntry<float>(configFile, "Extension Ladders", "FallDelay", 0.4f, new ConfigDescription("How long before the ladder begins to fall once fully extended, in seconds (0.4 in vanilla)", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 15f), Array.Empty<object>()), 0.4f); EnableKillTrigger = new SyncedConfigEntry<bool>(configFile, "Extension Ladders", "EnableKillTrigger", defaultValue: true, "Whether extension ladders should kill players they land on (true in vanilla)", vanillaValue: true); HoldToPickup = new LocalConfigEntry<bool>(configFile, "Extension Ladders", "HoldToPickup", defaultValue: true, "Whether the interact key needs to be held to pick up an activated extension ladder"); HoldTime = new LocalConfigEntry<float>(configFile, "Extension Ladders", "HoldTime", 0.5f, new ConfigDescription("How long the interact key must be held if holdToPickup is true, in seconds", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 15f), Array.Empty<object>())); DebugMode = new LocalConfigEntry<bool>(configFile, "Debug", "DebugMode", defaultValue: false, "Displays debug messages in the BepInEx console if true"); ClearOrphanedEntries(configFile); configFile.Save(); configFile.SaveOnConfigSet = true; } private static void ClearOrphanedEntries(ConfigFile configFile) { ((Dictionary<ConfigDefinition, string>)AccessTools.Property(typeof(ConfigFile), "OrphanedEntries").GetValue(configFile)).Clear(); } } public class LocalConfigEntry<T> : CustomConfigEntry<T> { public override T Value => ConfigEntry.Value; public LocalConfigEntry(ConfigFile configFile, string section, string key, T defaultValue, ConfigDescription configDescription) : base(configFile, section, key, defaultValue, configDescription) { Init(); } public LocalConfigEntry(ConfigFile configFile, string section, string key, T defaultValue, string configDescription) : this(configFile, section, key, defaultValue, new ConfigDescription(configDescription, (AcceptableValueBase)null, Array.Empty<object>())) { }//IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown protected override void LethalConfigCompat() { LethalConfig.AddConfigEntry<T>(ConfigEntry); } } public class SyncedConfig : NetworkBehaviour { internal readonly NetworkVariable<float> ClimbSpeedMultiplier = new NetworkVariable<float>(0f, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)0); internal readonly NetworkVariable<float> SprintingClimbSpeedMultiplier = new NetworkVariable<float>(0f, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)0); internal readonly NetworkVariable<float> TransitionSpeedMultiplier = new NetworkVariable<float>(0f, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)0); internal readonly NetworkVariable<bool> AllowTwoHanded = new NetworkVariable<bool>(false, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)0); internal readonly NetworkVariable<float> ExtensionTime = new NetworkVariable<float>(0f, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)0); internal readonly NetworkVariable<float> ExtensionSpeedMultiplier = new NetworkVariable<float>(0f, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)0); internal readonly NetworkVariable<float> ExtensionDelay = new NetworkVariable<float>(0f, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)0); internal readonly NetworkVariable<float> FallSpeedMultiplier = new NetworkVariable<float>(0f, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)0); internal readonly NetworkVariable<float> FallDelay = new NetworkVariable<float>(0f, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)0); internal readonly NetworkVariable<bool> EnableKillTrigger = new NetworkVariable<bool>(false, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)0); internal NetworkVariableBase[] NetworkVariables; public static SyncedConfig Instance { get; private set; } internal static event Action OnInitialized; internal static void Initialize(Scene sceneName, LoadSceneMode sceneEnum) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown if (!(((Scene)(ref sceneName)).name != "SampleSceneRelay")) { GameObject val = new GameObject("BetterLaddersSyncedConfig"); val.AddComponent<NetworkObject>(); Instance = val.AddComponent<SyncedConfig>(); BetterLaddersPlugin.Logger.LogInfo((object)("Initialized " + ((Object)val).name)); } } public override void OnNetworkSpawn() { BetterLaddersPlugin.Logger.LogInfo((object)"SyncedConfig network spawned"); SyncedConfig.OnInitialized?.Invoke(); Action onInitialized = SyncedConfig.OnInitialized; if (onInitialized != null) { ArrayHelpers.Clear<Delegate>(onInitialized.GetInvocationList()); } BetterLaddersPlugin.Logger.LogInfo((object)"Finished initializing NetworkVariables"); } [Rpc(/*Could not decode attribute arguments.*/)] public void RequestChangeItemVisibilityRpc(NetworkBehaviourReference itemReference, bool visible) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Invalid comparison between Unknown and I4 //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Invalid comparison between Unknown and I4 //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_004b: 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_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0074: 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_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: 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) NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager; if (networkManager == null || !networkManager.IsListening) { return; } if ((int)base.__rpc_exec_stage != 1) { RpcAttributeParams val = default(RpcAttributeParams); RpcParams val2 = default(RpcParams); FastBufferWriter val3 = ((NetworkBehaviour)this).__beginSendRpc(3987140488u, val2, val, (SendTo)5, (RpcDelivery)0); ((FastBufferWriter)(ref val3)).WriteValueSafe<NetworkBehaviourReference>(ref itemReference, default(ForNetworkSerializable)); ((FastBufferWriter)(ref val3)).WriteValueSafe<bool>(ref visible, default(ForPrimitives)); ((NetworkBehaviour)this).__endSendRpc(ref val3, 3987140488u, val2, val, (SendTo)5, (RpcDelivery)0); } if ((int)base.__rpc_exec_stage != 1) { return; } base.__rpc_exec_stage = (__RpcExecStage)0; GrabbableObject val4 = default(GrabbableObject); if (!((NetworkBehaviourReference)(ref itemReference)).TryGet<GrabbableObject>(ref val4, (NetworkManager)null)) { BetterLaddersPlugin.Logger.LogWarning((object)"Failed to get item from reference while hiding item"); return; } PlayerControllerB playerHeldBy = val4.playerHeldBy; if (!((Object)(object)playerHeldBy == (Object)null) && ((LocalConfig.Instance.HideOneHanded.Value && !playerHeldBy.twoHanded) || (LocalConfig.Instance.HideTwoHanded.Value && playerHeldBy.twoHanded))) { BetterLaddersPlugin.Logger.LogInfo((object)("Hiding item visibility for " + playerHeldBy.playerUsername)); val4.EnableItemMeshes(visible); } } [Rpc(/*Could not decode attribute arguments.*/)] public void RequestStartChangeAnimationSpeedRpc(NetworkBehaviourReference playerReference) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Invalid comparison between Unknown and I4 //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Invalid comparison between Unknown and I4 //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_004b: 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_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0074: 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_008e: 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) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager; if (networkManager == null || !networkManager.IsListening) { return; } if ((int)base.__rpc_exec_stage != 1) { RpcAttributeParams val = default(RpcAttributeParams); RpcParams val2 = default(RpcParams); FastBufferWriter val3 = ((NetworkBehaviour)this).__beginSendRpc(1239607073u, val2, val, (SendTo)5, (RpcDelivery)0); ((FastBufferWriter)(ref val3)).WriteValueSafe<NetworkBehaviourReference>(ref playerReference, default(ForNetworkSerializable)); ((NetworkBehaviour)this).__endSendRpc(ref val3, 1239607073u, val2, val, (SendTo)5, (RpcDelivery)0); } if ((int)base.__rpc_exec_stage == 1) { base.__rpc_exec_stage = (__RpcExecStage)0; PlayerControllerB val4 = default(PlayerControllerB); if (!((NetworkBehaviourReference)(ref playerReference)).TryGet<PlayerControllerB>(ref val4, (NetworkManager)null)) { BetterLaddersPlugin.Logger.LogWarning((object)"Failed to get player from reference while starting animation speed coroutine"); } else { ((MonoBehaviour)val4).StartCoroutine(ClimbSpeed.SetAnimationSpeed(val4)); } } } private void Awake() { NetworkVariables = (NetworkVariableBase[])(object)new NetworkVariableBase[10] { (NetworkVariableBase)ClimbSpeedMultiplier, (NetworkVariableBase)SprintingClimbSpeedMultiplier, (NetworkVariableBase)TransitionSpeedMultiplier, (NetworkVariableBase)AllowTwoHanded, (NetworkVariableBase)ExtensionTime, (NetworkVariableBase)ExtensionSpeedMultiplier, (NetworkVariableBase)ExtensionDelay, (NetworkVariableBase)FallSpeedMultiplier, (NetworkVariableBase)FallDelay, (NetworkVariableBase)EnableKillTrigger }; } protected override void __initializeVariables() { if (ClimbSpeedMultiplier == null) { throw new Exception("SyncedConfig.ClimbSpeedMultiplier cannot be null. All NetworkVariableBase instances must be initialized."); } ((NetworkVariableBase)ClimbSpeedMultiplier).Initialize((NetworkBehaviour)(object)this); ((NetworkBehaviour)this).__nameNetworkVariable((NetworkVariableBase)(object)ClimbSpeedMultiplier, "ClimbSpeedMultiplier"); base.NetworkVariableFields.Add((NetworkVariableBase)(object)ClimbSpeedMultiplier); if (SprintingClimbSpeedMultiplier == null) { throw new Exception("SyncedConfig.SprintingClimbSpeedMultiplier cannot be null. All NetworkVariableBase instances must be initialized."); } ((NetworkVariableBase)SprintingClimbSpeedMultiplier).Initialize((NetworkBehaviour)(object)this); ((NetworkBehaviour)this).__nameNetworkVariable((NetworkVariableBase)(object)SprintingClimbSpeedMultiplier, "SprintingClimbSpeedMultiplier"); base.NetworkVariableFields.Add((NetworkVariableBase)(object)SprintingClimbSpeedMultiplier); if (TransitionSpeedMultiplier == null) { throw new Exception("SyncedConfig.TransitionSpeedMultiplier cannot be null. All NetworkVariableBase instances must be initialized."); } ((NetworkVariableBase)TransitionSpeedMultiplier).Initialize((NetworkBehaviour)(object)this); ((NetworkBehaviour)this).__nameNetworkVariable((NetworkVariableBase)(object)TransitionSpeedMultiplier, "TransitionSpeedMultiplier"); base.NetworkVariableFields.Add((NetworkVariableBase)(object)TransitionSpeedMultiplier); if (AllowTwoHanded == null) { throw new Exception("SyncedConfig.AllowTwoHanded cannot be null. All NetworkVariableBase instances must be initialized."); } ((NetworkVariableBase)AllowTwoHanded).Initialize((NetworkBehaviour)(object)this); ((NetworkBehaviour)this).__nameNetworkVariable((NetworkVariableBase)(object)AllowTwoHanded, "AllowTwoHanded"); base.NetworkVariableFields.Add((NetworkVariableBase)(object)AllowTwoHanded); if (ExtensionTime == null) { throw new Exception("SyncedConfig.ExtensionTime cannot be null. All NetworkVariableBase instances must be initialized."); } ((NetworkVariableBase)ExtensionTime).Initialize((NetworkBehaviour)(object)this); ((NetworkBehaviour)this).__nameNetworkVariable((NetworkVariableBase)(object)ExtensionTime, "ExtensionTime"); base.NetworkVariableFields.Add((NetworkVariableBase)(object)ExtensionTime); if (ExtensionSpeedMultiplier == null) { throw new Exception("SyncedConfig.ExtensionSpeedMultiplier cannot be null. All NetworkVariableBase instances must be initialized."); } ((NetworkVariableBase)ExtensionSpeedMultiplier).Initialize((NetworkBehaviour)(object)this); ((NetworkBehaviour)this).__nameNetworkVariable((NetworkVariableBase)(object)ExtensionSpeedMultiplier, "ExtensionSpeedMultiplier"); base.NetworkVariableFields.Add((NetworkVariableBase)(object)ExtensionSpeedMultiplier); if (ExtensionDelay == null) { throw new Exception("SyncedConfig.ExtensionDelay cannot be null. All NetworkVariableBase instances must be initialized."); } ((NetworkVariableBase)ExtensionDelay).Initialize((NetworkBehaviour)(object)this); ((NetworkBehaviour)this).__nameNetworkVariable((NetworkVariableBase)(object)ExtensionDelay, "ExtensionDelay"); base.NetworkVariableFields.Add((NetworkVariableBase)(object)ExtensionDelay); if (FallSpeedMultiplier == null) { throw new Exception("SyncedConfig.FallSpeedMultiplier cannot be null. All NetworkVariableBase instances must be initialized."); } ((NetworkVariableBase)FallSpeedMultiplier).Initialize((NetworkBehaviour)(object)this); ((NetworkBehaviour)this).__nameNetworkVariable((NetworkVariableBase)(object)FallSpeedMultiplier, "FallSpeedMultiplier"); base.NetworkVariableFields.Add((NetworkVariableBase)(object)FallSpeedMultiplier); if (FallDelay == null) { throw new Exception("SyncedConfig.FallDelay cannot be null. All NetworkVariableBase instances must be initialized."); } ((NetworkVariableBase)FallDelay).Initialize((NetworkBehaviour)(object)this); ((NetworkBehaviour)this).__nameNetworkVariable((NetworkVariableBase)(object)FallDelay, "FallDelay"); base.NetworkVariableFields.Add((NetworkVariableBase)(object)FallDelay); if (EnableKillTrigger == null) { throw new Exception("SyncedConfig.EnableKillTrigger cannot be null. All NetworkVariableBase instances must be initialized."); } ((NetworkVariableBase)EnableKillTrigger).Initialize((NetworkBehaviour)(object)this); ((NetworkBehaviour)this).__nameNetworkVariable((NetworkVariableBase)(object)EnableKillTrigger, "EnableKillTrigger"); base.NetworkVariableFields.Add((NetworkVariableBase)(object)EnableKillTrigger); ((NetworkBehaviour)this).__initializeVariables(); } protected override void __initializeRpcs() { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected O, but got Unknown ((NetworkBehaviour)this).__registerRpc(3987140488u, new RpcReceiveHandler(__rpc_handler_3987140488), "RequestChangeItemVisibilityRpc"); ((NetworkBehaviour)this).__registerRpc(1239607073u, new RpcReceiveHandler(__rpc_handler_1239607073), "RequestStartChangeAnimationSpeedRpc"); ((NetworkBehaviour)this).__initializeRpcs(); } private static void __rpc_handler_3987140488(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams) { //IL_002f: 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_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_006a: 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) NetworkManager networkManager = target.NetworkManager; if (networkManager != null && networkManager.IsListening) { NetworkBehaviourReference itemReference = default(NetworkBehaviourReference); ((FastBufferReader)(ref reader)).ReadValueSafe<NetworkBehaviourReference>(ref itemReference, default(ForNetworkSerializable)); bool visible = default(bool); ((FastBufferReader)(ref reader)).ReadValueSafe<bool>(ref visible, default(ForPrimitives)); target.__rpc_exec_stage = (__RpcExecStage)1; ((SyncedConfig)(object)target).RequestChangeItemVisibilityRpc(itemReference, visible); target.__rpc_exec_stage = (__RpcExecStage)0; } } private static void __rpc_handler_1239607073(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams) { //IL_002f: 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_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) NetworkManager networkManager = target.NetworkManager; if (networkManager != null && networkManager.IsListening) { NetworkBehaviourReference playerReference = default(NetworkBehaviourReference); ((FastBufferReader)(ref reader)).ReadValueSafe<NetworkBehaviourReference>(ref playerReference, default(ForNetworkSerializable)); target.__rpc_exec_stage = (__RpcExecStage)1; ((SyncedConfig)(object)target).RequestStartChangeAnimationSpeedRpc(playerReference); target.__rpc_exec_stage = (__RpcExecStage)0; } } [MethodImpl(MethodImplOptions.NoInlining)] protected internal override string __getTypeName() { return "SyncedConfig"; } } internal static class Counter { public static int Count; } public class SyncedConfigEntry<T> : CustomConfigEntry<T> { public readonly T VanillaValue; private readonly int _id; private static bool IsHost { get { if (!NetworkManager.Singleton.IsHost) { return NetworkManager.Singleton.IsServer; } return true; } } private static bool InMainMenu { get { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) Scene activeScene = SceneManager.GetActiveScene(); return ((Scene)(ref activeScene)).name == "MainMenu"; } } private string ConfigName => ((ConfigEntryBase)ConfigEntry).Definition.Key; private NetworkVariable<T> NetworkVariable => (NetworkVariable<T>)(object)SyncedConfig.Instance.NetworkVariables[_id]; public override T Value { get { if (!IsHost && !((NetworkBehaviour)SyncedConfig.Instance).IsSpawned) { return VanillaValue; } return NetworkVariable.Value; } } public SyncedConfigEntry(ConfigFile configFile, string section, string key, T defaultValue, ConfigDescription configDescription, T vanillaValue) : base(configFile, section + " (Synced)", key, defaultValue, configDescription) { Init(); _id = Counter.Count++; VanillaValue = vanillaValue; ConfigEntry.SettingChanged += OnSettingChanged; SyncedConfig.OnInitialized += delegate { if (IsHost) { BetterLaddersPlugin.Logger.LogInfo((object)$"[HOST] Setting initial value for {ConfigName} NetworkVariable to {ConfigEntry.Value}"); NetworkVariable.Value = ConfigEntry.Value; } else { NetworkVariable<T> networkVariable = NetworkVariable; networkVariable.OnValueChanged = (OnValueChangedDelegate<T>)(object)Delegate.Combine((Delegate?)(object)networkVariable.OnValueChanged, (Delegate?)(object)(OnValueChangedDelegate<T>)delegate(T oldValue, T newValue) { BetterLaddersPlugin.Logger.LogInfo((object)$"[CLIENT] Host changed NetworkVariable for {ConfigName} to {newValue}"); }); } }; } public SyncedConfigEntry(ConfigFile configFile, string section, string key, T defaultValue, string configDescription, T vanillaValue) : this(configFile, section, key, defaultValue, new ConfigDescription(configDescription, (AcceptableValueBase)null, Array.Empty<object>()), vanillaValue) { }//IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Expected O, but got Unknown private void OnSettingChanged(object sender, EventArgs args) { T value = ConfigEntry.Value; if (NetworkManager.Singleton.IsHost && ((NetworkBehaviour)SyncedConfig.Instance).IsSpawned) { BetterLaddersPlugin.Logger.LogInfo((object)$"[HOST] Changed {ConfigName} to {value}, updating NetworkVariable..."); NetworkVariable.Value = value; } } private (bool, string) CanModifyCallback() { if (IsHost || InMainMenu) { return (true, ""); } if (!IsHost && !((NetworkBehaviour)SyncedConfig.Instance).IsSpawned && !InMainMenu) { return (false, $"Host is missing BetterLadders; using vanilla value of {VanillaValue}"); } string text = ((typeof(T) == typeof(float)) ? ((float)(object)Value).ToString("0.00") : Value.ToString()); return (false, "Using host's value of " + text); } protected override void LethalConfigCompat() { LethalConfig.AddConfigEntry<T>(ConfigEntry, CanModifyCallback); } } } namespace BetterLadders.Compatibility { internal static class LethalConfig { internal static bool IsInstalled { get; private set; } internal static void Init() { IsInstalled = true; } internal static void AddConfigEntry<T>(ConfigEntry<T> configEntry, Func<(bool allowed, string reason)> canModifyCallback = null) { //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Expected O, but got Unknown //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Expected O, but got Unknown BetterLaddersPlugin.Logger.LogInfo((object)("Setting up LethalConfig entry for " + ((ConfigEntryBase)configEntry).Definition.Key)); LethalConfigManager.SkipAutoGenFor((ConfigEntryBase)(object)configEntry); Type typeFromHandle = typeof(T); BaseConfigItem val; if (typeFromHandle == typeof(float)) { val = (BaseConfigItem)new FloatSliderConfigItem(configEntry as ConfigEntry<float>, Options<FloatSliderOptions>()); } else { if (!(typeFromHandle == typeof(bool))) { throw new NotImplementedException($"{typeof(T)} not implemented for Compatibility.LethalConfig.SetupConfigEntry<T>"); } val = (BaseConfigItem)new BoolCheckBoxConfigItem(configEntry as ConfigEntry<bool>, Options<BoolCheckBoxOptions>()); } LethalConfigManager.AddConfigItem(val); TOptions Options<TOptions>() where TOptions : BaseOptions, new() { //IL_0029: Unknown result type (might be due to invalid IL or missing references) object obj = new TOptions(); ((BaseOptions)(TOptions)obj).RequiresRestart = false; obj = (((BaseOptions)(TOptions)obj).CanModifyCallback = ((canModifyCallback == null) ? ((CanModifyDelegate)null) : ((CanModifyDelegate)(() => CanModifyResult.op_Implicit(canModifyCallback()))))); return (TOptions)obj; } } } internal static class LobbyCompatibility { internal static void Init(BepInPlugin info) { PluginHelper.RegisterPlugin(info.GUID, info.Version, (CompatibilityLevel)0, (VersionStrictness)2); } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } } [CompilerGenerated] internal sealed class <>z__ReadOnlyArray<T> : IEnumerable, ICollection, IList, IEnumerable<T>, IReadOnlyCollection<T>, IReadOnlyList<T>, ICollection<T>, IList<T> { int ICollection.Count => _items.Length; bool ICollection.IsSynchronized => false; object ICollection.SyncRoot => this; object IList.this[int index] { get { return _items[index]; } set { throw new NotSupportedException(); } } bool IList.IsFixedSize => true; bool IList.IsReadOnly => true; int IReadOnlyCollection<T>.Count => _items.Length; T IReadOnlyList<T>.this[int index] => _items[index]; int ICollection<T>.Count => _items.Length; bool ICollection<T>.IsReadOnly => true; T IList<T>.this[int index] { get { return _items[index]; } set { throw new NotSupportedException(); } } public <>z__ReadOnlyArray(T[] items) { _items = items; } IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)_items).GetEnumerator(); } void ICollection.CopyTo(Array array, int index) { ((ICollection)_items).CopyTo(array, index); } int IList.Add(object value) { throw new NotSupportedException(); } void IList.Clear() { throw new NotSupportedException(); } bool IList.Contains(object value) { return ((IList)_items).Contains(value); } int IList.IndexOf(object value) { return ((IList)_items).IndexOf(value); } void IList.Insert(int index, object value) { throw new NotSupportedException(); } void IList.Remove(object value) { throw new NotSupportedException(); } void IList.RemoveAt(int index) { throw new NotSupportedException(); } IEnumerator<T> IEnumerable<T>.GetEnumerator() { return ((IEnumerable<T>)_items).GetEnumerator(); } void ICollection<T>.Add(T item) { throw new NotSupportedException(); } void ICollection<T>.Clear() { throw new NotSupportedException(); } bool ICollection<T>.Contains(T item) { return ((ICollection<T>)_items).Contains(item); } void ICollection<T>.CopyTo(T[] array, int arrayIndex) { ((ICollection<T>)_items).CopyTo(array, arrayIndex); } bool ICollection<T>.Remove(T item) { throw new NotSupportedException(); } int IList<T>.IndexOf(T item) { return ((IList<T>)_items).IndexOf(item); } void IList<T>.Insert(int index, T item) { throw new NotSupportedException(); } void IList<T>.RemoveAt(int index) { throw new NotSupportedException(); } } namespace __GEN { internal class NetworkVariableSerializationHelper { [RuntimeInitializeOnLoadMethod] internal static void InitializeSerialization() { NetworkVariableSerializationTypes.InitializeSerializer_UnmanagedByMemcpy<float>(); NetworkVariableSerializationTypes.InitializeEqualityChecker_UnmanagedIEquatable<float>(); NetworkVariableSerializationTypes.InitializeSerializer_UnmanagedByMemcpy<bool>(); NetworkVariableSerializationTypes.InitializeEqualityChecker_UnmanagedIEquatable<bool>(); } } } namespace e3s1.BetterLadders.NetcodePatcher { [AttributeUsage(AttributeTargets.Module)] internal class NetcodePatchedAssemblyAttribute : Attribute { } }