Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of RevivalSync v1.0.4
RevivalSync.dll
Decompiled 6 hours agousing 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 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.0.3.0")] [assembly: AssemblyInformationalVersion("1.0.3+3db4f8c1d373e4a357297b57513458d2600d7918")] [assembly: AssemblyProduct("RevivalSync")] [assembly: AssemblyTitle("RevivalSync")] [assembly: AssemblyVersion("1.0.3.0")] namespace RevivalSync { [BepInPlugin("com.Revival.revivalsync", "RevivalSync", "1.0.3")] public class Plugin : BaseUnityPlugin { public const string PluginGuid = "com.Revival.revivalsync"; public const string PluginName = "RevivalSync"; public const string PluginVersion = "1.0.3"; internal static ManualLogSource Log; internal static ConfigEntry<bool> SimulateCarts; internal static ConfigEntry<bool> SimulateHinges; internal static ConfigEntry<bool> InstantCartHandle; internal static ConfigEntry<float> PassiveSyncStrength; internal static ConfigEntry<float> PostThrowGrace; internal static ConfigEntry<float> SnapDistance; internal static ConfigEntry<float> HeldDriftCorrectAt; 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 bool PhotonReady; private static Harmony harmony; private static bool capturePatched; 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_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_0113: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Expected O, but got Unknown //IL_0150: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Expected O, but got Unknown //IL_018d: Unknown result type (might be due to invalid IL or missing references) //IL_0197: Expected O, but got Unknown //IL_024a: Unknown result type (might be due to invalid IL or missing references) //IL_0254: Expected O, but got Unknown //IL_0287: Unknown result type (might be due to invalid IL or missing references) //IL_0291: Expected O, but got Unknown //IL_02c4: Unknown result type (might be due to invalid IL or missing references) //IL_02ce: Expected O, but got Unknown //IL_030f: Unknown result type (might be due to invalid IL or missing references) //IL_0319: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; SimulateCarts = ((BaseUnityPlugin)this).Config.Bind<bool>("Simulation", "SimulateCarts", true, "Simulate carts locally (removes cart input lag)."); SimulateHinges = ((BaseUnityPlugin)this).Config.Bind<bool>("Simulation", "SimulateHinges", true, "Simulate doors/cabinets locally: the game's own hinge logic (closing, latching, bounce) runs on your machine so they respond instantly. Turn off to make them host-driven."); InstantCartHandle = ((BaseUnityPlugin)this).Config.Bind<bool>("Simulation", "InstantCartHandle", true, "Register cart handle grabs locally right away instead of waiting for the host."); PassiveSyncStrength = ((BaseUnityPlugin)this).Config.Bind<float>("Simulation", "PassiveSyncStrength", 0.075f, new ConfigDescription("How strongly objects you are NOT holding blend toward the host's state each physics tick. This constant correction is what keeps both players seeing the same world.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.01f, 0.5f), Array.Empty<object>())); PostThrowGrace = ((BaseUnityPlugin)this).Config.Bind<float>("Simulation", "PostThrowGrace", 0.6f, new ConfigDescription("Seconds after you release/throw an object during which the correction is extra gentle, so your throw flies the way you saw it leave your hand.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 3f), Array.Empty<object>())); SnapDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Simulation", "SnapDistance", 6f, new ConfigDescription("If an object you are not holding is further than this (meters) from the host's copy, snap it instead of blending.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(2f, 30f), Array.Empty<object>())); HeldDriftCorrectAt = ((BaseUnityPlugin)this).Config.Bind<float>("Simulation", "HeldDriftCorrectAt", 1.5f, new ConfigDescription("While you hold an object: if your copy drifts further than this (meters) beyond the normal ping-trail from the host's copy, gently pull it back.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 10f), Array.Empty<object>())); HeldDriftHandbackAt = ((BaseUnityPlugin)this).Config.Bind<float>("Simulation", "HeldDriftHandbackAt", 4f, new ConfigDescription("While you hold an object: if your copy stays further than this (meters) beyond the normal ping-trail (e.g. the host's version got stuck), give control back to the host until you re-grab.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 20f), Array.Empty<object>())); DisableTimeout = ((BaseUnityPlugin)this).Config.Bind<bool>("NetworkTweaks", "DisableTimeout", true, "Remove Photon's client-sided timeout that randomly kicks you from lobbies on brief lag spikes."); PhotonLateUpdate = ((BaseUnityPlugin)this).Config.Bind<bool>("NetworkTweaks", "PhotonLateUpdate", true, "Process network packets every rendered frame instead of on the physics tick. Lower perceived latency."); SmoothSync = ((BaseUnityPlugin)this).Config.Bind<bool>("SmoothSync", "Enabled", true, "Hermite interpolation for host-driven objects the simulation doesn't own (enemies, doors...)."); Extrapolate = ((BaseUnityPlugin)this).Config.Bind<bool>("SmoothSync", "Extrapolate", true, "Keep projecting movement briefly when an update is late or lost."); Future = ((BaseUnityPlugin)this).Config.Bind<float>("SmoothSync", "Future", 1f, new ConfigDescription("How far to project received data into the future, in update intervals.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 3f), Array.Empty<object>())); RateSmoothing = ((BaseUnityPlugin)this).Config.Bind<float>("SmoothSync", "RateSmoothing", 0.1f, new ConfigDescription("How quickly the measured update rate adapts.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); TimingThreshold = ((BaseUnityPlugin)this).Config.Bind<float>("SmoothSync", "TimingThreshold", 1f, new ConfigDescription("Seconds between updates after which data is considered discontinuous.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.2f, 5f), Array.Empty<object>())); VerboseLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("Advanced", "VerboseLogging", true, "Log everything the sync system does: registrations, grabs/releases, snaps, handbacks, host packet flow, stale-data warnings and periodic stats. ON by default while the mod is in its experimental testing phase — attach LogOutput.log to bug reports."); 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[10] { typeof(DriverHooksPatch), typeof(PhotonHandlerAwakePatch), typeof(HingeJointKeeperPatch), typeof(PhysGrabObjectStartPatch), typeof(GrabStartedPatch), typeof(GrabEndedPatch), typeof(GrabPlayerAddDedupePatch), typeof(TransformViewUpdatePatch), typeof(TransformViewSerializePatch), typeof(CartAuthorityPatch) }; 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.0.3", 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(); } 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 postThrowTimer; public float desyncTimer; public float stuckTimer; public float debugTimer; public int ridingTick; 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 FieldRef<PhysGrabObject, bool> pgoIsMaster; private static FieldRef<PhysGrabObject, bool> pgoIsActive; 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 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 int RegisteredCount => states.Count; internal static int HeldCount { get { int num = 0; foreach (SimState value in states.Values) { if (value.localGrab) { num++; } } return num; } } internal static bool InitAccessors() { try { pgoIsMaster = AccessTools.FieldRefAccess<PhysGrabObject, bool>("isMaster"); pgoIsActive = AccessTools.FieldRefAccess<PhysGrabObject, bool>("isActive"); 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"); 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) { return byPtv.ContainsKey(ptv); } return false; } internal static bool IsRegistered(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) { return states.ContainsKey(pgo); } 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<ItemAttributes>() != (Object)null) { return false; } 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_00c4: 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_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_0109: 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_012b: 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_0134: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_0141: 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 val && data[i + 6] is Vector3 val2 && data[i + 7] is Quaternion hostRot) { st.hostSleeping = hostSleeping; st.hostTeleport |= flag; st.hostKinematic = hostKinematic; st.hostVel = hostVel; st.hostAngVel = hostAngVel; float num = Mathf.Abs((float)(PhotonNetwork.Time - (double)networkTime / 1000.0)); st.hostPos = val + val2 * num; st.hostRot = hostRot; st.hasHostState = true; st.lastPacketTime = Time.unscaledTime; PacketsCaptured++; break; } } } internal static SimState TryRegister(PhysGrabObject pgo) { //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) 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 (!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) { 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 = (((Object)(object)value.cart != (Object)null) ? (Plugin.PostThrowGrace.Value * 2.5f) : Plugin.PostThrowGrace.Value); pgoIsMaster.Invoke(pgo) = false; if (Plugin.VerboseLogging.Value) { Plugin.Log.LogInfo((object)("Released grab authority: " + ((Object)pgo).name)); } } } internal static void LocalThrow(PhysGrabObject pgo, PhysGrabber player) { //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0089: 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) { 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 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() { 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++; tickBuffer.Clear(); tickBuffer.AddRange(states.Values); foreach (SimState item in tickBuffer) { if (!item.localGrab || (Object)(object)item.cart == (Object)null) { continue; } 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; } } } 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); } else if (item2.localGrab) { TickHeld(item2); } else { TickShadow(item2); } } } private static void TickHeld(SimState st) { //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0097: 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_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_01ab: Unknown result type (might be due to invalid IL or missing references) //IL_01b0: 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) 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 (!st.hasHostState) { DebugHeld(st, localGrabber, -1f, 0f); return; } st.hostTeleport = false; Vector3 velocity = st.rb.velocity; float magnitude = ((Vector3)(ref velocity)).magnitude; float num = magnitude * 0.4f; Vector3 val = st.hostPos + st.hostVel * 0.15f; float num2 = (((Object)(object)st.cart != (Object)null) ? (Plugin.HeldDriftCorrectAt.Value * 0.4f) : Plugin.HeldDriftCorrectAt.Value) + num; float num3 = Vector3.Distance(st.rb.position, val); if (num3 > Plugin.HeldDriftHandbackAt.Value + num) { st.desyncTimer += Time.fixedDeltaTime; if (st.desyncTimer > 0.6f) { ForceHandback(st); return; } } else { st.desyncTimer = 0f; } if (num3 > 1.5f && magnitude < 1f) { st.stuckTimer += Time.fixedDeltaTime; if (st.stuckTimer > 0.8f) { st.stuckTimer = 0f; Snap(st, "held object wedged in geometry, freeing to host position"); return; } } else { st.stuckTimer = 0f; } if (num3 > num2) { st.rb.position = Vector3.Lerp(st.rb.position, val, 0.05f); } DebugHeld(st, localGrabber, num3, 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_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: 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_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_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0171: 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_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_0296: Unknown result type (might be due to invalid IL or missing references) //IL_029b: Unknown result type (might be due to invalid IL or missing references) //IL_01a5: 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_01b2: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_01cd: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_01fd: Unknown result type (might be due to invalid IL or missing references) //IL_0203: 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_020d: 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) //IL_02d1: Unknown result type (might be due to invalid IL or missing references) //IL_0223: Unknown result type (might be due to invalid IL or missing references) //IL_0229: 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_0250: Unknown result type (might be due to invalid IL or missing references) //IL_0261: 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_0363: Unknown result type (might be due to invalid IL or missing references) //IL_0368: Unknown result type (might be due to invalid IL or missing references) //IL_036b: Unknown result type (might be due to invalid IL or missing references) //IL_0381: Unknown result type (might be due to invalid IL or missing references) //IL_0387: Unknown result type (might be due to invalid IL or missing references) //IL_038e: Unknown result type (might be due to invalid IL or missing references) //IL_03a4: Unknown result type (might be due to invalid IL or missing references) //IL_03a9: Unknown result type (might be due to invalid IL or missing references) //IL_03ac: Unknown result type (might be due to invalid IL or missing references) //IL_03c2: Unknown result type (might be due to invalid IL or missing references) //IL_03c7: Unknown result type (might be due to invalid IL or missing references) //IL_03cb: 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; return; } if (!st.hasHostState) { return; } if (st.postThrowTimer > 0f) { st.postThrowTimer -= Time.fixedDeltaTime; } if (st.hostTeleport) { st.hostTeleport = false; Snap(st, "host teleported it"); return; } float num = Time.unscaledTime - st.lastPacketTime; bool flag = num > 0.35f; Vector3 val = (flag ? st.hostPos : (st.hostPos + st.hostVel * Mathf.Min(num, 0.25f))); Vector3 val2 = (flag ? Vector3.zero : st.hostVel); Vector3 val3 = (flag ? Vector3.zero : st.hostAngVel); if (st.hostKinematic && !st.isHinge) { if (!st.rb.isKinematic) { st.rb.isKinematic = true; } st.rb.MovePosition(val); st.rb.MoveRotation(st.hostRot); return; } if (st.rb.isKinematic) { st.rb.isKinematic = false; } if (st.isHinge) { CheckHingeBroken(st); if (Quaternion.Angle(st.rb.rotation, st.hostRot) > 0.5f) { float num2 = Mathf.Clamp01(Plugin.PassiveSyncStrength.Value); st.rb.MoveRotation(Quaternion.Slerp(st.rb.rotation, st.hostRot, num2)); st.rb.angularVelocity = Vector3.Lerp(st.rb.angularVelocity, val3, num2); } return; } Vector3 val4; if (st.hostSleeping || flag) { if (st.rb.IsSleeping()) { return; } val4 = st.rb.position - st.hostPos; if (((Vector3)(ref val4)).sqrMagnitude < 0.0025f && Quaternion.Angle(st.rb.rotation, st.hostRot) < 3f) { st.rb.velocity = Vector3.zero; st.rb.angularVelocity = Vector3.zero; st.rb.position = st.hostPos; st.rb.rotation = st.hostRot; if (st.hostSleeping) { st.rb.Sleep(); } return; } } float num3 = Vector3.Distance(st.rb.position, val); if (num3 > Plugin.SnapDistance.Value) { Snap(st, "beyond snap distance"); return; } if (num3 > 1.5f) { val4 = st.rb.velocity; if (((Vector3)(ref val4)).sqrMagnitude < 1f && st.postThrowTimer <= 0f) { st.stuckTimer += Time.fixedDeltaTime; if (st.stuckTimer > 1.2f) { st.stuckTimer = 0f; Snap(st, "wedged in geometry, freeing to host position"); return; } goto IL_032f; } } st.stuckTimer = 0f; goto IL_032f; IL_032f: float num4 = Mathf.Clamp01(Plugin.PassiveSyncStrength.Value); if (st.postThrowTimer > 0f) { num4 *= 0.3f; } st.rb.MovePosition(Vector3.Lerp(st.rb.position, val, num4)); st.rb.MoveRotation(Quaternion.Slerp(st.rb.rotation, st.hostRot, num4)); st.rb.velocity = Vector3.Lerp(st.rb.velocity, val2, num4); st.rb.angularVelocity = Vector3.Lerp(st.rb.angularVelocity, val3, num4); } 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); } } 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) { //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 (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 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; internal static void FrameUpdate() { 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 (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]); } } } 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; } } Plugin.ApplyPhotonSettings(); 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 readonly LinkedList<Snapshot> snapshots = new LinkedList<Snapshot>(); internal Snapshot prev; internal float interpStartTime = -1f; internal float smoothFreq = 0.1f; internal int lastTimestamp; internal bool haveFirst; internal Vector3 interpVel; internal Vector3 interpAngVel; internal void Clear() { snapshots.Clear(); prev = null; interpStartTime = -1f; } } [HarmonyPatch(typeof(PhotonTransformView), "OnPhotonSerializeView")] internal static class SerializePatch { private static void Postfix(PhotonTransformView __instance, PhotonStream stream, PhotonMessageInfo info, bool __runOriginal) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) if (!__runOriginal || stream.IsWriting || !ShouldSmooth(__instance) || info.Sender != PhotonNetwork.MasterClient) { return; } InterpState orCreate = GetOrCreate(__instance); int sentServerTimestamp = ((PhotonMessageInfo)(ref info)).SentServerTimestamp; if (orCreate.haveFirst && sentServerTimestamp == orCreate.lastTimestamp) { return; } try { Record(__instance, orCreate, sentServerTimestamp); } catch (Exception ex) { Plugin.Log.LogWarning((object)("SmoothSync record failed on " + ((Object)__instance).name + ": " + ex.Message)); orCreate.Clear(); } } } [HarmonyPatch(typeof(PhotonTransformView), "Update")] internal static class UpdatePatch { private static void Postfix(PhotonTransformView __instance) { if (ShouldSmooth(__instance) && states.TryGetValue(__instance, out var value) && value.snapshots.Count != 0 && !teleportField.Invoke(__instance) && !sleepingField.Invoke(__instance)) { Apply(value); } } } [HarmonyPatch(typeof(PhotonTransformView), "Teleport")] internal static class TeleportPatch { private static void Postfix(PhotonTransformView __instance) { if (states.TryGetValue(__instance, out var value)) { value.Clear(); } } } [HarmonyPatch(typeof(PhotonTransformView), "OnEnable")] internal static class EnablePatch { private static void Postfix(PhotonTransformView __instance) { if (states.TryGetValue(__instance, out var value)) { value.Clear(); value.haveFirst = false; } } } internal static bool Active; private static readonly Dictionary<PhotonTransformView, InterpState> states = new Dictionary<PhotonTransformView, InterpState>(); private static FieldRef<PhotonTransformView, Vector3> recvPos; private static FieldRef<PhotonTransformView, Quaternion> recvRot; private static FieldRef<PhotonTransformView, Vector3> recvVel; private static FieldRef<PhotonTransformView, Vector3> recvAngVel; private static FieldRef<PhotonTransformView, Vector3> direction; private static FieldRef<PhotonTransformView, bool> teleportField; private static FieldRef<PhotonTransformView, bool> sleepingField; private static FieldRef<PhysGrabHinge, bool> hingeBroken; 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>(), 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 references) //IL_01ba: Unknown result type (might be due to invalid IL or missing references) //IL_01c1: Unknown result type (might be due to invalid IL or missing references) //IL_01c7: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_01e5: Unknown result type (might be due to invalid IL or missing references) //IL_01f1: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_020c: Unknown result type (might be due to invalid IL or missing references) //IL_0218: Unknown result type (might be due to invalid IL or missing references) float num = InterpFactor(st); while (num >= 1f && st.snapshots.Count > 1) { st.prev = st.snapshots.First.Value; st.snapshots.RemoveFirst(); st.interpStartTime += st.smoothFreq; num = InterpFactor(st); } Vector3 val; Quaternion val2; if (st.snapshots.Count == 1) { Snapshot value = st.snapshots.First.Value; if (st.prev != null && Plugin.Extrapolate.Value) { float num2 = 2f - Mathf.Pow((float)Math.E, 0f - num); val = value.position + Vector3.SlerpUnclamped(st.prev.velocity, value.velocity, num2) * ((num2 - 1f) * st.smoothFreq); val2 = Quaternion.SlerpUnclamped(st.prev.rotation, value.rotation, num2); } else { val = value.position; val2 = value.rotation; } st.interpVel = value.velocity; st.interpAngVel = value.angularVelocity; } else { Snapshot value2 = st.snapshots.First.Value; Snapshot value3 = st.snapshots.First.Next.Value; val = HermitePosition(value2.position, value2.velocity, value3.position, value3.velocity, num, st.smoothFreq); val2 = HermiteRotation(value2.rotation, value2.angularVelocity, value3.rotation, value3.angularVelocity, num, st.smoothFreq); st.interpVel = Vector3.Slerp(value2.velocity, value3.velocity, num); st.interpAngVel = Vector3.Lerp(value2.angularVelocity, value3.angularVelocity, num); } if ((Object)(object)st.rb != (Object)null) { st.rb.MovePosition(val); st.rb.MoveRotation(val2); } else if ((Object)(object)st.tf != (Object)null) { st.tf.position = val; st.tf.rotation = val2; } } private static float InterpFactor(InterpState st) { if (st.smoothFreq <= 0f || st.interpStartTime < 0f) { return 1f; } return (Time.timeSinceLevelLoad - st.interpStartTime) / st.smoothFreq; } private static Vector3 HermitePosition(Vector3 startPos, Vector3 startVel, Vector3 endPos, Vector3 endVel, float t, float freq) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) Vector3 val = startPos + startVel * (freq * t) / 3f; Vector3 val2 = endPos - endVel * (freq * (1f - t)) / 3f; return Vector3.Lerp(val, val2, t); } private static Quaternion HermiteRotation(Quaternion startRot, Vector3 startSpin, Quaternion endRot, Vector3 endSpin, float t, float freq) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) Quaternion val = startRot * Quaternion.Euler(startSpin * (freq * t) / 3f); Quaternion val2 = endRot * Quaternion.Euler(endSpin * (-1f * freq * (1f - t)) / 3f); return Quaternion.Slerp(val, val2, t); } } } namespace RevivalSync.Patches { [HarmonyPatch(typeof(PhysGrabObject), "Start")] internal static class PhysGrabObjectStartPatch { private static void Postfix(PhysGrabObject __instance) { if (SimManager.Ready) { SimManager.TryRegister(__instance); } } } [HarmonyPatch] internal static class SerializeReadCapturePatch { private static MethodBase TargetMethod() { return AccessTools.Method(typeof(PhotonNetwork), "OnSerializeRead", (Type[])null, (Type[])null); } private static void Prefix(object[] data, Player sender, int networkTime) { if (!SimManager.Ready || data == null || data.Length < 4 || PhotonNetwork.IsMasterClient || sender == null || sender != PhotonNetwork.MasterClient || !(data[0] is int num)) { return; } SimManager.SimState byViewId = SimManager.GetByViewId(num); if (byViewId == null) { return; } try { SimManager.CacheHostState(byViewId, data, networkTime); } catch (Exception ex) { if (Plugin.VerboseLogging.Value) { Plugin.Log.LogWarning((object)$"Capture failed for view {num}: {ex.Message}"); } } } } [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.IsHandedBack(__instance) && 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.ClearHandback(__instance); if (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)) { if (Plugin.VerboseLogging.Value) { Plugin.Log.LogInfo((object)("[dedupe] host grab broadcast for " + ((Object)__instance).name + " (already registered locally)")); } 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_0020: Unknown result type (might be due to invalid IL or missing references) if (!__runOriginal) { return false; } if (!SimManager.Ready || stream.IsWriting) { return true; } if (!SimManager.IsRegistered(__instance)) { return true; } if (info.Sender != PhotonNetwork.MasterClient) { return false; } try { stream.ReceiveNext(); stream.ReceiveNext(); stream.ReceiveNext(); stream.ReceiveNext(); stream.ReceiveNext(); stream.ReceiveNext(); stream.ReceiveNext(); stream.ReceiveNext(); } catch (Exception ex) { if (Plugin.VerboseLogging.Value) { Plugin.Log.LogWarning((object)("Stream discard failed on " + ((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(PhysGrabObject), "FixedUpdate"); Add(typeof(PhysGrabCart), "FixedUpdate"); Add(typeof(PhysGrabCart), "CartSteer"); if (Plugin.SimulateHinges.Value) { Add(typeof(PhysGrabHinge), "FixedUpdate"); } 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; } } [HarmonyPatch(typeof(PhysGrabHinge), "Awake")] internal static class HingeJointKeeperPatch { private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { MethodInfo notMaster = AccessTools.Method(typeof(SemiFunc), "IsNotMasterClient", (Type[])null, (Type[])null); MethodInfo replacement = AccessTools.Method(typeof(HingeJointKeeperPatch), "NotMasterAndHingeSimOff", (Type[])null, (Type[])null); int replaced = 0; foreach (CodeInstruction instruction in instructions) { if (notMaster != null && CodeInstructionExtensions.Calls(instruction, notMaster)) { instruction.operand = replacement; replaced++; } yield return instruction; } if (replaced == 0) { Plugin.Log.LogWarning((object)"HingeJointKeeperPatch: PhysGrabHinge.Awake changed — doors stay host-driven."); } } public static bool NotMasterAndHingeSimOff() { if (SemiFunc.IsNotMasterClient()) { return !Plugin.SimulateHinges.Value; } return false; } } [HarmonyPatch] internal static class DriverHooksPatch { [HarmonyPatch(typeof(GameDirector), "Update")] [HarmonyPostfix] private static void OnFrame() { SimDriver.FrameUpdate(); } [HarmonyPatch(typeof(PlayerController), "FixedUpdate")] [HarmonyPostfix] private static void OnPhysicsTick() { SimManager.Tick(); } } [HarmonyPatch(typeof(PhotonHandler), "Awake")] internal static class PhotonHandlerAwakePatch { private static void Postfix() { bool num = !Plugin.PhotonReady; Plugin.PhotonReady = true; Plugin.ApplyPhotonSettings(); if (num) { Plugin.Log.LogInfo((object)"Photon is up — timeout and LateUpdate dispatch settings applied."); } } } }