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 NetworkingRevived v1.1.2
NetworkingRevived.dll
Decompiled 21 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 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; } } }