Decompiled source of Tied Together v1.0.1

TiedTogether.dll

Decompiled 2 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
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.Logging;
using ExitGames.Client.Photon;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using Photon.Realtime;
using UnityEngine;
using UnityEngine.Rendering;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("Omniscye")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("TiedTogether")]
[assembly: AssemblyTitle("TiedTogether")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace Empress.TiedTogether
{
	[BepInPlugin("Omniscye.TiedTogether", "TiedTogether", "1.0.7")]
	public class TiedTogether : BaseUnityPlugin
	{
		public const string PluginGuid = "Omniscye.TiedTogether";

		public const string PluginName = "TiedTogether";

		public const string PluginVersion = "1.0.7";

		internal static ConfigEntry<bool> C_Enable;

		internal static ConfigEntry<float> C_LinkLength;

		internal static ConfigEntry<bool> C_DrawChain;

		internal static ConfigEntry<float> C_LineWidth;

		internal static ConfigEntry<float> C_LineYOffset;

		internal static ConfigEntry<float> C_PullHardness;

		internal static ConfigEntry<bool> C_HardStopCC;

		internal static ConfigEntry<bool> C_UseLateUpdate;

		internal static ConfigEntry<bool> C_UseFixedUpdate;

		internal static ConfigEntry<bool> C_BlockOutward;

		internal static ConfigEntry<float> C_ReturnSpeed;

		internal static ConfigEntry<float> C_ReturnAccel;

		internal static ConfigEntry<bool> C_SyncLineFromMaster;

		internal static ConfigEntry<int> C_SamplesPerLink;

		internal static ConfigEntry<float> C_SagAmount;

		internal static ConfigEntry<float> C_HardClampMultiplier;

		internal static TiedTogether Instance { get; private set; }

		internal static ManualLogSource Logger => Instance._logger;

		private ManualLogSource _logger => ((BaseUnityPlugin)this).Logger;

		internal Harmony? Harmony { get; set; }

		private void Awake()
		{
			//IL_024d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0252: Unknown result type (might be due to invalid IL or missing references)
			//IL_025c: Expected O, but got Unknown
			//IL_0283: Unknown result type (might be due to invalid IL or missing references)
			//IL_0288: Unknown result type (might be due to invalid IL or missing references)
			//IL_028a: Expected O, but got Unknown
			//IL_028f: Expected O, but got Unknown
			Instance = this;
			((Component)this).gameObject.transform.parent = null;
			((Object)((Component)this).gameObject).hideFlags = (HideFlags)61;
			C_Enable = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enable", true, "Master switch for the mod.");
			C_LinkLength = ((BaseUnityPlugin)this).Config.Bind<float>("General", "LinkLength", 4f, "Maximum distance between chained neighbors (HOST ONLY).");
			C_DrawChain = ((BaseUnityPlugin)this).Config.Bind<bool>("Visual", "DrawChain", true, "Render visible line between players.");
			C_LineWidth = ((BaseUnityPlugin)this).Config.Bind<float>("Visual", "LineWidth", 0.06f, "LineRenderer width.");
			C_LineYOffset = ((BaseUnityPlugin)this).Config.Bind<float>("Visual", "LineYOffset", 0.8f, "Vertical offset for line.");
			C_PullHardness = ((BaseUnityPlugin)this).Config.Bind<float>("Gameplay", "PullHardness", 1f, "Used for non-RB fallback corrections (HOST ONLY).");
			C_HardStopCC = ((BaseUnityPlugin)this).Config.Bind<bool>("Gameplay", "HardStopCC", true, "Allow CC toggle teleport as last resort.");
			C_UseLateUpdate = ((BaseUnityPlugin)this).Config.Bind<bool>("Advanced", "UseLateUpdate", true, "Also enforce in LateUpdate.");
			C_UseFixedUpdate = ((BaseUnityPlugin)this).Config.Bind<bool>("Advanced", "UseFixedUpdate", true, "Also enforce in FixedUpdate.");
			C_BlockOutward = ((BaseUnityPlugin)this).Config.Bind<bool>("Advanced", "BlockOutward", true, "At max range, remove outward input.");
			C_ReturnSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Gameplay", "ReturnSpeed", 12f, "Target inward speed when outside (HOST ONLY).");
			C_ReturnAccel = ((BaseUnityPlugin)this).Config.Bind<float>("Gameplay", "ReturnAccel", 60f, "Accel to reach inward target speed (HOST ONLY).");
			C_SyncLineFromMaster = ((BaseUnityPlugin)this).Config.Bind<bool>("Visual", "SyncLineFromMaster", true, "Master publishes polyline; clients render exactly that.");
			C_SamplesPerLink = ((BaseUnityPlugin)this).Config.Bind<int>("Visual", "SamplesPerLink", 6, "Polyline samples per link.");
			C_SagAmount = ((BaseUnityPlugin)this).Config.Bind<float>("Visual", "SagAmount", 0.6f, "Sag when slack.");
			C_HardClampMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Advanced", "HardClampMultiplier", 2.5f, "Failsafe snap threshold multiplier (HOST ONLY).");
			GameObject val = new GameObject("__TiedTogether_Manager")
			{
				hideFlags = (HideFlags)61
			};
			Object.DontDestroyOnLoad((Object)(object)val);
			val.AddComponent<TiedTogetherManager>();
			if (Harmony == null)
			{
				Harmony val2 = new Harmony(((BaseUnityPlugin)this).Info.Metadata.GUID);
				Harmony val3 = val2;
				Harmony = val2;
			}
			Harmony.PatchAll();
			Logger.LogInfo((object)$"{((BaseUnityPlugin)this).Info.Metadata.GUID} v{((BaseUnityPlugin)this).Info.Metadata.Version} loaded.");
		}

		private void OnDestroy()
		{
			Harmony? harmony = Harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}
	}
	internal class TiedTogetherManager : MonoBehaviour
	{
		private const string PROP_ORDER = "TT_ORDER";

		private const string PROP_ANCHOR = "TT_ANCHOR";

		private const string PROP_LEN = "TT_LEN";

		private const string PROP_POINTS = "TT_PTS";

		private const string PROP_PTREV = "TT_PTSR";

		private const string PROP_CFG = "TT_CFG";

		private const int CFG_LINK = 0;

		private const int CFG_RETSPD = 1;

		private const int CFG_RETACC = 2;

		private const int CFG_BLOCK = 3;

		private const int CFG_PULLHARD = 4;

		private const int CFG_CLAMPMUL = 5;

		private const int CFG_SAG = 6;

		private const int CFG_SAMPLES = 7;

		private const int CFG_LINEY = 8;

		private readonly List<int> orderViewIds = new List<int>();

		private int anchorViewId = -1;

		private float linkLength = 0.5f;

		private float authReturnSpeed = 12f;

		private float authReturnAccel = 60f;

		private bool authBlockOutward = true;

		private float authPullHard = 1f;

		private float authClampMul = 2.5f;

		private float authSag = 0.6f;

		private int authSamples = 6;

		private float authLineY = 0.8f;

		private LineRenderer? line;

		private Material? lineMat;

		private float masterTick;

		private bool wasActive;

		private readonly List<Vector3> syncedPoints = new List<Vector3>();

		private object[]? lastSentPackedPoints;

		private object[]? lastSentPackedCfg;

		private float pointsTick;

		private readonly List<Vector3> scratchPts = new List<Vector3>(128);

		internal static TiedTogetherManager Instance { get; private set; }

		internal static bool BlockOutward => Instance?.authBlockOutward ?? true;

		internal static float ReturnSpeed => Instance?.authReturnSpeed ?? 12f;

		internal static float ReturnAccel => Instance?.authReturnAccel ?? 60f;

		internal static float ClampMul => Instance?.authClampMul ?? 2.5f;

		private void Awake()
		{
			Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
			Instance = this;
		}

		private void OnDisable()
		{
			Deactivate();
		}

		private void Update()
		{
			try
			{
				if (!TiedTogether.C_Enable.Value)
				{
					if (wasActive)
					{
						Deactivate();
					}
					return;
				}
				if (!RuntimeReady())
				{
					if (wasActive)
					{
						Deactivate();
					}
					return;
				}
				if (!wasActive)
				{
					wasActive = true;
					if (PhotonNetwork.IsMasterClient)
					{
						ApplyHostConfigLocallyFromBepInEx();
					}
					else
					{
						ApplyStrictClientFallback();
					}
				}
				EnsureOrderLocalFallback();
				masterTick -= Time.deltaTime;
				if (masterTick <= 0f)
				{
					masterTick = 0.5f;
					if (PhotonNetwork.IsMasterClient && PhotonNetwork.InRoom)
					{
						TryMasterSync();
						TryMasterPublishConfig();
					}
				}
				TryMasterPublishPoints();
				if (PhotonNetwork.InRoom)
				{
					Room currentRoom = PhotonNetwork.CurrentRoom;
					PullRoomProps((currentRoom != null) ? ((RoomInfo)currentRoom).CustomProperties : null);
				}
				UpdateLine();
				EnforceLocalTether();
			}
			catch (Exception ex)
			{
				TiedTogether.Logger.LogWarning((object)("Update loop exception: " + ex.Message));
			}
		}

		private void LateUpdate()
		{
			if (TiedTogether.C_Enable.Value && TiedTogether.C_UseLateUpdate.Value && RuntimeReady())
			{
				EnforceLocalTether();
			}
		}

		private void FixedUpdate()
		{
			if (TiedTogether.C_Enable.Value && TiedTogether.C_UseFixedUpdate.Value && RuntimeReady())
			{
				EnforceLocalTether(physicsStep: true);
			}
		}

		internal static bool RuntimeReady()
		{
			if (!PhotonNetwork.IsConnected || !PhotonNetwork.InRoom)
			{
				return false;
			}
			if (SemiFunc.MenuLevel())
			{
				return false;
			}
			if (!Object.op_Implicit((Object)(object)LevelGenerator.Instance) || !LevelGenerator.Instance.Generated)
			{
				return false;
			}
			if (!Object.op_Implicit((Object)(object)PlayerAvatar.instance))
			{
				return false;
			}
			return true;
		}

		private void Deactivate()
		{
			wasActive = false;
			orderViewIds.Clear();
			anchorViewId = -1;
			syncedPoints.Clear();
			lastSentPackedPoints = null;
			lastSentPackedCfg = null;
			HideLine();
		}

		private void ApplyHostConfigLocallyFromBepInEx()
		{
			linkLength = Mathf.Max(0.05f, TiedTogether.C_LinkLength.Value);
			authReturnSpeed = Mathf.Max(0.1f, TiedTogether.C_ReturnSpeed.Value);
			authReturnAccel = Mathf.Max(0.1f, TiedTogether.C_ReturnAccel.Value);
			authBlockOutward = TiedTogether.C_BlockOutward.Value;
			authPullHard = Mathf.Clamp01(TiedTogether.C_PullHardness.Value);
			authClampMul = Mathf.Max(1f, TiedTogether.C_HardClampMultiplier.Value);
			authSag = Mathf.Max(0f, TiedTogether.C_SagAmount.Value);
			authSamples = Mathf.Max(1, TiedTogether.C_SamplesPerLink.Value);
			authLineY = Mathf.Max(0f, TiedTogether.C_LineYOffset.Value);
		}

		private void ApplyStrictClientFallback()
		{
			linkLength = 0.5f;
			authReturnSpeed = 12f;
			authReturnAccel = 60f;
			authBlockOutward = true;
			authPullHard = 1f;
			authClampMul = 2.5f;
			authSag = 0.6f;
			authSamples = 6;
			authLineY = 0.8f;
		}

		private object[] PackHostCfg()
		{
			return new object[9]
			{
				linkLength,
				authReturnSpeed,
				authReturnAccel,
				authBlockOutward ? 1 : 0,
				authPullHard,
				authClampMul,
				authSag,
				authSamples,
				authLineY
			};
		}

		private void TryMasterPublishConfig()
		{
			//IL_0028: 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_0039: Expected O, but got Unknown
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Expected O, but got Unknown
			//IL_0052: Expected O, but got Unknown
			ApplyHostConfigLocallyFromBepInEx();
			object[] array = PackHostCfg();
			if (!PackedEquals(lastSentPackedCfg, array))
			{
				lastSentPackedCfg = array;
				Hashtable val = new Hashtable();
				((Dictionary<object, object>)val).Add((object)"TT_CFG", (object)array);
				((Dictionary<object, object>)val).Add((object)"TT_LEN", (object)linkLength);
				Hashtable val2 = val;
				PhotonNetwork.CurrentRoom.SetCustomProperties(val2, (Hashtable)null, (WebFlags)null);
			}
		}

		private void PullCfgFromProps(object obj)
		{
			if (obj is object[] array && array.Length >= 9)
			{
				linkLength = Mathf.Max(0.05f, Convert.ToSingle(array[0]));
				authReturnSpeed = Mathf.Max(0.1f, Convert.ToSingle(array[1]));
				authReturnAccel = Mathf.Max(0.1f, Convert.ToSingle(array[2]));
				authBlockOutward = Convert.ToInt32(array[3]) != 0;
				authPullHard = Mathf.Clamp01(Convert.ToSingle(array[4]));
				authClampMul = Mathf.Max(1f, Convert.ToSingle(array[5]));
				authSag = Mathf.Max(0f, Convert.ToSingle(array[6]));
				authSamples = Mathf.Max(1, Convert.ToInt32(array[7]));
				authLineY = Mathf.Max(0f, Convert.ToSingle(array[8]));
			}
		}

		private void TryMasterSync()
		{
			//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_00fd: Expected O, but got Unknown
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Expected O, but got Unknown
			//IL_0112: Expected O, but got Unknown
			List<PlayerAvatar> list = SafePlayerList();
			if (list.Count >= 2)
			{
				List<PlayerAvatar> source = (from a in list
					where Object.op_Implicit((Object)(object)a) && Object.op_Implicit((Object)(object)a.photonView)
					orderby a.photonView.OwnerActorNr
					select a).ToList();
				int[] array = source.Select((PlayerAvatar a) => a.photonView.ViewID).ToArray();
				int num = ((array.Length != 0) ? array[0] : (-1));
				if (!orderViewIds.SequenceEqual(array) || anchorViewId != num)
				{
					orderViewIds.Clear();
					orderViewIds.AddRange(array);
					anchorViewId = num;
					Hashtable val = new Hashtable();
					((Dictionary<object, object>)val).Add((object)"TT_ORDER", (object)array);
					((Dictionary<object, object>)val).Add((object)"TT_ANCHOR", (object)num);
					Hashtable val2 = val;
					PhotonNetwork.CurrentRoom.SetCustomProperties(val2, (Hashtable)null, (WebFlags)null);
				}
			}
		}

		private void TryMasterPublishPoints()
		{
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Expected O, but got Unknown
			//IL_00ce: Expected O, but got Unknown
			if (!TiedTogether.C_SyncLineFromMaster.Value || !PhotonNetwork.IsMasterClient || !PhotonNetwork.InRoom || orderViewIds.Count < 2)
			{
				return;
			}
			pointsTick -= Time.deltaTime;
			if (pointsTick > 0f)
			{
				return;
			}
			pointsTick = 0.1f;
			if (BuildPolylinePoints(scratchPts))
			{
				object[] array = PackPoints(scratchPts);
				if (!PackedEquals(lastSentPackedPoints, array))
				{
					lastSentPackedPoints = array;
					Hashtable val = new Hashtable();
					((Dictionary<object, object>)val).Add((object)"TT_PTS", (object)array);
					Hashtable val2 = val;
					PhotonNetwork.CurrentRoom.SetCustomProperties(val2, (Hashtable)null, (WebFlags)null);
				}
			}
		}

		private void PullRoomProps(Hashtable props)
		{
			if (props == null || ((Dictionary<object, object>)(object)props).Count == 0)
			{
				return;
			}
			bool flag = false;
			if (((Dictionary<object, object>)(object)props).ContainsKey((object)"TT_ORDER"))
			{
				orderViewIds.Clear();
				if (props[(object)"TT_ORDER"] is int[] collection)
				{
					orderViewIds.AddRange(collection);
				}
				else if (props[(object)"TT_ORDER"] is object[] source)
				{
					orderViewIds.AddRange(source.Select((object o) => Convert.ToInt32(o)));
				}
				flag = true;
			}
			if (((Dictionary<object, object>)(object)props).ContainsKey((object)"TT_ANCHOR"))
			{
				anchorViewId = Convert.ToInt32(props[(object)"TT_ANCHOR"]);
				flag = true;
			}
			if (((Dictionary<object, object>)(object)props).ContainsKey((object)"TT_LEN"))
			{
				linkLength = Mathf.Max(0.05f, Convert.ToSingle(props[(object)"TT_LEN"]));
				flag = true;
			}
			if (((Dictionary<object, object>)(object)props).ContainsKey((object)"TT_CFG"))
			{
				PullCfgFromProps(props[(object)"TT_CFG"]);
				flag = true;
			}
			if (((Dictionary<object, object>)(object)props).ContainsKey((object)"TT_PTS") && UnpackPoints(props[(object)"TT_PTS"], syncedPoints))
			{
				flag = true;
			}
			if (flag)
			{
				EnsureLine();
			}
		}

		private void EnsureLine()
		{
			//IL_006b: 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_007a: Expected O, but got Unknown
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Expected O, but got Unknown
			if (!TiedTogether.C_DrawChain.Value)
			{
				HideLine();
				return;
			}
			if ((Object)(object)line == (Object)null)
			{
				if (!Object.op_Implicit((Object)(object)lineMat))
				{
					lineMat = new Material(Shader.Find("Sprites/Default"))
					{
						renderQueue = 3000
					};
				}
				GameObject val = new GameObject("__TiedTogether_Line")
				{
					hideFlags = (HideFlags)61
				};
				Object.DontDestroyOnLoad((Object)(object)val);
				line = val.AddComponent<LineRenderer>();
				line.useWorldSpace = true;
				((Renderer)line).receiveShadows = false;
				((Renderer)line).shadowCastingMode = (ShadowCastingMode)0;
				line.alignment = (LineAlignment)1;
				line.textureMode = (LineTextureMode)0;
				((Renderer)line).material = lineMat;
				line.startColor = new Color(0.9f, 0.9f, 1f, 0.65f);
				line.endColor = new Color(0.9f, 0.9f, 1f, 0.65f);
			}
			line.widthMultiplier = Mathf.Max(0.005f, TiedTogether.C_LineWidth.Value);
			((Renderer)line).enabled = true;
		}

		private void HideLine()
		{
			if (Object.op_Implicit((Object)(object)line))
			{
				((Renderer)line).enabled = false;
			}
		}

		private void UpdateLine()
		{
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: 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_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: 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_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)line == (Object)null || !TiedTogether.C_DrawChain.Value)
			{
				return;
			}
			if (TiedTogether.C_SyncLineFromMaster.Value && syncedPoints.Count >= 2)
			{
				line.positionCount = syncedPoints.Count;
				for (int i = 0; i < syncedPoints.Count; i++)
				{
					line.SetPosition(i, syncedPoints[i]);
				}
				return;
			}
			if (orderViewIds.Count < 2)
			{
				line.positionCount = 0;
				return;
			}
			line.positionCount = orderViewIds.Count;
			for (int j = 0; j < orderViewIds.Count; j++)
			{
				Transform val = ResolveNodeTransform(orderViewIds[j]);
				Vector3 val2 = (Object.op_Implicit((Object)(object)val) ? val.position : Vector3.zero);
				val2 += Vector3.up * Mathf.Max(0f, authLineY);
				line.SetPosition(j, val2);
			}
		}

		private bool BuildPolylinePoints(List<Vector3> outPts)
		{
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: 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_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: 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_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: 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_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: 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_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			outPts.Clear();
			if (orderViewIds.Count < 2)
			{
				return false;
			}
			int num = Mathf.Max(1, authSamples);
			float num2 = Mathf.Max(0f, authLineY);
			float num3 = Mathf.Max(0f, authSag);
			Transform val = ResolveNodeTransform(orderViewIds[0]);
			if (!Object.op_Implicit((Object)(object)val))
			{
				return false;
			}
			Vector3 val2 = val.position + Vector3.up * num2;
			outPts.Add(val2);
			for (int i = 1; i < orderViewIds.Count; i++)
			{
				Transform val3 = ResolveNodeTransform(orderViewIds[i]);
				if (!Object.op_Implicit((Object)(object)val3))
				{
					return false;
				}
				Vector3 val4 = val3.position + Vector3.up * num2;
				Vector3 val5 = val4 - val2;
				float magnitude = ((Vector3)(ref val5)).magnitude;
				float num4 = 1f - Mathf.Clamp01(magnitude / Mathf.Max(0.001f, linkLength));
				float num5 = num3 * num4;
				for (int j = 1; j <= num; j++)
				{
					float num6 = (float)j / (float)num;
					Vector3 val6 = Vector3.Lerp(val2, val4, num6);
					if (num5 > 0f)
					{
						val6 += Vector3.down * (Mathf.Sin(MathF.PI * num6) * num5);
					}
					outPts.Add(val6);
				}
				val2 = val4;
			}
			if (outPts.Count > 256)
			{
				outPts.RemoveRange(256, outPts.Count - 256);
			}
			return outPts.Count >= 2;
		}

		private static object[] PackPoints(List<Vector3> pts)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			int count = pts.Count;
			object[] array = new object[count * 3];
			int num = 0;
			for (int i = 0; i < count; i++)
			{
				Vector3 val = pts[i];
				array[num++] = val.x;
				array[num++] = val.y;
				array[num++] = val.z;
			}
			return array;
		}

		private static bool UnpackPoints(object obj, List<Vector3> outPts)
		{
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			outPts.Clear();
			if (obj is object[] array)
			{
				int num = array.Length - array.Length % 3;
				num = Mathf.Min(num, 768);
				for (int i = 0; i < num; i += 3)
				{
					float num2 = Convert.ToSingle(array[i]);
					float num3 = Convert.ToSingle(array[i + 1]);
					float num4 = Convert.ToSingle(array[i + 2]);
					outPts.Add(new Vector3(num2, num3, num4));
				}
				return outPts.Count >= 2;
			}
			return false;
		}

		private static bool PackedEquals(object[]? a, object[] b)
		{
			if (a == null || a.Length != b.Length)
			{
				return false;
			}
			for (int i = 0; i < a.Length; i++)
			{
				float num = Convert.ToSingle(a[i]);
				float num2 = Convert.ToSingle(b[i]);
				if (Mathf.Abs(num - num2) > 0.01f)
				{
					return false;
				}
			}
			return true;
		}

		internal bool TryGetLocalChainContext(out Vector3 neighborPos, out Vector3 myPos, out float maxDist)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: 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)
			//IL_00e6: 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_00f2: Unknown result type (might be due to invalid IL or missing references)
			neighborPos = Vector3.zero;
			myPos = Vector3.zero;
			maxDist = Mathf.Max(0.05f, linkLength);
			PlayerAvatar instance = PlayerAvatar.instance;
			if (!Object.op_Implicit((Object)(object)instance) || instance.deadSet)
			{
				return false;
			}
			if (orderViewIds.Count < 2 || anchorViewId < 0)
			{
				return false;
			}
			int item = (((Object)(object)instance.photonView != (Object)null) ? instance.photonView.ViewID : (-1));
			int num = orderViewIds.IndexOf(item);
			if (num <= 0)
			{
				return false;
			}
			int viewId = orderViewIds[num - 1];
			Transform val = ResolveNodeTransform(viewId);
			if (!Object.op_Implicit((Object)(object)val))
			{
				return false;
			}
			neighborPos = val.position;
			myPos = CurrentNodePosition(instance);
			return true;
		}

		private void EnforceLocalTether(bool physicsStep = false, bool forceHard = false)
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: 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)
			//IL_004d: 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)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: 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_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: 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_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: 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_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b9: 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_02e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e7: 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_02eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0301: Unknown result type (might be due to invalid IL or missing references)
			//IL_0254: Unknown result type (might be due to invalid IL or missing references)
			//IL_0259: 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_0287: Unknown result type (might be due to invalid IL or missing references)
			//IL_028c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0202: 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_02ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b0: 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_02c8: Unknown result type (might be due to invalid IL or missing references)
			PlayerAvatar instance = PlayerAvatar.instance;
			if (!Object.op_Implicit((Object)(object)instance) || instance.deadSet || !TryGetLocalChainContext(out var neighborPos, out var myPos, out var maxDist))
			{
				return;
			}
			Vector3 val = myPos - neighborPos;
			float magnitude = ((Vector3)(ref val)).magnitude;
			if (magnitude <= maxDist)
			{
				return;
			}
			Vector3 val2 = ((magnitude > 0.0001f) ? (val / magnitude) : Vector3.forward);
			float num = magnitude - maxDist;
			if (instance.isTumbling && Object.op_Implicit((Object)(object)instance.tumble))
			{
				Transform transform = ((Component)instance.tumble).transform;
				Rigidbody component = ((Component)instance.tumble).GetComponent<Rigidbody>();
				if ((Object)(object)component != (Object)null && !component.isKinematic)
				{
					float num2 = Vector3.Dot(component.velocity, val2);
					float num3 = 0f - Mathf.Max(authReturnSpeed, num * 4f);
					component.velocity += val2 * (num3 - num2);
				}
				else
				{
					transform.position = Vector3.MoveTowards(transform.position, neighborPos + val2 * maxDist, authReturnSpeed * Time.deltaTime);
				}
				return;
			}
			CharacterController component2 = ((Component)instance).GetComponent<CharacterController>();
			if ((Object)(object)component2 != (Object)null && ((Collider)component2).enabled)
			{
				float num4 = Mathf.Max(0f, Mathf.Min(authReturnSpeed * Time.deltaTime, num));
				if (num4 > 0f)
				{
					component2.Move(-val2 * num4);
				}
				if (magnitude > maxDist * authClampMul)
				{
					bool enabled = ((Collider)component2).enabled;
					if (enabled)
					{
						((Collider)component2).enabled = false;
					}
					((Component)instance).transform.position = neighborPos + val2 * maxDist;
					if (enabled)
					{
						((Collider)component2).enabled = true;
					}
				}
				return;
			}
			Rigidbody component3 = ((Component)instance).GetComponent<Rigidbody>();
			if ((Object)(object)component3 != (Object)null && !component3.isKinematic)
			{
				float num5 = Vector3.Dot(component3.velocity, val2);
				float num6 = 0f - Mathf.Max(authReturnSpeed, num * 4f);
				component3.velocity += val2 * (num6 - num5);
				if (magnitude > maxDist * authClampMul)
				{
					component3.position = neighborPos + val2 * maxDist;
					((Component)instance).transform.position = component3.position;
				}
			}
			else
			{
				((Component)instance).transform.position = Vector3.MoveTowards(((Component)instance).transform.position, neighborPos + val2 * maxDist, authReturnSpeed * Time.deltaTime);
			}
		}

		private static List<PlayerAvatar> SafePlayerList()
		{
			List<PlayerAvatar> list = SemiFunc.PlayerGetList();
			if (list == null)
			{
				return new List<PlayerAvatar>();
			}
			return list.Where((PlayerAvatar p) => (Object)(object)p != (Object)null).ToList();
		}

		private static Vector3 CurrentNodePosition(PlayerAvatar av)
		{
			//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_007e: 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_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: 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)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)av))
			{
				return Vector3.zero;
			}
			if (av.deadSet && Object.op_Implicit((Object)(object)av.playerDeathHead))
			{
				return ((Component)av.playerDeathHead).transform.position;
			}
			if (av.isTumbling && Object.op_Implicit((Object)(object)av.tumble))
			{
				return ((Component)av.tumble).transform.position;
			}
			return ((Component)av).transform.position;
		}

		private static Transform? ResolveNodeTransform(int viewId)
		{
			PhotonView val = PhotonView.Find(viewId);
			if (!Object.op_Implicit((Object)(object)val))
			{
				return null;
			}
			PlayerAvatar component = ((Component)val).GetComponent<PlayerAvatar>();
			if (Object.op_Implicit((Object)(object)component))
			{
				if (component.deadSet && Object.op_Implicit((Object)(object)component.playerDeathHead))
				{
					return ((Component)component.playerDeathHead).transform;
				}
				if (component.isTumbling && Object.op_Implicit((Object)(object)component.tumble))
				{
					return ((Component)component.tumble).transform;
				}
				return ((Component)component).transform;
			}
			PlayerDeathHead component2 = ((Component)val).GetComponent<PlayerDeathHead>();
			if (Object.op_Implicit((Object)(object)component2))
			{
				return ((Component)component2).transform;
			}
			return ((Component)val).transform;
		}

		private void EnsureOrderLocalFallback()
		{
			if (orderViewIds.Count >= 2 && anchorViewId >= 0)
			{
				return;
			}
			List<PlayerAvatar> list = SafePlayerList();
			if (list.Count >= 2)
			{
				List<int> list2 = (from a in list
					where Object.op_Implicit((Object)(object)a) && Object.op_Implicit((Object)(object)a.photonView)
					orderby a.photonView.OwnerActorNr
					select a.photonView.ViewID).ToList();
				if (list2.Count >= 2)
				{
					orderViewIds.Clear();
					orderViewIds.AddRange(list2);
					anchorViewId = list2[0];
				}
			}
		}
	}
	[HarmonyPatch(typeof(PlayerController), "FixedUpdate")]
	internal static class Patch_PlayerController_FixedUpdate_Tether
	{
		[HarmonyPostfix]
		private static void Postfix(PlayerController __instance)
		{
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//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_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: 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)
			//IL_00ac: 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_00c0: 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_00c4: 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_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: 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_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: 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_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			if (!TiedTogether.C_Enable.Value || !TiedTogetherManager.RuntimeReady() || __instance != PlayerController.instance)
			{
				return;
			}
			TiedTogetherManager instance = TiedTogetherManager.Instance;
			if ((Object)(object)instance == (Object)null || !instance.TryGetLocalChainContext(out var neighborPos, out var myPos, out var maxDist))
			{
				return;
			}
			Vector3 val = myPos - neighborPos;
			float magnitude = ((Vector3)(ref val)).magnitude;
			if (magnitude < maxDist - 0.001f)
			{
				return;
			}
			Vector3 val2 = ((magnitude > 0.0001f) ? (val / magnitude) : Vector3.forward);
			if (TiedTogetherManager.BlockOutward)
			{
				Vector3 inputDirection = __instance.InputDirection;
				float num = Vector3.Dot(inputDirection, val2);
				if (num > 0f)
				{
					__instance.InputDirection = inputDirection - val2 * num;
				}
			}
			Rigidbody rb = __instance.rb;
			if ((Object)(object)rb != (Object)null)
			{
				float num2 = magnitude - maxDist;
				float num3 = Vector3.Dot(rb.velocity, val2);
				float num4 = 0f - Mathf.Max(TiedTogetherManager.ReturnSpeed, num2 * 4f);
				rb.velocity += val2 * (num4 - num3);
				float num5 = Mathf.Max(1f, TiedTogetherManager.ClampMul);
				if (magnitude > maxDist * num5)
				{
					Vector3 position = (rb.position = neighborPos + val2 * maxDist);
					((Component)__instance).transform.position = position;
				}
			}
		}
	}
	[HarmonyPatch]
	internal static class HarmonyAnchors
	{
	}
}