Decompiled source of RevivalSync v1.2.23

RevivalSync.dll

Decompiled a month ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using ExitGames.Client.Photon;
using HarmonyLib;
using Photon.Pun;
using Photon.Realtime;
using RevivalSync.Patches;
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.2.23.0")]
[assembly: AssemblyInformationalVersion("1.2.23+8237d8d8f14a06c4237804850f878f6694e7c0ae")]
[assembly: AssemblyProduct("RevivalSync")]
[assembly: AssemblyTitle("RevivalSync")]
[assembly: AssemblyVersion("1.2.23.0")]
namespace RevivalSync
{
	[BepInPlugin("com.Revival.revivalsync", "RevivalSync", "1.2.23")]
	public class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "com.Revival.revivalsync";

		public const string PluginName = "RevivalSync";

		public const string PluginVersion = "1.2.23";

		internal static ManualLogSource Log;

		internal static ConfigEntry<bool> SimulateCarts;

		internal static ConfigEntry<bool> SimulateHinges;

		internal static ConfigEntry<bool> SimulateItems;

		internal static ConfigEntry<bool> InstantCartHandle;

		internal static ConfigEntry<float> PassiveSyncStrength;

		internal static ConfigEntry<float> PostThrowGrace;

		internal static ConfigEntry<float> SnapDistance;

		internal static ConfigEntry<float> HeldDriftHandbackAt;

		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 ConfigEntry<bool> VerboseLogging;

		internal static ConfigEntry<string> ResyncKey;

		internal static ConfigEntry<float> AutoResyncSeconds;

		private static string resyncKeyRaw;

		private static KeyCode resyncKeyCode = (KeyCode)289;

		internal static bool PhotonReady;

		private static Harmony harmony;

		private static bool capturePatched;

		private static string sessionLogPath;

		private static float nextLogArchive;

		internal static KeyCode ResyncKeyCode
		{
			get
			{
				//IL_004f: 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_003a: Unknown result type (might be due to invalid IL or missing references)
				string text = ResyncKey?.Value;
				if (text != resyncKeyRaw)
				{
					resyncKeyRaw = text;
					resyncKeyCode = ParseKey(text);
					Log.LogInfo((object)$"Resync key set to {resyncKeyCode} (from \"{text}\").");
				}
				return resyncKeyCode;
			}
		}

		private static KeyCode ParseKey(string raw)
		{
			//IL_0026: 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_044e: Unknown result type (might be due to invalid IL or missing references)
			if (string.IsNullOrWhiteSpace(raw))
			{
				return (KeyCode)0;
			}
			string text = raw.Trim();
			if (Enum.TryParse<KeyCode>(text, ignoreCase: true, out KeyCode result) && Enum.IsDefined(typeof(KeyCode), result))
			{
				return result;
			}
			switch (text.ToLowerInvariant().Replace(" ", ""))
			{
			case "none":
			case "off":
			case "disabled":
				return (KeyCode)0;
			case "spacebar":
			case "space":
				return (KeyCode)32;
			case "esc":
				return (KeyCode)27;
			case "enter":
			case "return":
				return (KeyCode)13;
			case "del":
				return (KeyCode)127;
			case "ins":
				return (KeyCode)277;
			case "ctrl":
			case "leftctrl":
			case "lctrl":
			case "control":
				return (KeyCode)306;
			case "rctrl":
			case "rightctrl":
				return (KeyCode)305;
			case "lalt":
			case "alt":
			case "leftalt":
				return (KeyCode)308;
			case "shift":
			case "lshift":
			case "leftshift":
				return (KeyCode)304;
			case "middlemouse":
			case "mousemiddle":
				return (KeyCode)325;
			case "rightmouse":
				return (KeyCode)324;
			case "leftmouse":
				return (KeyCode)323;
			default:
			{
				if (text.Length == 1 && text[0] >= '0' && text[0] <= '9' && Enum.TryParse<KeyCode>("Alpha" + text, out KeyCode result2))
				{
					return result2;
				}
				Log.LogWarning((object)("Resync key \"" + raw + "\" is not a recognized key name — resync key disabled. Try a name like F8, K, Mouse3 or None."));
				return (KeyCode)0;
			}
			}
		}

		internal static void EnsureCapturePatch()
		{
			if (capturePatched || !PhotonReady || harmony == null)
			{
				return;
			}
			capturePatched = true;
			try
			{
				harmony.PatchAll(typeof(SerializeReadCapturePatch));
				Log.LogInfo((object)"Host-state capture hooked (deferred until Photon start).");
			}
			catch (Exception arg)
			{
				Log.LogError((object)$"Failed to hook host-state capture: {arg}");
			}
		}

