Decompiled source of NetworkTweaksRevived v1.0.1

NetworkTweaksRevived.dll

Decompiled 16 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using ExitGames.Client.Photon;
using HarmonyLib;
using Photon.Pun;
using Photon.Realtime;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("Revival")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyCopyright("Revival")]
[assembly: AssemblyFileVersion("1.0.1.0")]
[assembly: AssemblyInformationalVersion("1.0.1")]
[assembly: AssemblyProduct("NetworkTweaksRevived")]
[assembly: AssemblyTitle("NetworkTweaksRevived")]
[assembly: AssemblyVersion("1.0.1.0")]
namespace NetworkTweaksRevived;

[BepInPlugin("com.Revival.networktweaksrevived", "NetworkTweaksRevived", "1.0.1")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class Plugin : BaseUnityPlugin
{
	public const string PluginGuid = "com.Revival.networktweaksrevived";

	public const string PluginName = "NetworkTweaksRevived";

	public const string PluginVersion = "1.0.1";

	internal static ManualLogSource Log;

	internal static ConfigEntry<bool> DisableTimeout;

	internal static ConfigEntry<bool> PhotonLateUpdate;

	internal static ConfigEntry<bool> SmoothSync;

	internal static ConfigEntry<bool> Extrapolate;

	internal static ConfigEntry<float> Future;

	internal static ConfigEntry<float> RateSmoothing;

	internal static ConfigEntry<float> TimingThreshold;

	internal static Func<PhotonTransformView, bool> IsLocallySimulated;

	internal static bool PhotonReady;

	private void Awake()
	{
		//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c3: Expected O, but got Unknown
		//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
		//IL_0100: 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_016e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0174: Expected O, but got Unknown
		//IL_023d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0242: Unknown result type (might be due to invalid IL or missing references)
		//IL_0248: Expected O, but got Unknown
		Log = ((BaseUnityPlugin)this).Logger;
		DisableTimeout = ((BaseUnityPlugin)this).Config.Bind<bool>("NetworkTweaks", "DisableTimeout", true, "Remove Photon's client-sided timeout that randomly kicks you from lobbies on brief lag spikes. Done via Photon's own settings, no game code patched.");
		PhotonLateUpdate = ((BaseUnityPlugin)this).Config.Bind<bool>("NetworkTweaks", "PhotonLateUpdate", true, "Process network packets every rendered frame (LateUpdate) instead of on the physics tick. Lower perceived latency.");
		SmoothSync = ((BaseUnityPlugin)this).Config.Bind<bool>("SmoothSync", "Enabled", true, "Replace choppy movement of synced objects with snapshot (Hermite) interpolation.");
		Extrapolate = ((BaseUnityPlugin)this).Config.Bind<bool>("SmoothSync", "Extrapolate", true, "Keep projecting movement briefly when an update is late or lost.");
		Future = ((BaseUnityPlugin)this).Config.Bind<float>("SmoothSync", "Future", 1f, new ConfigDescription("How far to project received data into the future, in update intervals. Too little feels laggy, too much rubberbands.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 3f), Array.Empty<object>()));
		RateSmoothing = ((BaseUnityPlugin)this).Config.Bind<float>("SmoothSync", "RateSmoothing", 0.1f, new ConfigDescription("How quickly the measured update rate adapts.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
		TimingThreshold = ((BaseUnityPlugin)this).Config.Bind<float>("SmoothSync", "TimingThreshold", 1f, new ConfigDescription("Seconds between updates after which data is considered discontinuous.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.2f, 5f), Array.Empty<object>()));
		bool flag = Chainloader.PluginInfos.ContainsKey("BlueAmulet.REPONetworkTweaks");
		if (flag)
		{
			Log.LogWarning((object)"Old REPONetworkTweaks is still installed. Its transform-view replacement conflicts with everything, so SmoothSync stays OFF this session. Please uninstall/disable the old mod.");
		}
		ResolveNetworkingRevivedInterop();
		Harmony val = new Harmony("com.Revival.networktweaksrevived");
		try
		{
			val.PatchAll(typeof(PhotonHandlerAwakePatch));
		}
		catch (Exception arg)
		{
			Log.LogError((object)$"Failed to hook PhotonHandler.Awake — timeout/LateUpdate tweaks limited to fallback: {arg}");
		}
		if (SmoothSync.Value && !flag)
		{
			if (TransformSmoothing.InitAccessors())
			{
				try
				{
					val.PatchAll(typeof(TransformSmoothing.SerializePatch));
					val.PatchAll(typeof(TransformSmoothing.UpdatePatch));
					val.PatchAll(typeof(TransformSmoothing.TeleportPatch));
					val.PatchAll(typeof(TransformSmoothing.EnablePatch));
					TransformSmoothing.Active = true;
					Log.LogInfo((object)"SmoothSync interpolation active.");
				}
				catch (Exception arg2)
				{
					Log.LogError((object)$"Failed to apply SmoothSync patches, interpolation disabled: {arg2}");
				}
			}
			else
			{
				Log.LogWarning((object)"Game internals changed — SmoothSync disabled, timeout/late-update tweaks still active.");
			}
		}
		GameObject val2 = new GameObject("NetworkTweaksRevivedDriver");
		Object.DontDestroyOnLoad((Object)val2);
		val2.AddComponent<TweaksDriver>();
		Log.LogInfo((object)(string.Format("{0} {1} loaded. Timeout fix: {2}, ", "NetworkTweaksRevived", "1.0.1", DisableTimeout.Value) + $"LateUpdate dispatch: {PhotonLateUpdate.Value}, SmoothSync: {TransformSmoothing.Active}. " + "Photon settings apply when the game brings networking up."));
	}

	private static void ResolveNetworkingRevivedInterop()
	{
		try
		{
			MethodInfo methodInfo = Type.GetType("NetworkingRevived.NetworkingRevivedAPI, NetworkingRevived")?.GetMethod("IsLocallySimulated", new Type[1] { typeof(PhotonTransformView) });
			if (methodInfo != null)
			{
				IsLocallySimulated = (Func<PhotonTransformView, bool>)Delegate.CreateDelegate(typeof(Func<PhotonTransformView, bool>), methodInfo);
				Log.LogInfo((object)"NetworkingRevived detected — smoothing will defer to its local simulation.");
			}
		}
		catch (Exception ex)
		{
			Log.LogWarning((object)("NetworkingRevived interop unavailable: " + ex.Message));
		}
	}

	internal static void ApplyPhotonSettings()
	{
		if (!PhotonReady)
		{
			return;
		}
		try
		{
			if (PhotonLateUpdate.Value)
			{
				PhotonNetwork.MinimalTimeScaleToDispatchInFixedUpdate = float.PositiveInfinity;
			}
			if (DisableTimeout.Value)
			{
				LoadBalancingClient networkingClient = PhotonNetwork.NetworkingClient;
				LoadBalancingPeer val = ((networkingClient != null) ? networkingClient.LoadBalancingPeer : null);
				if (val != null)
				{
					((PhotonPeer)val).DisconnectTimeout = 3600000;
					((PhotonPeer)val).SentCountAllowance = 10000;
				}
			}
		}
		catch (Exception ex)
		{
			Log.LogWarning((object)("Could not apply Photon settings: " + ex.Message));
		}
	}
}
[HarmonyPatch(typeof(PhotonHandler), "Awake")]
internal static class PhotonHandlerAwakePatch
{
	private static void Postfix()
	{
		bool num = !Plugin.PhotonReady;
		Plugin.PhotonReady = true;
		Plugin.ApplyPhotonSettings();
		if (num)
		{
			Plugin.Log.LogInfo((object)"Photon is up — timeout and LateUpdate dispatch settings applied.");
		}
	}
}
internal class TweaksDriver : MonoBehaviour
{
	private float nextTick;

	private void Update()
	{
		if (!(Time.unscaledTime < nextTick))
		{
			nextTick = Time.unscaledTime + 10f;
			if (!Plugin.PhotonReady && (Object)(object)Object.FindObjectOfType<PhotonHandler>() != (Object)null)
			{
				Plugin.PhotonReady = true;
			}
			Plugin.ApplyPhotonSettings();
			TransformSmoothing.Sweep();
		}
	}
}
internal static class TransformSmoothing
{
	private class Snapshot
	{
		internal Vector3 position;

		internal Quaternion rotation;

		internal Vector3 velocity;

		internal Vector3 angularVelocity;
	}

	private class InterpState
	{
		internal Rigidbody rb;

		internal Transform tf;

		internal PhysGrabHinge hinge;

		internal readonly LinkedList<Snapshot> snapshots = new LinkedList<Snapshot>();

		internal Snapshot prev;

		internal float interpStartTime = -1f;

		internal float smoothFreq = 0.1f;

		internal int lastTimestamp;

		internal bool haveFirst;

		internal Vector3 interpVel;

		internal Vector3 interpAngVel;

		internal void Clear()
		{
			snapshots.Clear();
			prev = null;
			interpStartTime = -1f;
		}
	}

	[HarmonyPatch(typeof(PhotonTransformView), "OnPhotonSerializeView")]
	internal static class SerializePatch
	{
		private static void Postfix(PhotonTransformView __instance, PhotonStream stream, PhotonMessageInfo info, bool __runOriginal)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			if (!__runOriginal || stream.IsWriting || !ShouldSmooth(__instance) || info.Sender != PhotonNetwork.MasterClient)
			{
				return;
			}
			InterpState orCreate = GetOrCreate(__instance);
			int sentServerTimestamp = ((PhotonMessageInfo)(ref info)).SentServerTimestamp;
			if (orCreate.haveFirst && sentServerTimestamp == orCreate.lastTimestamp)
			{
				return;
			}
			try
			{
				Record(__instance, orCreate, sentServerTimestamp);
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("SmoothSync record failed on " + ((Object)__instance).name + ": " + ex.Message));
				orCreate.Clear();
			}
		}
	}

	[HarmonyPatch(typeof(PhotonTransformView), "Update")]
	internal static class UpdatePatch
	{
		private static void Postfix(PhotonTransformView __instance)
		{
			if (ShouldSmooth(__instance) && states.TryGetValue(__instance, out var value) && value.snapshots.Count != 0 && !teleportField.Invoke(__instance) && !sleepingField.Invoke(__instance))
			{
				Apply(value);
			}
		}
	}

	[HarmonyPatch(typeof(PhotonTransformView), "Teleport")]
	internal static class TeleportPatch
	{
		private static void Postfix(PhotonTransformView __instance)
		{
			if (states.TryGetValue(__instance, out var value))
			{
				value.Clear();
			}
		}
	}

	[HarmonyPatch(typeof(PhotonTransformView), "OnEnable")]
	internal static class EnablePatch
	{
		private static void Postfix(PhotonTransformView __instance)
		{
			if (states.TryGetValue(__instance, out var value))
			{
				value.Clear();
				value.haveFirst = false;
			}
		}
	}

	internal static bool Active;

	private static readonly Dictionary<PhotonTransformView, InterpState> states = new Dictionary<PhotonTransformView, InterpState>();

	private static FieldRef<PhotonTransformView, Vector3> recvPos;

	private static FieldRef<PhotonTransformView, Quaternion> recvRot;

	private static FieldRef<PhotonTransformView, Vector3> recvVel;

	private static FieldRef<PhotonTransformView, Vector3> recvAngVel;

	private static FieldRef<PhotonTransformView, Vector3> direction;

	private static FieldRef<PhotonTransformView, bool> teleportField;

	private static FieldRef<PhotonTransformView, bool> sleepingField;

	private static FieldRef<PhysGrabHinge, bool> hingeBroken;

	internal static bool InitAccessors()
	{
		try
		{
			recvPos = AccessTools.FieldRefAccess<PhotonTransformView, Vector3>("receivedPosition");
			recvRot = AccessTools.FieldRefAccess<PhotonTransformView, Quaternion>("receivedRotation");
			recvVel = AccessTools.FieldRefAccess<PhotonTransformView, Vector3>("receivedVelocity");
			recvAngVel = AccessTools.FieldRefAccess<PhotonTransformView, Vector3>("receivedAngularVelocity");
			direction = AccessTools.FieldRefAccess<PhotonTransformView, Vector3>("m_Direction");
			teleportField = AccessTools.FieldRefAccess<PhotonTransformView, bool>("teleport");
			sleepingField = AccessTools.FieldRefAccess<PhotonTransformView, bool>("isSleeping");
			hingeBroken = AccessTools.FieldRefAccess<PhysGrabHinge, bool>("broken");
			return true;
		}
		catch (Exception arg)
		{
			Plugin.Log.LogError((object)$"SmoothSync accessor init failed: {arg}");
			return false;
		}
	}

	private static float BaseFrequency()
	{
		return 1f / (float)Mathf.Max(1, PhotonNetwork.SerializationRate);
	}

	private static bool ShouldSmooth(PhotonTransformView ptv)
	{
		if (!Active || PhotonNetwork.IsMasterClient || !PhotonNetwork.InRoom)
		{
			return false;
		}
		if (Plugin.IsLocallySimulated != null && Plugin.IsLocallySimulated(ptv))
		{
			return false;
		}
		return true;
	}

	private static InterpState GetOrCreate(PhotonTransformView ptv)
	{
		if (!states.TryGetValue(ptv, out var value))
		{
			value = new InterpState
			{
				rb = ((Component)ptv).GetComponent<Rigidbody>(),
				tf = ((Component)ptv).transform,
				hinge = ((Component)ptv).GetComponent<PhysGrabHinge>(),
				smoothFreq = BaseFrequency()
			};
			states[ptv] = value;
		}
		return value;
	}

	internal static void Sweep()
	{
		if (states.Count == 0)
		{
			return;
		}
		if (!PhotonNetwork.InRoom)
		{
			states.Clear();
			return;
		}
		List<PhotonTransformView> list = null;
		foreach (KeyValuePair<PhotonTransformView, InterpState> state in states)
		{
			if ((Object)(object)state.Key == (Object)null)
			{
				(list ?? (list = new List<PhotonTransformView>())).Add(state.Key);
			}
		}
		if (list == null)
		{
			return;
		}
		foreach (PhotonTransformView item in list)
		{
			states.Remove(item);
		}
	}

	private static void Record(PhotonTransformView ptv, InterpState st, int timestamp)
	{
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_0054: 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_006a: Unknown result type (might be due to invalid IL or missing references)
		//IL_006f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0075: 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_0087: Unknown result type (might be due to invalid IL or missing references)
		//IL_008c: Unknown result type (might be due to invalid IL or missing references)
		//IL_020a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0210: Unknown result type (might be due to invalid IL or missing references)
		//IL_0216: Unknown result type (might be due to invalid IL or missing references)
		//IL_021b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0220: 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_022d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0233: Unknown result type (might be due to invalid IL or missing references)
		//IL_0238: Unknown result type (might be due to invalid IL or missing references)
		//IL_023d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0242: Unknown result type (might be due to invalid IL or missing references)
		//IL_00be: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_0160: Unknown result type (might be due to invalid IL or missing references)
		//IL_0167: Unknown result type (might be due to invalid IL or missing references)
		//IL_016c: 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_017c: 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_0186: Unknown result type (might be due to invalid IL or missing references)
		//IL_018c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0196: Unknown result type (might be due to invalid IL or missing references)
		//IL_0198: Unknown result type (might be due to invalid IL or missing references)
		//IL_019e: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b3: 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_01d0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01df: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
		//IL_0201: 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_00ee: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f8: 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_00d6: 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_029f: 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_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_02bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c1: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_02cc: Unknown result type (might be due to invalid IL or missing references)
		bool num = teleportField.Invoke(ptv);
		bool flag = sleepingField.Invoke(ptv);
		if (num || flag)
		{
			st.Clear();
			st.lastTimestamp = timestamp;
			st.haveFirst = true;
			return;
		}
		Vector3 velocity = recvVel.Invoke(ptv);
		Snapshot snapshot = new Snapshot
		{
			position = recvPos.Invoke(ptv),
			rotation = recvRot.Invoke(ptv),
			velocity = velocity,
			angularVelocity = recvAngVel.Invoke(ptv)
		};
		if ((Object)(object)st.hinge != (Object)null && !hingeBroken.Invoke(st.hinge))
		{
			Vector3 val = direction.Invoke(ptv);
			snapshot.velocity = (st.haveFirst ? (val / (float)Mathf.Max(1, timestamp - st.lastTimestamp) * 1000f) : (val / st.smoothFreq));
		}
		float num2 = Mathf.Max(Plugin.Future.Value * st.smoothFreq, 0f);
		if (st.snapshots.Count > 0 && (float)(timestamp - st.lastTimestamp) / 1000f < Plugin.TimingThreshold.Value)
		{
			Snapshot value = st.snapshots.Last.Value;
			Vector3 val2 = (snapshot.velocity - value.velocity) / st.smoothFreq;
			snapshot.position += snapshot.velocity * num2 + 0.5f * val2 * num2 * num2;
			Vector3 val3 = (snapshot.angularVelocity - value.angularVelocity) / st.smoothFreq;
			snapshot.rotation *= Quaternion.Euler((snapshot.angularVelocity + val3 * num2) * num2);
		}
		else
		{
			snapshot.position += snapshot.velocity * num2;
			snapshot.rotation *= Quaternion.Euler(snapshot.angularVelocity * num2);
		}
		st.snapshots.AddLast(snapshot);
		if (st.snapshots.Count == 2)
		{
			st.interpStartTime = Time.timeSinceLevelLoad;
		}
		else if (st.snapshots.Count >= 4)
		{
			st.snapshots.RemoveFirst();
			Snapshot value2 = st.snapshots.First.Value;
			value2.position = st.tf.position;
			value2.rotation = st.tf.rotation;
			value2.velocity = st.interpVel;
			value2.angularVelocity = st.interpAngVel;
			st.interpStartTime = Time.timeSinceLevelLoad;
		}
		if (st.haveFirst)
		{
			float num3 = (float)(timestamp - st.lastTimestamp) / 1000f;
			st.smoothFreq = ((num3 >= Plugin.TimingThreshold.Value) ? BaseFrequency() : Mathf.Lerp(st.smoothFreq, num3, Plugin.RateSmoothing.Value));
		}
		else
		{
			st.haveFirst = true;
		}
		st.lastTimestamp = timestamp;
	}

	private static void Apply(InterpState st)
	{
		//IL_014d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0154: Unknown result type (might be due to invalid IL or missing references)
		//IL_015b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0162: Unknown result type (might be due to invalid IL or missing references)
		//IL_016e: 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_0176: Unknown result type (might be due to invalid IL or missing references)
		//IL_017d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0184: Unknown result type (might be due to invalid IL or missing references)
		//IL_018b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0197: Unknown result type (might be due to invalid IL or missing references)
		//IL_019c: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f8: 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_00ff: Unknown result type (might be due to invalid IL or missing references)
		//IL_0104: 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_01f1: Unknown result type (might be due to invalid IL or missing references)
		//IL_0107: Unknown result type (might be due to invalid IL or missing references)
		//IL_010c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0113: Unknown result type (might be due to invalid IL or missing references)
		//IL_0118: 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_00b0: 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_00bd: 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_00d6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00db: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e2: 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_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_020c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0218: Unknown result type (might be due to invalid IL or missing references)
		float num = InterpFactor(st);
		while (num >= 1f && st.snapshots.Count > 1)
		{
			st.prev = st.snapshots.First.Value;
			st.snapshots.RemoveFirst();
			st.interpStartTime += st.smoothFreq;
			num = InterpFactor(st);
		}
		Vector3 val;
		Quaternion val2;
		if (st.snapshots.Count == 1)
		{
			Snapshot value = st.snapshots.First.Value;
			if (st.prev != null && Plugin.Extrapolate.Value)
			{
				float num2 = 2f - Mathf.Pow((float)Math.E, 0f - num);
				val = value.position + Vector3.SlerpUnclamped(st.prev.velocity, value.velocity, num2) * ((num2 - 1f) * st.smoothFreq);
				val2 = Quaternion.SlerpUnclamped(st.prev.rotation, value.rotation, num2);
			}
			else
			{
				val = value.position;
				val2 = value.rotation;
			}
			st.interpVel = value.velocity;
			st.interpAngVel = value.angularVelocity;
		}
		else
		{
			Snapshot value2 = st.snapshots.First.Value;
			Snapshot value3 = st.snapshots.First.Next.Value;
			val = HermitePosition(value2.position, value2.velocity, value3.position, value3.velocity, num, st.smoothFreq);
			val2 = HermiteRotation(value2.rotation, value2.angularVelocity, value3.rotation, value3.angularVelocity, num, st.smoothFreq);
			st.interpVel = Vector3.Slerp(value2.velocity, value3.velocity, num);
			st.interpAngVel = Vector3.Lerp(value2.angularVelocity, value3.angularVelocity, num);
		}
		if ((Object)(object)st.rb != (Object)null)
		{
			st.rb.MovePosition(val);
			st.rb.MoveRotation(val2);
		}
		else if ((Object)(object)st.tf != (Object)null)
		{
			st.tf.position = val;
			st.tf.rotation = val2;
		}
	}

	private static float InterpFactor(InterpState st)
	{
		if (st.smoothFreq <= 0f || st.interpStartTime < 0f)
		{
			return 1f;
		}
		return (Time.timeSinceLevelLoad - st.interpStartTime) / st.smoothFreq;
	}

	private static Vector3 HermitePosition(Vector3 startPos, Vector3 startVel, Vector3 endPos, Vector3 endVel, float t, float freq)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0001: 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_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_001b: 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_0028: 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_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_003d: 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)
		Vector3 val = startPos + startVel * (freq * t) / 3f;
		Vector3 val2 = endPos - endVel * (freq * (1f - t)) / 3f;
		return Vector3.Lerp(val, val2, t);
	}

	private static Quaternion HermiteRotation(Quaternion startRot, Vector3 startSpin, Quaternion endRot, Vector3 endSpin, float t, float freq)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0001: 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_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: 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_0033: 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_0042: 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_004c: 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_0050: Unknown result type (might be due to invalid IL or missing references)
		Quaternion val = startRot * Quaternion.Euler(startSpin * (freq * t) / 3f);
		Quaternion val2 = endRot * Quaternion.Euler(endSpin * (-1f * freq * (1f - t)) / 3f);
		return Quaternion.Slerp(val, val2, t);
	}
}