Decompiled source of BigWalkLeash v1.1.13

BepInEx/plugins/BigWalkLeash/BigWalkLeash.dll

Decompiled 3 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.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<KeyCode> ToggleKey;

	internal static ConfigEntry<KeyCode> EmergencyReleaseKey;

	internal static ConfigEntry<KeyCode> DebugPreviewKey;

	internal static ConfigEntry<KeyCode> DebugFirstPersonPreviewKey;

	internal static ConfigEntry<KeyCode> ColourMenuKey;

	internal static ConfigEntry<float> LeashLength;

	internal static ConfigEntry<float> AttachRange;

	internal static ConfigEntry<float> PullStrength;

	internal static ConfigEntry<float> RopeWidth;

	internal static ConfigEntry<bool> ShowCollar;

	internal static ConfigEntry<float> CollarRadius;

	internal static ConfigEntry<float> CollarHeightOffset;

	internal static ConfigEntry<float> CollarDepthOffset;

	internal static ConfigEntry<float> CollarDepthFineTune;

	internal static ConfigEntry<float> CrouchHorizontalFollow;

	internal static ConfigEntry<float> JumpHorizontalFollow;

	internal static ConfigEntry<float> CrouchTiltDegrees;

	internal static ConfigEntry<float> CollarTiltFollow;

	internal static ConfigEntry<float> LeashColourRed;

	internal static ConfigEntry<float> LeashColourGreen;

	internal static ConfigEntry<float> LeashColourBlue;

	internal static ConfigEntry<float> LocalFirstPersonCollarScale;

	internal static ConfigEntry<float> ColourMenuScale;

	internal static ConfigEntry<float> LocalFirstPersonAnchorHeight;

	internal static ConfigEntry<float> LocalFirstPersonAnchorBehind;

	internal static Color LeashColour => new Color(LeashColourRed.Value, LeashColourGreen.Value, LeashColourBlue.Value, 1f);

	internal static void Bind(ConfigFile config)
	{
		//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cd: Expected O, but got Unknown
		//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0105: Expected O, but got Unknown
		//IL_0133: Unknown result type (might be due to invalid IL or missing references)
		//IL_013d: Expected O, but got Unknown
		//IL_016b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0175: Expected O, but got Unknown
		//IL_01be: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c8: Expected O, but got Unknown
		//IL_01f6: Unknown result type (might be due to invalid IL or missing references)
		//IL_0200: Expected O, but got Unknown
		//IL_022e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0238: Expected O, but got Unknown
		//IL_0266: Unknown result type (might be due to invalid IL or missing references)
		//IL_0270: Expected O, but got Unknown
		//IL_029e: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a8: Expected O, but got Unknown
		//IL_02d6: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e0: Expected O, but got Unknown
		//IL_030e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0318: Expected O, but got Unknown
		//IL_0346: Unknown result type (might be due to invalid IL or missing references)
		//IL_0350: Expected O, but got Unknown
		//IL_037e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0388: Expected O, but got Unknown
		//IL_03b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_03c0: Expected O, but got Unknown
		//IL_03ee: Unknown result type (might be due to invalid IL or missing references)
		//IL_03f8: Expected O, but got Unknown
		//IL_0426: Unknown result type (might be due to invalid IL or missing references)
		//IL_0430: Expected O, but got Unknown
		//IL_045e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0468: Expected O, but got Unknown
		//IL_0496: Unknown result type (might be due to invalid IL or missing references)
		//IL_04a0: Expected O, but got Unknown
		//IL_04ce: Unknown result type (might be due to invalid IL or missing references)
		//IL_04d8: Expected O, but got Unknown
		file = config;
		ToggleKey = config.Bind<KeyCode>("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<KeyCode>("Controls", "EmergencyRelease", (KeyCode)8, "The leashed player can always press this key to immediately remove their leash.");
		DebugPreviewKey = config.Bind<KeyCode>("Debug", "ToggleSelfPreview", (KeyCode)289, "Toggles a local-only preview rope between your right hand and your own neck. It does not affect movement or other players.");
		DebugFirstPersonPreviewKey = config.Bind<KeyCode>("Debug", "ToggleFirstPersonPreview", (KeyCode)290, "Toggles a local-only preview using the same hidden first-person rope endpoint.");
		ColourMenuKey = config.Bind<KeyCode>("Controls", "OpenColourMenu", (KeyCode)288, "Opens the in-game leash colour panel.");
		LeashLength = config.Bind<float>("Host settings", "LeashLengthMetres", 5f, new ConfigDescription("Maximum separation. The host's value is used for the whole walk.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 20f), Array.Empty<object>()));
		AttachRange = config.Bind<float>("Host settings", "AttachRangeMetres", 4f, new ConfigDescription("How close a player must be before a leash can be attached.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 8f), Array.Empty<object>()));
		PullStrength = config.Bind<float>("Host settings", "PullBackStrength", 18f, new ConfigDescription("How quickly the leashed player is corrected when reaching the end.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 60f), Array.Empty<object>()));
		RopeWidth = config.Bind<float>("Visuals", "RopeWidth", 0.045f, new ConfigDescription("Thickness of the visible rope.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.01f, 0.2f), Array.Empty<object>()));
		ShowCollar = config.Bind<bool>("Visuals", "ShowCollar", true, "Show a soft orange collar on the leashed player.");
		CollarRadius = config.Bind<float>("Visuals", "CollarRadius", 0.11f, new ConfigDescription("Radius of the visible neck collar.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.06f, 0.35f), Array.Empty<object>()));
		CollarHeightOffset = config.Bind<float>("Visuals", "CollarHeightOffset", -0.005f, new ConfigDescription("Fine-tunes the collar height. Zero is the tested neck position.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-0.5f, 1.5f), Array.Empty<object>()));
		CollarDepthOffset = config.Bind<float>("Visuals", "CollarDepthOffset", 0.02f, new ConfigDescription("Moves the collar forward (positive) or backward (negative).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-0.5f, 0.5f), Array.Empty<object>()));
		CollarDepthFineTune = config.Bind<float>("Visuals", "CollarDepthFineTune", 0f, new ConfigDescription("Extra depth adjustment in tiny 0.001-unit steps. Keep the main depth value as your working baseline.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-50f, 50f), Array.Empty<object>()));
		CrouchHorizontalFollow = config.Bind<float>("Visuals", "CrouchHorizontalFollow", 0.5f, 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<float>(0f, 1f), Array.Empty<object>()));
		JumpHorizontalFollow = config.Bind<float>("Visuals", "JumpHorizontalFollow", 0.5f, 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<float>(0f, 1f), Array.Empty<object>()));
		CrouchTiltDegrees = config.Bind<float>("Visuals", "CrouchTiltDegrees", 12f, new ConfigDescription("Extra forward tilt applied at a full crouch, because the crouch pose does not rotate the head bone.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-45f, 45f), Array.Empty<object>()));
		CollarTiltFollow = config.Bind<float>("Visuals", "CollarTiltFollow", 0.5f, new ConfigDescription("How much the collar tilts with the head. 0 stays level; 1 fully follows the head tilt.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
		LeashColourRed = config.Bind<float>("Colour", "Red", 0.95f, new ConfigDescription("Leash colour red component.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
		LeashColourGreen = config.Bind<float>("Colour", "Green", 0.45f, new ConfigDescription("Leash colour green component.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
		LeashColourBlue = config.Bind<float>("Colour", "Blue", 0.08f, new ConfigDescription("Leash colour blue component.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
		LocalFirstPersonCollarScale = config.Bind<float>("Visuals", "LocalFirstPersonCollarScale", 0.5f, new ConfigDescription("Scale of your own collar in first-person view. Other players always see the normal size.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 1f), Array.Empty<object>()));
		ColourMenuScale = config.Bind<float>("Colour", "MenuScale", 1.6f, new ConfigDescription("Scale of the in-game F7 colour panel.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.75f, 3f), Array.Empty<object>()));
		LocalFirstPersonAnchorHeight = config.Bind<float>("Visuals", "LocalFirstPersonAnchorHeight", -0.3f, new ConfigDescription("Moves only your own first-person rope endpoint up or down from the camera.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-1f, 1f), Array.Empty<object>()));
		LocalFirstPersonAnchorBehind = config.Bind<float>("Visuals", "LocalFirstPersonAnchorBehind", 1.2f, new ConfigDescription("Moves only your own first-person rope endpoint behind the camera.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1.5f), Array.Empty<object>()));
	}

	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 RopeVisual
	{
		private const float NeckHeightBaseline = -0.19f;

		private readonly GameObject ropeObject;

		private readonly LineRenderer rope;

		private readonly GameObject collarObject;

		private readonly LineRenderer collar;

		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_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Expected O, but got Unknown
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Expected O, but got Unknown
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Expected O, but got Unknown
			ropeObject = new GameObject("Big Walk Leash Rope");
			Object.DontDestroyOnLoad((Object)(object)ropeObject);
			rope = ropeObject.AddComponent<LineRenderer>();
			rope.positionCount = 20;
			rope.numCapVertices = 3;
			rope.widthMultiplier = LeashConfig.RopeWidth.Value;
			((Renderer)rope).material = new Material(Shader.Find("Sprites/Default"));
			collarObject = new GameObject("Big Walk Leash Collar");
			Object.DontDestroyOnLoad((Object)(object)collarObject);
			collar = collarObject.AddComponent<LineRenderer>();
			collar.positionCount = 20;
			collar.loop = true;
			collar.useWorldSpace = false;
			collar.numCapVertices = 3;
			collar.widthMultiplier = 0.035f;
			((Renderer)collar).material = new Material(Shader.Find("Sprites/Default"));
		}

		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_00ec: 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_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_00ce: 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_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: 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)
			//IL_0128: 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_034b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0350: Unknown result type (might be due to invalid IL or missing references)
			//IL_0376: Unknown result type (might be due to invalid IL or missing references)
			//IL_035c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0360: Unknown result type (might be due to invalid IL or missing references)
			//IL_036f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_0378: Unknown result type (might be due to invalid IL or missing references)
			//IL_0390: Unknown result type (might be due to invalid IL or missing references)
			//IL_0392: Unknown result type (might be due to invalid IL or missing references)
			//IL_0397: Unknown result type (might be due to invalid IL or missing references)
			//IL_039c: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_041b: Unknown result type (might be due to invalid IL or missing references)
			//IL_041d: Unknown result type (might be due to invalid IL or missing references)
			//IL_041f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0424: Unknown result type (might be due to invalid IL or missing references)
			//IL_042b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0430: Unknown result type (might be due to invalid IL or missing references)
			//IL_0435: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_03cc: 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_03dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e1: 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_03fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0437: Unknown result type (might be due to invalid IL or missing references)
			//IL_0439: Unknown result type (might be due to invalid IL or missing references)
			//IL_043e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0443: Unknown result type (might be due to invalid IL or missing references)
			//IL_0448: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: 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_01ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0485: Unknown result type (might be due to invalid IL or missing references)
			//IL_0473: Unknown result type (might be due to invalid IL or missing references)
			//IL_0475: 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_0487: 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_04b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_04bf: 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_04d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_029e: Unknown result type (might be due to invalid IL or missing references)
			//IL_021d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0222: Unknown result type (might be due to invalid IL or missing references)
			//IL_0227: Unknown result type (might be due to invalid IL or missing references)
			//IL_022b: 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_0235: Unknown result type (might be due to invalid IL or missing references)
			//IL_023a: Unknown result type (might be due to invalid IL or missing references)
			//IL_023e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0243: Unknown result type (might be due to invalid IL or missing references)
			//IL_0245: Unknown result type (might be due to invalid IL or missing references)
			//IL_024a: Unknown result type (might be due to invalid IL or missing references)
			//IL_025f: Unknown result type (might be due to invalid IL or missing references)
			//IL_026b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0270: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02af: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_050c: Unknown result type (might be due to invalid IL or missing references)
			//IL_050e: Unknown result type (might be due to invalid IL or missing references)
			//IL_02dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_02df: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_056a: 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_0323: Unknown result type (might be due to invalid IL or missing references)
			//IL_032b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0330: 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_033f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0344: Unknown result type (might be due to invalid IL or missing references)
			//IL_0349: 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);
			float num3 = -0.19f + LeashConfig.CollarHeightOffset.Value - 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 flag2 = target.ground != null && target.ground.isGrounded;
				if (!hasStandingBonePosition && num2 < 0.01f && flag2)
				{
					collarBone = val3;
					collarOffsetFromBone = Quaternion.Inverse(LevelRotation(target.kernal)) * (val2 - val3.position);
					standingBoneLocalPosition = val5;
					hasStandingBonePosition = true;
				}
				if (hasStandingBonePosition && num2 < 0.01f && flag2 && standingCalibrationTime < 1f)
				{
					Vector3 val6 = Quaternion.Inverse(LevelRotation(target.kernal)) * (val2 - val3.position);
					standingOffsetTotal += val6;
					standingOffsetSamples++;
					collarOffsetFromBone = standingOffsetTotal / (float)standingOffsetSamples;
					standingCalibrationTime += Time.deltaTime;
				}
				val4 = (((Object)(object)collarBone == (Object)(object)val3 && hasStandingBonePosition) ? (val3.position + LevelRotation(target.kernal) * collarOffsetFromBone) : val2);
				if (hasStandingBonePosition && !(num2 < 0.01f && flag2))
				{
					Vector3 val7 = val5 - standingBoneLocalPosition;
					val7.y = 0f;
					float num4 = ((num2 >= 0.01f) ? LeashConfig.CrouchHorizontalFollow.Value : ((!flag2) ? LeashConfig.JumpHorizontalFollow.Value : 1f));
					val4 -= LevelRotation(target.kernal) * val7 * (1f - num4);
				}
			}
			Quaternion val8 = LevelRotation(kernal);
			Quaternion val9 = (((Object)(object)val3 == (Object)null) ? val8 : Quaternion.Slerp(val8, val3.rotation, LeashConfig.CollarTiltFollow.Value));
			if (num2 > 0.01f)
			{
				val9 = Quaternion.AngleAxis(LeashConfig.CrouchTiltDegrees.Value * num2, val8 * Vector3.right) * val9;
			}
			if (flag)
			{
				val4 = ViewTransform(target).position + Vector3.up * LeashConfig.LocalFirstPersonAnchorHeight.Value - LevelRotation(target.kernal) * Vector3.forward * LeashConfig.LocalFirstPersonAnchorBehind.Value;
			}
			else
			{
				float num5 = LeashConfig.CollarDepthOffset.Value + LeashConfig.CollarDepthFineTune.Value * 0.001f;
				val4 += val9 * Vector3.forward * num5;
			}
			Vector3 val10 = -(val9 * Vector3.forward);
			float num6 = (flag ? LeashConfig.LocalFirstPersonCollarScale.Value : 1f);
			float num7 = LeashConfig.CollarRadius.Value * num6;
			end = (flag ? val4 : (val4 + val10 * num7));
			rope.widthMultiplier = LeashConfig.RopeWidth.Value;
			rope.startColor = colour;
			rope.endColor = colour;
			collar.startColor = colour;
			collar.endColor = colour;
			DrawRope(start);
			bool flag3 = LeashConfig.ShowCollar.Value && !flag;
			collarObject.SetActive(flag3);
			if (flag3)
			{
				collarObject.transform.SetPositionAndRotation(val4, val9);
				collar.widthMultiplier = 0.035f * num6;
				float num8 = num7;
				for (int i = 0; i < collar.positionCount; i++)
				{
					float num9 = (float)i / (float)collar.positionCount * (float)Math.PI * 2f;
					collar.SetPosition(i, new Vector3(Mathf.Cos(num9), 0f, Mathf.Sin(num9)) * num8);
				}
			}
		}

		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)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);
		}

		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<uint, RopeVisual> visuals = new Dictionary<uint, RopeVisual>();

	private float nextStateBroadcast;

	private bool debugPreview;

	private bool firstPersonPreview;

	private bool showColourMenu;

	private float colourRed;

	private float colourGreen;

	private float colourBlue;

	private float leashLimit;

	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, 270f), "Big Walk Leash — Colour", GUI.skin.window);
		GUILayout.Label("Red", (Il2CppReferenceArray<GUILayoutOption>)null);
		colourRed = GUILayout.HorizontalSlider(colourRed, 0f, 1f, Array.Empty<GUILayoutOption>());
		GUILayout.Label("Green", (Il2CppReferenceArray<GUILayoutOption>)null);
		colourGreen = GUILayout.HorizontalSlider(colourGreen, 0f, 1f, Array.Empty<GUILayoutOption>());
		GUILayout.Label("Blue", (Il2CppReferenceArray<GUILayoutOption>)null);
		colourBlue = GUILayout.HorizontalSlider(colourBlue, 0f, 1f, Array.Empty<GUILayoutOption>());
		GUILayout.Space(6f);
		GUILayout.Label($"Max leash length: {leashLimit:0.0}m", (Il2CppReferenceArray<GUILayoutOption>)null);
		leashLimit = GUILayout.HorizontalSlider(leashLimit, 1f, 20f, Array.Empty<GUILayoutOption>());
		GUILayout.Space(8f);
		if (GUILayout.Button("Apply colour", (Il2CppReferenceArray<GUILayoutOption>)null))
		{
			LeashConfig.SetLeashColour(colourRed, colourGreen, colourBlue);
			LeashConfig.LeashLength.Value = leashLimit;
			if (TryGetLocalNetId(out var netId))
			{
				LeashNet.RequestColourUpdate(netId);
				LeashNet.RequestLengthUpdate(netId, leashLimit);
			}
		}
		if (GUILayout.Button("Close", (Il2CppReferenceArray<GUILayoutOption>)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_007f: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
		//IL_0125: Unknown result type (might be due to invalid IL or missing references)
		//IL_015c: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
		//IL_018a: Unknown result type (might be due to invalid IL or missing references)
		if (!TryFindLocalPlayer(out var player) || !TryGetNetId(player, out var netId))
		{
			return;
		}
		LeashLink link;
		LeashLink link2;
		LeashLink link3;
		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;
		}
		else if (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 (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 link))
		{
			LeashNet.RequestRelease(link.HolderId, link.TargetId);
		}
		else if (LeashState.TryGetForTarget(netId, out link2))
		{
			if (Input.GetKeyDown(LeashConfig.ToggleKey.Value))
			{
				Plugin.Log.LogInfo((object)"Leashed players cannot hold a leash.");
			}
		}
		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, 1f, LeashConfig.LeashLength.Value);
					LeashNet.RequestLengthUpdate(netId, length);
				}
			}
			if (Input.GetKeyDown(LeashConfig.ToggleKey.Value))
			{
				LeashNet.RequestRelease(link3.HolderId, link3.TargetId);
			}
		}
		else if (Input.GetKeyDown(LeashConfig.ToggleKey.Value))
		{
			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
			{
				LeashNet.RequestAttach(netId, netId2);
			}
		}
	}

	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<PlayerCharacter> 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_0082: 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_0139: Unknown result type (might be due to invalid IL or missing references)
		HashSet<uint> hashSet = new HashSet<uint>();
		foreach (LeashLink item in LeashState.All)
		{
			hashSet.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))
		{
			hashSet.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))
		{
			hashSet.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);
		}
		List<uint> list = new List<uint>();
		foreach (KeyValuePair<uint, RopeVisual> visual in visuals)
		{
			if (!hashSet.Contains(visual.Key))
			{
				visual.Value.Dispose();
				list.Add(visual.Key);
			}
		}
		foreach (uint item2 in list)
		{
			visuals.Remove(item2);
		}
	}

	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_00a5: 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_00ae: 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_00bd: 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_010e: 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_0114: Unknown result type (might be due to invalid IL or missing references)
		//IL_0119: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d1: 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_00d7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e1: 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;
		if (!(magnitude <= link.Length) && !(magnitude < 0.001f))
		{
			Vector3 val2 = val / magnitude;
			Vector3 val3 = pc.rb.linearVelocity;
			float num = Vector3.Dot(val3, val2);
			if (num > 0f)
			{
				val3 -= val2 * num;
			}
			float num2 = Mathf.Min((magnitude - link.Length) * LeashConfig.PullStrength.Value, LeashConfig.PullStrength.Value);
			pc.rb.linearVelocity = val3 - val2 * num2;
		}
	}

	internal static bool TryFindPlayer(uint netId, out PlayerCharacter player)
	{
		player = null;
		List<PlayerCharacter> 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<PlayerCharacter> 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;
	}

	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
{
	private static bool barkNext;

	[HarmonyPrefix]
	private static void BeforeSend(PlayerTexter __instance, ref string message)
	{
		if (!((Object)(object)__instance.playerCharacter == (Object)null) && LeashController.IsLeashed(__instance.playerCharacter))
		{
			message = (barkNext ? "bark" : "woof");
			barkNext = !barkNext;
		}
	}
}
internal static class LeashNet
{
	private const ushort FunctionHash = 52193;

	private const uint Magic = 1280526385u;

	private const byte Protocol = 3;

	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 int PayloadSize = 21;

	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)
	{
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0009: Unknown result type (might be due to invalid IL or missing references)
		if (NetworkServer.active)
		{
			AttachOnServer(holderId, targetId, LeashConfig.LeashColour, LeashConfig.LeashLength.Value);
		}
		else
		{
			SendCommand(1, holderId, targetId, LeashConfig.LeashLength.Value, LeashConfig.LeashColour);
		}
	}

	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);
		}
	}

	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);
			}
		}
	}

	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);
			}
		}
	}

	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);
		}
	}

	private static void SendCommand(byte packetType, uint holderId, uint targetId, float length, Color colour)
	{
		//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<CommandMessage>());
			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));
			NetworkClient.connection.Send(((NetworkWriter)val).ToArraySegment(), Channels.Reliable);
		}
		finally
		{
			NetworkWriterPool.Return(val);
		}
	}

	private static Il2CppStructArray<byte> BuildPayload(byte packetType, uint holderId, uint targetId, float length, Color colour)
	{
		//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)3);
			((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));
			return ((NetworkWriter)val).ToArray();
		}
		finally
		{
			NetworkWriterPool.Return(val);
		}
	}

	private static bool TryRead(ArraySegment<byte> payload, out NetworkReader reader, out byte packetType, out uint holderId, out uint targetId, out float length, out Color colour)
	{
		//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_002f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0035: Expected O, but got Unknown
		//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ab: 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;
		if (payload.Count < 21)
		{
			return false;
		}
		reader = new NetworkReader(payload);
		if (NetworkReaderExtensions.ReadUInt(reader) != 1280526385 || reader.ReadByte() != 3)
		{
			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);
		return float.IsFinite(length);
	}

	private static bool OnCommandMessage(NetworkConnectionToClient conn, CommandMessage msg, int channelId)
	{
		//IL_007d: 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)
		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))
		{
			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);
			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;
		default:
			return false;
		}
	}

	private static bool OnRpcMessage(RpcMessage message)
	{
		//IL_0037: 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))
		{
			return false;
		}
		switch (packetType)
		{
		case 3:
			LeashState.Set(holderId, targetId, length, colour);
			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)
	{
		//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_0070: Unknown result type (might be due to invalid IL or missing references)
		//IL_007b: 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))
		{
			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, 1f, 20f);
				LeashState.Set(holderId, targetId, length, colour);
				Relay(3, holderId, targetId, length, colour);
			}
		}
	}

	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);
		}
	}

	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_002b: 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);
			Relay(3, holderId, targetId, link.Length, colour);
		}
	}

	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_0038: 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, 1f, 20f);
			LeashState.Set(holderId, targetId, length2, link.Colour);
			Relay(3, holderId, targetId, length2, link.Colour);
		}
	}

	private static void Relay(byte packetType, uint holderId, uint targetId, float length, Color colour)
	{
		//IL_0095: Unknown result type (might be due to invalid IL or missing references)
		//IL_009c: 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_0043: Expected O, but got Unknown
		//IL_00d8: 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<byte>((Il2CppArrayBase<byte>)(object)BuildPayload(packetType, holderId, targetId, length, colour))
		};
		Enumerator<int, NetworkConnectionToClient> 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<string>(ex.Message);
				}
				log.LogWarning(val2);
			}
		}
		if (NetworkClient.active)
		{
			if (packetType == 3)
			{
				LeashState.Set(holderId, targetId, length, colour);
			}
			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 LeashLink(uint holderId, uint targetId, float length, Color colour)
	{
		//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;
	}
}
internal static class LeashState
{
	private static readonly Dictionary<uint, LeashLink> ByTarget = new Dictionary<uint, LeashLink>();

	internal static IEnumerable<LeashLink> 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)
	{
		//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);
	}

	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<uint> list = new List<uint>();
		foreach (KeyValuePair<uint, LeashLink> 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 Walk Leash", "1.1.13")]
public sealed class Plugin : BasePlugin
{
	public const string PluginGuid = "com.henssler.bigwalk.leash";

	public const string PluginName = "Big Walk Leash";

	public const string PluginVersion = "1.1.13";

	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<LeashController>();
		GameObject val = new GameObject("BigWalkLeash_Controller");
		Object.DontDestroyOnLoad((Object)val);
		val.AddComponent<LeashController>();
		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.");
	}
}