		private void Awake()
		{
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Expected O, but got Unknown
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Expected O, but got Unknown
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Expected O, but got Unknown
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01be: Expected O, but got Unknown
			//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fb: Expected O, but got Unknown
			//IL_028e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0298: Expected O, but got Unknown
			//IL_02cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d5: Expected O, but got Unknown
			//IL_0308: Unknown result type (might be due to invalid IL or missing references)
			//IL_0312: Expected O, but got Unknown
			//IL_0353: Unknown result type (might be due to invalid IL or missing references)
			//IL_035d: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			SimulateCarts = ((BaseUnityPlugin)this).Config.Bind<bool>("1. Main", "Instant Carts", true, "Carts respond the moment you grab and push them, no waiting on the host. Only turn this off if carts misbehave for you. Changes apply from the next level.");
			SimulateHinges = ((BaseUnityPlugin)this).Config.Bind<bool>("1. Main", "Instant Doors", true, "Doors and cabinets swing the moment you touch them, no waiting on the host. Only turn this off if doors misbehave for you. Takes full effect on the next game launch.");
			SimulateItems = ((BaseUnityPlugin)this).Config.Bind<bool>("1. Main", "Instant Items", true, "Weapons, grenades and gadgets follow your hand instantly, aim with your camera and fly the way you throw them. Damage and explosions are still decided by the host, like normal. Vehicles, drones and the duck always use the game's normal sync (they move themselves). Only turn this off if an item misbehaves for you. Changes apply from the next level.");
			DisableTimeout = ((BaseUnityPlugin)this).Config.Bind<bool>("1. Main", "No Timeout Kicks", true, "Stops the game from kicking you out of the lobby during short lag spikes.");
			ResyncKey = ((BaseUnityPlugin)this).Config.Bind<string>("1. Main", "Resync Loot Key", "F8", "Emergency desync fix: press this key to instantly teleport every synced object to exactly where the host sees it. Type any key name here, for example: F8, K, Mouse3, Keypad5, LeftAlt, Backspace. Set it to None to turn the key off.");
			AutoResyncSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("1. Main", "Auto Resync Seconds", 0f, new ConfigDescription("0 = off. If set, automatically performs the Resync Loot teleport every this many seconds, so you never have to press the key yourself.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 120f), Array.Empty<object>()));
			SmoothSync = ((BaseUnityPlugin)this).Config.Bind<bool>("1. Main", "Smooth Enemies", true, "Enemies and other host-controlled things move smoothly instead of stuttering. Takes effect on the next game launch.");
			PassiveSyncStrength = ((BaseUnityPlugin)this).Config.Bind<float>("2. Fine-Tuning (defaults are good)", "World Sync Strength", 0.075f, new ConfigDescription("How firmly the world is pulled toward what the host sees. Higher = tighter sync but harsher corrections, lower = gentler but objects drift longer.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.01f, 0.5f), Array.Empty<object>()));
			PostThrowGrace = ((BaseUnityPlugin)this).Config.Bind<float>("2. Fine-Tuning (defaults are good)", "Throw Freedom Seconds", 0.6f, new ConfigDescription("How long a thrown object flies purely on your screen before syncing takes over again.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 3f), Array.Empty<object>()));
			SnapDistance = ((BaseUnityPlugin)this).Config.Bind<float>("2. Fine-Tuning (defaults are good)", "Teleport Distance", 6f, new ConfigDescription("If an object ends up further than this many meters from where the host has it, it teleports there instead of gliding. Do NOT set this low: a cart you are steering naturally rides up to ~3m from the host's copy, so a low value makes it teleport constantly — through you and scattering its loot. 6 is the sweet spot.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(4f, 30f), Array.Empty<object>()));
			HeldDriftHandbackAt = ((BaseUnityPlugin)this).Config.Bind<float>("2. Fine-Tuning (defaults are good)", "Held Object Give Up At", 4f, new ConfigDescription("While you hold something: if it stays further off than this many meters (e.g. the host's copy got stuck), control returns to the host until you grab it again.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 20f), Array.Empty<object>()));
			InstantCartHandle = ((BaseUnityPlugin)this).Config.Bind<bool>("2. Fine-Tuning (defaults are good)", "Instant Cart Handle", true, "Cart handle grabs register on your machine right away instead of waiting for the host.");
			PhotonLateUpdate = ((BaseUnityPlugin)this).Config.Bind<bool>("2. Fine-Tuning (defaults are good)", "Process Packets Every Frame", true, "Handles network data every rendered frame instead of every physics tick. Lower felt latency.");
			Extrapolate = ((BaseUnityPlugin)this).Config.Bind<bool>("2. Fine-Tuning (defaults are good)", "Smooth Enemies - Extrapolate", true, "Keep enemies moving on a predicted path for a moment when an update arrives late.");
			Future = ((BaseUnityPlugin)this).Config.Bind<float>("2. Fine-Tuning (defaults are good)", "Smooth Enemies - Look Ahead", 1f, new ConfigDescription("How far ahead of the received data enemies are projected, in update intervals.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 3f), Array.Empty<object>()));
			RateSmoothing = ((BaseUnityPlugin)this).Config.Bind<float>("2. Fine-Tuning (defaults are good)", "Smooth Enemies - Rate Adapt", 0.1f, new ConfigDescription("How quickly the measured update rate adapts. Leave at 0.1 — high values make enemies jitter with every network wobble.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			TimingThreshold = ((BaseUnityPlugin)this).Config.Bind<float>("2. Fine-Tuning (defaults are good)", "Smooth Enemies - Gap Seconds", 1f, new ConfigDescription("A silence longer than this many seconds counts as a gap instead of movement to smooth over.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.2f, 5f), Array.Empty<object>()));
			VerboseLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("3. Debug", "Verbose Logging", false, "Records everything the mod does into BepInEx/LogOutput.log. Turn this ON before reporting a bug and include that file with the report.");
			if (!SimManager.InitAccessors())
			{
				Log.LogError((object)"RevivalSync could not find expected game internals (the game probably updated). The mod has disabled itself to avoid breaking your game.");
				return;
			}
			harmony = new Harmony("com.Revival.revivalsync");
			int num = 0;
			int num2 = 0;
			Type[] array = new Type[13]
			{
				typeof(DriverHooksPatch),
				typeof(PhotonHandlerAwakePatch),
				typeof(HingeJointKeeperPatch),
				typeof(HingePushPatch),
				typeof(PhysGrabObjectStartPatch),
				typeof(GrabStartedPatch),
				typeof(GrabEndedPatch),
				typeof(GrabPlayerAddDedupePatch),
				typeof(TransformViewUpdatePatch),
				typeof(TransformViewSerializePatch),
				typeof(CartAuthorityPatch),
				typeof(ToggleClaimLogPatch),
				typeof(UpgradeCreditLogPatch)
			};
			foreach (Type type in array)
			{
				try
				{
					harmony.PatchAll(type);
					num++;
				}
				catch (Exception arg)
				{
					num2++;
					Log.LogError((object)$"Failed to apply patch {type.Name}: {arg}");
				}
			}
			if (SmoothSync.Value && Smoothing.InitAccessors())
			{
				try
				{
					harmony.PatchAll(typeof(Smoothing.SerializePatch));
					harmony.PatchAll(typeof(Smoothing.UpdatePatch));
					harmony.PatchAll(typeof(Smoothing.TeleportPatch));
					harmony.PatchAll(typeof(Smoothing.EnablePatch));
					Smoothing.Active = true;
				}
				catch (Exception arg2)
				{
					Log.LogError((object)$"Failed to apply SmoothSync patches, interpolation disabled: {arg2}");
				}
			}
			if (num == 0)
			{
				Log.LogError((object)"No patches could be applied — RevivalSync is inactive.");
				return;
			}
			Log.LogInfo((object)(string.Format("{0} {1} loaded. Patches: {2} ok, {3} failed. ", "RevivalSync", "1.2.23", num, num2) + $"SmoothSync: {Smoothing.Active}. Prediction activates when you join someone else's lobby; " + "the mod is inert while hosting."));
		}

		private void Update()
		{
			SimDriver.FrameUpdate();
		}

		private void FixedUpdate()
		{
			SimManager.Tick();
		}

		private void OnDestroy()
		{
			SimManager.RestoreAll();
			ArchiveSessionLog(force: true);
		}

		internal static void ArchiveSessionLog(bool force = false)
		{
			try
			{
				if (!force && Time.unscaledTime < nextLogArchive)
				{
					return;
				}
				nextLogArchive = Time.unscaledTime + 60f;
				string text = Path.Combine(Paths.BepInExRootPath, "LogOutput.log");
				if (!File.Exists(text))
				{
					return;
				}
				if (sessionLogPath == null)
				{
					string text2 = Path.Combine(Paths.BepInExRootPath, "RevivalSync-logs");
					Directory.CreateDirectory(text2);
					sessionLogPath = Path.Combine(text2, $"session-{DateTime.Now:yyyyMMdd-HHmmss}.log");
					FileInfo[] files = new DirectoryInfo(text2).GetFiles("session-*.log");
					Array.Sort(files, (FileInfo a, FileInfo b) => string.CompareOrdinal(b.Name, a.Name));
					for (int num = 9; num < files.Length; num++)
					{
						files[num].Delete();
					}
				}
				File.Copy(text, sessionLogPath, overwrite: true);
			}
			catch
			{
			}
		}

		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));
			}
		}
	}
	internal static class SimManager
	{
		internal class SimState
		{
			public PhysGrabObject pgo;

			public PhotonTransformView ptv;

			public Rigidbody rb;

			public PhysGrabCart cart;

			public bool isHinge;

			public PhysGrabHinge hinge;

			public HingeJoint joint;

			public int viewId;

			public bool localGrab;

			public float localPushTimer;

			public float postThrowTimer;

			public float postThrowRamp;

			public float noSnapTimer;

			public float hingeSyncPause;

			public bool droneExempt;

			public float farTimer;

			public ItemDrone droneSelf;

			public ItemToggle droneToggle;

			public float desyncTimer;

			public float stuckTimer;

			public float debugTimer;

			public int ridingTick;

			public SimState ridingCart;

			public bool wasRiding;

			public float rideHoldTimer;

			public bool mirrorHeldRot;

			public ItemGun gun;

			public ItemMelee melee;

			public bool hasHostState;

			public float lastPacketTime = -999f;

			public Vector3 hostPos;

			public Quaternion hostRot = Quaternion.identity;

			public Vector3 hostVel;

			public Vector3 hostAngVel;

			public bool hostKinematic;

			public bool hostSleeping;

			public bool hostTeleport;
		}

		private static readonly Dictionary<PhysGrabObject, SimState> states = new Dictionary<PhysGrabObject, SimState>();

		private static readonly Dictionary<PhotonTransformView, SimState> byPtv = new Dictionary<PhotonTransformView, SimState>();

		private static readonly Dictionary<int, SimState> byViewId = new Dictionary<int, SimState>();

		private static readonly List<SimState> tickBuffer = new List<SimState>(256);

		private static readonly HashSet<PhysGrabObject> handedBack = new HashSet<PhysGrabObject>();

		private static readonly List<PhysGrabObject> handedBackSweep = new List<PhysGrabObject>();

		internal static int PacketsCaptured;

		private static float lastCaptureTime = -999f;

		private static Vector3 disabledPos = new Vector3(0f, 3000f, 0f);

		private static bool disabledPosRead;

		private static FieldRef<PhysGrabObject, bool> pgoIsMaster;

		private static FieldRef<ItemMelee, Quaternion> meleeYRot;

		private static FieldRef<PhysGrabObject, bool> pgoIsActive;

		internal static FieldRef<PhysGrabObject, bool> pgoHeldByLocal;

		internal static FieldRef<ItemToggle, int> togglePlayerId;

		private static FieldRef<PhysGrabber, PhysGrabObject> grabberObject;

		private static FieldRef<PhysGrabCart, List<PhysGrabObject>> cartItems;

		private static FieldRef<PhysGrabCart, Transform> cartInCart;

		private static FieldRef<PhysGrabCart, PhysGrabObjectGrabArea> cartGrabArea;

		private static FieldRef<PlayerAvatar, bool> avatarSprinting;

		private static FieldRef<PhysGrabHinge, bool> hingeBroken;

		private static MethodInfo pgoThrow;

		private static FieldRef<PhotonTransformView, Vector3> ptvNetPos;

		private static FieldRef<PhotonTransformView, Quaternion> ptvNetRot;

		private static FieldRef<PhotonTransformView, Vector3> ptvStoredPos;

		private static FieldRef<PhotonTransformView, Vector3> ptvSmoothedPos;

		private static FieldRef<PhotonTransformView, Quaternion> ptvSmoothedRot;

		private static FieldRef<PhotonTransformView, Vector3> ptvRecvPos;

		private static FieldRef<PhotonTransformView, Quaternion> ptvRecvRot;

		private static FieldRef<PhotonTransformView, Vector3> ptvPrevPos;

		private static FieldRef<PhotonTransformView, Quaternion> ptvPrevRot;

		private static FieldRef<PhotonTransformView, Vector3> ptvRecvVel;

		private static FieldRef<PhotonTransformView, Vector3> ptvRecvAngVel;

		private static FieldRef<PhotonTransformView, float> ptvDistance;

		private static FieldRef<PhotonTransformView, float> ptvAngle;

		private static FieldRef<PhotonTransformView, bool> ptvFirstTake;

		private static FieldRef<PhotonTransformView, bool> ptvTeleport;

		private static FieldRef<PhotonTransformView, bool> ptvIsSleeping;

		private static FieldRef<PhotonTransformView, bool> ptvKinForced;

		private static FieldRef<PhotonTransformView, float> ptvKinForcedTimer;

		private static int tickCounter;

		private static int cargoStagger;

		private static FieldRef<ItemDrone, bool> droneMagnetActive;

		private static FieldRef<ItemDrone, PhysGrabObject> droneMagnetTarget;

		private static bool droneAccessorsTried;

		internal static ItemDrone[] cachedDrones;

		private static readonly Dictionary<PhysGrabObject, ItemDrone> droneTargetMap = new Dictionary<PhysGrabObject, ItemDrone>();

		private static bool wasClientInLobby;

		private static float lastTickFixedTime = -1f;

		private static bool tickMarker;

		private static readonly List<PhysGrabObject> deadPgos = new List<PhysGrabObject>();

		private static readonly List<PhotonTransformView> deadPtvs = new List<PhotonTransformView>();

		private static readonly List<int> deadIds = new List<int>();

		internal static bool Ready { get; private set; }

		internal static bool HostStalled => Time.unscaledTime - lastCaptureTime > 2f;

		internal static int RegisteredCount => states.Count;

		internal static int HeldCount
		{
			get
			{
				int num = 0;
				foreach (SimState value in states.Values)
				{
					if (value.localGrab)
					{
						num++;
					}
				}
				return num;
			}
		}

		private static Vector3 DisabledPosition()
		{
			//IL_0058: 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)
			if (!disabledPosRead)
			{
				try
				{
					if ((Object)(object)AssetManager.instance != (Object)null)
					{
						FieldInfo fieldInfo = AccessTools.Field(typeof(AssetManager), "physDisabledPosition");
						if (fieldInfo != null)
						{
							disabledPos = (Vector3)fieldInfo.GetValue(AssetManager.instance);
							disabledPosRead = true;
						}
					}
				}
				catch
				{
					disabledPosRead = true;
				}
			}
			return disabledPos;
		}

		internal static bool InitAccessors()
		{
			try
			{
				pgoIsMaster = AccessTools.FieldRefAccess<PhysGrabObject, bool>("isMaster");
				pgoIsActive = AccessTools.FieldRefAccess<PhysGrabObject, bool>("isActive");
				pgoHeldByLocal = AccessTools.FieldRefAccess<PhysGrabObject, bool>("heldByLocalPlayer");
				togglePlayerId = AccessTools.FieldRefAccess<ItemToggle, int>("playerTogglePhotonID");
				grabberObject = AccessTools.FieldRefAccess<PhysGrabber, PhysGrabObject>("grabbedPhysGrabObject");
				cartItems = AccessTools.FieldRefAccess<PhysGrabCart, List<PhysGrabObject>>("itemsInCart");
				cartInCart = AccessTools.FieldRefAccess<PhysGrabCart, Transform>("inCart");
				cartGrabArea = AccessTools.FieldRefAccess<PhysGrabCart, PhysGrabObjectGrabArea>("physGrabObjectGrabArea");
				avatarSprinting = AccessTools.FieldRefAccess<PlayerAvatar, bool>("isSprinting");
				hingeBroken = AccessTools.FieldRefAccess<PhysGrabHinge, bool>("broken");
				meleeYRot = AccessTools.FieldRefAccess<ItemMelee, Quaternion>("currentYRotation");
				pgoThrow = AccessTools.Method(typeof(PhysGrabObject), "Throw", (Type[])null, (Type[])null);
				ptvNetPos = AccessTools.FieldRefAccess<PhotonTransformView, Vector3>("m_NetworkPosition");
				ptvNetRot = AccessTools.FieldRefAccess<PhotonTransformView, Quaternion>("m_NetworkRotation");
				ptvStoredPos = AccessTools.FieldRefAccess<PhotonTransformView, Vector3>("m_StoredPosition");
				ptvSmoothedPos = AccessTools.FieldRefAccess<PhotonTransformView, Vector3>("smoothedPosition");
				ptvSmoothedRot = AccessTools.FieldRefAccess<PhotonTransformView, Quaternion>("smoothedRotation");
				ptvRecvPos = AccessTools.FieldRefAccess<PhotonTransformView, Vector3>("receivedPosition");
				ptvRecvRot = AccessTools.FieldRefAccess<PhotonTransformView, Quaternion>("receivedRotation");
				ptvPrevPos = AccessTools.FieldRefAccess<PhotonTransformView, Vector3>("prevPosition");
				ptvPrevRot = AccessTools.FieldRefAccess<PhotonTransformView, Quaternion>("prevRotation");
				ptvRecvVel = AccessTools.FieldRefAccess<PhotonTransformView, Vector3>("receivedVelocity");
				ptvRecvAngVel = AccessTools.FieldRefAccess<PhotonTransformView, Vector3>("receivedAngularVelocity");
				ptvDistance = AccessTools.FieldRefAccess<PhotonTransformView, float>("m_Distance");
				ptvAngle = AccessTools.FieldRefAccess<PhotonTransformView, float>("m_Angle");
				ptvFirstTake = AccessTools.FieldRefAccess<PhotonTransformView, bool>("m_firstTake");
				ptvTeleport = AccessTools.FieldRefAccess<PhotonTransformView, bool>("teleport");
				ptvIsSleeping = AccessTools.FieldRefAccess<PhotonTransformView, bool>("isSleeping");
				ptvKinForced = AccessTools.FieldRefAccess<PhotonTransformView, bool>("kinematicClientForced");
				ptvKinForcedTimer = AccessTools.FieldRefAccess<PhotonTransformView, float>("kinematicClientForcedTimer");
				if (pgoThrow == null)
				{
					Plugin.Log.LogWarning((object)"PhysGrabObject.Throw not found — throws will rely on host only.");
				}
				Ready = true;
				return true;
			}
			catch (Exception arg)
			{
				Plugin.Log.LogError((object)$"Accessor init failed: {arg}");
				Ready = false;
				return false;
			}
		}

		internal static bool IsClientInLobby()
		{
			if (GameManager.Multiplayer() && PhotonNetwork.InRoom)
			{
				return !PhotonNetwork.IsMasterClient;
			}
			return false;
		}

		internal static bool IsSuppressed(PhotonTransformView ptv)
		{
			if ((Object)(object)ptv != (Object)null && byPtv.TryGetValue(ptv, out var value))
			{
				return !value.droneExempt;
			}
			return false;
		}

		internal static bool IsRegistered(PhotonTransformView ptv)
		{
			if ((Object)(object)ptv != (Object)null && byPtv.TryGetValue(ptv, out var value))
			{
				return !value.droneExempt;
			}
			return false;
		}

		internal static bool IsLocalGrab(PhysGrabObject pgo)
		{
			if ((Object)(object)pgo != (Object)null && states.TryGetValue(pgo, out var value))
			{
				return value.localGrab;
			}
			return false;
		}

		internal static bool HasPhysicsAuthority(PhysGrabObject pgo)
		{
			if ((Object)(object)pgo != (Object)null && states.TryGetValue(pgo, out var value))
			{
				return !value.droneExempt;
			}
			return false;
		}

		internal static bool IsHandedBack(PhysGrabObject pgo)
		{
			if ((Object)(object)pgo != (Object)null)
			{
				return handedBack.Contains(pgo);
			}
			return false;
		}

		internal static void ClearHandback(PhysGrabObject pgo)
		{
			if ((Object)(object)pgo != (Object)null)
			{
				handedBack.Remove(pgo);
			}
		}

		internal static bool CanSimulate(PhysGrabObject o)
		{
			if ((Object)(object)o == (Object)null || (Object)(object)o.rb == (Object)null)
			{
				return false;
			}
			if ((Object)(object)((Component)o).GetComponent<PhotonView>() == (Object)null)
			{
				return false;
			}
			if ((Object)(object)((Component)o).GetComponent<PhotonTransformView>() == (Object)null)
			{
				return false;
			}
			if ((Object)(object)((Component)o).GetComponent<PhysGrabCart>() != (Object)null)
			{
				return Plugin.SimulateCarts.Value;
			}
			if ((Object)(object)((Component)o).GetComponent<PlayerTumble>() != (Object)null)
			{
				return false;
			}
			if ((Object)(object)((Component)o).GetComponentInParent<Enemy>() != (Object)null)
			{
				return false;
			}
			if ((Object)(object)((Component)o).GetComponentInParent<EnemyRigidbody>() != (Object)null)
			{
				return false;
			}
			if ((Object)(object)((Component)o).GetComponentInParent<PhysGrabHinge>() != (Object)null)
			{
				return Plugin.SimulateHinges.Value;
			}
			if ((Object)(object)((Component)o).GetComponentInParent<ItemVehicle>() != (Object)null)
			{
				return false;
			}
			if ((Object)(object)((Component)o).GetComponentInParent<ItemCartCannonMain>() != (Object)null)
			{
				return false;
			}
			if ((Object)(object)((Component)o).GetComponentInParent<ItemUpgrade>() != (Object)null)
			{
				return false;
			}
			if ((Object)(object)((Component)o).GetComponentInParent<ItemAttributes>() != (Object)null)
			{
				Component[] componentsInParent = ((Component)o).GetComponentsInParent<Component>(true);
				foreach (Component val in componentsInParent)
				{
					if (!((Object)(object)val == (Object)null) && ((object)val).GetType().Name.StartsWith("ItemRubberDuck"))
					{
						return false;
					}
				}
				return Plugin.SimulateItems.Value;
			}
			return true;
		}

		internal static SimState GetByViewId(int viewId)
		{
			if (!byViewId.TryGetValue(viewId, out var value))
			{
				return null;
			}
			return value;
		}

		internal static void CacheHostState(SimState st, object[] data, int networkTime)
		{
			//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_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_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: 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_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_00fb: 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_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: 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_0113: 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)
			for (int i = 3; i + 7 < data.Length; i++)
			{
				if (!(data[i] is bool hostSleeping) || !(data[i + 1] is bool flag) || !(data[i + 2] is bool hostKinematic) || !(data[i + 3] is Vector3 hostVel) || !(data[i + 4] is Vector3 hostAngVel) || !(data[i + 5] is Vector3 hostPos))
				{
					continue;
				}
				object obj = data[i + 6];
				if (obj is Vector3)
				{
					_ = (Vector3)obj;
					if (data[i + 7] is Quaternion hostRot)
					{
						st.hostSleeping = hostSleeping;
						st.hostTeleport |= flag;
						st.hostKinematic = hostKinematic;
						st.hostVel = hostVel;
						st.hostAngVel = hostAngVel;
						st.hostPos = hostPos;
						st.hostRot = hostRot;
						st.hasHostState = true;
						st.lastPacketTime = Time.unscaledTime;
						lastCaptureTime = Time.unscaledTime;
						PacketsCaptured++;
						break;
					}
				}
			}
		}

		internal static SimState TryRegister(PhysGrabObject pgo)
		{
			//IL_010b: 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_01e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fa: 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_0210: Unknown result type (might be due to invalid IL or missing references)
			//IL_0215: Unknown result type (might be due to invalid IL or missing references)
			if (!Ready || (Object)(object)pgo == (Object)null)
			{
				return null;
			}
			if (states.TryGetValue(pgo, out var value))
			{
				return value;
			}
			if (!IsClientInLobby())
			{
				return null;
			}
			if (!CanSimulate(pgo))
			{
				return null;
			}
			PhotonTransformView component = ((Component)pgo).GetComponent<PhotonTransformView>();
			PhotonView component2 = ((Component)pgo).GetComponent<PhotonView>();
			if ((Object)(object)component == (Object)null || (Object)(object)component2 == (Object)null || (Object)(object)pgo.rb == (Object)null)
			{
				return null;
			}
			SimState simState = new SimState
			{
				pgo = pgo,
				ptv = component,
				rb = pgo.rb,
				cart = ((Component)pgo).GetComponent<PhysGrabCart>(),
				hinge = ((Component)pgo).GetComponent<PhysGrabHinge>(),
				viewId = component2.ViewID
			};
			simState.isHinge = (Object)(object)simState.hinge != (Object)null;
			if (simState.isHinge)
			{
				simState.joint = ((Component)pgo).GetComponent<HingeJoint>();
				if ((Object)(object)simState.joint != (Object)null)
				{
					((Joint)simState.joint).breakForce = float.PositiveInfinity;
					((Joint)simState.joint).breakTorque = float.PositiveInfinity;
				}
				pgo.spawned = true;
			}
			if ((int)simState.rb.collisionDetectionMode == 0)
			{
				simState.rb.collisionDetectionMode = (CollisionDetectionMode)2;
			}
			if (!simState.isHinge && (Object)(object)simState.cart == (Object)null && (Object)(object)((Component)pgo).GetComponentInParent<ItemAttributes>() != (Object)null)
			{
				simState.gun = ((Component)pgo).GetComponentInChildren<ItemGun>(true);
				simState.melee = ((Component)pgo).GetComponentInChildren<ItemMelee>(true);
				simState.mirrorHeldRot = (Object)(object)simState.gun == (Object)null && (Object)(object)simState.melee == (Object)null;
				simState.droneSelf = ((Component)pgo).GetComponentInChildren<ItemDrone>(true);
				if ((Object)(object)simState.droneSelf != (Object)null)
				{
					simState.droneToggle = ((Component)pgo).GetComponentInChildren<ItemToggle>(true);
				}
			}
			if (!ptvFirstTake.Invoke(component))
			{
				simState.hasHostState = true;
				simState.hostPos = ptvNetPos.Invoke(component);
				simState.hostRot = ptvNetRot.Invoke(component);
				simState.hostVel = ptvRecvVel.Invoke(component);
				simState.hostAngVel = ptvRecvAngVel.Invoke(component);
				simState.hostKinematic = simState.rb.isKinematic;
				simState.hostSleeping = ptvIsSleeping.Invoke(component);
			}
			states[pgo] = simState;
			byPtv[component] = simState;
			if (simState.viewId != 0)
			{
				byViewId[simState.viewId] = simState;
			}
			if (Plugin.VerboseLogging.Value)
			{
				Plugin.Log.LogInfo((object)$"[reg] {((Object)pgo).name} (view {simState.viewId}, cart={(Object)(object)simState.cart != (Object)null}, seeded={simState.hasHostState})");
			}
			return simState;
		}

		internal static void StartLocalGrab(PhysGrabObject pgo)
		{
			if (!Ready || (Object)(object)pgo == (Object)null)
			{
				return;
			}
			SimState simState = TryRegister(pgo);
			if (simState != null)
			{
				if (!simState.localGrab && Plugin.VerboseLogging.Value)
				{
					Plugin.Log.LogInfo((object)("Local grab authority: " + ((Object)pgo).name));
				}
				simState.localGrab = true;
				simState.postThrowTimer = 0f;
				simState.desyncTimer = 0f;
				simState.stuckTimer = 0f;
				pgoIsMaster.Invoke(pgo) = true;
				EnsureDynamic(simState);
			}
		}

		internal static void EndLocalGrab(PhysGrabObject pgo)
		{
			//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_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0109: 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)
			if (Ready && !((Object)(object)pgo == (Object)null) && states.TryGetValue(pgo, out var value) && value.localGrab)
			{
				value.localGrab = false;
				value.desyncTimer = 0f;
				value.stuckTimer = 0f;
				value.postThrowTimer = (value.isHinge ? 0f : (((Object)(object)value.cart != (Object)null) ? (Plugin.PostThrowGrace.Value * 2.5f) : Plugin.PostThrowGrace.Value));
				if (!value.isHinge)
				{
					value.noSnapTimer = 3f;
				}
				else
				{
					value.hingeSyncPause = 1.5f;
				}
				pgoIsMaster.Invoke(pgo) = false;
				if (!value.isHinge && value.hasHostState && (Object)(object)value.rb != (Object)null)
				{
					value.hostPos = value.rb.position;
					value.hostRot = value.rb.rotation;
					value.hostVel = value.rb.velocity;
					value.hostAngVel = value.rb.angularVelocity;
					value.hostSleeping = false;
					value.hostKinematic = false;
					value.hostTeleport = false;
					value.lastPacketTime = Time.unscaledTime;
				}
				ScrubStaleLocalGrabber(pgo);
				if (Plugin.VerboseLogging.Value)
				{
					Plugin.Log.LogInfo((object)("Released grab authority: " + ((Object)pgo).name));
				}
			}
		}

		private static void ScrubStaleLocalGrabber(PhysGrabObject pgo)
		{
			if ((Object)(object)pgo == (Object)null)
			{
				return;
			}
			List<PhysGrabber> playerGrabbing = pgo.playerGrabbing;
			for (int num = playerGrabbing.Count - 1; num >= 0; num--)
			{
				PhysGrabber val = playerGrabbing[num];
				if (!((Object)(object)val == (Object)null) && val.isLocal && (!val.grabbed || !((Object)(object)grabberObject.Invoke(val) == (Object)(object)pgo)))
				{
					playerGrabbing.RemoveAt(num);
					if (Plugin.VerboseLogging.Value)
					{
						Plugin.Log.LogInfo((object)("[stale-grab] " + ((Object)pgo).name + ": removed stale local grabber entry (object read as held-by-us)"));
					}
				}
			}
		}

		internal static void LocalThrow(PhysGrabObject pgo, PhysGrabber player)
		{
			//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)
			if (pgoThrow == null || (Object)(object)pgo == (Object)null || (Object)(object)player == (Object)null || !states.TryGetValue(pgo, out var value) || (Object)(object)value.rb == (Object)null || value.rb.isKinematic || value.isHinge)
			{
				return;
			}
			try
			{
				pgoThrow.Invoke(pgo, new object[1] { player });
				if (Plugin.VerboseLogging.Value)
				{
					ManualLogSource log = Plugin.Log;
					string name = ((Object)pgo).name;
					Vector3 velocity = value.rb.velocity;
					log.LogInfo((object)$"[throw] {name} vel={((Vector3)(ref velocity)).magnitude:F1}");
				}
			}
			catch (Exception ex)
			{
				if (Plugin.VerboseLogging.Value)
				{
					Plugin.Log.LogWarning((object)("Local throw failed: " + ex.Message));
				}
			}
		}

		private static void ApplyHeldOrientation(SimState st, PhysGrabber grabber)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: 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_00d0: 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_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: 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_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_01b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d4: 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_01de: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)st.gun != (Object)null)
			{
				st.pgo.TurnXYZ(Quaternion.Euler(st.gun.aimVerticalOffset, 0f, 0f), Quaternion.identity, Quaternion.identity);
				st.pgo.OverrideTorqueStrength(2f, 0.1f);
				st.pgo.OverrideAngularDrag(20f, 0.1f);
			}
			else if ((Object)(object)st.melee != (Object)null)
			{
				if (st.melee.usesForceRotation)
				{
					Quaternion val = (st.melee.turnWeapon ? Quaternion.Euler(st.melee.forwardTilt, 0f, 0f) : Quaternion.Euler(st.melee.forwardTilt + st.melee.orientationOffset.x, st.melee.orientationOffset.y, st.melee.orientationOffset.z));
					st.pgo.TurnXYZ(val, meleeYRot.Invoke(st.melee), Quaternion.identity);
					st.pgo.OverrideTorqueStrength(st.melee.customTorqueStrength ? st.melee.torqueStrength : 0.4f, 0.1f);
					st.pgo.OverrideAngularDrag(5f, 0.1f);
				}
			}
			else if (st.mirrorHeldRot && st.hasHostState && !((Object)(object)grabber.playerAvatar == (Object)null) && !((Object)(object)grabber.playerAvatar.localCamera == (Object)null))
			{
				Transform overrideTransform = grabber.playerAvatar.localCamera.GetOverrideTransform();
				if (!((Object)(object)overrideTransform == (Object)null))
				{
					grabber.cameraRelativeGrabbedForward = overrideTransform.InverseTransformDirection(st.hostRot * Vector3.forward);
					grabber.cameraRelativeGrabbedUp = overrideTransform.InverseTransformDirection(st.hostRot * Vector3.up);
				}
			}
		}

		internal static void MirrorHeldOrientationTargets()
		{
			if (states.Count == 0)
			{
				return;
			}
			foreach (SimState value in states.Values)
			{
				if (value.localGrab && (!((Object)(object)value.gun == (Object)null) || !((Object)(object)value.melee == (Object)null) || value.mirrorHeldRot))
				{
					PhysGrabber localGrabber = GetLocalGrabber(value);
					if (!((Object)(object)localGrabber == (Object)null) && !localGrabber.isRotating)
					{
						ApplyHeldOrientation(value, localGrabber);
					}
				}
			}
		}

		private static void EnsureDynamic(SimState st)
		{
			if (!((Object)(object)st.rb == (Object)null))
			{
				if (st.rb.isKinematic)
				{
					st.rb.isKinematic = false;
				}
				if (st.rb.IsSleeping())
				{
					st.rb.WakeUp();
				}
			}
		}

		internal static void TickKinematicTimer(PhotonTransformView ptv)
		{
			if (ptvKinForcedTimer.Invoke(ptv) > 0f)
			{
				ptvKinForcedTimer.Invoke(ptv) -= Time.deltaTime;
				if (ptvKinForcedTimer.Invoke(ptv) <= 0f)
				{
					ptvKinForced.Invoke(ptv) = false;
				}
			}
		}

		internal static void EnsureDroneAccessors()
		{
			if (droneAccessorsTried)
			{
				return;
			}
			droneAccessorsTried = true;
			try
			{
				droneMagnetActive = AccessTools.FieldRefAccess<ItemDrone, bool>("magnetActive");
				droneMagnetTarget = AccessTools.FieldRefAccess<ItemDrone, PhysGrabObject>("magnetTargetPhysGrabObject");
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Drone handoff disabled (game internals changed): " + ex.Message));
			}
		}

		private static void RebuildDroneTargets()
		{
			droneTargetMap.Clear();
			if (droneMagnetActive == null || cachedDrones == null)
			{
				return;
			}
			ItemDrone[] array = cachedDrones;
			foreach (ItemDrone val in array)
			{
				if (!((Object)(object)val == (Object)null) && droneMagnetActive.Invoke(val))
				{
					PhysGrabObject val2 = droneMagnetTarget.Invoke(val);
					if ((Object)(object)val2 != (Object)null)
					{
						droneTargetMap[val2] = val;
					}
				}
			}
		}

		internal static void Tick()
		{
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			if (!Ready || Time.fixedTime == lastTickFixedTime)
			{
				return;
			}
			lastTickFixedTime = Time.fixedTime;
			if (!tickMarker)
			{
				tickMarker = true;
				Plugin.Log.LogInfo((object)"[driver] physics tick loop running");
			}
			SweepHandedBack();
			bool flag = IsClientInLobby();
			if (flag != wasClientInLobby)
			{
				wasClientInLobby = flag;
				if (Plugin.VerboseLogging.Value)
				{
					Plugin.Log.LogInfo((object)(flag ? "[mode] CLIENT — simulation active (we are not the host)" : "[mode] simulation idle (hosting, singleplayer or no lobby)"));
				}
			}
			if (states.Count == 0)
			{
				return;
			}
			tickCounter++;
			RebuildDroneTargets();
			tickBuffer.Clear();
			tickBuffer.AddRange(states.Values);
			foreach (SimState item in tickBuffer)
			{
				if ((Object)(object)item.cart == (Object)null || (Object)(object)item.pgo == (Object)null || (Object)(object)item.rb == (Object)null)
				{
					continue;
				}
				if (!item.localGrab && item.pgo.playerGrabbing.Count <= 0)
				{
					Vector3 velocity = item.rb.velocity;
					if (!(((Vector3)(ref velocity)).sqrMagnitude > 0.25f))
					{
						if (!(item.rideHoldTimer > 0f))
						{
							continue;
						}
						item.rideHoldTimer -= Time.fixedDeltaTime;
						goto IL_0167;
					}
				}
				item.rideHoldTimer = 1.5f;
				goto IL_0167;
				IL_0167:
				List<PhysGrabObject> list = cartItems.Invoke(item.cart);
				if (list == null)
				{
					continue;
				}
				for (int i = 0; i < list.Count; i++)
				{
					if ((Object)(object)list[i] != (Object)null && states.TryGetValue(list[i], out var value))
					{
						value.ridingTick = tickCounter;
						value.ridingCart = item;
					}
				}
			}
			foreach (SimState item2 in tickBuffer)
			{
				if ((Object)(object)item2.pgo == (Object)null || (Object)(object)item2.rb == (Object)null || (Object)(object)item2.ptv == (Object)null)
				{
					HardRemove(item2);
					continue;
				}
				if (item2.viewId == 0)
				{
					PhotonView component = ((Component)item2.pgo).GetComponent<PhotonView>();
					if ((Object)(object)component != (Object)null && component.ViewID != 0)
					{
						item2.viewId = component.ViewID;
						byViewId[item2.viewId] = item2;
					}
				}
				if (!flag)
				{
					Restore(item2);
					continue;
				}
				bool flag2 = !item2.localGrab && ((droneTargetMap.Count > 0 && droneTargetMap.ContainsKey(item2.pgo)) || ((Object)(object)item2.droneSelf != (Object)null && (Object)(object)item2.droneToggle != (Object)null && item2.droneToggle.toggleState));
				if (flag2 != item2.droneExempt)
				{
					item2.droneExempt = flag2;
					if (flag2)
					{
						pgoIsMaster.Invoke(item2.pgo) = false;
						SeedPtvFields(item2);
						if (Plugin.VerboseLogging.Value)
						{
							Plugin.Log.LogInfo((object)("[drone] " + ((Object)item2.pgo).name + ": magnet-grabbed — host drives it until released"));
						}
					}
				}
				if (!item2.droneExempt)
				{
					if (item2.localGrab)
					{
						TickHeld(item2);
						continue;
					}
					ScrubStaleLocalGrabber(item2.pgo);
					TickShadow(item2);
				}
			}
		}

		private static void TickHeld(SimState st)
		{
			//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_015c: 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_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			PhysGrabber localGrabber = GetLocalGrabber(st);
			if (!pgoIsActive.Invoke(st.pgo) || (Object)(object)localGrabber == (Object)null)
			{
				EndLocalGrab(st.pgo);
				return;
			}
			pgoIsMaster.Invoke(st.pgo) = true;
			EnsureDynamic(st);
			if (st.isHinge)
			{
				CheckHingeBroken(st);
				return;
			}
			if ((Object)(object)st.cart != (Object)null)
			{
				DriveHeldCart(st, localGrabber);
			}
			if (droneTargetMap.Count > 0 && droneTargetMap.TryGetValue(st.pgo, out var value) && (Object)(object)value != (Object)null && (Object)(object)((Component)value).GetComponent<ItemDroneFeather>() != (Object)null)
			{
				st.pgo.OverrideMass(0.5f, 0.1f);
				st.pgo.OverrideDrag(1f, 0.1f);
				st.pgo.OverrideAngularDrag(5f, 0.1f);
			}
			if (!st.hasHostState)
			{
				DebugHeld(st, localGrabber, -1f, 0f);
				return;
			}
			st.hostTeleport = false;
			Vector3 velocity;
			if (HostStalled)
			{
				st.desyncTimer = 0f;
				st.stuckTimer = 0f;
				velocity = st.rb.velocity;
				DebugHeld(st, localGrabber, -1f, ((Vector3)(ref velocity)).magnitude);
				return;
			}
			velocity = st.rb.velocity;
			float magnitude = ((Vector3)(ref velocity)).magnitude;
			float num = Vector3.Distance(st.rb.position, st.hostPos);
			float num2 = Plugin.HeldDriftHandbackAt.Value + magnitude * 0.4f;
			if ((Object)(object)st.cart != (Object)null)
			{
				num2 *= 1.5f;
			}
			if (num > num2)
			{
				st.desyncTimer += Time.fixedDeltaTime;
				if (st.desyncTimer > (((Object)(object)st.cart != (Object)null) ? 1.2f : 0.6f))
				{
					ForceHandback(st);
					return;
				}
			}
			else
			{
				st.desyncTimer = 0f;
			}
			st.stuckTimer = 0f;
			if (!localGrabber.isRotating)
			{
				ApplyHeldOrientation(st, localGrabber);
			}
			DebugHeld(st, localGrabber, num, magnitude);
		}

		private static void DebugHeld(SimState st, PhysGrabber grabber, float drift, float speed)
		{
			if (Plugin.VerboseLogging.Value)
			{
				st.debugTimer -= Time.fixedDeltaTime;
				if (!(st.debugTimer > 0f))
				{
					st.debugTimer = 1f;
					float num = (st.hasHostState ? (Time.unscaledTime - st.lastPacketTime) : (-1f));
					Plugin.Log.LogInfo((object)($"[held] {((Object)st.pgo).name}: speed={speed:F1} drift={drift:F1} hostState={st.hasHostState} " + $"packetAge={num:F1}s hostKin={st.hostKinematic} hostSleep={st.hostSleeping} " + $"steered={grabber.physGrabForcesDisabledTimer > 0f}"));
				}
			}
		}

		private static void DriveHeldCart(SimState st, PhysGrabber grabber)
		{
			//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_0090: 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_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: 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_016b: 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_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_01a1: 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_01b2: 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_01bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c9: 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_01dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f3: 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_0201: Unknown result type (might be due to invalid IL or missing references)
			//IL_0208: Unknown result type (might be due to invalid IL or missing references)
			//IL_0212: Unknown result type (might be due to invalid IL or missing references)
			//IL_0217: Unknown result type (might be due to invalid IL or missing references)
			//IL_021f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0231: Unknown result type (might be due to invalid IL or missing references)
			//IL_0236: Unknown result type (might be due to invalid IL or missing references)
			//IL_0240: 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_0256: Unknown result type (might be due to invalid IL or missing references)
			//IL_025d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0272: Unknown result type (might be due to invalid IL or missing references)
			//IL_0282: 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_0291: Unknown result type (might be due to invalid IL or missing references)
			//IL_0296: Unknown result type (might be due to invalid IL or missing references)
			//IL_029a: 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_02bf: 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_02c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d7: 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_02de: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_0347: Unknown result type (might be due to invalid IL or missing references)
			//IL_034c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0353: Unknown result type (might be due to invalid IL or missing references)
			//IL_035d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0362: Unknown result type (might be due to invalid IL or missing references)
			//IL_0370: Unknown result type (might be due to invalid IL or missing references)
			//IL_0375: Unknown result type (might be due to invalid IL or missing references)
			//IL_0379: Unknown result type (might be due to invalid IL or missing references)
			//IL_0383: Unknown result type (might be due to invalid IL or missing references)
			if (grabber.physGrabForcesDisabledTimer > 0f)
			{
				return;
			}
			PhysGrabObjectGrabArea val = cartGrabArea.Invoke(st.cart);
			if ((Object)(object)val == (Object)null || !val.listOfAllGrabbers.Contains(grabber))
			{
				return;
			}
			PlayerAvatar playerAvatar = grabber.playerAvatar;
			if ((Object)(object)playerAvatar == (Object)null || (Object)(object)PlayerController.instance == (Object)null)
			{
				return;
			}
			Transform val2 = cartInCart.Invoke(st.cart);
			BoxCollider val3 = (((Object)(object)val2 != (Object)null) ? ((Component)val2).GetComponent<BoxCollider>() : null);
			Vector3 val4 = ((Component)playerAvatar).transform.position + Vector3.up * 0.25f;
			if (!((Object)(object)val3 != (Object)null) || !(Vector3.Distance(((Collider)val3).ClosestPoint(val4), val4) < 0.01f))
			{
				grabber.OverridePhysGrabForcesDisable(0.1f);
				bool num = avatarSprinting.Invoke(playerAvatar);
				float num2 = (st.cart.isSmallCart ? 1.5f : 2f);
				float num3 = (st.cart.isSmallCart ? 2f : 2.5f);
				float num4 = (num ? 7f : 5f);
				bool flag = Vector3.Dot(PlayerController.instance.rb.velocity, ((Component)st.pgo).transform.forward) > 0f;
				if (num && flag)
				{
					num2 = 3f;
					num3 = 4f;
				}
				float num5 = Mathf.Clamp01(Vector3.Dot(st.rb.velocity, ((Component)grabber).transform.forward) / num4);
				float num6 = Mathf.Lerp(num2, num3, num5);
				Vector3 val5 = ((Component)grabber).transform.rotation * Vector3.back;
				Vector3 val6 = ((Component)playerAvatar).transform.position - val5 * num6;
				float num7 = Mathf.Clamp01(Vector3.Distance(((Component)st.pgo).transform.position, val6));
				Vector3 val7 = val6 - ((Component)st.pgo).transform.position;
				Vector3 val8 = Vector3.ClampMagnitude(((Vector3)(ref val7)).normalized * 5f * num7, 5f);
				float y = st.rb.velocity.y;
				Vector3 val9 = Vector3.MoveTowards(st.rb.velocity, val8, num7 * 2f);
				val9.y = y;
				st.rb.velocity = Vector3.ClampMagnitude(val9, 5f);
				Quaternion val10 = Quaternion.LookRotation(((Component)grabber).transform.position - ((Component)st.pgo).transform.position, Vector3.up);
				Quaternion val11 = Quaternion.Euler(0f, ((Quaternion)(ref val10)).eulerAngles.y + 180f, 0f);
				val10 = st.rb.rotation;
				Quaternion val12 = Quaternion.Euler(0f, ((Quaternion)(ref val10)).eulerAngles.y, 0f);
				val10 = val11 * Quaternion.Inverse(val12);
				float num8 = default(float);
				Vector3 val13 = default(Vector3);
				((Quaternion)(ref val10)).ToAngleAxis(ref num8, ref val13);
				if (num8 > 180f)
				{
					num8 -= 360f;
				}
				float num9 = Mathf.Clamp(Mathf.Clamp(Mathf.Abs(num8) / 180f, 0.2f, 1f) * 20f, 0f, 4f);
				Vector3 val14 = Vector3.ClampMagnitude((float)Math.PI / 180f * num8 * ((Vector3)(ref val13)).normalized * num9, 4f);
				st.rb.angularVelocity = Vector3.ClampMagnitude(Vector3.MoveTowards(st.rb.angularVelocity, val14, num9), 4f);
			}
		}

		private static void TickShadow(SimState st)
		{
			//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_0027: 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_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)st.cart == (Object)null)
			{
				TickShadowInner(st);
				return;
			}
			Vector3 position = st.rb.position;
			Quaternion rotation = st.rb.rotation;
			TickShadowInner(st);
			CarryCargo(st, position, rotation);
		}

		private static void CarryCargo(SimState cartState, Vector3 oldPos, Quaternion oldRot)
		{
			//IL_0023: 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_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: 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_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: 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_0111: 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_011f: 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_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: 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)
			if ((Object)(object)cartState.cart == (Object)null || (Object)(object)cartState.rb == (Object)null)
			{
				return;
			}
			Vector3 position = cartState.rb.position;
			Quaternion rotation = cartState.rb.rotation;
			Vector3 val = position - oldPos;
			if (((Vector3)(ref val)).sqrMagnitude < 1E-08f && Quaternion.Angle(oldRot, rotation) < 0.01f)
			{
				return;
			}
			Quaternion val2 = rotation * Quaternion.Inverse(oldRot);
			List<PhysGrabObject> list = cartItems.Invoke(cartState.cart);
			if (list == null)
			{
				return;
			}
			for (int i = 0; i < list.Count; i++)
			{
				PhysGrabObject val3 = list[i];
				if (!((Object)(object)val3 == (Object)null) && states.TryGetValue(val3, out var value) && value != cartState && !((Object)(object)value.rb == (Object)null) && value.ridingTick == tickCounter && !value.localGrab && !value.droneExempt && !value.rb.isKinematic && pgoIsActive.Invoke(val3))
				{
					value.rb.position = position + val2 * (value.rb.position - oldPos);
					value.rb.rotation = val2 * value.rb.rotation;
				}
			}
		}

		private static void TickShadowInner(SimState st)
		{
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: 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_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bb: 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_0319: Unknown result type (might be due to invalid IL or missing references)
			//IL_031f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0324: Unknown result type (might be due to invalid IL or missing references)
			//IL_0329: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ad: 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_033f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0345: Unknown result type (might be due to invalid IL or missing references)
			//IL_0268: Unknown result type (might be due to invalid IL or missing references)
			//IL_0273: Unknown result type (might be due to invalid IL or missing references)
			//IL_0278: Unknown result type (might be due to invalid IL or missing references)
			//IL_027d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0282: Unknown result type (might be due to invalid IL or missing references)
			//IL_0251: Unknown result type (might be due to invalid IL or missing references)
			//IL_0256: Unknown result type (might be due to invalid IL or missing references)
			//IL_040e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0414: Unknown result type (might be due to invalid IL or missing references)
			//IL_0369: Unknown result type (might be due to invalid IL or missing references)
			//IL_0379: 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_02c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0300: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_0505: Unknown result type (might be due to invalid IL or missing references)
			//IL_050b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0511: Unknown result type (might be due to invalid IL or missing references)
			//IL_0527: Unknown result type (might be due to invalid IL or missing references)
			//IL_052d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0533: Unknown result type (might be due to invalid IL or missing references)
			//IL_0549: Unknown result type (might be due to invalid IL or missing references)
			//IL_054f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0555: Unknown result type (might be due to invalid IL or missing references)
			pgoIsMaster.Invoke(st.pgo) = false;
			if (!pgoIsActive.Invoke(st.pgo))
			{
				return;
			}
			if (st.ridingTick == tickCounter)
			{
				if (st.rb.isKinematic)
				{
					st.rb.isKinematic = false;
				}
				st.hostTeleport = false;
				st.wasRiding = true;
				return;
			}
			if (st.wasRiding)
			{
				st.wasRiding = false;
				st.ridingCart = null;
				st.postThrowRamp = 0.5f + (float)(cargoStagger++ & 7) * 0.05f;
			}
			if (!st.hasHostState || HostStalled)
			{
				return;
			}
			Vector3 val = st.hostPos - DisabledPosition();
			if (((Vector3)(ref val)).sqrMagnitude < 25f)
			{
				return;
			}
			if (st.postThrowTimer > 0f)
			{
				st.postThrowTimer -= Time.fixedDeltaTime;
				if (st.postThrowTimer <= 0f)
				{
					st.postThrowRamp = 0.4f;
				}
			}
			else if (st.postThrowRamp > 0f)
			{
				st.postThrowRamp -= Time.fixedDeltaTime;
			}
			if (st.noSnapTimer > 0f)
			{
				st.noSnapTimer -= Time.fixedDeltaTime;
			}
			if (st.hostTeleport)
			{
				st.hostTeleport = false;
				val = st.rb.position - st.hostPos;
				if (((Vector3)(ref val)).sqrMagnitude > 0.01f)
				{
					Snap(st, "host teleported it");
					return;
				}
			}
			if (st.postThrowTimer > 0f)
			{
				return;
			}
			if (st.hostKinematic && !st.isHinge)
			{
				if (!st.rb.isKinematic)
				{
					st.rb.isKinematic = true;
				}
				st.rb.MovePosition(st.hostPos);
				st.rb.MoveRotation(st.hostRot);
				return;
			}
			if (st.rb.isKinematic)
			{
				st.rb.isKinematic = false;
			}
			if (st.isHinge)
			{
				CheckHingeBroken(st);
				if (st.localPushTimer > 0f)
				{
					st.localPushTimer -= Time.fixedDeltaTime;
					st.hingeSyncPause = 1f;
					return;
				}
				if (st.hingeSyncPause > 0f)
				{
					st.hingeSyncPause -= Time.fixedDeltaTime;
					val = st.rb.angularVelocity;
					if (((Vector3)(ref val)).sqrMagnitude > 0.25f)
					{
						return;
					}
				}
				Quaternion val2 = st.hostRot * Quaternion.Inverse(st.rb.rotation);
				float num = default(float);
				Vector3 val3 = default(Vector3);
				((Quaternion)(ref val2)).ToAngleAxis(ref num, ref val3);
				if (num > 180f)
				{
					num -= 360f;
				}
				if (Mathf.Abs(num) > 1.5f && !float.IsInfinity(val3.x))
				{
					Vector3 val4 = Vector3.ClampMagnitude((float)Math.PI / 180f * num * ((Vector3)(ref val3)).normalized * 4f, 6f);
					st.rb.angularVelocity = Vector3.Lerp(st.rb.angularVelocity, val4, 0.35f);
				}
				return;
			}
			if (st.hostSleeping)
			{
				val = st.rb.position - st.hostPos;
				if (((Vector3)(ref val)).sqrMagnitude < 0.0025f && Quaternion.Angle(st.rb.rotation, st.hostRot) < 3f)
				{
					if (!st.rb.IsSleeping())
					{
						st.rb.velocity = Vector3.zero;
						st.rb.angularVelocity = Vector3.zero;
						st.rb.Sleep();
					}
					return;
				}
			}
			if (st.rb.IsSleeping())
			{
				st.rb.WakeUp();
			}
			float num2 = Vector3.Distance(st.rb.position, st.hostPos);
			if (num2 > Plugin.SnapDistance.Value && st.postThrowRamp <= 0f && st.noSnapTimer <= 0f)
			{
				Snap(st, "beyond snap distance");
				return;
			}
			bool flag = (Object)(object)st.cart != (Object)null;
			float num3 = (flag ? Quaternion.Angle(st.rb.rotation, st.hostRot) : 0f);
			if (num2 > 1.5f || (flag && num3 > 30f))
			{
				st.farTimer += Time.fixedDeltaTime;
				if (st.farTimer > 5f && st.noSnapTimer <= 0f && st.postThrowRamp <= 0f)
				{
					st.farTimer = 0f;
					Snap(st, "stuck away from host position too long");
					return;
				}
			}
			else if (num2 < 0.75f && (!flag || num3 < 10f))
			{
				st.farTimer = 0f;
			}
			float num4 = Mathf.Clamp01(Plugin.PassiveSyncStrength.Value);
			if (st.postThrowRamp > 0f)
			{
				num4 *= 1f - Mathf.Clamp01(st.postThrowRamp / 0.5f);
			}
			st.rb.position = Vector3.Lerp(st.rb.position, st.hostPos, num4);
			st.rb.rotation = Quaternion.Slerp(st.rb.rotation, st.hostRot, num4);
			st.rb.velocity = Vector3.Lerp(st.rb.velocity, st.hostVel, num4);
			st.rb.angularVelocity = Vector3.Lerp(st.rb.angularVelocity, st.hostAngVel, num4);
		}

		internal static void NotifyHingePushed(PhysGrabHinge hinge, Collision collision)
		{
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)hinge == (Object)null || collision == null)
			{
				return;
			}
			PhysGrabObject component = ((Component)hinge).GetComponent<PhysGrabObject>();
			if ((Object)(object)component == (Object)null || !states.TryGetValue(component, out var value) || !value.isHinge)
			{
				return;
			}
			bool flag = false;
			if (collision.gameObject.CompareTag("Player") && (Object)(object)PlayerController.instance != (Object)null && Vector3.Distance(collision.transform.position, ((Component)PlayerController.instance).transform.position) < 3f)
			{
				flag = true;
			}
			else if ((Object)(object)collision.rigidbody != (Object)null)
			{
				PhysGrabObject component2 = ((Component)collision.rigidbody).GetComponent<PhysGrabObject>();
				if ((Object)(object)component2 != (Object)null && states.TryGetValue(component2, out var value2) && (value2.localGrab || value2.ridingTick >= tickCounter - 2))
				{
					flag = true;
				}
			}
			if (flag)
			{
				value.localPushTimer = 0.75f;
			}
		}

		private static void CheckHingeBroken(SimState st)
		{
			if (st.isHinge && !((Object)(object)st.hinge == (Object)null) && hingeBroken.Invoke(st.hinge))
			{
				if ((Object)(object)st.joint != (Object)null)
				{
					Object.Destroy((Object)(object)st.joint);
					st.joint = null;
				}
				st.isHinge = false;
				if (Plugin.VerboseLogging.Value)
				{
					Plugin.Log.LogInfo((object)("[hinge] " + ((Object)st.pgo).name + " broke on the host — local joint dropped"));
				}
			}
		}

		private static void ForceHandback(SimState st)
		{
			st.localGrab = false;
			st.desyncTimer = 0f;
			st.stuckTimer = 0f;
			st.postThrowTimer = 0f;
			pgoIsMaster.Invoke(st.pgo) = false;
			handedBack.Add(st.pgo);
			if (Plugin.VerboseLogging.Value)
			{
				Plugin.Log.LogInfo((object)("Handed " + ((Object)st.pgo).name + " back to the host (drifted too far from its copy)."));
			}
		}

		private static void SweepHandedBack()
		{
			if (handedBack.Count == 0)
			{
				return;
			}
			handedBackSweep.Clear();
			foreach (PhysGrabObject item in handedBack)
			{
				if ((Object)(object)item == (Object)null)
				{
					handedBackSweep.Add(item);
					continue;
				}
				bool flag = false;
				List<PhysGrabber> playerGrabbing = item.playerGrabbing;
				for (int i = 0; i < playerGrabbing.Count; i++)
				{
					PhysGrabber val = playerGrabbing[i];
					if ((Object)(object)val != (Object)null && val.isLocal && val.grabbed)
					{
						flag = true;
						break;
					}
				}
				if (!flag)
				{
					handedBackSweep.Add(item);
				}
			}
			foreach (PhysGrabObject item2 in handedBackSweep)
			{
				handedBack.Remove(item2);
			}
		}

		internal static string DescribeGrabState(PhysGrabObject pgo)
		{
			if ((Object)(object)pgo == (Object)null)
			{
				return "(no PhysGrabObject)";
			}
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append("heldByLocalPlayer=");
			stringBuilder.Append((pgoHeldByLocal != null) ? pgoHeldByLocal.Invoke(pgo).ToString() : "?");
			stringBuilder.Append(" simulated=").Append(states.ContainsKey(pgo));
			stringBuilder.Append(" localGrab=").Append(IsLocalGrab(pgo));
			stringBuilder.Append(" grabbers=[");
			List<PhysGrabber> playerGrabbing = pgo.playerGrabbing;
			for (int i = 0; i < playerGrabbing.Count; i++)
			{
				PhysGrabber val = playerGrabbing[i];
				if (i > 0)
				{
					stringBuilder.Append(", ");
				}
				if ((Object)(object)val == (Object)null)
				{
					stringBuilder.Append("null");
					continue;
				}
				stringBuilder.Append(val.isLocal ? "LOCAL" : "remote");
				stringBuilder.Append(((Object)(object)grabberObject.Invoke(val) == (Object)(object)pgo) ? "(holding)" : "(stale!)");
			}
			stringBuilder.Append(']');
			return stringBuilder.ToString();
		}

		private static PhysGrabber GetLocalGrabber(SimState st)
		{
			List<PhysGrabber> playerGrabbing = st.pgo.playerGrabbing;
			for (int i = 0; i < playerGrabbing.Count; i++)
			{
				PhysGrabber val = playerGrabbing[i];
				if ((Object)(object)val != (Object)null && val.isLocal && val.grabbed && (Object)(object)grabberObject.Invoke(val) == (Object)(object)st.pgo)
				{
					return val;
				}
			}
			return null;
		}

		private static void Snap(SimState st, string reason)
		{
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: 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_0018: 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_0090: Unknown result type (might be due to invalid IL or missing references)
			if (Plugin.VerboseLogging.Value)
			{
				float num = Vector3.Distance(st.rb.position, st.hostPos);
				Plugin.Log.LogInfo((object)$"[snap] {((Object)st.pgo).name}: {reason} (dist={num:F1}m)");
			}
			st.rb.position = st.hostPos;
			st.rb.rotation = st.hostRot;
			if (!st.rb.isKinematic)
			{
				st.rb.velocity = st.hostVel;
				st.rb.angularVelocity = st.hostAngVel;
			}
		}

		private static void Restore(SimState st)
		{
			SeedPtvFields(st);
			HardRemove(st);
		}

		private static void SeedPtvFields(SimState st)
		{
			//IL_0058: 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_005d: 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_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: 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_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: 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_00e3: 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_00f9: 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_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: 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_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: 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_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_01be: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f3: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if ((Object)(object)st.pgo != (Object)null)
				{
					pgoIsMaster.Invoke(st.pgo) = false;
				}
				if ((Object)(object)st.ptv != (Object)null && (Object)(object)st.rb != (Object)null)
				{
					Vector3 val = (st.hasHostState ? st.hostPos : st.rb.position);
					Quaternion val2 = (st.hasHostState ? st.hostRot : st.rb.rotation);
					ptvNetPos.Invoke(st.ptv) = val;
					ptvNetRot.Invoke(st.ptv) = val2;
					ptvStoredPos.Invoke(st.ptv) = val;
					ptvRecvPos.Invoke(st.ptv) = val;
					ptvRecvRot.Invoke(st.ptv) = val2;
					ptvPrevPos.Invoke(st.ptv) = val;
					ptvPrevRot.Invoke(st.ptv) = val2;
					ptvSmoothedPos.Invoke(st.ptv) = st.rb.position;
					ptvSmoothedRot.Invoke(st.ptv) = st.rb.rotation;
					ptvDistance.Invoke(st.ptv) = Vector3.Distance(st.rb.position, val);
					ptvAngle.Invoke(st.ptv) = Quaternion.Angle(st.rb.rotation, val2);
					ptvRecvVel.Invoke(st.ptv) = (st.hasHostState ? st.hostVel : st.rb.velocity);
					ptvRecvAngVel.Invoke(st.ptv) = (st.hasHostState ? st.hostAngVel : st.rb.angularVelocity);
					ptvFirstTake.Invoke(st.ptv) = false;
					ptvTeleport.Invoke(st.ptv) = false;
					ptvIsSleeping.Invoke(st.ptv) = st.hasHostState && st.hostSleeping;
					if (st.hasHostState)
					{
						st.rb.isKinematic = st.hostKinematic;
					}
				}
			}
			catch (Exception ex)
			{
				if (Plugin.VerboseLogging.Value)
				{
					Plugin.Log.LogWarning((object)("Restore failed: " + ex.Message));
				}
			}
		}

		private static void HardRemove(SimState st)
		{
			if ((Object)(object)st.pgo != (Object)null)
			{
				states.Remove(st.pgo);
			}
			if ((Object)(object)st.ptv != (Object)null)
			{
				byPtv.Remove(st.ptv);
			}
			if (st.viewId != 0)
			{
				byViewId.Remove(st.viewId);
			}
			if ((Object)(object)st.pgo == (Object)null || (Object)(object)st.ptv == (Object)null)
			{
				SweepDead();
			}
		}

		private static void SweepDead()
		{
			deadPgos.Clear();
			deadPtvs.Clear();
			deadIds.Clear();
			foreach (KeyValuePair<PhysGrabObject, SimState> state in states)
			{
				if ((Object)(object)state.Key == (Object)null)
				{
					deadPgos.Add(state.Key);
				}
			}
			foreach (KeyValuePair<PhotonTransformView, SimState> item in byPtv)
			{
				if ((Object)(object)item.Key == (Object)null)
				{
					deadPtvs.Add(item.Key);
				}
			}
			foreach (KeyValuePair<int, SimState> item2 in byViewId)
			{
				if ((Object)(object)item2.Value.pgo == (Object)null)
				{
					deadIds.Add(item2.Key);
				}
			}
			foreach (PhysGrabObject deadPgo in deadPgos)
			{
				states.Remove(deadPgo);
			}
			foreach (PhotonTransformView deadPtv in deadPtvs)
			{
				byPtv.Remove(deadPtv);
			}
			foreach (int deadId in deadIds)
			{
				byViewId.Remove(deadId);
			}
		}

		internal static void RestoreAll()
		{
			if (Plugin.VerboseLogging.Value && states.Count > 0)
			{
				Plugin.Log.LogInfo((object)$"[mode] restoring {states.Count} objects to vanilla sync");
			}
			tickBuffer.Clear();
			tickBuffer.AddRange(states.Values);
			foreach (SimState item in tickBuffer)
			{
				Restore(item);
			}
			states.Clear();
			byPtv.Clear();
			byViewId.Clear();
			handedBack.Clear();
		}

		internal static void ResyncAll()
		{
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			int num = 0;
			foreach (SimState value in states.Values)
			{
				if (value.hasHostState && !value.localGrab && !value.droneExempt && !((Object)(object)value.pgo == (Object)null) && !((Object)(object)value.rb == (Object)null) && pgoIsActive.Invoke(value.pgo))
				{
					value.rb.position = value.hostPos;
					value.rb.rotation = value.hostRot;
					if (!value.rb.isKinematic)
					{
						value.rb.velocity = value.hostVel;
						value.rb.angularVelocity = value.hostAngVel;
					}
					value.farTimer = 0f;
					num++;
				}
			}
			Plugin.Log.LogInfo((object)$"[resync] manual hard sync: {num} objects teleported to the host's state");
		}
	}
	internal static class SimDriver
	{
		private static bool announced;

