using System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Core.Logging.Interpolation; using BepInEx.Logging; using BepInEx.Unity.IL2CPP; using HarmonyLib; using Il2CppInterop.Runtime.Injection; using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppSystem; using Il2CppSystem.Collections.Generic; using Mirror; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyCompany("BigWalkLeash")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("BigWalkLeash")] [assembly: AssemblyTitle("BigWalkLeash")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] namespace BigWalkLeash; internal static class LeashConfig { private static ConfigFile file; internal static ConfigEntry ToggleKey; internal static ConfigEntry EmergencyReleaseKey; internal static ConfigEntry DebugPreviewKey; internal static ConfigEntry DebugFirstPersonPreviewKey; internal static ConfigEntry EnableDebugKeys; internal static ConfigEntry ColourMenuKey; internal static ConfigEntry LeashLength; internal static ConfigEntry AttachRange; internal static ConfigEntry PullStrength; internal static ConfigEntry RopeWidth; internal static ConfigEntry ShowCollar; internal static ConfigEntry CollarRadius; internal static ConfigEntry CollarHeightOffset; internal static ConfigEntry CollarDepthOffset; internal static ConfigEntry CrouchHorizontalFollow; internal static ConfigEntry JumpHorizontalFollow; internal static ConfigEntry CrouchTiltDegrees; internal static ConfigEntry CollarTiltFollow; internal static ConfigEntry LeashColourRed; internal static ConfigEntry LeashColourGreen; internal static ConfigEntry LeashColourBlue; internal static ConfigEntry LocalFirstPersonCollarScale; internal static ConfigEntry ColourMenuScale; internal static ConfigEntry LocalFirstPersonAnchorHeight; internal static ConfigEntry LocalFirstPersonAnchorBehind; internal static Color LeashColour => new Color(LeashColourRed.Value, LeashColourGreen.Value, LeashColourBlue.Value, 1f); internal static void Bind(ConfigFile config) { //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Expected O, but got Unknown //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Expected O, but got Unknown //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Expected O, but got Unknown //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_0190: Expected O, but got Unknown //IL_01d9: Unknown result type (might be due to invalid IL or missing references) //IL_01e3: Expected O, but got Unknown //IL_0211: Unknown result type (might be due to invalid IL or missing references) //IL_021b: Expected O, but got Unknown //IL_0249: Unknown result type (might be due to invalid IL or missing references) //IL_0253: Expected O, but got Unknown //IL_0281: Unknown result type (might be due to invalid IL or missing references) //IL_028b: Expected O, but got Unknown //IL_02b9: Unknown result type (might be due to invalid IL or missing references) //IL_02c3: Expected O, but got Unknown //IL_02f1: Unknown result type (might be due to invalid IL or missing references) //IL_02fb: Expected O, but got Unknown //IL_0329: Unknown result type (might be due to invalid IL or missing references) //IL_0333: Expected O, but got Unknown //IL_0361: Unknown result type (might be due to invalid IL or missing references) //IL_036b: Expected O, but got Unknown //IL_0399: Unknown result type (might be due to invalid IL or missing references) //IL_03a3: Expected O, but got Unknown //IL_03d1: Unknown result type (might be due to invalid IL or missing references) //IL_03db: Expected O, but got Unknown //IL_0409: Unknown result type (might be due to invalid IL or missing references) //IL_0413: Expected O, but got Unknown //IL_0441: Unknown result type (might be due to invalid IL or missing references) //IL_044b: Expected O, but got Unknown //IL_0479: Unknown result type (might be due to invalid IL or missing references) //IL_0483: Expected O, but got Unknown //IL_04b1: Unknown result type (might be due to invalid IL or missing references) //IL_04bb: Expected O, but got Unknown file = config; ToggleKey = config.Bind("Controls", "AttachOrRelease", (KeyCode)108, "Look at a nearby friend and press this key to attach a leash. Press it again to release your leash."); EmergencyReleaseKey = config.Bind("Controls", "EmergencyRelease", (KeyCode)8, "The leashed player can always press this key to immediately remove their leash."); DebugPreviewKey = config.Bind("Debug", "ToggleSelfPreview", (KeyCode)289, "Toggles a preview rope between your right hand and your own neck."); DebugFirstPersonPreviewKey = config.Bind("Debug", "ToggleFirstPersonPreview", (KeyCode)290, "Toggles a first-person rope endpoint."); EnableDebugKeys = config.Bind("Debug", "EnableDebugKeys", true, "Enables the F8 and F9 preview keys."); ColourMenuKey = config.Bind("Controls", "OpenColourMenu", (KeyCode)288, "Opens the in-game leash colour panel."); LeashLength = config.Bind("Host settings", "LeashLengthMetres", 11f, new ConfigDescription("Maximum separation.", (AcceptableValueBase)(object)new AcceptableValueRange(1.5f, 20f), Array.Empty())); AttachRange = config.Bind("Host settings", "AttachRangeMetres", 4f, new ConfigDescription("How close a player must be before a leash can be attached.", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 8f), Array.Empty())); PullStrength = config.Bind("Host settings", "PullBackStrength", 18f, new ConfigDescription("How quickly the leashed player is corrected when reaching the end.", (AcceptableValueBase)(object)new AcceptableValueRange(1f, 60f), Array.Empty())); RopeWidth = config.Bind("Visuals", "RopeWidth", 0.045f, new ConfigDescription("Thickness of the visible rope.", (AcceptableValueBase)(object)new AcceptableValueRange(0.01f, 0.2f), Array.Empty())); ShowCollar = config.Bind("Visuals", "ShowCollar", true, "Show collar"); CollarRadius = config.Bind("Visuals", "CollarRadius", 0.11f, new ConfigDescription("Radius of the visible neck collar.", (AcceptableValueBase)(object)new AcceptableValueRange(0.06f, 0.35f), Array.Empty())); CollarHeightOffset = config.Bind("Visuals", "CollarHeightOffset", -0.02f, new ConfigDescription("Fine-tunes the collar height.", (AcceptableValueBase)(object)new AcceptableValueRange(-0.5f, 1.5f), Array.Empty())); CollarDepthOffset = config.Bind("Visuals", "CollarDepthOffset", 0f, new ConfigDescription("Moves the collar forward (positive) or backward (negative).", (AcceptableValueBase)(object)new AcceptableValueRange(-0.5f, 0.5f), Array.Empty())); CrouchHorizontalFollow = config.Bind("Visuals", "CrouchHorizontalFollow", 0.35f, new ConfigDescription("How much the collar follows the head's forward/back movement while crouching. 0 locks it to the neck; 1 fully follows the head.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 1f), Array.Empty())); JumpHorizontalFollow = config.Bind("Visuals", "JumpHorizontalFollow", 0.4f, new ConfigDescription("How much the collar follows the head's forward/back movement while jumping. 0 locks it to the neck; 1 fully follows the head.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 1f), Array.Empty())); CrouchTiltDegrees = config.Bind("Visuals", "CrouchTiltDegrees", 12f, new ConfigDescription("Extra crouch forward tilt", (AcceptableValueBase)(object)new AcceptableValueRange(-45f, 45f), Array.Empty())); CollarTiltFollow = config.Bind("Visuals", "CollarTiltFollow", 0.1f, new ConfigDescription("How much the collar tilts with the head. 0 stays level; 1 fully follows the head tilt.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 1f), Array.Empty())); LeashColourRed = config.Bind("Colour", "Red", 0.95f, new ConfigDescription("Leash colour red component.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 1f), Array.Empty())); LeashColourGreen = config.Bind("Colour", "Green", 0.45f, new ConfigDescription("Leash colour green component.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 1f), Array.Empty())); LeashColourBlue = config.Bind("Colour", "Blue", 0.08f, new ConfigDescription("Leash colour blue component.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 1f), Array.Empty())); LocalFirstPersonCollarScale = config.Bind("Visuals", "LocalFirstPersonCollarScale", 0.5f, new ConfigDescription("Scale of your own collar in first-person view. Other players always see the normal size. Disabled Currently", (AcceptableValueBase)(object)new AcceptableValueRange(0.1f, 1f), Array.Empty())); ColourMenuScale = config.Bind("Colour", "MenuScale", 1.6f, new ConfigDescription("Scale of the in-game F7 colour panel.", (AcceptableValueBase)(object)new AcceptableValueRange(0.75f, 3f), Array.Empty())); LocalFirstPersonAnchorHeight = config.Bind("Visuals", "LocalFirstPersonAnchorHeight", -0.2f, new ConfigDescription("Moves only your own first-person rope endpoint up or down from the camera.", (AcceptableValueBase)(object)new AcceptableValueRange(-1f, 1f), Array.Empty())); LocalFirstPersonAnchorBehind = config.Bind("Visuals", "LocalFirstPersonAnchorBehind", 0.2f, new ConfigDescription("Moves only your own first-person rope endpoint behind the camera.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 1.5f), Array.Empty())); } internal static void ReloadFromDisk() { file.Reload(); } internal static void SetLeashColour(float red, float green, float blue) { LeashColourRed.Value = Mathf.Clamp01(red); LeashColourGreen.Value = Mathf.Clamp01(green); LeashColourBlue.Value = Mathf.Clamp01(blue); } } public sealed class LeashController : MonoBehaviour { private sealed class StandingCalibration { internal Vector3 OffsetTotal; internal int Samples; internal float Time; internal Vector3 Offset; internal Vector3 BoneLocalPosition; } private sealed class RopeVisual { private const float NeckHeightBaseline = -0.19f; private readonly GameObject ropeObject; private readonly LineRenderer rope; private readonly Material ropeMaterial; private readonly GameObject collarObject; private readonly LineRenderer collar; private readonly Material collarMaterial; private Transform collarBone; private PlayerCharacter holder; private Vector3 end; private Vector3 collarOffsetFromBone; private bool hasStandingBonePosition; private Vector3 standingBoneLocalPosition; private float standingCalibrationTime; private Vector3 standingOffsetTotal; private int standingOffsetSamples; internal RopeVisual() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected O, but got Unknown //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Expected O, but got Unknown //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Expected O, but got Unknown //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Expected O, but got Unknown ropeObject = new GameObject("Big Walk Leash Rope"); Object.DontDestroyOnLoad((Object)(object)ropeObject); rope = ropeObject.AddComponent(); rope.positionCount = 20; rope.numCapVertices = 3; rope.widthMultiplier = LeashConfig.RopeWidth.Value; ropeMaterial = new Material(Shader.Find("Sprites/Default")); ((Renderer)rope).material = ropeMaterial; collarObject = new GameObject("Big Walk Leash Collar"); Object.DontDestroyOnLoad((Object)(object)collarObject); collar = collarObject.AddComponent(); collar.positionCount = 20; collar.loop = true; collar.useWorldSpace = false; collar.numCapVertices = 3; collar.widthMultiplier = 0.035f; collarMaterial = new Material(Shader.Find("Sprites/Default")); ((Renderer)collar).material = collarMaterial; } internal void Draw(PlayerCharacter holder, PlayerCharacter target, Color colour, bool useFirstPersonAnchor, bool forceFirstPersonAnchor) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_002d: 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_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_03f0: Unknown result type (might be due to invalid IL or missing references) //IL_03f5: Unknown result type (might be due to invalid IL or missing references) //IL_0428: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_018b: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_042a: Unknown result type (might be due to invalid IL or missing references) //IL_0421: Unknown result type (might be due to invalid IL or missing references) //IL_0405: Unknown result type (might be due to invalid IL or missing references) //IL_0409: Unknown result type (might be due to invalid IL or missing references) //IL_0418: Unknown result type (might be due to invalid IL or missing references) //IL_0442: Unknown result type (might be due to invalid IL or missing references) //IL_0444: Unknown result type (might be due to invalid IL or missing references) //IL_0449: Unknown result type (might be due to invalid IL or missing references) //IL_044e: Unknown result type (might be due to invalid IL or missing references) //IL_0453: Unknown result type (might be due to invalid IL or missing references) //IL_0455: Unknown result type (might be due to invalid IL or missing references) //IL_045a: Unknown result type (might be due to invalid IL or missing references) //IL_04b0: Unknown result type (might be due to invalid IL or missing references) //IL_04b2: Unknown result type (might be due to invalid IL or missing references) //IL_04c1: Unknown result type (might be due to invalid IL or missing references) //IL_04c6: Unknown result type (might be due to invalid IL or missing references) //IL_04cb: Unknown result type (might be due to invalid IL or missing references) //IL_04d9: Unknown result type (might be due to invalid IL or missing references) //IL_04db: Unknown result type (might be due to invalid IL or missing references) //IL_04dd: Unknown result type (might be due to invalid IL or missing references) //IL_04e2: Unknown result type (might be due to invalid IL or missing references) //IL_04e9: Unknown result type (might be due to invalid IL or missing references) //IL_04ee: Unknown result type (might be due to invalid IL or missing references) //IL_04f3: Unknown result type (might be due to invalid IL or missing references) //IL_0465: Unknown result type (might be due to invalid IL or missing references) //IL_046a: Unknown result type (might be due to invalid IL or missing references) //IL_0479: Unknown result type (might be due to invalid IL or missing references) //IL_047e: Unknown result type (might be due to invalid IL or missing references) //IL_0489: Unknown result type (might be due to invalid IL or missing references) //IL_048e: Unknown result type (might be due to invalid IL or missing references) //IL_0493: Unknown result type (might be due to invalid IL or missing references) //IL_04a2: Unknown result type (might be due to invalid IL or missing references) //IL_04a7: Unknown result type (might be due to invalid IL or missing references) //IL_04ac: Unknown result type (might be due to invalid IL or missing references) //IL_04f5: Unknown result type (might be due to invalid IL or missing references) //IL_04f7: Unknown result type (might be due to invalid IL or missing references) //IL_04fc: Unknown result type (might be due to invalid IL or missing references) //IL_0501: Unknown result type (might be due to invalid IL or missing references) //IL_0506: Unknown result type (might be due to invalid IL or missing references) //IL_01c2: Unknown result type (might be due to invalid IL or missing references) //IL_01c4: Unknown result type (might be due to invalid IL or missing references) //IL_01ca: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: Unknown result type (might be due to invalid IL or missing references) //IL_020b: Unknown result type (might be due to invalid IL or missing references) //IL_0210: Unknown result type (might be due to invalid IL or missing references) //IL_0215: Unknown result type (might be due to invalid IL or missing references) //IL_0219: Unknown result type (might be due to invalid IL or missing references) //IL_021e: Unknown result type (might be due to invalid IL or missing references) //IL_0223: Unknown result type (might be due to invalid IL or missing references) //IL_0228: Unknown result type (might be due to invalid IL or missing references) //IL_022e: Unknown result type (might be due to invalid IL or missing references) //IL_0230: Unknown result type (might be due to invalid IL or missing references) //IL_0543: Unknown result type (might be due to invalid IL or missing references) //IL_0531: Unknown result type (might be due to invalid IL or missing references) //IL_0533: Unknown result type (might be due to invalid IL or missing references) //IL_0537: Unknown result type (might be due to invalid IL or missing references) //IL_053c: Unknown result type (might be due to invalid IL or missing references) //IL_0545: Unknown result type (might be due to invalid IL or missing references) //IL_0565: Unknown result type (might be due to invalid IL or missing references) //IL_0571: Unknown result type (might be due to invalid IL or missing references) //IL_057d: Unknown result type (might be due to invalid IL or missing references) //IL_0589: Unknown result type (might be due to invalid IL or missing references) //IL_0590: Unknown result type (might be due to invalid IL or missing references) //IL_02d4: Unknown result type (might be due to invalid IL or missing references) //IL_02d9: Unknown result type (might be due to invalid IL or missing references) //IL_02e3: Unknown result type (might be due to invalid IL or missing references) //IL_02e8: Unknown result type (might be due to invalid IL or missing references) //IL_02ed: Unknown result type (might be due to invalid IL or missing references) //IL_02ef: Unknown result type (might be due to invalid IL or missing references) //IL_02f1: Unknown result type (might be due to invalid IL or missing references) //IL_02f5: Unknown result type (might be due to invalid IL or missing references) //IL_02fc: Unknown result type (might be due to invalid IL or missing references) //IL_0268: Unknown result type (might be due to invalid IL or missing references) //IL_026d: Unknown result type (might be due to invalid IL or missing references) //IL_0272: Unknown result type (might be due to invalid IL or missing references) //IL_0276: Unknown result type (might be due to invalid IL or missing references) //IL_027b: Unknown result type (might be due to invalid IL or missing references) //IL_0280: Unknown result type (might be due to invalid IL or missing references) //IL_0285: Unknown result type (might be due to invalid IL or missing references) //IL_0289: Unknown result type (might be due to invalid IL or missing references) //IL_028e: Unknown result type (might be due to invalid IL or missing references) //IL_0290: Unknown result type (might be due to invalid IL or missing references) //IL_0295: Unknown result type (might be due to invalid IL or missing references) //IL_02aa: Unknown result type (might be due to invalid IL or missing references) //IL_02b6: Unknown result type (might be due to invalid IL or missing references) //IL_02bb: Unknown result type (might be due to invalid IL or missing references) //IL_05ca: Unknown result type (might be due to invalid IL or missing references) //IL_05cc: Unknown result type (might be due to invalid IL or missing references) //IL_0336: Unknown result type (might be due to invalid IL or missing references) //IL_0332: Unknown result type (might be due to invalid IL or missing references) //IL_033c: Unknown result type (might be due to invalid IL or missing references) //IL_0369: Unknown result type (might be due to invalid IL or missing references) //IL_0354: Unknown result type (might be due to invalid IL or missing references) //IL_034b: Unknown result type (might be due to invalid IL or missing references) //IL_0628: Unknown result type (might be due to invalid IL or missing references) //IL_062f: Unknown result type (might be due to invalid IL or missing references) //IL_035a: Unknown result type (might be due to invalid IL or missing references) //IL_035f: Unknown result type (might be due to invalid IL or missing references) //IL_0364: Unknown result type (might be due to invalid IL or missing references) //IL_0381: Unknown result type (might be due to invalid IL or missing references) //IL_0384: Unknown result type (might be due to invalid IL or missing references) //IL_0389: Unknown result type (might be due to invalid IL or missing references) //IL_038e: Unknown result type (might be due to invalid IL or missing references) //IL_03c8: Unknown result type (might be due to invalid IL or missing references) //IL_03d0: Unknown result type (might be due to invalid IL or missing references) //IL_03d5: Unknown result type (might be due to invalid IL or missing references) //IL_03d7: Unknown result type (might be due to invalid IL or missing references) //IL_03e4: Unknown result type (might be due to invalid IL or missing references) //IL_03e9: Unknown result type (might be due to invalid IL or missing references) //IL_03ee: Unknown result type (might be due to invalid IL or missing references) this.holder = holder; bool flag = forceFirstPersonAnchor || (useFirstPersonAnchor && IsLocalFirstPerson(target)); Transform hand = GetHand(holder); Vector3 start = (((Object)(object)hand == (Object)null) ? (holder.kernal.position + Vector3.up * 0.8f) : hand.position); Transform val = ((target.head == null) ? null : target.head.cameraUprighter); float num = ((target.croucher == null) ? 0f : (target.croucher.smoothedCrouchness * target.croucher.crouchCameraOffset)); float num2 = ((target.croucher == null) ? 0f : target.croucher.smoothedCrouchness); bool flag2 = target.sleeper != null && target.sleeper.combinedIsSleeping; float num3 = -0.19f - num; Vector3 val2 = (((Object)(object)val == (Object)null) ? (target.kernal.position + Vector3.up * (1.7f - num)) : (val.position + Vector3.up * num3)); Transform val3 = ((target.registry == null) ? null : target.registry.headBone); Transform kernal = target.kernal; Vector3 val4 = val2; if ((Object)(object)val3 != (Object)null) { if ((Object)(object)collarBone != (Object)(object)val3) { hasStandingBonePosition = false; standingCalibrationTime = 0f; standingOffsetTotal = Vector3.zero; standingOffsetSamples = 0; } Vector3 val5 = target.kernal.InverseTransformPoint(val3.position); bool flag3 = target.ground != null && target.ground.isGrounded; if (!hasStandingBonePosition && TryGetStandingCalibration(target, out var offset, out var boneLocalPosition)) { collarBone = val3; collarOffsetFromBone = offset; standingBoneLocalPosition = boneLocalPosition; hasStandingBonePosition = true; standingCalibrationTime = 1f; } if (!hasStandingBonePosition && num2 < 0.01f && flag3) { collarBone = val3; collarOffsetFromBone = Quaternion.Inverse(LevelRotation(target.kernal)) * (val2 - val3.position); standingBoneLocalPosition = val5; hasStandingBonePosition = true; } if (hasStandingBonePosition && num2 < 0.01f && flag3 && standingCalibrationTime < 1f) { Vector3 val6 = Quaternion.Inverse(LevelRotation(target.kernal)) * (val2 - val3.position); standingOffsetTotal += val6; standingOffsetSamples++; collarOffsetFromBone = standingOffsetTotal / (float)standingOffsetSamples; standingCalibrationTime += Time.deltaTime; } Vector3 val7 = val3.position + Vector3.up * -0.19f; Vector3 val8 = val7; val8.y = Mathf.Lerp(val2.y, val7.y, 0.75f); val4 = (((Object)(object)collarBone == (Object)(object)val3 && hasStandingBonePosition) ? (val3.position + (flag2 ? val3.rotation : LevelRotation(target.kernal)) * collarOffsetFromBone) : ((num2 > 0.01f) ? val8 : val2)); if (hasStandingBonePosition && !(num2 < 0.01f && flag3)) { Vector3 val9 = val5 - standingBoneLocalPosition; val9.y = 0f; float num4 = ((num2 >= 0.01f) ? LeashConfig.CrouchHorizontalFollow.Value : ((!flag3) ? LeashConfig.JumpHorizontalFollow.Value : 1f)); val4 -= LevelRotation(target.kernal) * val9 * (1f - num4); } } Quaternion val10 = LevelRotation(kernal); Quaternion val11 = (((Object)(object)val3 == (Object)null) ? val10 : (flag2 ? val3.rotation : Quaternion.Slerp(val10, val3.rotation, LeashConfig.CollarTiltFollow.Value))); if (num2 > 0.01f) { val11 = Quaternion.AngleAxis(LeashConfig.CrouchTiltDegrees.Value * num2, val10 * Vector3.right) * val11; } if (flag) { val4 = ViewTransform(target).position + Vector3.up * LeashConfig.LocalFirstPersonAnchorHeight.Value - LevelRotation(target.kernal) * Vector3.forward * LeashConfig.LocalFirstPersonAnchorBehind.Value; } else { val4 += Vector3.up * LeashConfig.CollarHeightOffset.Value; float value = LeashConfig.CollarDepthOffset.Value; val4 += val11 * Vector3.forward * value; } Vector3 val12 = -(val11 * Vector3.forward); float num5 = (flag ? LeashConfig.LocalFirstPersonCollarScale.Value : 1f); float num6 = LeashConfig.CollarRadius.Value * num5; end = (flag ? val4 : (val4 + val12 * num6)); rope.widthMultiplier = LeashConfig.RopeWidth.Value; rope.startColor = colour; rope.endColor = colour; collar.startColor = colour; collar.endColor = colour; DrawRope(start); bool flag4 = LeashConfig.ShowCollar.Value && !flag; collarObject.SetActive(flag4); if (flag4) { collarObject.transform.SetPositionAndRotation(val4, val11); collar.widthMultiplier = 0.035f * num5; float num7 = num6; for (int i = 0; i < collar.positionCount; i++) { float num8 = (float)i / (float)collar.positionCount * (float)Math.PI * 2f; collar.SetPosition(i, new Vector3(Mathf.Cos(num8), 0f, Mathf.Sin(num8)) * num7); } } } internal void RefreshHandAnchor(PlayerCharacter player) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)holder != (Object)(object)player)) { Transform hand = GetHand(holder); if ((Object)(object)hand != (Object)null) { DrawRope(hand.position); } } } internal void Dispose() { Object.Destroy((Object)(object)ropeMaterial); Object.Destroy((Object)(object)collarMaterial); Object.Destroy((Object)(object)ropeObject); Object.Destroy((Object)(object)collarObject); } private void DrawRope(Vector3 start) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0038: 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) //IL_0048: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < rope.positionCount; i++) { float num = (float)i / (float)(rope.positionCount - 1); float num2 = Mathf.Sin(num * (float)Math.PI) * 0.13f; rope.SetPosition(i, Vector3.Lerp(start, end, num) + Vector3.down * num2); } } private static Quaternion LevelRotation(Transform body) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: 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) Vector3 val = Vector3.ProjectOnPlane(body.forward, Vector3.up); if (!(((Vector3)(ref val)).sqrMagnitude > 0.0001f)) { return Quaternion.identity; } return Quaternion.LookRotation(val, Vector3.up); } internal static bool TryGetStandingData(PlayerCharacter target, out Vector3 offset, out Vector3 boneLocalPosition) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) offset = Vector3.zero; boneLocalPosition = Vector3.zero; if ((Object)(object)target == (Object)null || (Object)(object)target.kernal == (Object)null || target.head == null || (Object)(object)target.head.cameraUprighter == (Object)null || target.registry == null || (Object)(object)target.registry.headBone == (Object)null || target.ground == null || !target.ground.isGrounded || target.croucher == null || target.croucher.smoothedCrouchness >= 0.01f) { return false; } float num = -0.19f; Vector3 val = target.head.cameraUprighter.position + Vector3.up * num; offset = Quaternion.Inverse(LevelRotation(target.kernal)) * (val - target.registry.headBone.position); boneLocalPosition = target.kernal.InverseTransformPoint(target.registry.headBone.position); return true; } private static bool IsLocalFirstPerson(PlayerCharacter target) { //IL_004a: 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_0059: 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) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0065: 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) if (!((NetworkBehaviour)target).isLocalPlayer) { return false; } Transform val = ViewTransform(target); if ((Object)(object)val == (Object)null) { return false; } Transform val2 = ((target.registry == null) ? null : target.registry.headBone); Vector3 val3 = (((Object)(object)val2 == (Object)null) ? (target.kernal.position + Vector3.up * 1.5f) : val2.position); return Vector3.Distance(val.position, val3) < 1.1f; } private static Transform ViewTransform(PlayerCharacter target) { if (!((Object)(object)Camera.main == (Object)null)) { return ((Component)Camera.main).transform; } return target.cameraTransform; } private static Transform GetHand(PlayerCharacter holder) { if (holder.arms == null) { return null; } if (((NetworkBehaviour)holder).isLocalPlayer) { LimbSpline localRightArmSpline = holder.arms.localRightArmSpline; return ((localRightArmSpline != null) ? localRightArmSpline.endTransform : null) ?? holder.arms.localRightHand ?? holder.arms.rightHand; } LimbSpline rightArmLimbSpline = holder.arms.rightArmLimbSpline; return ((rightArmLimbSpline != null) ? rightArmLimbSpline.endTransform : null) ?? holder.arms.rightHand ?? holder.arms.localRightHand; } } private const uint DebugPreviewId = uint.MaxValue; private static LeashController instance; private readonly Dictionary visuals = new Dictionary(); private readonly Dictionary standingCalibrations = new Dictionary(); private readonly HashSet activeTargets = new HashSet(); private readonly List removeVisuals = new List(); private float nextStateBroadcast; private float nextStandingCalibrationSample; private bool debugPreview; private bool firstPersonPreview; private bool showColourMenu; private float colourRed; private float colourGreen; private float colourBlue; private float leashLimit; private bool chatRestricted = true; private bool wasNetworkActive; public LeashController(IntPtr pointer) : base(pointer) { } private void Awake() { instance = this; } private void OnDestroy() { if ((Object)(object)instance == (Object)(object)this) { instance = null; } } private void Update() { HandleControls(); if (NetworkClient.active || NetworkServer.active) { wasNetworkActive = true; } else if (wasNetworkActive) { LeashState.Clear(); wasNetworkActive = false; } if (NetworkServer.active && Time.unscaledTime >= nextStateBroadcast) { nextStateBroadcast = Time.unscaledTime + 5f; LeashNet.RebroadcastCurrentLinks(); } } private void LateUpdate() { UpdateVisuals(); } internal static void RefreshHandAnchor(PlayerArms arms) { if ((Object)(object)instance == (Object)null || arms == null || (Object)(object)arms.playerCharacter == (Object)null) { return; } foreach (RopeVisual value in instance.visuals.Values) { value.RefreshHandAnchor(arms.playerCharacter); } } private void OnGUI() { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) if (!showColourMenu) { return; } Matrix4x4 matrix = GUI.matrix; GUI.matrix = Matrix4x4.Scale(Vector3.one * LeashConfig.ColourMenuScale.Value); GUILayout.BeginArea(new Rect(20f, 20f, 290f, 310f), "Big Walkies", GUI.skin.window); GUILayout.Label("Red", (Il2CppReferenceArray)null); colourRed = GUILayout.HorizontalSlider(colourRed, 0f, 1f, Array.Empty()); GUILayout.Label("Green", (Il2CppReferenceArray)null); colourGreen = GUILayout.HorizontalSlider(colourGreen, 0f, 1f, Array.Empty()); GUILayout.Label("Blue", (Il2CppReferenceArray)null); colourBlue = GUILayout.HorizontalSlider(colourBlue, 0f, 1f, Array.Empty()); GUILayout.Space(6f); GUILayout.Label($"Max leash length: {leashLimit:0.0}m", (Il2CppReferenceArray)null); leashLimit = GUILayout.HorizontalSlider(leashLimit, 1.5f, 20f, Array.Empty()); GUILayout.Space(8f); chatRestricted = GUILayout.Toggle(chatRestricted, "Leashed chat: woof / bark", Array.Empty()); GUILayout.Space(8f); if (GUILayout.Button("Apply", (Il2CppReferenceArray)null)) { LeashConfig.SetLeashColour(colourRed, colourGreen, colourBlue); LeashConfig.LeashLength.Value = leashLimit; if (TryGetLocalNetId(out var netId)) { LeashNet.RequestColourUpdate(netId); LeashNet.RequestLengthUpdate(netId, leashLimit); LeashNet.RequestChatRestrictionUpdate(netId, chatRestricted); } } if (GUILayout.Button("Close", (Il2CppReferenceArray)null)) { showColourMenu = false; } GUILayout.EndArea(); GUI.matrix = matrix; } private void HandleControls() { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0228: Unknown result type (might be due to invalid IL or missing references) //IL_0207: Unknown result type (might be due to invalid IL or missing references) //IL_01da: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) if (!TryFindLocalPlayer(out var player) || !TryGetNetId(player, out var netId)) { return; } LeashLink link2; LeashLink link3; LeashLink link4; if (Input.GetKeyDown(LeashConfig.ColourMenuKey.Value)) { LeashConfig.ReloadFromDisk(); showColourMenu = !showColourMenu; colourRed = LeashConfig.LeashColourRed.Value; colourGreen = LeashConfig.LeashColourGreen.Value; colourBlue = LeashConfig.LeashColourBlue.Value; leashLimit = LeashConfig.LeashLength.Value; if (LeashState.TryGetForHolder(netId, out var link)) { chatRestricted = link.ChatRestricted; } } else if (LeashConfig.EnableDebugKeys.Value && Input.GetKeyDown(LeashConfig.DebugPreviewKey.Value)) { LeashConfig.ReloadFromDisk(); debugPreview = !debugPreview; if (debugPreview) { firstPersonPreview = false; } Plugin.Log.LogInfo((object)(debugPreview ? "Self-preview leash enabled." : "Self-preview leash disabled.")); } else if (LeashConfig.EnableDebugKeys.Value && Input.GetKeyDown(LeashConfig.DebugFirstPersonPreviewKey.Value)) { LeashConfig.ReloadFromDisk(); firstPersonPreview = !firstPersonPreview; if (firstPersonPreview) { debugPreview = false; } Plugin.Log.LogInfo((object)(firstPersonPreview ? "First-person preview leash enabled." : "First-person preview leash disabled.")); } else if (Input.GetKeyDown(LeashConfig.EmergencyReleaseKey.Value) && LeashState.TryGetForTarget(netId, out link2)) { LeashNet.RequestRelease(link2.HolderId, link2.TargetId); } else if (LeashState.TryGetForHolder(netId, out link3)) { if (!showColourMenu) { float y = Input.mouseScrollDelta.y; if (Mathf.Abs(y) > 0.001f) { float length = Mathf.Clamp(link3.Length + y * 0.25f, 1.5f, LeashConfig.LeashLength.Value); LeashNet.RequestLengthUpdate(netId, length); } } if (Input.GetKeyDown(LeashConfig.ToggleKey.Value)) { LeashNet.RequestRelease(link3.HolderId, link3.TargetId); } } else if (LeashState.TryGetForTarget(netId, out link4)) { if (Input.GetKeyDown(LeashConfig.ToggleKey.Value)) { Plugin.Log.LogInfo((object)"Leashed players cannot start a new leash."); } } else if (Input.GetKeyDown(LeashConfig.ToggleKey.Value)) { LeashConfig.ReloadFromDisk(); PlayerCharacter val = FindPlayerYouAreLookingAt(player); if ((Object)(object)val == (Object)null || !TryGetNetId(val, out var netId2)) { Plugin.Log.LogInfo((object)"No nearby player in view to leash."); } else if (LeashState.TryGetForTarget(netId2, out link4)) { Plugin.Log.LogInfo((object)"That player is already leashed."); } else { LeashNet.RequestAttach(netId, netId2, chatRestricted); } } } private static PlayerCharacter FindPlayerYouAreLookingAt(PlayerCharacter local) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008d: 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_0093: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)local.cameraTransform == (Object)null || (Object)(object)local.kernal == (Object)null || PlayerCharacter.allPlayerCharacters == null) { return null; } Vector3 position = local.cameraTransform.position; Vector3 forward = local.cameraTransform.forward; float num = 0.8f; PlayerCharacter result = null; List allPlayerCharacters = PlayerCharacter.allPlayerCharacters; for (int i = 0; i < allPlayerCharacters.Count; i++) { PlayerCharacter val = allPlayerCharacters[i]; if (!IsAlive(val) || (Object)(object)val == (Object)(object)local || (Object)(object)val.kernal == (Object)null) { continue; } Vector3 val2 = val.kernal.position - position; float magnitude = ((Vector3)(ref val2)).magnitude; if (!(magnitude > LeashConfig.AttachRange.Value) && !(magnitude < 0.01f)) { float num2 = Vector3.Dot(forward, val2 / magnitude); if (num2 > num) { num = num2; result = val; } } } return result; } private void UpdateVisuals() { //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) UpdateStandingCalibrations(); activeTargets.Clear(); foreach (LeashLink item in LeashState.All) { activeTargets.Add(item.TargetId); if (TryFindPlayer(item.HolderId, out var player) && TryFindPlayer(item.TargetId, out var player2)) { if (!visuals.TryGetValue(item.TargetId, out var value)) { value = new RopeVisual(); visuals.Add(item.TargetId, value); } value.Draw(player, player2, item.Colour, useFirstPersonAnchor: true, forceFirstPersonAnchor: false); } } PlayerCharacter player4; if (debugPreview && TryFindLocalPlayer(out var player3)) { activeTargets.Add(uint.MaxValue); if (!visuals.TryGetValue(uint.MaxValue, out var value2)) { value2 = new RopeVisual(); visuals.Add(uint.MaxValue, value2); } value2.Draw(player3, player3, LeashConfig.LeashColour, useFirstPersonAnchor: false, forceFirstPersonAnchor: false); } else if (firstPersonPreview && TryFindLocalPlayer(out player4)) { activeTargets.Add(uint.MaxValue); if (!visuals.TryGetValue(uint.MaxValue, out var value3)) { value3 = new RopeVisual(); visuals.Add(uint.MaxValue, value3); } value3.Draw(player4, player4, LeashConfig.LeashColour, useFirstPersonAnchor: true, forceFirstPersonAnchor: true); } removeVisuals.Clear(); foreach (KeyValuePair visual in visuals) { if (!activeTargets.Contains(visual.Key)) { visual.Value.Dispose(); removeVisuals.Add(visual.Key); } } foreach (uint removeVisual in removeVisuals) { visuals.Remove(removeVisual); } } private void UpdateStandingCalibrations() { //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_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) if (Time.unscaledTime < nextStandingCalibrationSample) { return; } nextStandingCalibrationSample = Time.unscaledTime + 0.05f; if (PlayerCharacter.allPlayerCharacters == null) { return; } List allPlayerCharacters = PlayerCharacter.allPlayerCharacters; for (int i = 0; i < allPlayerCharacters.Count; i++) { PlayerCharacter val = allPlayerCharacters[i]; if (TryGetNetId(val, out var netId) && (!standingCalibrations.TryGetValue(netId, out var value) || !(value.Time >= 1f)) && RopeVisual.TryGetStandingData(val, out var offset, out var boneLocalPosition)) { if (!standingCalibrations.TryGetValue(netId, out var value2)) { value2 = new StandingCalibration(); standingCalibrations.Add(netId, value2); } if (value2.Time < 1f) { StandingCalibration standingCalibration = value2; standingCalibration.OffsetTotal += offset; value2.Samples++; value2.Offset = value2.OffsetTotal / (float)value2.Samples; value2.BoneLocalPosition = boneLocalPosition; value2.Time += 0.05f; } } } } private static bool TryGetStandingCalibration(PlayerCharacter player, out Vector3 offset, out Vector3 boneLocalPosition) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) offset = Vector3.zero; boneLocalPosition = Vector3.zero; if ((Object)(object)instance == (Object)null || !TryGetNetId(player, out var netId) || !instance.standingCalibrations.TryGetValue(netId, out var value) || value.Time < 1f) { return false; } offset = value.Offset; boneLocalPosition = value.BoneLocalPosition; return true; } internal static void EnforceDistance(PlayerMover mover) { //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0072: 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_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) PlayerCharacter pc = mover.pc; if (!IsAlive(pc) || !((NetworkBehaviour)pc).isLocalPlayer || !TryGetNetId(pc, out var netId) || !LeashState.TryGetForTarget(netId, out var link) || !TryFindPlayer(link.HolderId, out var player) || (Object)(object)pc.kernal == (Object)null || (Object)(object)player.kernal == (Object)null || (Object)(object)pc.rb == (Object)null) { return; } Vector3 position = player.kernal.position; Vector3 val = pc.kernal.position - position; float magnitude = ((Vector3)(ref val)).magnitude; float num = link.Length + (AreCarriedTogether(player, pc) ? 0.5f : 0f); if (!(magnitude <= num) && !(magnitude < 0.001f)) { Vector3 val2 = val / magnitude; Vector3 val3 = pc.rb.linearVelocity; float num2 = Vector3.Dot(val3, val2); if (num2 > 0f) { val3 -= val2 * num2; } float num3 = Mathf.Min((magnitude - num) * LeashConfig.PullStrength.Value, LeashConfig.PullStrength.Value); pc.rb.linearVelocity = val3 - val2 * num3; } } private static bool AreCarriedTogether(PlayerCharacter holder, PlayerCharacter target) { if (!IsHeldBy(target, holder)) { return IsHeldBy(holder, target); } return true; } private static bool IsHeldBy(PlayerCharacter carried, PlayerCharacter carrier) { if ((Object)(object)carried.kernal == (Object)null || (Object)(object)carrier.kernal == (Object)null) { return false; } Transform parent = carried.kernal.parent; while ((Object)(object)parent != (Object)null) { if ((Object)(object)parent == (Object)(object)carrier.kernal) { return true; } GrabKernal component = ((Component)parent).GetComponent(); if ((Object)(object)component != (Object)null && (Object)(object)component.playerCharacter == (Object)(object)carrier) { return true; } parent = parent.parent; } return false; } internal static bool TryFindPlayer(uint netId, out PlayerCharacter player) { player = null; List allPlayerCharacters = PlayerCharacter.allPlayerCharacters; if (allPlayerCharacters == null) { return false; } for (int i = 0; i < allPlayerCharacters.Count; i++) { PlayerCharacter val = allPlayerCharacters[i]; if (IsAlive(val) && TryGetNetId(val, out var netId2) && netId2 == netId) { player = val; return true; } } return false; } private static bool TryFindLocalPlayer(out PlayerCharacter player) { player = null; List allPlayerCharacters = PlayerCharacter.allPlayerCharacters; if (allPlayerCharacters == null) { return false; } for (int i = 0; i < allPlayerCharacters.Count; i++) { PlayerCharacter val = allPlayerCharacters[i]; if (IsAlive(val) && ((NetworkBehaviour)val).isLocalPlayer) { player = val; return true; } } return false; } internal static bool TryGetLocalNetId(out uint netId) { netId = 0u; if (TryFindLocalPlayer(out var player)) { return TryGetNetId(player, out netId); } return false; } internal static bool IsLeashed(PlayerCharacter player) { LeashLink link; if (TryGetNetId(player, out var netId)) { return LeashState.TryGetForTarget(netId, out link); } return false; } internal static bool IsChatRestricted(PlayerCharacter player) { if (TryGetNetId(player, out var netId) && LeashState.TryGetForTarget(netId, out var link)) { return link.ChatRestricted; } return false; } private static bool TryGetNetId(PlayerCharacter player, out uint netId) { netId = 0u; if (!IsAlive(player) || (Object)(object)player.playerNetworking == (Object)null) { return false; } netId = ((NetworkBehaviour)player.playerNetworking).netId; return netId != 0; } private static bool IsAlive(PlayerCharacter player) { return (Object)(object)player != (Object)null; } } [HarmonyPatch(typeof(PlayerTexter), "CompleteInput")] internal static class LeashedChatPatch { [HarmonyPrefix] private static void BeforeSend(PlayerTexter __instance, ref string message) { if (!((Object)(object)__instance.playerCharacter == (Object)null) && LeashController.IsChatRestricted(__instance.playerCharacter)) { string[] array = message.Split((char[]?)null, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < array.Length; i++) { array[i] = ((Random.value < 0.5f) ? "woof" : "bark"); } message = string.Join(" ", array); } } } internal static class LeashNet { private const ushort FunctionHash = 52193; private const uint Magic = 1280526385u; private const byte Protocol = 4; private const byte AttachRequest = 1; private const byte ReleaseRequest = 2; private const byte SyncAttach = 3; private const byte SyncRelease = 4; private const byte ColourRequest = 5; private const byte LengthRequest = 6; private const byte ChatRequest = 7; private const int PayloadSize = 22; private static MethodInfo bufferRpc; internal static void Install(Harmony harmony) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Expected O, but got Unknown //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Expected O, but got Unknown harmony.Patch((MethodBase)AccessTools.Method(typeof(NetworkServer), "OnCommandMessage", (Type[])null, (Type[])null), new HarmonyMethod(typeof(LeashNet), "OnCommandMessage", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)AccessTools.Method(typeof(NetworkClient), "OnRPCMessage", (Type[])null, (Type[])null), new HarmonyMethod(typeof(LeashNet), "OnRpcMessage", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); bufferRpc = AccessTools.Method(typeof(NetworkConnectionToClient), "BufferRpc", new Type[2] { typeof(RpcMessage), typeof(int) }, (Type[])null); if (bufferRpc == null) { Plugin.Log.LogError((object)"Could not access Mirror's RPC relay; leash links will not synchronize."); } } internal static void RequestAttach(uint holderId, uint targetId, bool chatRestricted) { //IL_003f: 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) float num = Mathf.Clamp(LeashConfig.LeashLength.Value * 0.5f, 1.5f, LeashConfig.LeashLength.Value); if (NetworkServer.active) { AttachOnServer(holderId, targetId, LeashConfig.LeashColour, num, chatRestricted); } else { SendCommand(1, holderId, targetId, num, LeashConfig.LeashColour, chatRestricted); } } internal static void RequestRelease(uint holderId, uint targetId) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) if (NetworkServer.active) { ReleaseOnServer(holderId, targetId); } else { SendCommand(2, holderId, targetId, 0f, Color.white, chatRestricted: false); } } internal static void RequestColourUpdate(uint holderId) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) if (LeashState.TryGetForHolder(holderId, out var link)) { if (NetworkServer.active) { UpdateColourOnServer(holderId, link.TargetId, LeashConfig.LeashColour); } else { SendCommand(5, holderId, link.TargetId, 0f, LeashConfig.LeashColour, chatRestricted: false); } } } internal static void RequestLengthUpdate(uint holderId, float length) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) if (LeashState.TryGetForHolder(holderId, out var link)) { if (NetworkServer.active) { UpdateLengthOnServer(holderId, link.TargetId, length); } else { SendCommand(6, holderId, link.TargetId, length, Color.white, chatRestricted: false); } } } internal static void RequestChatRestrictionUpdate(uint holderId, bool chatRestricted) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) if (LeashState.TryGetForHolder(holderId, out var link)) { if (NetworkServer.active) { UpdateChatRestrictionOnServer(holderId, link.TargetId, chatRestricted); } else { SendCommand(7, holderId, link.TargetId, 0f, Color.white, chatRestricted); } } } internal static void RebroadcastCurrentLinks() { //IL_0030: Unknown result type (might be due to invalid IL or missing references) if (!NetworkServer.active) { return; } foreach (LeashLink item in LeashState.All) { Relay(3, item.HolderId, item.TargetId, item.Length, item.Colour, item.ChatRestricted); } } private static void SendCommand(byte packetType, uint holderId, uint targetId, float length, Color colour, bool chatRestricted) { //IL_003e: Unknown result type (might be due to invalid IL or missing references) if (!NetworkClient.active || NetworkClient.connection == null) { return; } NetworkWriterPooled val = NetworkWriterPool.Get(); try { NetworkWriterExtensions.WriteUShort((NetworkWriter)(object)val, NetworkMessages.GetId()); NetworkWriterExtensions.WriteUInt((NetworkWriter)(object)val, holderId); ((NetworkWriter)val).WriteByte((byte)0); NetworkWriterExtensions.WriteUShort((NetworkWriter)(object)val, (ushort)52193); NetworkWriterExtensions.WriteBytesAndSize((NetworkWriter)(object)val, BuildPayload(packetType, holderId, targetId, length, colour, chatRestricted)); NetworkClient.connection.Send(((NetworkWriter)val).ToArraySegment(), Channels.Reliable); } finally { NetworkWriterPool.Return(val); } } private static Il2CppStructArray BuildPayload(byte packetType, uint holderId, uint targetId, float length, Color colour, bool chatRestricted) { //IL_0035: 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_0071: Unknown result type (might be due to invalid IL or missing references) NetworkWriterPooled val = NetworkWriterPool.Get(); try { NetworkWriterExtensions.WriteUInt((NetworkWriter)(object)val, 1280526385u); ((NetworkWriter)val).WriteByte((byte)4); ((NetworkWriter)val).WriteByte(packetType); NetworkWriterExtensions.WriteUInt((NetworkWriter)(object)val, holderId); NetworkWriterExtensions.WriteUInt((NetworkWriter)(object)val, targetId); NetworkWriterExtensions.WriteFloat((NetworkWriter)(object)val, length); ((NetworkWriter)val).WriteByte((byte)Mathf.RoundToInt(Mathf.Clamp01(colour.r) * 255f)); ((NetworkWriter)val).WriteByte((byte)Mathf.RoundToInt(Mathf.Clamp01(colour.g) * 255f)); ((NetworkWriter)val).WriteByte((byte)Mathf.RoundToInt(Mathf.Clamp01(colour.b) * 255f)); ((NetworkWriter)val).WriteByte(chatRestricted ? ((byte)1) : ((byte)0)); return ((NetworkWriter)val).ToArray(); } finally { NetworkWriterPool.Return(val); } } private static bool TryRead(ArraySegment payload, out NetworkReader reader, out byte packetType, out uint holderId, out uint targetId, out float length, out Color colour, out bool chatRestricted) { //IL_0017: 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_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) reader = null; packetType = 0; holderId = 0u; targetId = 0u; length = 0f; colour = Color.white; chatRestricted = false; if (payload.Count < 22) { return false; } reader = new NetworkReader(payload); if (NetworkReaderExtensions.ReadUInt(reader) != 1280526385 || reader.ReadByte() != 4) { return false; } packetType = reader.ReadByte(); holderId = NetworkReaderExtensions.ReadUInt(reader); targetId = NetworkReaderExtensions.ReadUInt(reader); length = NetworkReaderExtensions.ReadFloat(reader); colour = new Color((float)(int)reader.ReadByte() / 255f, (float)(int)reader.ReadByte() / 255f, (float)(int)reader.ReadByte() / 255f, 1f); chatRestricted = reader.ReadByte() != 0; return float.IsFinite(length); } private static bool OnCommandMessage(NetworkConnectionToClient conn, CommandMessage msg, int channelId) { //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) if (msg.functionHash != 52193) { return true; } if (!TryRead(msg.payload, out var _, out var packetType, out var holderId, out var targetId, out var length, out var colour, out var chatRestricted)) { return false; } NetworkIdentity identity = ((NetworkConnection)conn).identity; if ((Object)(object)identity == (Object)null || identity.netId != msg.netId) { return false; } switch (packetType) { case 1: if (identity.netId != holderId) { return false; } AttachOnServer(holderId, targetId, colour, length, chatRestricted); return false; case 2: if (identity.netId != holderId && identity.netId != targetId) { return false; } ReleaseOnServer(holderId, targetId); return false; case 5: if (identity.netId != holderId) { return false; } UpdateColourOnServer(holderId, targetId, colour); return false; case 6: if (identity.netId != holderId) { return false; } UpdateLengthOnServer(holderId, targetId, length); return false; case 7: if (identity.netId != holderId) { return false; } UpdateChatRestrictionOnServer(holderId, targetId, chatRestricted); return false; default: return false; } } private static bool OnRpcMessage(RpcMessage message) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) if (message.functionHash != 52193) { return true; } if (!TryRead(message.payload, out var _, out var packetType, out var holderId, out var targetId, out var length, out var colour, out var chatRestricted)) { return false; } switch (packetType) { case 3: LeashState.Set(holderId, targetId, length, colour, chatRestricted); return false; case 4: LeashState.Remove(holderId, targetId); return false; default: return false; } } private static void AttachOnServer(uint holderId, uint targetId, Color colour, float requestedLength, bool chatRestricted) { //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0062: 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_009c: Unknown result type (might be due to invalid IL or missing references) if (holderId != 0 && holderId != targetId && LeashController.TryFindPlayer(holderId, out var player) && LeashController.TryFindPlayer(targetId, out var player2) && !LeashState.TryGetForTarget(holderId, out var link) && !LeashState.TryGetForHolder(holderId, out link) && !LeashState.TryGetForTarget(targetId, out link)) { Transform kernal = player.kernal; Transform kernal2 = player2.kernal; if (!((Object)(object)kernal == (Object)null) && !((Object)(object)kernal2 == (Object)null) && !(Vector3.Distance(kernal.position, kernal2.position) > LeashConfig.AttachRange.Value)) { float length = Mathf.Clamp(requestedLength, 1.5f, 20f); LeashState.Set(holderId, targetId, length, colour, chatRestricted); Relay(3, holderId, targetId, length, colour, chatRestricted); } } } private static void ReleaseOnServer(uint holderId, uint targetId) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) if (LeashState.TryGetForTarget(targetId, out var link) && link.HolderId == holderId) { LeashState.Remove(holderId, targetId); Relay(4, holderId, targetId, 0f, Color.white, chatRestricted: false); } } private static void UpdateColourOnServer(uint holderId, uint targetId, Color colour) { //IL_001c: 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) if (LeashState.TryGetForTarget(targetId, out var link) && link.HolderId == holderId) { LeashState.Set(holderId, targetId, link.Length, colour, link.ChatRestricted); Relay(3, holderId, targetId, link.Length, colour, link.ChatRestricted); } } private static void UpdateLengthOnServer(uint holderId, uint targetId, float length) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) if (LeashState.TryGetForTarget(targetId, out var link) && link.HolderId == holderId) { float length2 = Mathf.Clamp(length, 1.5f, 20f); LeashState.Set(holderId, targetId, length2, link.Colour, link.ChatRestricted); Relay(3, holderId, targetId, length2, link.Colour, link.ChatRestricted); } } private static void UpdateChatRestrictionOnServer(uint holderId, uint targetId, bool chatRestricted) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) if (LeashState.TryGetForTarget(targetId, out var link) && link.HolderId == holderId) { LeashState.Set(holderId, targetId, link.Length, link.Colour, chatRestricted); Relay(3, holderId, targetId, link.Length, link.Colour, chatRestricted); } } private static void Relay(byte packetType, uint holderId, uint targetId, float length, Color colour, bool chatRestricted) { //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Expected O, but got Unknown //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Expected O, but got Unknown //IL_00da: Unknown result type (might be due to invalid IL or missing references) if (bufferRpc == null) { return; } RpcMessage val = new RpcMessage { netId = targetId, componentIndex = 0, functionHash = 52193, payload = new ArraySegment((Il2CppArrayBase)(object)BuildPayload(packetType, holderId, targetId, length, colour, chatRestricted)) }; Enumerator enumerator = NetworkServer.connections.Values.GetEnumerator(); bool flag = default(bool); while (enumerator.MoveNext()) { NetworkConnectionToClient current = enumerator.Current; if (!((NetworkConnection)current).isReady) { continue; } try { bufferRpc.Invoke(current, new object[2] { val, Channels.Reliable }); } catch (Exception ex) { ManualLogSource log = Plugin.Log; BepInExWarningLogInterpolatedStringHandler val2 = new BepInExWarningLogInterpolatedStringHandler(35, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Could not synchronize leash state: "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(ex.Message); } log.LogWarning(val2); } } if (NetworkClient.active) { if (packetType == 3) { LeashState.Set(holderId, targetId, length, colour, chatRestricted); } else { LeashState.Remove(holderId, targetId); } } } } internal readonly struct LeashLink { internal readonly uint HolderId; internal readonly uint TargetId; internal readonly float Length; internal readonly Color Colour; internal readonly bool ChatRestricted; internal LeashLink(uint holderId, uint targetId, float length, Color colour, bool chatRestricted) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) HolderId = holderId; TargetId = targetId; Length = length; Colour = colour; ChatRestricted = chatRestricted; } } internal static class LeashState { private static readonly Dictionary ByTarget = new Dictionary(); internal static IEnumerable All => ByTarget.Values; internal static bool TryGetForTarget(uint targetId, out LeashLink link) { return ByTarget.TryGetValue(targetId, out link); } internal static bool TryGetForHolder(uint holderId, out LeashLink link) { foreach (LeashLink value in ByTarget.Values) { if (value.HolderId == holderId) { link = value; return true; } } link = default(LeashLink); return false; } internal static void Set(uint holderId, uint targetId, float length, Color colour, bool chatRestricted) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) RemoveWhere(holderId, targetId); ByTarget[targetId] = new LeashLink(holderId, targetId, length, colour, chatRestricted); } internal static void Remove(uint holderId, uint targetId) { if (ByTarget.TryGetValue(targetId, out var value) && value.HolderId == holderId) { ByTarget.Remove(targetId); } } internal static void RemoveWhere(uint holderId, uint targetId) { List list = new List(); foreach (KeyValuePair item in ByTarget) { if (item.Value.HolderId == holderId || item.Value.TargetId == targetId) { list.Add(item.Key); } } foreach (uint item2 in list) { ByTarget.Remove(item2); } } internal static void Clear() { ByTarget.Clear(); } } [HarmonyPatch(typeof(PlayerArms), "LateUpdate")] internal static class PlayerArmsPatch { [HarmonyPostfix] private static void AfterArms(PlayerArms __instance) { LeashController.RefreshHandAnchor(__instance); } } [HarmonyPatch(typeof(PlayerMover), "FixedUpdate")] internal static class PlayerMoverPatch { [HarmonyPostfix] private static void AfterMovement(PlayerMover __instance) { LeashController.EnforceDistance(__instance); } } [BepInPlugin("com.henssler.bigwalk.leash", "Big Walkies", "1.1.32")] public sealed class Plugin : BasePlugin { public const string PluginGuid = "com.henssler.bigwalk.leash"; public const string PluginName = "Big Walkies"; public const string PluginVersion = "1.1.32"; internal static ManualLogSource Log; public override void Load() { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Expected O, but got Unknown Log = ((BasePlugin)this).Log; LeashConfig.Bind(((BasePlugin)this).Config); ClassInjector.RegisterTypeInIl2Cpp(); GameObject val = new GameObject("BigWalkLeash_Controller"); Object.DontDestroyOnLoad((Object)val); val.AddComponent(); Harmony val2 = new Harmony("com.henssler.bigwalk.leash"); val2.PatchAll(); LeashNet.Install(val2); Log.LogInfo((object)"Big Walk Leash loaded. Everyone in the walk needs this mod for a shared leash."); } }