Decompiled source of NetworkingRevived v1.1.2

NetworkingRevived.dll

Decompiled 21 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using NetworkingRevived.Patches;
using Photon.Pun;
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.1.1.0")]
[assembly: AssemblyInformationalVersion("1.1.1")]
[assembly: AssemblyProduct("NetworkingRevived")]
[assembly: AssemblyTitle("NetworkingRevived")]
[assembly: AssemblyVersion("1.1.1.0")]
namespace NetworkingRevived
{
	public static class NetworkingRevivedAPI
	{
		public static bool IsLocallySimulated(PhotonTransformView ptv)
		{
			if (SimManager.Ready)
			{
				return SimManager.IsSuppressed(ptv);
			}
			return false;
		}

		public static bool IsLocallySimulated(PhysGrabObject pgo)
		{
			if (SimManager.Ready)
			{
				return SimManager.HasPhysicsAuthority(pgo);
			}
			return false;
		}
	}
	[BepInPlugin("com.Revival.networkingrevived", "NetworkingRevived", "1.1.1")]
	public class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "com.Revival.networkingrevived";

		public const string PluginName = "NetworkingRevived";

		public const string PluginVersion = "1.1.1";

		internal static ManualLogSource Log;

		internal static ConfigEntry<bool> SimulateCarts;

		internal static ConfigEntry<bool> SimulateCartContents;

		internal static ConfigEntry<bool> InstantCartHandle;

		internal static ConfigEntry<float> SoftSyncDuration;

		internal static ConfigEntry<float> SoftSyncStrength;

		internal static ConfigEntry<bool> VerboseLogging;

