using System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using NetworkingRevived.Patches; using Photon.Pun; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("Revival")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("Revival")] [assembly: AssemblyFileVersion("1.1.1.0")] [assembly: AssemblyInformationalVersion("1.1.1")] [assembly: AssemblyProduct("NetworkingRevived")] [assembly: AssemblyTitle("NetworkingRevived")] [assembly: AssemblyVersion("1.1.1.0")] namespace NetworkingRevived { public static class NetworkingRevivedAPI { public static bool IsLocallySimulated(PhotonTransformView ptv) { if (SimManager.Ready) { return SimManager.IsSuppressed(ptv); } return false; } public static bool IsLocallySimulated(PhysGrabObject pgo) { if (SimManager.Ready) { return SimManager.HasPhysicsAuthority(pgo); } return false; } } [BepInPlugin("com.Revival.networkingrevived", "NetworkingRevived", "1.1.1")] public class Plugin : BaseUnityPlugin { public const string PluginGuid = "com.Revival.networkingrevived"; public const string PluginName = "NetworkingRevived"; public const string PluginVersion = "1.1.1"; internal static ManualLogSource Log; internal static ConfigEntry SimulateCarts; internal static ConfigEntry SimulateCartContents; internal static ConfigEntry InstantCartHandle; internal static ConfigEntry SoftSyncDuration; internal static ConfigEntry SoftSyncStrength; internal static ConfigEntry 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("General", "SimulateCarts", true, "Simulate carts locally while you drag them (removes cart input lag)."); SimulateCartContents = ((BaseUnityPlugin)this).Config.Bind("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("General", "InstantCartHandle", true, "Register cart handle grabs locally right away instead of waiting for the host."); SoftSyncDuration = ((BaseUnityPlugin)this).Config.Bind("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(0.1f, 5f), Array.Empty())); SoftSyncStrength = ((BaseUnityPlugin)this).Config.Bind("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(0.01f, 1f), Array.Empty())); VerboseLogging = ((BaseUnityPlugin)this).Config.Bind("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(); 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 states = new Dictionary(); private static readonly Dictionary byPtv = new Dictionary(); private static readonly List tickBuffer = new List(32); private static FieldRef pgoIsMaster; private static FieldRef> cartItems; private static FieldRef grabberObject; private static MethodInfo pgoThrow; private static FieldRef ptvNetPos; private static FieldRef ptvNetRot; private static FieldRef ptvStoredPos; private static FieldRef ptvSmoothedPos; private static FieldRef ptvSmoothedRot; private static FieldRef ptvRecvPos; private static FieldRef ptvRecvRot; private static FieldRef ptvPrevPos; private static FieldRef ptvPrevRot; private static FieldRef ptvRecvVel; private static FieldRef ptvRecvAngVel; private static FieldRef ptvDistance; private static FieldRef ptvAngle; private static FieldRef ptvFirstTake; private static FieldRef ptvTeleport; private static FieldRef ptvIsSleeping; private static FieldRef ptvKinForced; private static FieldRef ptvKinForcedTimer; private static readonly List deadPgos = new List(); private static readonly List deadPtvs = new List(); internal static bool Ready { get; private set; } internal static bool InitAccessors() { try { pgoIsMaster = AccessTools.FieldRefAccess("isMaster"); cartItems = AccessTools.FieldRefAccess>("itemsInCart"); grabberObject = AccessTools.FieldRefAccess("grabbedPhysGrabObject"); pgoThrow = AccessTools.Method(typeof(PhysGrabObject), "Throw", (Type[])null, (Type[])null); ptvNetPos = AccessTools.FieldRefAccess("m_NetworkPosition"); ptvNetRot = AccessTools.FieldRefAccess("m_NetworkRotation"); ptvStoredPos = AccessTools.FieldRefAccess("m_StoredPosition"); ptvSmoothedPos = AccessTools.FieldRefAccess("smoothedPosition"); ptvSmoothedRot = AccessTools.FieldRefAccess("smoothedRotation"); ptvRecvPos = AccessTools.FieldRefAccess("receivedPosition"); ptvRecvRot = AccessTools.FieldRefAccess("receivedRotation"); ptvPrevPos = AccessTools.FieldRefAccess("prevPosition"); ptvPrevRot = AccessTools.FieldRefAccess("prevRotation"); ptvRecvVel = AccessTools.FieldRefAccess("receivedVelocity"); ptvRecvAngVel = AccessTools.FieldRefAccess("receivedAngularVelocity"); ptvDistance = AccessTools.FieldRefAccess("m_Distance"); ptvAngle = AccessTools.FieldRefAccess("m_Angle"); ptvFirstTake = AccessTools.FieldRefAccess("m_firstTake"); ptvTeleport = AccessTools.FieldRefAccess("teleport"); ptvIsSleeping = AccessTools.FieldRefAccess("isSleeping"); ptvKinForced = AccessTools.FieldRefAccess("kinematicClientForced"); ptvKinForcedTimer = AccessTools.FieldRefAccess("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() == (Object)null) { return false; } if ((Object)(object)((Component)o).GetComponent() == (Object)null) { return false; } if ((Object)(object)((Component)o).GetComponent() != (Object)null) { return Plugin.SimulateCarts.Value; } if ((Object)(object)((Component)o).GetComponent() != (Object)null) { return false; } if ((Object)(object)((Component)o).GetComponentInParent() != (Object)null) { return false; } if ((Object)(object)((Component)o).GetComponentInParent() != (Object)null) { return false; } if ((Object)(object)((Component)o).GetComponentInParent() != (Object)null) { return false; } if ((Object)(object)((Component)o).GetComponentInParent() != (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(); 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(); if ((Object)(object)component == (Object)null) { return; } List 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 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 state in states) { if ((Object)(object)state.Key == (Object)null) { deadPgos.Add(state.Key); } } foreach (KeyValuePair 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() : 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 TargetMethods() { List targets = new List(); 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 Transpiler(IEnumerable 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(); } if ((Object)(object)val == (Object)null) { val = self.GetComponentInParent(); } if ((Object)(object)val != (Object)null) { return SimManager.HasPhysicsAuthority(val); } return false; } } }