		private static bool conflictsChecked;

		private static float nextRegisterSweep;

		private static float nextStatsLog;

		private static int lastPacketCount;

		private static int lastFrame = -1;

		private static float nextAutoResync;

		internal static void FrameUpdate()
		{
			//IL_01c3: 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)
			if (Time.frameCount == lastFrame)
			{
				return;
			}
			lastFrame = Time.frameCount;
			if (!announced)
			{
				announced = true;
				Plugin.Log.LogInfo((object)"[driver] alive — update loop running");
			}
			Plugin.EnsureCapturePatch();
			if (!conflictsChecked && Time.unscaledTime > 10f)
			{
				conflictsChecked = true;
				string[] array = new string[4] { "net.ovchinikov.nwrework", "BlueAmulet.REPONetworkTweaks", "com.Revival.networkingrevived", "com.Revival.networktweaksrevived" };
				foreach (string text in array)
				{
					if (Chainloader.PluginInfos.ContainsKey(text))
					{
						Plugin.Log.LogWarning((object)("Conflicting mod '" + text + "' is still installed! RevivalSync replaces it — please uninstall/disable the old mod."));
					}
				}
				if (Chainloader.PluginInfos.ContainsKey("discjenny.CartSpeedSync"))
				{
					Plugin.Log.LogWarning((object)"CartSpeedSync is installed. RevivalSync now steers carts locally on its own, and CartSpeedSync steers the same cart on top of that (it doubles the turn rate and boosts speed while sprinting) — the two fight, which can make a held cart feel weak, whip around, or fling its loot. Remove CartSpeedSync, or turn OFF 'Instant Carts' in RevivalSync's config if you would rather keep it.");
				}
			}
			if (Time.unscaledTime >= nextRegisterSweep)
			{
				nextRegisterSweep = Time.unscaledTime + 5f;
				if (SimManager.Ready && SimManager.IsClientInLobby())
				{
					PhysGrabObject[] array2 = Object.FindObjectsOfType<PhysGrabObject>();
					for (int i = 0; i < array2.Length; i++)
					{
						SimManager.TryRegister(array2[i]);
					}
					SimManager.EnsureDroneAccessors();
					SimManager.cachedDrones = Object.FindObjectsOfType<ItemDrone>();
				}
			}
			if (Plugin.VerboseLogging.Value && Time.unscaledTime >= nextStatsLog)
			{
				nextStatsLog = Time.unscaledTime + 10f;
				if (SimManager.IsClientInLobby())
				{
					int packetsCaptured = SimManager.PacketsCaptured;
					Plugin.Log.LogInfo((object)($"[stats] registered={SimManager.RegisteredCount} held={SimManager.HeldCount} " + $"packets={packetsCaptured} (+{packetsCaptured - lastPacketCount} in 10s)"));
					lastPacketCount = packetsCaptured;
				}
			}
			if (SimManager.Ready && SimManager.IsClientInLobby())
			{
				if ((int)Plugin.ResyncKeyCode != 0 && Input.GetKeyDown(Plugin.ResyncKeyCode))
				{
					SimManager.ResyncAll();
				}
				if (Plugin.AutoResyncSeconds.Value > 0f && Time.unscaledTime >= nextAutoResync)
				{
					nextAutoResync = Time.unscaledTime + Mathf.Max(5f, Plugin.AutoResyncSeconds.Value);
					SimManager.ResyncAll();
				}
			}
			Plugin.ApplyPhotonSettings();
			Plugin.ArchiveSessionLog();
			SimManager.MirrorHeldOrientationTargets();
			Smoothing.Sweep();
		}
	}
	internal static class Smoothing
	{
		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 PhotonView view;

			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_001c: 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)
				if (!__runOriginal || stream.IsWriting || !ShouldSmooth(__instance))
				{
					return;
				}
				InterpState orCreate = GetOrCreate(__instance);
				if (info.Sender != PhotonNetwork.MasterClient && ((Object)(object)orCreate.view == (Object)null || info.Sender != orCreate.view.Owner))
				{
					return;
				}
				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;

		private static float nextSweep;

		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 (SimManager.IsSuppressed(ptv))
			{
				states.Remove(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>(),
					view = ((Component)ptv).GetComponent<PhotonView>(),
					smoothFreq = BaseFrequency()
				};
				states[ptv] = value;
			}
			return value;
		}

		internal static void Sweep()
		{
			if (Time.unscaledTime < nextSweep || states.Count == 0)
			{
				return;
			}
			nextSweep = Time.unscaledTime + 10f;
			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