		private void Awake()
		{
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Expected O, but got Unknown
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Expected O, but got Unknown
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Expected O, but got Unknown
			//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ee: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			SimulateCarts = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "SimulateCarts", true, "Simulate carts locally while you drag them (removes cart input lag).");
			SimulateCartContents = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "SimulateCartContents", true, "Also simulate items sitting inside a cart you are dragging, so they ride along instead of jittering behind.");
			InstantCartHandle = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "InstantCartHandle", true, "Register cart handle grabs locally right away instead of waiting for the host.");
			SoftSyncDuration = ((BaseUnityPlugin)this).Config.Bind<float>("Sync", "SoftSyncDuration", 1.25f, new ConfigDescription("How long (seconds) after you release an object it keeps blending back to the host's state.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 5f), Array.Empty<object>()));
			SoftSyncStrength = ((BaseUnityPlugin)this).Config.Bind<float>("Sync", "SoftSyncStrength", 0.12f, new ConfigDescription("Blend strength per physics tick while re-syncing to the host after release. Higher = snappier, lower = smoother.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.01f, 1f), Array.Empty<object>()));
			VerboseLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("Advanced", "VerboseLogging", false, "Log simulation start/stop events (for debugging).");
			if (!SimManager.InitAccessors())
			{
				Log.LogError((object)"NetworkingRevived could not find expected game internals (the game probably updated). The mod has disabled itself to avoid breaking your game.");
				return;
			}
			Harmony val = new Harmony("com.Revival.networkingrevived");
			int num = 0;
			int num2 = 0;
			Type[] array = new Type[6]
			{
				typeof(GrabStartedPatch),
				typeof(GrabEndedPatch),
				typeof(GrabPlayerAddDedupePatch),
				typeof(TransformViewUpdatePatch),
				typeof(TransformViewSerializePatch),
				typeof(CartAuthorityPatch)
			};
			foreach (Type type in array)
			{
				try
				{
					val.PatchAll(type);
					num++;
				}
				catch (Exception arg)
				{
					num2++;
					Log.LogError((object)$"Failed to apply patch {type.Name}: {arg}");
				}
			}
			if (num == 0)
			{
				Log.LogError((object)"No patches could be applied — NetworkingRevived is inactive.");
				return;
			}
			GameObject val2 = new GameObject("NetworkingRevivedDriver");
			Object.DontDestroyOnLoad((Object)val2);
			val2.AddComponent<SimDriver>();
			Log.LogInfo((object)(string.Format("NetworkingRevived {0} loaded. Patches applied: {1}, failed: {2}. ", "1.1.1", num, num2) + "Client-side prediction is active when you join someone else's lobby."));
		}
	}
	internal static class SimManager
	{
		internal class SimState
		{
			public PhysGrabObject pgo;

			public PhotonTransformView ptv;

			public Rigidbody rb;

			public bool localGrab;

			public PhysGrabObject ownerCart;

			public float softSyncTimer;

			public bool hasHostState;

			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 List<SimState> tickBuffer = new List<SimState>(32);

		private static FieldRef<PhysGrabObject, bool> pgoIsMaster;

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

		private static FieldRef<PhysGrabber, PhysGrabObject> grabberObject;

		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 readonly List<PhysGrabObject> deadPgos = new List<PhysGrabObject>();

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

		internal static bool Ready { get; private set; }

		internal static bool InitAccessors()
		{
			try
			{
				pgoIsMaster = AccessTools.FieldRefAccess<PhysGrabObject, bool>("isMaster");
				cartItems = AccessTools.FieldRefAccess<PhysGrabCart, List<PhysGrabObject>>("itemsInCart");
				grabberObject = AccessTools.FieldRefAccess<PhysGrabber, PhysGrabObject>("grabbedPhysGrabObject");
				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 SimState GetByPtv(PhotonTransformView ptv)
		{
			if (!((Object)(object)ptv != (Object)null) || !byPtv.TryGetValue(ptv, out var value))
			{
				return null;
			}
			return value;
		}

		internal static bool IsSuppressed(PhotonTransformView ptv)
		{
			if ((Object)(object)ptv != (Object)null)
			{
				return byPtv.ContainsKey(ptv);
			}
			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))
			{
				if (!value.localGrab)
				{
					return (Object)(object)value.ownerCart != (Object)null;
				}
				return true;
			}
			return false;
		}

		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 false;
			}
			if ((Object)(object)((Component)o).GetComponentInParent<ItemAttributes>() != (Object)null)
			{
				return false;
			}
			return true;
		}

		internal static void StartLocalGrab(PhysGrabObject pgo)
		{
			if (!Ready || (Object)(object)pgo == (Object)null)
			{
				return;
			}
			if (!states.TryGetValue(pgo, out var value))
			{
				value = CreateState(pgo);
				if (value == null)
				{
					return;
				}
			}
			if (!value.localGrab && Plugin.VerboseLogging.Value)
			{
				Plugin.Log.LogInfo((object)("Local simulation started: " + ((Object)pgo).name));
			}
			value.localGrab = true;
			value.ownerCart = null;
			value.softSyncTimer = 0f;
			pgoIsMaster.Invoke(pgo) = true;
			EnsureDynamic(value);
		}

		internal static void EndLocalGrab(PhysGrabObject pgo)
		{
			if (!Ready || (Object)(object)pgo == (Object)null || !states.TryGetValue(pgo, out var value) || !value.localGrab)
			{
				return;
			}
			value.localGrab = false;
			value.softSyncTimer = Plugin.SoftSyncDuration.Value;
			pgoIsMaster.Invoke(pgo) = false;
			if (Plugin.VerboseLogging.Value)
			{
				Plugin.Log.LogInfo((object)("Local simulation released: " + ((Object)pgo).name + ", blending back to host."));
			}
			foreach (SimState value2 in states.Values)
			{
				if ((Object)(object)value2.ownerCart == (Object)(object)pgo)
				{
					value2.ownerCart = null;
					value2.softSyncTimer = Plugin.SoftSyncDuration.Value;
				}
			}
		}

		internal static void LocalThrow(PhysGrabObject pgo, PhysGrabber player)
		{
			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)
			{
				return;
			}
			try
			{
				pgoThrow.Invoke(pgo, new object[1] { player });
			}
			catch (Exception ex)
			{
				if (Plugin.VerboseLogging.Value)
				{
					Plugin.Log.LogWarning((object)("Local throw failed: " + ex.Message));
				}
			}
		}

		private static SimState CreateState(PhysGrabObject pgo)
		{
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			PhotonTransformView component = ((Component)pgo).GetComponent<PhotonTransformView>();
			if ((Object)(object)component == (Object)null || (Object)(object)pgo.rb == (Object)null)
			{
				return null;
			}
			SimState simState = new SimState
			{
				pgo = pgo,
				ptv = component,
				rb = pgo.rb
			};
			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;
			return simState;
		}

		private static void AdoptCartContents(SimState cartState)
		{
			PhysGrabCart component = ((Component)cartState.pgo).GetComponent<PhysGrabCart>();
			if ((Object)(object)component == (Object)null)
			{
				return;
			}
			List<PhysGrabObject> list = cartItems.Invoke(component);
			if (list == null)
			{
				return;
			}
			foreach (PhysGrabObject item in list)
			{
				if ((Object)(object)item == (Object)null || (Object)(object)item == (Object)(object)cartState.pgo || states.ContainsKey(item) || !CanSimulate(item))
				{
					continue;
				}
				SimState simState = CreateState(item);
				if (simState != null)
				{
					simState.ownerCart = cartState.pgo;
					EnsureDynamic(simState);
					if (Plugin.VerboseLogging.Value)
					{
						Plugin.Log.LogInfo((object)("Simulating cart content: " + ((Object)item).name));
					}
				}
			}
		}

		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 Tick()
		{
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0195: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b1: 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_021b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0221: Unknown result type (might be due to invalid IL or missing references)
			//IL_0226: Unknown result type (might be due to invalid IL or missing references)
			//IL_022b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01db: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0204: Unknown result type (might be due to invalid IL or missing references)
			//IL_020b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0241: Unknown result type (might be due to invalid IL or missing references)
			//IL_0247: Unknown result type (might be due to invalid IL or missing references)
			if (!Ready || states.Count == 0)
			{
				return;
			}
			bool flag = IsClientInLobby();
			tickBuffer.Clear();
			tickBuffer.AddRange(states.Values);
			foreach (SimState item in tickBuffer)
			{
				if ((Object)(object)item.pgo == (Object)null || (Object)(object)item.rb == (Object)null || (Object)(object)item.ptv == (Object)null)
				{
					HardRemove(item);
					continue;
				}
				if (!flag)
				{
					Restore(item);
					continue;
				}
				if (item.localGrab)
				{
					if (!LocalGrabberStillHolding(item))
					{
						EndLocalGrab(item.pgo);
						continue;
					}
					pgoIsMaster.Invoke(item.pgo) = true;
					EnsureDynamic(item);
					if (Plugin.SimulateCartContents.Value)
					{
						AdoptCartContents(item);
					}
					continue;
				}
				if ((Object)(object)item.ownerCart != (Object)null)
				{
					if (!states.TryGetValue(item.ownerCart, out var value) || !value.localGrab)
					{
						item.ownerCart = null;
						item.softSyncTimer = Plugin.SoftSyncDuration.Value;
					}
					else
					{
						EnsureDynamic(item);
					}
					continue;
				}
				item.softSyncTimer -= Time.fixedDeltaTime;
				bool flag2 = false;
				if (item.hasHostState)
				{
					if (item.hostTeleport)
					{
						Snap(item);
						flag2 = true;
					}
					else
					{
						float num = Mathf.Clamp01(Plugin.SoftSyncStrength.Value);
						item.rb.position = Vector3.Lerp(item.rb.position, item.hostPos, num);
						item.rb.rotation = Quaternion.Slerp(item.rb.rotation, item.hostRot, num);
						if (!item.rb.isKinematic)
						{
							item.rb.velocity = Vector3.Lerp(item.rb.velocity, item.hostVel, num);
							item.rb.angularVelocity = Vector3.Lerp(item.rb.angularVelocity, item.hostAngVel, num);
						}
						Vector3 val = item.rb.position - item.hostPos;
						if (((Vector3)(ref val)).sqrMagnitude < 0.0009f && Quaternion.Angle(item.rb.rotation, item.hostRot) < 1.5f)
						{
							flag2 = true;
						}
					}
				}
				if (flag2 || item.softSyncTimer <= 0f)
				{
					Restore(item);
				}
			}
		}

		private static bool LocalGrabberStillHolding(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 true;
				}
			}
			return false;
		}

		private static void Snap(SimState st)
		{
			//IL_0007: 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_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			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)
		{
			//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));
				}
			}
			finally
			{
				HardRemove(st);
			}
		}

		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 ((Object)(object)st.pgo == (Object)null || (Object)(object)st.ptv == (Object)null)
			{
				SweepDead();
			}
		}

		private static void SweepDead()
		{
			deadPgos.Clear();
			deadPtvs.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 (PhysGrabObject deadPgo in deadPgos)
			{
				states.Remove(deadPgo);
			}
			foreach (PhotonTransformView deadPtv in deadPtvs)
			{
				byPtv.Remove(deadPtv);
			}
		}

		internal static void RestoreAll()
		{
			tickBuffer.Clear();
			tickBuffer.AddRange(states.Values);
			foreach (SimState item in tickBuffer)
			{
				Restore(item);
			}
			states.Clear();
			byPtv.Clear();
		}
	}
	internal class SimDriver : MonoBehaviour
	{
		private void Start()
		{
			if (Chainloader.PluginInfos.ContainsKey("net.ovchinikov.nwrework"))
			{
				Plugin.Log.LogWarning((object)"The old NetworkingReworked mod is still installed! It is broken on current game versions and will fight this mod. Please uninstall/disable it.");
			}
			if (Chainloader.PluginInfos.ContainsKey("BlueAmulet.REPONetworkTweaks"))
			{
				Plugin.Log.LogWarning((object)"The old REPONetworkTweaks mod is still installed! It forces client rigidbodies kinematic and replaces PhotonTransformView, which breaks this mod's local simulation. Please uninstall/disable it (use NetworkTweaksRevived instead).");
			}
		}

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

		private void OnDestroy()
		{
			SimManager.RestoreAll();
		}
	}
}
namespace NetworkingRevived.Patches
{
	[HarmonyPatch(typeof(PhysGrabObject), "GrabStarted")]
	internal static class GrabStartedPatch
	{
		private static void Postfix(PhysGrabObject __instance, PhysGrabber player)
		{
			if (!SimManager.Ready || !SimManager.IsClientInLobby() || (Object)(object)player == (Object)null || !player.isLocal)
			{
				return;
			}
			if (SimManager.IsLocalGrab(__instance))
			{
				if (!__instance.playerGrabbing.Contains(player))
				{
					__instance.playerGrabbing.Add(player);
				}
			}
			else if (SimManager.CanSimulate(__instance))
			{
				if (!__instance.playerGrabbing.Contains(player))
				{
					__instance.playerGrabbing.Add(player);
				}
				SimManager.StartLocalGrab(__instance);
			}
		}
	}
	[HarmonyPatch(typeof(PhysGrabObject), "GrabEnded")]
	internal static class GrabEndedPatch
	{
		private static void Postfix(PhysGrabObject __instance, PhysGrabber player)
		{
			if (SimManager.Ready && SimManager.IsClientInLobby() && !((Object)(object)player == (Object)null) && player.isLocal && SimManager.IsLocalGrab(__instance))
			{
				__instance.playerGrabbing.Remove(player);
				SimManager.LocalThrow(__instance, player);
				SimManager.EndLocalGrab(__instance);
			}
		}
	}
	[HarmonyPatch(typeof(PhysGrabObject), "GrabPlayerAddRPC")]
	internal static class GrabPlayerAddDedupePatch
	{
		private static bool Prefix(PhysGrabObject __instance, int photonViewID)
		{
			if (!SimManager.Ready || !SimManager.IsClientInLobby())
			{
				return true;
			}
			PhotonView val = PhotonView.Find(photonViewID);
			PhysGrabber val2 = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponent<PhysGrabber>() : null);
			if ((Object)(object)val2 != (Object)null && __instance.playerGrabbing.Contains(val2))
			{
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(PhotonTransformView), "Update")]
	internal static class TransformViewUpdatePatch
	{
		private static bool Prefix(PhotonTransformView __instance)
		{
			if (!SimManager.Ready || !SimManager.IsSuppressed(__instance))
			{
				return true;
			}
			SimManager.TickKinematicTimer(__instance);
			return false;
		}
	}
	[HarmonyPatch(typeof(PhotonTransformView), "OnPhotonSerializeView")]
	internal static class TransformViewSerializePatch
	{
		private static bool Prefix(PhotonTransformView __instance, PhotonStream stream, PhotonMessageInfo info, bool __runOriginal)
		{
			//IL_0022: 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_007a: 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_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: 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_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			if (!__runOriginal)
			{
				return false;
			}
			if (!SimManager.Ready || stream.IsWriting)
			{
				return true;
			}
			SimManager.SimState byPtv = SimManager.GetByPtv(__instance);
			if (byPtv == null)
			{
				return true;
			}
			if (info.Sender != PhotonNetwork.MasterClient)
			{
				return false;
			}
			try
			{
				byPtv.hostSleeping = (bool)stream.ReceiveNext();
				bool flag = (bool)stream.ReceiveNext();
				byPtv.hostTeleport |= flag;
				byPtv.hostKinematic = (bool)stream.ReceiveNext();
				byPtv.hostVel = (Vector3)stream.ReceiveNext();
				byPtv.hostAngVel = (Vector3)stream.ReceiveNext();
				Vector3 val = (Vector3)stream.ReceiveNext();
				Vector3 val2 = (Vector3)stream.ReceiveNext();
				float num = Mathf.Abs((float)(PhotonNetwork.Time - ((PhotonMessageInfo)(ref info)).SentServerTime));
				byPtv.hostPos = val + val2 * num;
				byPtv.hostRot = (Quaternion)stream.ReceiveNext();
				byPtv.hasHostState = true;
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Failed to read host state for " + ((Object)__instance).name + ": " + ex.Message));
			}
			return false;
		}
	}
	[HarmonyPatch]
	internal static class CartAuthorityPatch
	{
		private static IEnumerable<MethodBase> TargetMethods()
		{
			List<MethodBase> targets = new List<MethodBase>();
			Add(typeof(PhysGrabCart), "FixedUpdate");
			Add(typeof(PhysGrabCart), "CartSteer");
			if (Plugin.InstantCartHandle.Value)
			{
				Add(typeof(PhysGrabObjectGrabArea), "Update");
			}
			return targets;
			void Add(Type type, string name)
			{
				MethodInfo methodInfo = AccessTools.Method(type, name, (Type[])null, (Type[])null);
				if (methodInfo != null)
				{
					targets.Add(methodInfo);
				}
				else
				{
					Plugin.Log.LogWarning((object)("CartAuthorityPatch: " + type.Name + "." + name + " not found, skipping."));
				}
			}
		}

		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase original)
		{
			MethodInfo masterOrSingle = AccessTools.Method(typeof(SemiFunc), "IsMasterClientOrSingleplayer", (Type[])null, (Type[])null);
			MethodInfo punIsMaster = AccessTools.PropertyGetter(typeof(PhotonNetwork), "IsMasterClient");
			MethodInfo replacement = AccessTools.Method(typeof(CartAuthorityPatch), "MasterOrLocallySimulated", (Type[])null, (Type[])null);
			int replaced = 0;
			foreach (CodeInstruction instruction in instructions)
			{
				if ((masterOrSingle != null && CodeInstructionExtensions.Calls(instruction, masterOrSingle)) || (punIsMaster != null && CodeInstructionExtensions.Calls(instruction, punIsMaster)))
				{
					CodeInstruction val = new CodeInstruction(OpCodes.Ldarg_0, (object)null);
					val.labels.AddRange(instruction.labels);
					val.blocks.AddRange(instruction.blocks);
					yield return val;
					yield return new CodeInstruction(OpCodes.Call, (object)replacement);
					replaced++;
				}
				else
				{
					yield return instruction;
				}
			}
			if (replaced == 0)
			{
				Plugin.Log.LogWarning((object)("CartAuthorityPatch: no authority checks found in " + original.DeclaringType?.Name + "." + original.Name + " — game code may have changed."));
			}
		}

		public static bool MasterOrLocallySimulated(Component self)
		{
			if (!GameManager.Multiplayer())
			{
				return true;
			}
			if (PhotonNetwork.IsMasterClient)
			{
				return true;
			}
			if ((Object)(object)self == (Object)null)
			{
				return false;
			}
			PhysGrabObject val = (PhysGrabObject)(object)((self is PhysGrabObject) ? self : null);
			if ((Object)(object)val == (Object)null)
			{
				val = self.GetComponent<PhysGrabObject>();
			}
			if ((Object)(object)val == (Object)null)
			{
				val = self.GetComponentInParent<PhysGrabObject>();
			}
			if ((Object)(object)val != (Object)null)
			{
				return SimManager.HasPhysicsAuthority(val);
			}
			return false;
		}
	}
}