using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using ExitGames.Client.Photon; using HarmonyLib; using Peak; using Peak.Afflictions; using Photon.Pun; using Photon.Realtime; using TMPro; using UnityEngine; using UnityEngine.InputSystem; using UnityEngine.SceneManagement; using Zorro.Core; using Zorro.Core.Serizalization; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("Co-op mod")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("Co-op mod")] [assembly: AssemblyCopyright("Copyright © 2026")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("3228d7cf-9df9-4542-8bc9-3acc82920b68")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyVersion("1.0.0.0")] [BepInPlugin("com.peak.coopmod", "Co-op Mod", "0.0.7")] public sealed class CoopMod : BaseUnityPlugin { public const string PluginGuid = "com.peak.coopmod"; public const string PluginName = "Co-op Mod"; public const string PluginVersion = "0.0.7"; private void Awake() { Freepass.Initialize(this); ShareStamina.Initialize(this); PairPlayerStartLog.EnsureCreated(); OnlyEven.Initialize(this); Piggyback.Initialize(this); Latejoin.Initialize(this); Rolechanger.Initialize(this); SeparateRole.Initialize(this); ShareInventory.Initialize(this); ItemFix.Initialize(this); ShareDeath.Initialize(this); ShareAlive.Initialize(this); } private void OnDestroy() { ShareAlive.Shutdown(); ShareDeath.Shutdown(); ItemFix.Shutdown(); ShareInventory.Shutdown(); SeparateRole.Shutdown(); Rolechanger.Shutdown(); Latejoin.Shutdown(); Piggyback.Shutdown(); OnlyEven.Shutdown(); ShareStamina.Shutdown(); Freepass.Shutdown(); } } public static class Freepass { private sealed class FreepassState { public Character Climber; public Character Carrier; public Collider[] ClimberColliders; public Collider[] CarrierColliders; public Item Item; public Collider[] ItemColliders; public bool[] CarrierColliderEnabledBuffer; } private struct GroundedProxyState { public Character Climber; public bool Applied; public bool OriginalGrounded; } private struct CarrierRaycastProxyState { public FreepassState State; public bool Applied; } [HarmonyPatch(typeof(Item), "RPC_SetThrownData", new Type[] { typeof(int), typeof(float) })] private static class Item_RPC_SetThrownData_CarrierPass_Patch { [HarmonyPostfix] [HarmonyPriority(0)] private static void Postfix(Item __instance, int characterID) { if (initialized && !((Object)(object)__instance == (Object)null) && !((Object)(object)GameUtils.instance == (Object)null)) { PhotonView photonView = PhotonNetwork.GetPhotonView(characterID); Character climber = default(Character); if (!((Object)(object)photonView == (Object)null) && ((Component)photonView).TryGetComponent(ref climber) && TryGetPair(climber, out var carrier)) { GameUtils.instance.IgnoreCollisions(carrier, __instance, 0.5f); } } } } [HarmonyPatch(typeof(RescueHook), "GetHit")] private static class RescueHook_GetHit_CarrierRaycastPass_Patch { [HarmonyPrefix] [HarmonyPriority(800)] private static void Prefix(RescueHook __instance, out CarrierRaycastProxyState __state) { __state = BeginCarrierRaycastPass(__instance); } [HarmonyFinalizer] [HarmonyPriority(0)] private static Exception Finalizer(Exception __exception, CarrierRaycastProxyState __state) { EndCarrierRaycastPass(__state); return __exception; } } [HarmonyPatch(typeof(RopeShooter), "WillAttach")] private static class RopeShooter_WillAttach_GroundedProxy_Patch { [HarmonyPrefix] [HarmonyPriority(800)] private static void Prefix(RopeShooter __instance, out GroundedProxyState __state) { __state = BeginGroundedProxy(((Object)(object)__instance != (Object)null) ? ((ItemComponent)__instance).item : null); } [HarmonyFinalizer] [HarmonyPriority(0)] private static Exception Finalizer(Exception __exception, GroundedProxyState __state) { EndGroundedProxy(__state); return __exception; } } [HarmonyPatch(typeof(RopeShooter), "OnPrimaryFinishedCast")] private static class RopeShooter_OnPrimaryFinishedCast_GroundedProxy_Patch { [HarmonyPrefix] [HarmonyPriority(800)] private static void Prefix(RopeShooter __instance, out GroundedProxyState __state) { __state = BeginGroundedProxy(((Object)(object)__instance != (Object)null) ? ((ItemComponent)__instance).item : null); } [HarmonyFinalizer] [HarmonyPriority(0)] private static Exception Finalizer(Exception __exception, GroundedProxyState __state) { EndGroundedProxy(__state); return __exception; } } [HarmonyPatch(typeof(VineShooter), "WillAttach")] private static class VineShooter_WillAttach_GroundedProxy_Patch { [HarmonyPrefix] [HarmonyPriority(800)] private static void Prefix(VineShooter __instance, out GroundedProxyState __state) { __state = BeginGroundedProxy(((Object)(object)__instance != (Object)null) ? ((ItemComponent)__instance).item : null); } [HarmonyFinalizer] [HarmonyPriority(0)] private static Exception Finalizer(Exception __exception, GroundedProxyState __state) { EndGroundedProxy(__state); return __exception; } } [HarmonyPatch(typeof(VineShooter), "OnPrimaryFinishedCast")] private static class VineShooter_OnPrimaryFinishedCast_GroundedProxy_Patch { [HarmonyPrefix] [HarmonyPriority(800)] private static void Prefix(VineShooter __instance, out GroundedProxyState __state) { __state = BeginGroundedProxy(((Object)(object)__instance != (Object)null) ? ((ItemComponent)__instance).item : null); } [HarmonyFinalizer] [HarmonyPriority(0)] private static Exception Finalizer(Exception __exception, GroundedProxyState __state) { EndGroundedProxy(__state); return __exception; } } [HarmonyPatch(typeof(Constructable), "TryUpdatePreview")] private static class Constructable_TryUpdatePreview_GroundedProxy_Patch { [HarmonyPrefix] [HarmonyPriority(800)] private static void Prefix(Constructable __instance, out GroundedProxyState __state) { __state = BeginGroundedProxy(((Object)(object)__instance != (Object)null) ? ((ItemComponent)__instance).item : null); } [HarmonyFinalizer] [HarmonyPriority(0)] private static Exception Finalizer(Exception __exception, GroundedProxyState __state) { EndGroundedProxy(__state); return __exception; } } [HarmonyPatch(typeof(CharacterItems), "RaycastClimbingSpikeStart")] private static class CharacterItems_RaycastClimbingSpikeStart_GroundedProxy_Patch { [HarmonyPrefix] [HarmonyPriority(800)] private static void Prefix(CharacterItems __instance, out GroundedProxyState __state) { Character climber = (((Object)(object)__instance != (Object)null) ? ((Component)__instance).GetComponent() : null); __state = BeginGroundedProxy(climber); } [HarmonyFinalizer] [HarmonyPriority(0)] private static Exception Finalizer(Exception __exception, GroundedProxyState __state) { EndGroundedProxy(__state); return __exception; } } [HarmonyPatch(typeof(Action_RaycastSpawnSomething), "FixedUpdate")] private static class ActionRaycastSpawnSomething_FixedUpdate_GroundedProxy_Patch { [HarmonyPrefix] [HarmonyPriority(800)] private static void Prefix(Action_RaycastSpawnSomething __instance, out GroundedProxyState __state) { Item item = (((Object)(object)__instance != (Object)null) ? ((Component)__instance).GetComponent() : null); __state = BeginGroundedProxy(item); } [HarmonyFinalizer] [HarmonyPriority(0)] private static Exception Finalizer(Exception __exception, GroundedProxyState __state) { EndGroundedProxy(__state); return __exception; } } [HarmonyPatch(typeof(CharacterItems), "FixedUpdate")] private static class CharacterItems_FixedUpdate_Patch { [HarmonyPrefix] [HarmonyPriority(800)] private static void Prefix(CharacterItems __instance) { if (IsCarriedClimberItems(__instance, out var climber, out var _)) { UpdateFreepass(climber); } } } [HarmonyPatch(typeof(Character), "FixedUpdate")] private static class Character_FixedUpdate_Patch { [HarmonyPostfix] [HarmonyPriority(0)] private static void Postfix(Character __instance) { UpdateFreepass(__instance); } } private const string HarmonyId = "com.peak.coopmod.freepass"; private static Harmony harmony; private static bool initialized; private static readonly Dictionary states = new Dictionary(); public static void Initialize(CoopMod plugin) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown if (!initialized && !((Object)(object)plugin == (Object)null)) { harmony = new Harmony("com.peak.coopmod.freepass"); harmony.CreateClassProcessor(typeof(CharacterItems_FixedUpdate_Patch)).Patch(); harmony.CreateClassProcessor(typeof(Character_FixedUpdate_Patch)).Patch(); harmony.CreateClassProcessor(typeof(RescueHook_GetHit_CarrierRaycastPass_Patch)).Patch(); harmony.CreateClassProcessor(typeof(Item_RPC_SetThrownData_CarrierPass_Patch)).Patch(); harmony.CreateClassProcessor(typeof(RopeShooter_WillAttach_GroundedProxy_Patch)).Patch(); harmony.CreateClassProcessor(typeof(RopeShooter_OnPrimaryFinishedCast_GroundedProxy_Patch)).Patch(); harmony.CreateClassProcessor(typeof(VineShooter_WillAttach_GroundedProxy_Patch)).Patch(); harmony.CreateClassProcessor(typeof(VineShooter_OnPrimaryFinishedCast_GroundedProxy_Patch)).Patch(); harmony.CreateClassProcessor(typeof(Constructable_TryUpdatePreview_GroundedProxy_Patch)).Patch(); harmony.CreateClassProcessor(typeof(CharacterItems_RaycastClimbingSpikeStart_GroundedProxy_Patch)).Patch(); harmony.CreateClassProcessor(typeof(ActionRaycastSpawnSomething_FixedUpdate_GroundedProxy_Patch)).Patch(); initialized = true; } } public static void Shutdown() { if (initialized) { RestoreAll(); if (harmony != null) { harmony.UnpatchSelf(); harmony = null; } initialized = false; } } private static bool TryGetPair(Character climber, out Character carrier) { carrier = null; if ((Object)(object)climber == (Object)null || (Object)(object)climber.data == (Object)null || !climber.data.isCarried) { return false; } carrier = climber.data.carrier; if ((Object)(object)carrier == (Object)null || (Object)(object)carrier.data == (Object)null || (Object)(object)carrier.data.carriedPlayer != (Object)(object)climber) { carrier = null; return false; } return true; } private static Item GetHeldItem(Character climber) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Invalid comparison between Unknown and I4 if ((Object)(object)climber == (Object)null || (Object)(object)climber.data == (Object)null) { return null; } Item currentItem = climber.data.currentItem; if ((Object)(object)currentItem == (Object)null || (int)currentItem.itemState != 1 || (Object)(object)currentItem.holderCharacter != (Object)(object)climber) { return null; } return currentItem; } private static Collider[] GetCharacterBodyColliders(Character character) { if ((Object)(object)character == (Object)null || character.refs == null || (Object)(object)character.refs.ragdoll == (Object)null) { return Array.Empty(); } RigCreatorCollider[] componentsInChildren = ((Component)character.refs.ragdoll).GetComponentsInChildren(true); if (componentsInChildren == null || componentsInChildren.Length == 0) { return Array.Empty(); } HashSet hashSet = new HashSet(); foreach (RigCreatorCollider val in componentsInChildren) { if ((Object)(object)val == (Object)null) { continue; } Collider component = ((Component)val).GetComponent(); if (!((Object)(object)component == (Object)null)) { Character componentInParent = ((Component)component).GetComponentInParent(); if (!((Object)(object)componentInParent != (Object)(object)character)) { hashSet.Add(component); } } } if (hashSet.Count == 0) { return Array.Empty(); } Collider[] array = (Collider[])(object)new Collider[hashSet.Count]; hashSet.CopyTo(array); return array; } private static Collider[] GetItemColliders(Item item) { if ((Object)(object)item == (Object)null) { return Array.Empty(); } Collider[] componentsInChildren = ((Component)item).GetComponentsInChildren(true); if (componentsInChildren == null || componentsInChildren.Length == 0) { return Array.Empty(); } List list = new List(componentsInChildren.Length); foreach (Collider val in componentsInChildren) { if (!((Object)(object)val == (Object)null)) { Item componentInParent = ((Component)val).GetComponentInParent(); if (!((Object)(object)componentInParent != (Object)(object)item)) { list.Add(val); } } } return list.ToArray(); } private static void SetCollisionIgnore(Collider[] first, Collider[] second, bool ignore) { if (first == null || second == null) { return; } foreach (Collider val in first) { if ((Object)(object)val == (Object)null) { continue; } foreach (Collider val2 in second) { if (!((Object)(object)val2 == (Object)null) && !((Object)(object)val == (Object)(object)val2) && Physics.GetIgnoreCollision(val, val2) != ignore) { Physics.IgnoreCollision(val, val2, ignore); } } } } private static void RestoreHeldItem(FreepassState state) { if (state != null && !((Object)(object)state.Item == (Object)null)) { SetCollisionIgnore(state.ItemColliders, state.CarrierColliders, ignore: false); SetCollisionIgnore(state.ItemColliders, state.ClimberColliders, ignore: false); state.Item = null; state.ItemColliders = null; } } private static void ApplyHeldItemIsolation(FreepassState state, Item item) { if (state != null && !((Object)(object)item == (Object)null)) { if ((Object)(object)state.Item != (Object)(object)item) { RestoreHeldItem(state); state.Item = item; state.ItemColliders = GetItemColliders(item); } SetCollisionIgnore(state.ItemColliders, state.CarrierColliders, ignore: true); SetCollisionIgnore(state.ItemColliders, state.ClimberColliders, ignore: true); } } private static FreepassState CreateState(Character climber, Character carrier) { Collider[] characterBodyColliders = GetCharacterBodyColliders(climber); Collider[] characterBodyColliders2 = GetCharacterBodyColliders(carrier); FreepassState freepassState = new FreepassState(); freepassState.Climber = climber; freepassState.Carrier = carrier; freepassState.ClimberColliders = characterBodyColliders; freepassState.CarrierColliders = characterBodyColliders2; freepassState.CarrierColliderEnabledBuffer = new bool[characterBodyColliders2.Length]; FreepassState freepassState2 = freepassState; SetCollisionIgnore(freepassState2.ClimberColliders, freepassState2.CarrierColliders, ignore: true); return freepassState2; } private static void RestoreState(int climberId) { if (states.TryGetValue(climberId, out var value)) { if (value != null) { RestoreHeldItem(value); SetCollisionIgnore(value.ClimberColliders, value.CarrierColliders, ignore: false); } states.Remove(climberId); } } private static void RestoreAll() { List list = new List(states.Keys); for (int i = 0; i < list.Count; i++) { RestoreState(list[i]); } } private static FreepassState EnsureState(Character climber, Character carrier) { int instanceID = ((Object)climber).GetInstanceID(); if (states.TryGetValue(instanceID, out var value)) { if (value != null && (Object)(object)value.Climber == (Object)(object)climber && (Object)(object)value.Carrier == (Object)(object)carrier) { return value; } RestoreState(instanceID); } value = CreateState(climber, carrier); states[instanceID] = value; return value; } private static void UpdateFreepass(Character character) { if (!initialized || (Object)(object)character == (Object)null) { return; } if (!TryGetPair(character, out var carrier)) { RestoreState(((Object)character).GetInstanceID()); return; } FreepassState freepassState = EnsureState(character, carrier); if (freepassState != null) { SetCollisionIgnore(freepassState.ClimberColliders, freepassState.CarrierColliders, ignore: true); Item heldItem = GetHeldItem(character); if ((Object)(object)heldItem == (Object)null) { RestoreHeldItem(freepassState); } else { ApplyHeldItemIsolation(freepassState, heldItem); } } } private static bool IsCarriedClimberItems(CharacterItems items, out Character climber, out Character carrier) { climber = null; carrier = null; if ((Object)(object)items == (Object)null) { return false; } climber = ((Component)items).GetComponent(); return TryGetPair(climber, out carrier); } private static CarrierRaycastProxyState BeginCarrierRaycastPass(RescueHook rescueHook) { CarrierRaycastProxyState result = default(CarrierRaycastProxyState); if (!initialized || (Object)(object)rescueHook == (Object)null || (Object)(object)((ItemComponent)rescueHook).item == (Object)null) { return result; } Character holderCharacter = ((ItemComponent)rescueHook).item.holderCharacter; if (!TryGetPair(holderCharacter, out var carrier)) { return result; } FreepassState freepassState = EnsureState(holderCharacter, carrier); if (freepassState == null || freepassState.CarrierColliders == null || freepassState.CarrierColliderEnabledBuffer == null || freepassState.CarrierColliderEnabledBuffer.Length != freepassState.CarrierColliders.Length) { return result; } result.State = freepassState; result.Applied = true; for (int i = 0; i < freepassState.CarrierColliders.Length; i++) { Collider val = freepassState.CarrierColliders[i]; if ((Object)(object)val == (Object)null) { freepassState.CarrierColliderEnabledBuffer[i] = false; continue; } bool enabled = val.enabled; freepassState.CarrierColliderEnabledBuffer[i] = enabled; if (enabled) { val.enabled = false; } } return result; } private static void EndCarrierRaycastPass(CarrierRaycastProxyState proxyState) { if (!proxyState.Applied || proxyState.State == null || proxyState.State.CarrierColliders == null || proxyState.State.CarrierColliderEnabledBuffer == null) { return; } Collider[] carrierColliders = proxyState.State.CarrierColliders; bool[] carrierColliderEnabledBuffer = proxyState.State.CarrierColliderEnabledBuffer; int num = Mathf.Min(carrierColliders.Length, carrierColliderEnabledBuffer.Length); for (int i = 0; i < num; i++) { Collider val = carrierColliders[i]; if (!((Object)(object)val == (Object)null)) { val.enabled = carrierColliderEnabledBuffer[i]; } } } private static GroundedProxyState BeginGroundedProxy(Character climber) { GroundedProxyState result = default(GroundedProxyState); if (!initialized || (Object)(object)climber == (Object)null || (Object)(object)climber.data == (Object)null) { return result; } if (!TryGetPair(climber, out var carrier) || (Object)(object)carrier == (Object)null || (Object)(object)carrier.data == (Object)null) { return result; } result.Climber = climber; result.OriginalGrounded = climber.data.isGrounded; result.Applied = true; climber.data.isGrounded = carrier.data.isGrounded; return result; } private static GroundedProxyState BeginGroundedProxy(Item item) { if ((Object)(object)item == (Object)null) { return default(GroundedProxyState); } return BeginGroundedProxy(item.holderCharacter); } private static void EndGroundedProxy(GroundedProxyState state) { if (state.Applied && !((Object)(object)state.Climber == (Object)null) && !((Object)(object)state.Climber.data == (Object)null)) { state.Climber.data.isGrounded = state.OriginalGrounded; } } } public static class ItemFix { [StructLayout(LayoutKind.Explicit)] private struct FloatIntUnion { [FieldOffset(0)] public float FloatValue; [FieldOffset(0)] public int IntValue; } private struct ThrownItemState { public Character Character; public float Time; } [HarmonyPatch(typeof(RescueHook), "FixedUpdate")] private static class RescueHook_FixedUpdate_ContextPatch { [HarmonyPrefix] [HarmonyPriority(800)] private static void Prefix(RescueHook __instance) { activeRescueHook = null; activeRescueClimber = null; activeRescueCanSend = false; Character val = (((Object)(object)__instance != (Object)null) ? __instance.playerHoldingItem : null); if (!((Object)(object)val == (Object)null) && SeparateRole.IsClimber(val)) { activeRescueHook = __instance; activeRescueClimber = val; activeRescueCanSend = val.IsLocal && (Object)(object)((MonoBehaviourPun)__instance).photonView != (Object)null && ((MonoBehaviourPun)__instance).photonView.IsMine; } } [HarmonyFinalizer] [HarmonyPriority(0)] private static Exception Finalizer(Exception __exception) { activeRescueHook = null; activeRescueClimber = null; activeRescueCanSend = false; return __exception; } } [HarmonyPatch(typeof(Character), "AddForce", new Type[] { typeof(Vector3), typeof(float), typeof(float) })] private static class Character_AddForce_RescueTransportPatch { [HarmonyPrefix] [HarmonyPriority(800)] private static bool Prefix(Character __instance, Vector3 __0, float __1, float __2) { //IL_0056: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)activeRescueHook == (Object)null || (Object)(object)activeRescueClimber == (Object)null || (Object)(object)__instance != (Object)(object)activeRescueClimber || !SeparateRole.IsClimber(__instance)) { return true; } if (activeRescueCanSend && TryGetCarrier(__instance, out var carrier)) { SendRescueForce(__instance, carrier, __0, __1, __2, activeRescueHook.extraDragSelf); } return false; } } [HarmonyPatch(typeof(RescueHook), "RPCA_RescueWall", new Type[] { typeof(bool), typeof(Vector3) })] private static class RescueHook_RPCA_RescueWall_TransportPatch { [HarmonyPostfix] [HarmonyPriority(0)] private static void Postfix(RescueHook __instance) { Character val = (((Object)(object)__instance != (Object)null) ? __instance.playerHoldingItem : null); if (!((Object)(object)val == (Object)null) && val.IsLocal && !((Object)(object)((MonoBehaviourPun)__instance).photonView == (Object)null) && ((MonoBehaviourPun)__instance).photonView.IsMine && TryGetCarrier(val, out var carrier)) { activeSelfRescueHook = __instance; SendRescueFall(val, carrier, __instance.selfFallSeconds); } } } [HarmonyPatch(typeof(RescueHook), "RPCA_LetGo")] private static class RescueHook_RPCA_LetGo_TransportPatch { [HarmonyPrefix] [HarmonyPriority(800)] private static void Prefix(RescueHook __instance) { if (!((Object)(object)__instance == (Object)null) && !((Object)(object)__instance != (Object)(object)activeSelfRescueHook)) { Character playerHoldingItem = __instance.playerHoldingItem; if ((Object)(object)playerHoldingItem != (Object)null && playerHoldingItem.IsLocal && (Object)(object)((MonoBehaviourPun)__instance).photonView != (Object)null && ((MonoBehaviourPun)__instance).photonView.IsMine && TryGetCarrier(playerHoldingItem, out var carrier)) { SendRescueLetGo(playerHoldingItem, carrier, __instance.extraDragSelf); } activeSelfRescueHook = null; } } } [HarmonyPatch(typeof(RescueHook), "OnDestroy")] private static class RescueHook_OnDestroy_TransportPatch { [HarmonyPrefix] [HarmonyPriority(800)] private static void Prefix(RescueHook __instance) { if ((Object)(object)__instance == (Object)(object)activeSelfRescueHook) { activeSelfRescueHook = null; } } } [HarmonyPatch(typeof(Item), "RPC_SetThrownData", new Type[] { typeof(int), typeof(float) })] private static class Item_RPC_SetThrownData_TrackPatch { [HarmonyPostfix] [HarmonyPriority(0)] private static void Postfix(Item __instance, int characterID) { TrackThrownItem(__instance, characterID); } } [HarmonyPatch(typeof(WarpOnThrow), "OnCollisionEnter", new Type[] { typeof(Collision) })] private static class WarpOnThrow_OnCollisionEnter_TransportPatch { [HarmonyPrefix] [HarmonyPriority(800)] private static void Prefix(WarpOnThrow __instance, Collision collision) { //IL_0021: 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_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_0158: 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) if ((Object)(object)__instance == (Object)null || collision == null || (Object)(object)((ItemComponent)__instance).item == (Object)null || (int)((ItemComponent)__instance).item.itemState != 0 || (Object)(object)((MonoBehaviourPun)__instance).photonView == (Object)null || !((MonoBehaviourPun)__instance).photonView.IsMine || collision.contactCount <= 0 || !TryGetThrownItemState(((ItemComponent)__instance).item, out var state)) { return; } Character character = state.Character; if (!TryGetCarrierReplica(character, out var carrier) || (Object)(object)((MonoBehaviourPun)carrier).photonView == (Object)null) { return; } int layer = collision.gameObject.layer; if ((LayerMask.op_Implicit(HelperFunctions.terrainMapMask) & (1 << layer)) == 0) { return; } Vector3 relativeVelocity = collision.relativeVelocity; if (!(((Vector3)(ref relativeVelocity)).magnitude <= __instance.minVelocity)) { float num = Time.time - state.Time; if (!(num <= __instance.minTime) && !(num >= __instance.maxTime) && TryMarkWarpItem(((MonoBehaviourPun)__instance).photonView.ViewID)) { ContactPoint val = collision.contacts[0]; Vector3 val2 = ((ContactPoint)(ref val)).point + ((ContactPoint)(ref val)).normal * __instance.moveAwayFromWallDistance; ((MonoBehaviourPun)carrier).photonView.RPC("WarpPlayerRPC", (RpcTarget)0, new object[2] { val2, true }); } } } } [HarmonyPatch(typeof(Character), "WarpPlayerRPC", new Type[] { typeof(Vector3), typeof(bool) })] private static class Character_WarpPlayerRPC_CarriedCollisionPatch { [HarmonyPostfix] [HarmonyPriority(0)] private static void Postfix(Character __instance) { if (!((Object)(object)__instance == (Object)null) && SeparateRole.IsClimber(__instance)) { TrackWarpClimber(__instance); } } } private const string HarmonyId = "com.peak.coopmod.itemfix"; private const byte ItemMovementEventCode = 186; private const byte RescueForceAction = 1; private const byte RescueFallAction = 2; private const byte RescueLetGoAction = 3; private const byte WarpAction = 4; private const int HeaderLength = 9; private const int RescueForcePayloadLength = 33; private const int RescueFallPayloadLength = 13; private const int RescueLetGoPayloadLength = 13; private const int WarpPayloadLength = 22; private static Harmony harmony; private static RescueHook activeRescueHook; private static Character activeRescueClimber; private static bool activeRescueCanSend; private static RescueHook activeSelfRescueHook; private static readonly Dictionary thrownItemStates = new Dictionary(); private static readonly Dictionary recentWarpItems = new Dictionary(); private static readonly HashSet trackedWarpClimbers = new HashSet(); private static readonly int[] targetActors = new int[1]; private static readonly RaiseEventOptions raiseEventOptions = new RaiseEventOptions(); public static void Initialize(CoopMod plugin) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown if (harmony == null && !((Object)(object)plugin == (Object)null)) { harmony = new Harmony("com.peak.coopmod.itemfix"); Patch(typeof(RescueHook_FixedUpdate_ContextPatch)); Patch(typeof(Character_AddForce_RescueTransportPatch)); Patch(typeof(RescueHook_RPCA_RescueWall_TransportPatch)); Patch(typeof(RescueHook_RPCA_LetGo_TransportPatch)); Patch(typeof(RescueHook_OnDestroy_TransportPatch)); Patch(typeof(Item_RPC_SetThrownData_TrackPatch)); Patch(typeof(WarpOnThrow_OnCollisionEnter_TransportPatch)); Patch(typeof(Character_WarpPlayerRPC_CarriedCollisionPatch)); PhotonNetwork.NetworkingClient.EventReceived += HandleEvent; } } public static void Shutdown() { PhotonNetwork.NetworkingClient.EventReceived -= HandleEvent; foreach (Character trackedWarpClimber in trackedWarpClimbers) { if ((Object)(object)trackedWarpClimber != (Object)null) { trackedWarpClimber.WarpCompleted -= OnWarpCompleted; } } trackedWarpClimbers.Clear(); recentWarpItems.Clear(); thrownItemStates.Clear(); activeRescueHook = null; activeRescueClimber = null; activeRescueCanSend = false; activeSelfRescueHook = null; if (harmony != null) { harmony.UnpatchSelf(); harmony = null; } } private static void Patch(Type patchType) { harmony.CreateClassProcessor(patchType).Patch(); } private static int GetActorNumber(Character character) { if ((Object)(object)character == (Object)null || (Object)(object)((MonoBehaviourPun)character).photonView == (Object)null || ((MonoBehaviourPun)character).photonView.Owner == null) { return -1; } return ((MonoBehaviourPun)character).photonView.Owner.ActorNumber; } private static bool TryGetCarrier(Character climber, out Character carrier) { carrier = null; if ((Object)(object)climber == (Object)null || (Object)(object)climber.data == (Object)null || !climber.IsLocal || !SeparateRole.IsClimber(climber)) { return false; } carrier = climber.data.carrier; return (Object)(object)carrier != (Object)null && (Object)(object)carrier.data != (Object)null && SeparateRole.IsCarrier(carrier); } private static bool TryGetCarrierReplica(Character climber, out Character carrier) { carrier = null; if ((Object)(object)climber == (Object)null || (Object)(object)climber.data == (Object)null || !SeparateRole.IsClimber(climber)) { return false; } carrier = climber.data.carrier; return (Object)(object)carrier != (Object)null && (Object)(object)carrier.data != (Object)null && (Object)(object)carrier.data.carriedPlayer == (Object)(object)climber && SeparateRole.IsCarrier(carrier); } private static void ApplyAcceleration(Character carrier, Vector3 force, float minRandomMultiplier, float maxRandomMultiplier) { //IL_006e: 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_008e: Unknown result type (might be due to invalid IL or missing references) //IL_007e: 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) if ((Object)(object)carrier == (Object)null || carrier.refs == null || (Object)(object)carrier.refs.ragdoll == (Object)null || carrier.refs.ragdoll.partList == null) { return; } for (int i = 0; i < carrier.refs.ragdoll.partList.Count; i++) { Bodypart val = carrier.refs.ragdoll.partList[i]; if (!((Object)(object)val == (Object)null)) { Vector3 val2 = force; if (minRandomMultiplier != maxRandomMultiplier) { val2 *= Random.Range(minRandomMultiplier, maxRandomMultiplier); } val.AddForce(val2, (ForceMode)5); } } } private static void WriteInt32(byte[] buffer, ref int offset, int value) { buffer[offset++] = (byte)value; buffer[offset++] = (byte)(value >> 8); buffer[offset++] = (byte)(value >> 16); buffer[offset++] = (byte)(value >> 24); } private static int ReadInt32(byte[] buffer, ref int offset) { int result = buffer[offset] | (buffer[offset + 1] << 8) | (buffer[offset + 2] << 16) | (buffer[offset + 3] << 24); offset += 4; return result; } private static void WriteSingle(byte[] buffer, ref int offset, float value) { FloatIntUnion floatIntUnion = new FloatIntUnion { FloatValue = value }; WriteInt32(buffer, ref offset, floatIntUnion.IntValue); } private static float ReadSingle(byte[] buffer, ref int offset) { FloatIntUnion floatIntUnion = new FloatIntUnion { IntValue = ReadInt32(buffer, ref offset) }; return floatIntUnion.FloatValue; } private static bool PrepareTarget(Character climber, Character carrier, out int sourceActor, out int targetActor) { sourceActor = GetActorNumber(climber); targetActor = GetActorNumber(carrier); if (!PhotonNetwork.InRoom || PhotonNetwork.CurrentRoom == null || sourceActor <= 0 || targetActor <= 0) { return false; } targetActors[0] = targetActor; raiseEventOptions.TargetActors = targetActors; return true; } private static void SendRescueForce(Character climber, Character carrier, Vector3 force, float minRandomMultiplier, float maxRandomMultiplier, float extraDrag) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) if (PrepareTarget(climber, carrier, out var sourceActor, out var targetActor)) { byte[] array = new byte[33]; int offset = 0; array[offset++] = 1; WriteInt32(array, ref offset, sourceActor); WriteInt32(array, ref offset, targetActor); WriteSingle(array, ref offset, force.x); WriteSingle(array, ref offset, force.y); WriteSingle(array, ref offset, force.z); WriteSingle(array, ref offset, minRandomMultiplier); WriteSingle(array, ref offset, maxRandomMultiplier); WriteSingle(array, ref offset, extraDrag); PhotonNetwork.RaiseEvent((byte)186, (object)array, raiseEventOptions, SendOptions.SendUnreliable); } } private static void SendRescueFall(Character climber, Character carrier, float seconds) { //IL_0053: Unknown result type (might be due to invalid IL or missing references) if (PrepareTarget(climber, carrier, out var sourceActor, out var targetActor)) { byte[] array = new byte[13]; int offset = 0; array[offset++] = 2; WriteInt32(array, ref offset, sourceActor); WriteInt32(array, ref offset, targetActor); WriteSingle(array, ref offset, seconds); PhotonNetwork.RaiseEvent((byte)186, (object)array, raiseEventOptions, SendOptions.SendReliable); } } private static void SendRescueLetGo(Character climber, Character carrier, float extraDrag) { //IL_0053: Unknown result type (might be due to invalid IL or missing references) if (PrepareTarget(climber, carrier, out var sourceActor, out var targetActor)) { byte[] array = new byte[13]; int offset = 0; array[offset++] = 3; WriteInt32(array, ref offset, sourceActor); WriteInt32(array, ref offset, targetActor); WriteSingle(array, ref offset, extraDrag); PhotonNetwork.RaiseEvent((byte)186, (object)array, raiseEventOptions, SendOptions.SendReliable); } } private static void SendWarp(Character climber, Character carrier, Vector3 position, bool poof) { //IL_0041: 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_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) if (PrepareTarget(climber, carrier, out var sourceActor, out var targetActor)) { byte[] array = new byte[22]; int offset = 0; array[offset++] = 4; WriteInt32(array, ref offset, sourceActor); WriteInt32(array, ref offset, targetActor); WriteSingle(array, ref offset, position.x); WriteSingle(array, ref offset, position.y); WriteSingle(array, ref offset, position.z); array[offset++] = (byte)(poof ? 1 : 0); PhotonNetwork.RaiseEvent((byte)186, (object)array, raiseEventOptions, SendOptions.SendReliable); } } private static void HandleEvent(EventData photonEvent) { //IL_018a: 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) if (photonEvent == null || photonEvent.Code != 186 || !(photonEvent.CustomData is byte[] array) || array.Length < 9) { return; } int offset = 0; byte b = array[offset++]; int num = ReadInt32(array, ref offset); int num2 = ReadInt32(array, ref offset); Character localCharacter = Character.localCharacter; if ((Object)(object)localCharacter == (Object)null || !localCharacter.IsLocal || !SeparateRole.IsCarrier(localCharacter)) { return; } int actorNumber = GetActorNumber(localCharacter); Character carriedPlayer = localCharacter.data.carriedPlayer; int actorNumber2 = GetActorNumber(carriedPlayer); if (num2 != actorNumber || num != actorNumber2 || photonEvent.Sender != num) { return; } switch (b) { case 1: if (array.Length >= 33) { Vector3 force = default(Vector3); ((Vector3)(ref force))..ctor(ReadSingle(array, ref offset), ReadSingle(array, ref offset), ReadSingle(array, ref offset)); float minRandomMultiplier = ReadSingle(array, ref offset); float maxRandomMultiplier = ReadSingle(array, ref offset); float num3 = ReadSingle(array, ref offset); if (localCharacter.refs != null && (Object)(object)localCharacter.refs.movement != (Object)null) { localCharacter.refs.movement.ApplyExtraDrag(num3, true); } localCharacter.data.sinceGrounded = 0f; ApplyAcceleration(localCharacter, force, minRandomMultiplier, maxRandomMultiplier); } break; case 2: if (array.Length >= 13 && !((Object)(object)((MonoBehaviourPun)localCharacter).photonView == (Object)null)) { float num4 = ReadSingle(array, ref offset); ((MonoBehaviourPun)localCharacter).photonView.RPC("RPCA_Fall", (RpcTarget)0, new object[2] { num4, 0f }); } break; case 3: if (array.Length >= 13) { float num5 = ReadSingle(array, ref offset); if (localCharacter.refs != null && (Object)(object)localCharacter.refs.movement != (Object)null) { localCharacter.refs.movement.ApplyExtraDrag(num5, true); } } break; case 4: if (array.Length >= 22 && !((Object)(object)((MonoBehaviourPun)localCharacter).photonView == (Object)null)) { Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(ReadSingle(array, ref offset), ReadSingle(array, ref offset), ReadSingle(array, ref offset)); bool flag = array[offset] != 0; ((MonoBehaviourPun)localCharacter).photonView.RPC("WarpPlayerRPC", (RpcTarget)0, new object[2] { val, flag }); } break; } } private static void TrackThrownItem(Item item, int characterViewId) { if (!((Object)(object)item == (Object)null)) { PhotonView photonView = PhotonNetwork.GetPhotonView(characterViewId); Character character = null; if ((Object)(object)photonView != (Object)null) { ((Component)photonView).TryGetComponent(ref character); } thrownItemStates[((Object)item).GetInstanceID()] = new ThrownItemState { Character = character, Time = Time.time }; } } private static bool TryGetThrownItemState(Item item, out ThrownItemState state) { state = default(ThrownItemState); if ((Object)(object)item == (Object)null) { return false; } return thrownItemStates.TryGetValue(((Object)item).GetInstanceID(), out state) && (Object)(object)state.Character != (Object)null; } private static bool TryMarkWarpItem(int viewId) { if (viewId <= 0) { return true; } float realtimeSinceStartup = Time.realtimeSinceStartup; if (recentWarpItems.TryGetValue(viewId, out var value) && realtimeSinceStartup < value) { return false; } recentWarpItems[viewId] = realtimeSinceStartup + 3f; return true; } private static void TrackWarpClimber(Character climber) { if (!((Object)(object)climber == (Object)null) && SeparateRole.IsClimber(climber) && !trackedWarpClimbers.Contains(climber)) { trackedWarpClimbers.Add(climber); climber.WarpCompleted += OnWarpCompleted; } } private static void OnWarpCompleted(Character climber) { if ((Object)(object)climber != (Object)null) { climber.WarpCompleted -= OnWarpCompleted; } trackedWarpClimbers.Remove(climber); if (!((Object)(object)climber == (Object)null) && SeparateRole.IsClimber(climber) && climber.refs != null && !((Object)(object)climber.refs.ragdoll == (Object)null)) { climber.refs.ragdoll.ToggleCollision(false); } } } public static class Latejoin { [HarmonyPatch(typeof(CharacterCarrying), "Update")] private static class CharacterCarrying_Update_Patch { [HarmonyPrefix] [HarmonyPriority(800)] private static bool Prefix(CharacterCarrying __instance) { if ((Object)(object)__instance == (Object)null) { return true; } Character component = ((Component)__instance).GetComponent(); if ((Object)(object)component == (Object)null || (Object)(object)component.data == (Object)null) { return true; } Character carriedPlayer = component.data.carriedPlayer; if (!IsLockedPair(component, carriedPlayer)) { return true; } return ShouldAllowRelease(component, carriedPlayer); } } [HarmonyPatch(typeof(CharacterCarrying), "Drop", new Type[] { typeof(Character) })] private static class CharacterCarrying_Drop_Patch { [HarmonyPrefix] [HarmonyPriority(800)] private static bool Prefix(CharacterCarrying __instance, Character target) { if ((Object)(object)__instance == (Object)null || (Object)(object)target == (Object)null) { return true; } Character component = ((Component)__instance).GetComponent(); if (!IsLockedPair(component, target)) { return true; } return ShouldAllowRelease(component, target); } } [HarmonyPatch(typeof(CharacterCarrying), "RPCA_Drop", new Type[] { typeof(PhotonView) })] private static class CharacterCarrying_RPCA_Drop_Patch { [HarmonyPrefix] [HarmonyPriority(800)] private static bool Prefix(CharacterCarrying __instance, PhotonView targetView) { if ((Object)(object)__instance == (Object)null || (Object)(object)targetView == (Object)null) { return true; } Character component = ((Component)__instance).GetComponent(); Character component2 = ((Component)targetView).GetComponent(); if (!IsLockedPair(component, component2)) { return true; } return ShouldAllowRelease(component, component2); } [HarmonyPostfix] [HarmonyPriority(0)] private static void Postfix(CharacterCarrying __instance, PhotonView targetView) { if ((Object)(object)__instance == (Object)null || (Object)(object)targetView == (Object)null) { return; } Character component = ((Component)__instance).GetComponent(); Character component2 = ((Component)targetView).GetComponent(); if (!((Object)(object)component2 == (Object)null) && !((Object)(object)component2.data == (Object)null) && (!component2.data.isCarried || !((Object)(object)component2.data.carrier == (Object)(object)component))) { int actorNumber = GetActorNumber(component2); if (actorNumber > 0) { LockedRiderToCarrier.Remove(actorNumber); } } } } [HarmonyPatch(typeof(CharacterCarrying), "RPCA_StartCarry", new Type[] { typeof(PhotonView) })] private static class CharacterCarrying_RPCA_StartCarry_Patch { [HarmonyPostfix] [HarmonyPriority(0)] private static void Postfix(CharacterCarrying __instance, PhotonView targetView) { if (!((Object)(object)__instance == (Object)null) && !((Object)(object)targetView == (Object)null)) { Character component = ((Component)__instance).GetComponent(); Character component2 = ((Component)targetView).GetComponent(); if (IsLockedPair(component, component2) && !((Object)(object)component == (Object)null) && !((Object)(object)component.data == (Object)null) && !((Object)(object)component2 == (Object)null) && !((Object)(object)component2.data == (Object)null) && !((Object)(object)component.data.carriedPlayer != (Object)(object)component2) && component2.data.isCarried && !((Object)(object)component2.data.carrier != (Object)(object)component)) { MakeRiderAlive(component2); } } } } private const string HarmonyId = "com.peak.coopmod.latejoin"; private const byte PairEventCode = 193; private const byte PairAction = 1; private const byte PromoteCarrierAction = 2; private const byte RemovePairAction = 3; private static Harmony harmony; private static CoopMod plugin; private static LatejoinRuntime runtime; private static readonly Dictionary LockedRiderToCarrier = new Dictionary(); public static void Initialize(CoopMod owner) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown if (harmony == null && !((Object)(object)owner == (Object)null)) { plugin = owner; harmony = new Harmony("com.peak.coopmod.latejoin"); Patch(typeof(CharacterCarrying_Update_Patch)); Patch(typeof(CharacterCarrying_Drop_Patch)); Patch(typeof(CharacterCarrying_RPCA_Drop_Patch)); Patch(typeof(CharacterCarrying_RPCA_StartCarry_Patch)); runtime = ((Component)owner).gameObject.GetComponent(); if ((Object)(object)runtime == (Object)null) { runtime = ((Component)owner).gameObject.AddComponent(); } runtime.InitializeRuntime(); } } public static void Shutdown() { LockedRiderToCarrier.Clear(); if ((Object)(object)runtime != (Object)null) { runtime.ShutdownRuntime(); Object.Destroy((Object)(object)runtime); runtime = null; } if (harmony != null) { harmony.UnpatchSelf(); harmony = null; } plugin = null; } private static void Patch(Type patchType) { harmony.CreateClassProcessor(patchType).Patch(); } internal static void HandlePairEvent(EventData photonEvent) { if (photonEvent == null || photonEvent.Code != 193 || !(photonEvent.CustomData is byte[] array) || array.Length < 9) { return; } int offset = 0; byte b = array[offset++]; int num = ReadInt32(array, ref offset); int num2 = ReadInt32(array, ref offset); switch (b) { case 1: { RegisterPairActors(num, num2); Character rider = default(Character); if (PlayerHandler.TryGetCharacter(num2, ref rider)) { MakeRiderAlive(rider); } break; } case 2: PromoteActorToCarrier(num); break; case 3: RemovePairsForActor(num); if (num2 > 0) { RemovePairsForActor(num2); } break; } } internal static bool StartLatejoinPair(Character carrier, Character rider) { if (!PhotonNetwork.IsMasterClient || !PhotonNetwork.InRoom || (Object)(object)carrier == (Object)null || (Object)(object)rider == (Object)null || (Object)(object)carrier.data == (Object)null || (Object)(object)rider.data == (Object)null || (Object)(object)((MonoBehaviourPun)carrier).photonView == (Object)null || (Object)(object)((MonoBehaviourPun)rider).photonView == (Object)null) { return false; } int actorNumber = GetActorNumber(carrier); int actorNumber2 = GetActorNumber(rider); if (actorNumber <= 0 || actorNumber2 <= 0 || actorNumber == actorNumber2) { return false; } RegisterPairActors(actorNumber, actorNumber2); BroadcastPairAction(1, actorNumber, actorNumber2); ((MonoBehaviourPun)carrier).photonView.RPC("RPCA_StartCarry", (RpcTarget)0, new object[1] { ((MonoBehaviourPun)rider).photonView }); if (!((Object)(object)carrier.data.carriedPlayer == (Object)(object)rider) || !rider.data.isCarried || !((Object)(object)rider.data.carrier == (Object)(object)carrier)) { RemovePairsForActor(actorNumber2); BroadcastPairAction(3, actorNumber2, actorNumber); return false; } MakeRiderAlive(rider); return true; } internal static void PromoteCarrier(int actorNumber) { if (PhotonNetwork.IsMasterClient && actorNumber > 0) { PromoteActorToCarrier(actorNumber); BroadcastPairAction(2, actorNumber, 0); } } internal static bool IsActorLockedAsRider(int actorNumber) { return actorNumber > 0 && LockedRiderToCarrier.ContainsKey(actorNumber); } internal static bool IsActorLockedAsCarrier(int actorNumber) { if (actorNumber <= 0) { return false; } foreach (KeyValuePair item in LockedRiderToCarrier) { if (item.Value == actorNumber) { return true; } } return false; } internal static void RemovePairsForActor(int actorNumber) { if (actorNumber <= 0 || LockedRiderToCarrier.Count == 0) { return; } List list = null; foreach (KeyValuePair item in LockedRiderToCarrier) { if (item.Key == actorNumber || item.Value == actorNumber) { if (list == null) { list = new List(); } list.Add(item.Key); } } if (list != null) { for (int i = 0; i < list.Count; i++) { LockedRiderToCarrier.Remove(list[i]); } } } internal static void ClearPairs() { LockedRiderToCarrier.Clear(); } private static void RegisterPairActors(int carrierActor, int riderActor) { if (carrierActor > 0 && riderActor > 0 && carrierActor != riderActor) { RemovePairsForActor(riderActor); RemovePairsForActor(carrierActor); LockedRiderToCarrier[riderActor] = carrierActor; } } private static int GetActorNumber(Character character) { if ((Object)(object)character == (Object)null || (Object)(object)((MonoBehaviourPun)character).photonView == (Object)null || ((MonoBehaviourPun)character).photonView.Owner == null) { return -1; } return ((MonoBehaviourPun)character).photonView.Owner.ActorNumber; } private static bool IsLockedPair(Character carrier, Character rider) { if ((Object)(object)carrier == (Object)null || (Object)(object)rider == (Object)null) { return false; } int actorNumber = GetActorNumber(carrier); int actorNumber2 = GetActorNumber(rider); if (actorNumber <= 0 || actorNumber2 <= 0) { return false; } if (!LockedRiderToCarrier.TryGetValue(actorNumber2, out var value)) { return false; } return value == actorNumber; } private static bool ShouldAllowRelease(Character carrier, Character rider) { if ((Object)(object)carrier == (Object)null || (Object)(object)rider == (Object)null || (Object)(object)carrier.data == (Object)null || (Object)(object)rider.data == (Object)null) { return true; } if (carrier.data.dead || rider.data.dead) { return true; } if (!rider.data.isCarried) { return true; } if ((Object)(object)rider.data.carrier != (Object)(object)carrier) { return true; } if ((Object)(object)carrier.data.carriedPlayer != (Object)(object)rider) { return true; } return false; } private static void MakeRiderAlive(Character rider) { if (!((Object)(object)rider == (Object)null) && !((Object)(object)rider.data == (Object)null) && !rider.data.dead) { rider.data.deathTimer = 0f; rider.data.passOutValue = 0f; rider.data.passedOutOnTheBeach = 0f; rider.data.fallSeconds = 0f; rider.data.passedOut = false; rider.data.fullyPassedOut = false; rider.data.ragdollControlClamp = 1f; rider.data.currentRagdollControll = 1f; } } private static void BroadcastPairAction(byte action, int firstActor, int secondActor) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: 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_0043: Expected O, but got Unknown //IL_004a: Unknown result type (might be due to invalid IL or missing references) if (PhotonNetwork.InRoom) { byte[] array = new byte[9]; int offset = 0; array[offset++] = action; WriteInt32(array, ref offset, firstActor); WriteInt32(array, ref offset, secondActor); RaiseEventOptions val = new RaiseEventOptions { Receivers = (ReceiverGroup)0 }; PhotonNetwork.RaiseEvent((byte)193, (object)array, val, SendOptions.SendReliable); } } private static void PromoteActorToCarrier(int actorNumber) { if (actorNumber <= 0) { return; } RemovePairsForActor(actorNumber); Character val = default(Character); if (!PlayerHandler.TryGetCharacter(actorNumber, ref val) || (Object)(object)val == (Object)null || (Object)(object)val.data == (Object)null) { return; } Character carrier = val.data.carrier; if ((Object)(object)carrier != (Object)null && (Object)(object)carrier.data != (Object)null && (Object)(object)carrier.data.carriedPlayer == (Object)(object)val) { carrier.data.carriedPlayer = null; } Character carriedPlayer = val.data.carriedPlayer; if ((Object)(object)carriedPlayer != (Object)null && (Object)(object)carriedPlayer.data != (Object)null && (Object)(object)carriedPlayer.data.carrier == (Object)(object)val) { carriedPlayer.data.carrier = null; carriedPlayer.data.isCarried = false; } val.data.isCarried = false; val.data.carrier = null; val.data.carriedPlayer = null; if (val.refs != null) { if ((Object)(object)val.refs.ragdoll != (Object)null) { val.refs.ragdoll.ToggleCollision(true); } if ((Object)(object)val.refs.animator != (Object)null) { val.refs.animator.SetBool("IsCarried", false); } } MakeRiderAlive(val); } private static void WriteInt32(byte[] buffer, ref int offset, int value) { buffer[offset++] = (byte)value; buffer[offset++] = (byte)(value >> 8); buffer[offset++] = (byte)(value >> 16); buffer[offset++] = (byte)(value >> 24); } private static int ReadInt32(byte[] buffer, ref int offset) { int result = buffer[offset] | (buffer[offset + 1] << 8) | (buffer[offset + 2] << 16) | (buffer[offset + 3] << 24); offset += 4; return result; } } public sealed class LatejoinRuntime : MonoBehaviourPunCallbacks, IOnEventCallback { private sealed class PendingPairPlan { public int ExistingActor; public int JoinActor; public int CarrierActor; public int RiderActor; } private const float ScanInterval = 0.5f; private readonly HashSet knownActors = new HashSet(); private readonly HashSet pendingJoinActors = new HashSet(); private readonly Dictionary pendingPairPlans = new Dictionary(); private static readonly Random roleRandom = new Random(); private bool runtimeInitialized; private string activeRoomName; private float nextScanTime; private bool needsSurvivorNormalization; internal void InitializeRuntime() { if (!runtimeInitialized) { runtimeInitialized = true; SceneManager.sceneLoaded += OnSceneLoaded; RefreshRoomSnapshot(); } } internal void ShutdownRuntime() { if (runtimeInitialized) { SceneManager.sceneLoaded -= OnSceneLoaded; knownActors.Clear(); pendingJoinActors.Clear(); pendingPairPlans.Clear(); activeRoomName = null; needsSurvivorNormalization = false; runtimeInitialized = false; } } public override void OnEnable() { ((MonoBehaviourPunCallbacks)this).OnEnable(); } public override void OnDisable() { ((MonoBehaviourPunCallbacks)this).OnDisable(); } public void OnEvent(EventData photonEvent) { Latejoin.HandlePairEvent(photonEvent); } public override void OnJoinedRoom() { RefreshRoomSnapshot(); } public override void OnLeftRoom() { knownActors.Clear(); pendingJoinActors.Clear(); pendingPairPlans.Clear(); activeRoomName = null; needsSurvivorNormalization = false; Latejoin.ClearPairs(); } public override void OnMasterClientSwitched(Player newMasterClient) { if (PhotonNetwork.IsMasterClient) { needsSurvivorNormalization = true; } } public override void OnPlayerEnteredRoom(Player newPlayer) { if (newPlayer != null) { int actorNumber = newPlayer.ActorNumber; knownActors.Add(actorNumber); pendingJoinActors.Add(actorNumber); } } public override void OnPlayerLeftRoom(Player otherPlayer) { if (otherPlayer != null) { int actorNumber = otherPlayer.ActorNumber; knownActors.Remove(actorNumber); pendingJoinActors.Remove(actorNumber); RemovePendingPairPlansForActor(actorNumber); Latejoin.RemovePairsForActor(actorNumber); needsSurvivorNormalization = true; } } private void OnSceneLoaded(Scene scene, LoadSceneMode mode) { pendingJoinActors.Clear(); pendingPairPlans.Clear(); needsSurvivorNormalization = false; Latejoin.ClearPairs(); RefreshRoomSnapshot(); } private void Update() { if (!runtimeInitialized) { return; } float realtimeSinceStartup = Time.realtimeSinceStartup; if (realtimeSinceStartup < nextScanTime) { return; } nextScanTime = realtimeSinceStartup + 0.5f; if (!PhotonNetwork.InRoom || PhotonNetwork.CurrentRoom == null) { knownActors.Clear(); pendingJoinActors.Clear(); pendingPairPlans.Clear(); activeRoomName = null; needsSurvivorNormalization = false; Latejoin.ClearPairs(); return; } string name = PhotonNetwork.CurrentRoom.Name; if (!string.Equals(activeRoomName, name, StringComparison.Ordinal)) { RefreshRoomSnapshot(); return; } DetectNewActors(); RemoveMissingActors(); if (!PhotonNetwork.IsMasterClient || IsAirportScene()) { return; } if (needsSurvivorNormalization) { if (!NormalizeSurvivorsAfterLeave()) { return; } needsSurvivorNormalization = false; } ProcessPendingPairPlans(); AssignPendingJoiners(); AssignUnpairedSurvivors(); } private void RefreshRoomSnapshot() { knownActors.Clear(); pendingJoinActors.Clear(); pendingPairPlans.Clear(); needsSurvivorNormalization = false; Latejoin.ClearPairs(); if (!PhotonNetwork.InRoom || PhotonNetwork.CurrentRoom == null) { activeRoomName = null; return; } activeRoomName = PhotonNetwork.CurrentRoom.Name; Player[] playerList = PhotonNetwork.PlayerList; if (playerList == null) { return; } foreach (Player val in playerList) { if (val != null) { knownActors.Add(val.ActorNumber); } } } private void DetectNewActors() { Player[] playerList = PhotonNetwork.PlayerList; if (playerList == null) { return; } foreach (Player val in playerList) { if (val != null) { int actorNumber = val.ActorNumber; if (knownActors.Add(actorNumber)) { pendingJoinActors.Add(actorNumber); } } } } private void RemoveMissingActors() { if (knownActors.Count == 0) { return; } List list = null; foreach (int knownActor in knownActors) { if (PhotonNetwork.CurrentRoom.GetPlayer(knownActor, false) == null) { if (list == null) { list = new List(); } list.Add(knownActor); } } if (list != null) { for (int i = 0; i < list.Count; i++) { int num = list[i]; knownActors.Remove(num); pendingJoinActors.Remove(num); RemovePendingPairPlansForActor(num); Latejoin.RemovePairsForActor(num); } } } private bool NormalizeSurvivorsAfterLeave() { if (!PhotonNetwork.InRoom || PhotonNetwork.CurrentRoom == null) { return false; } Player[] playerList = PhotonNetwork.PlayerList; if (playerList == null || playerList.Length == 0) { return false; } if (playerList.Length == 1) { Player val = playerList[0]; if (val == null) { return false; } Character character = default(Character); if (!PlayerHandler.TryGetCharacter(val.ActorNumber, ref character) || !CharacterReady(character)) { return false; } Latejoin.PromoteCarrier(val.ActorNumber); return true; } List allPlayerCharacters = PlayerHandler.GetAllPlayerCharacters(); if (allPlayerCharacters == null) { return false; } for (int i = 0; i < allPlayerCharacters.Count; i++) { Character val2 = allPlayerCharacters[i]; if (!CharacterReady(val2)) { continue; } int actorNumber = GetActorNumber(val2); if (actorNumber <= 0 || PhotonNetwork.CurrentRoom.GetPlayer(actorNumber, false) == null) { continue; } bool flag = false; if (val2.data.isCarried || (Object)(object)val2.data.carrier != (Object)null) { Character carrier = val2.data.carrier; int actorNumber2 = GetActorNumber(carrier); if ((Object)(object)carrier == (Object)null || actorNumber2 <= 0 || PhotonNetwork.CurrentRoom.GetPlayer(actorNumber2, false) == null) { flag = true; } } Character carriedPlayer = val2.data.carriedPlayer; if ((Object)(object)carriedPlayer != (Object)null) { int actorNumber3 = GetActorNumber(carriedPlayer); if (actorNumber3 <= 0 || PhotonNetwork.CurrentRoom.GetPlayer(actorNumber3, false) == null) { flag = true; } } if (flag) { Latejoin.PromoteCarrier(actorNumber); } } return true; } private void ProcessPendingPairPlans() { if (pendingPairPlans.Count != 0) { List list = new List(pendingPairPlans.Values); for (int i = 0; i < list.Count; i++) { TryCompletePendingPair(list[i]); } } } private static bool IsAirportScene() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) Scene activeScene = SceneManager.GetActiveScene(); return ((Scene)(ref activeScene)).IsValid() && string.Equals(((Scene)(ref activeScene)).name, "Airport", StringComparison.Ordinal); } private void AssignUnpairedSurvivors() { if (IsAirportScene()) { return; } List allPlayerCharacters = PlayerHandler.GetAllPlayerCharacters(); if (allPlayerCharacters == null || allPlayerCharacters.Count < 2) { return; } List list = new List(); for (int i = 0; i < allPlayerCharacters.Count; i++) { Character val = allPlayerCharacters[i]; if (CharacterReady(val) && !val.data.dead) { int actorNumber = GetActorNumber(val); if (actorNumber > 0 && PhotonNetwork.CurrentRoom.GetPlayer(actorNumber, false) != null && !pendingJoinActors.Contains(actorNumber) && !ActorHasPendingPlan(actorNumber) && !IsActuallyPaired(val)) { Latejoin.RemovePairsForActor(actorNumber); list.Add(val); } } } if (list.Count < 2) { return; } ShuffleCharacters(list); for (int j = 0; j + 1 < list.Count; j += 2) { Character val2 = list[j]; Character val3 = list[j + 1]; int actorNumber2 = GetActorNumber(val2); int actorNumber3 = GetActorNumber(val3); if (actorNumber2 > 0 && actorNumber3 > 0 && actorNumber2 != actorNumber3) { bool flag = roleRandom.Next(0, 2) == 0; PendingPairPlan value = new PendingPairPlan { ExistingActor = actorNumber2, JoinActor = actorNumber3, CarrierActor = (flag ? actorNumber3 : actorNumber2), RiderActor = (flag ? actorNumber2 : actorNumber3) }; pendingPairPlans[actorNumber3] = value; WarpJoinerToExisting(val3, val2); } } } private bool ActorHasPendingPlan(int actorNumber) { if (actorNumber <= 0 || pendingPairPlans.Count == 0) { return false; } foreach (KeyValuePair pendingPairPlan in pendingPairPlans) { PendingPairPlan value = pendingPairPlan.Value; if (value == null || (value.JoinActor != actorNumber && value.ExistingActor != actorNumber && value.CarrierActor != actorNumber && value.RiderActor != actorNumber)) { continue; } return true; } return false; } private static bool IsActuallyPaired(Character character) { if ((Object)(object)character == (Object)null || (Object)(object)character.data == (Object)null) { return false; } if (character.data.isCarried) { Character carrier = character.data.carrier; if ((Object)(object)carrier != (Object)null && (Object)(object)carrier.data != (Object)null && (Object)(object)carrier.data.carriedPlayer == (Object)(object)character) { return true; } } Character carriedPlayer = character.data.carriedPlayer; if ((Object)(object)carriedPlayer != (Object)null && (Object)(object)carriedPlayer.data != (Object)null && carriedPlayer.data.isCarried && (Object)(object)carriedPlayer.data.carrier == (Object)(object)character) { return true; } return false; } private static void ShuffleCharacters(List characters) { for (int num = characters.Count - 1; num > 0; num--) { int index = roleRandom.Next(0, num + 1); Character value = characters[num]; characters[num] = characters[index]; characters[index] = value; } } private void AssignPendingJoiners() { if (pendingJoinActors.Count == 0) { return; } List list = new List(pendingJoinActors); Character val = default(Character); for (int i = 0; i < list.Count; i++) { int num = list[i]; if (PhotonNetwork.CurrentRoom.GetPlayer(num, false) == null) { pendingJoinActors.Remove(num); pendingPairPlans.Remove(num); } else { if (pendingPairPlans.ContainsKey(num) || !PlayerHandler.TryGetCharacter(num, ref val) || !CharacterReady(val) || val.data.dead) { continue; } if (IsCharacterAlreadyPaired(val, num)) { pendingJoinActors.Remove(num); continue; } Character val2 = FindUnpairedExistingFor(num); if (!((Object)(object)val2 == (Object)null)) { int actorNumber = GetActorNumber(val2); if (actorNumber > 0) { bool flag = roleRandom.Next(0, 2) == 0; PendingPairPlan value = new PendingPairPlan { ExistingActor = actorNumber, JoinActor = num, CarrierActor = (flag ? num : actorNumber), RiderActor = (flag ? actorNumber : num) }; pendingPairPlans[num] = value; WarpJoinerToExisting(val, val2); } } } } } private void TryCompletePendingPair(PendingPairPlan plan) { //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) if (plan == null) { return; } if (PhotonNetwork.CurrentRoom.GetPlayer(plan.JoinActor, false) == null || PhotonNetwork.CurrentRoom.GetPlayer(plan.ExistingActor, false) == null) { pendingPairPlans.Remove(plan.JoinActor); pendingJoinActors.Remove(plan.JoinActor); } else { Character val = default(Character); Character val2 = default(Character); if (!PlayerHandler.TryGetCharacter(plan.JoinActor, ref val) || !PlayerHandler.TryGetCharacter(plan.ExistingActor, ref val2) || !CharacterReady(val) || !CharacterReady(val2) || val.data.dead || val2.data.dead) { return; } if (IsCharacterAlreadyPaired(val, plan.JoinActor) || IsCharacterAlreadyPaired(val2, plan.ExistingActor)) { pendingPairPlans.Remove(plan.JoinActor); pendingJoinActors.Remove(plan.JoinActor); } else { if (val.warping) { return; } if (Vector3.Distance(val.Center, val2.Center) > 2f) { WarpJoinerToExisting(val, val2); return; } Character carrier = ((plan.CarrierActor == plan.JoinActor) ? val : val2); Character rider = ((plan.RiderActor == plan.JoinActor) ? val : val2); if (Latejoin.StartLatejoinPair(carrier, rider)) { pendingPairPlans.Remove(plan.JoinActor); pendingJoinActors.Remove(plan.JoinActor); } } } } private static void WarpJoinerToExisting(Character joiner, Character existing) { //IL_003e: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)joiner == (Object)null) && !((Object)(object)existing == (Object)null) && !((Object)(object)((MonoBehaviourPun)joiner).photonView == (Object)null)) { ((MonoBehaviourPun)joiner).photonView.RPC("WarpPlayerRPC", (RpcTarget)0, new object[2] { existing.Center, false }); } } private static bool IsCharacterAlreadyPaired(Character character, int actorNumber) { if ((Object)(object)character == (Object)null || (Object)(object)character.data == (Object)null) { return true; } return character.data.isCarried || (Object)(object)character.data.carrier != (Object)null || (Object)(object)character.data.carriedPlayer != (Object)null || Latejoin.IsActorLockedAsRider(actorNumber) || Latejoin.IsActorLockedAsCarrier(actorNumber); } private Character FindUnpairedExistingFor(int joinActor) { List allPlayerCharacters = PlayerHandler.GetAllPlayerCharacters(); if (allPlayerCharacters == null || allPlayerCharacters.Count == 0) { return null; } Character result = null; int num = int.MaxValue; for (int i = 0; i < allPlayerCharacters.Count; i++) { Character val = allPlayerCharacters[i]; if (CharacterReady(val)) { int actorNumber = GetActorNumber(val); if (actorNumber > 0 && actorNumber != joinActor && !pendingJoinActors.Contains(actorNumber) && !val.data.dead && !IsCharacterAlreadyPaired(val, actorNumber) && actorNumber < num) { num = actorNumber; result = val; } } } return result; } private void RemovePendingPairPlansForActor(int actorNumber) { if (actorNumber <= 0 || pendingPairPlans.Count == 0) { return; } List list = null; foreach (KeyValuePair pendingPairPlan in pendingPairPlans) { PendingPairPlan value = pendingPairPlan.Value; if (value == null || value.JoinActor == actorNumber || value.ExistingActor == actorNumber || value.CarrierActor == actorNumber || value.RiderActor == actorNumber) { if (list == null) { list = new List(); } list.Add(pendingPairPlan.Key); } } if (list == null) { return; } for (int i = 0; i < list.Count; i++) { int num = list[i]; pendingPairPlans.Remove(num); if (num != actorNumber) { pendingJoinActors.Add(num); } } } private static bool CharacterReady(Character character) { return (Object)(object)character != (Object)null && (Object)(object)character.data != (Object)null && character.refs != null && (Object)(object)character.refs.carriying != (Object)null && (Object)(object)((MonoBehaviourPun)character).photonView != (Object)null && (Object)(object)character.player != (Object)null; } private static int GetActorNumber(Character character) { if ((Object)(object)character == (Object)null || (Object)(object)((MonoBehaviourPun)character).photonView == (Object)null || ((MonoBehaviourPun)character).photonView.Owner == null) { return -1; } return ((MonoBehaviourPun)character).photonView.Owner.ActorNumber; } } public sealed class PairPlayerStartLog : MonoBehaviour { private const string LogColor = "#FFB347"; private const float LogDuration = 8f; private static PairPlayerStartLog instance; private string currentDisplayedColoredText = ""; private float nativeLogExpireTime = 0f; private Coroutine nativeLogCoroutine; public static void EnsureCreated() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown if (!((Object)(object)instance != (Object)null)) { GameObject val = new GameObject("PairPlayerStartLog"); Object.DontDestroyOnLoad((Object)(object)val); instance = val.AddComponent(); } } private void Awake() { if ((Object)(object)instance != (Object)null && (Object)(object)instance != (Object)(object)this) { Object.Destroy((Object)(object)((Component)this).gameObject); return; } instance = this; Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject); } private void OnDestroy() { if ((Object)(object)instance == (Object)(object)this) { instance = null; } } private string GetLocalizedMessage() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: 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_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Expected I4, but got Unknown Language cURRENT_LANGUAGE = LocalizedText.CURRENT_LANGUAGE; Language val = cURRENT_LANGUAGE; return (int)val switch { 0 => "An even number of players is required to start.", 1 => "Un nombre pair de joueurs est requis pour commencer.", 2 => "È necessario un numero pari di giocatori per iniziare.", 3 => "Zum Starten ist eine gerade Anzahl von Spielern erforderlich.", 4 => "Se necesita un número par de jugadores para empezar.", 5 => "Se necesita un número par de jugadores para comenzar.", 6 => "É necessário um número par de jogadores para começar.", 7 => "Для начала требуется четное количество игроков.", 8 => "Для початку потрібна парна кількість гравців.", 9 => "需要偶数名玩家才能开始游戏。", 10 => "需要偶數名玩家才能開始遊戲。", 11 => "開始するには偶数人のプレイヤーが必要です。", 12 => "짝수 플레이어가 있어야 시작할 수 있습니다.", 13 => "Do rozpoczęcia wymagana jest parzysta liczba graczy.", 14 => "Başlamak için çift sayıda oyuncu gereklidir.", _ => "An even number of players is required to start.", }; } public static void ShowEvenPlayerRequired() { EnsureCreated(); if (!((Object)(object)instance == (Object)null)) { instance.ShowNativeGameLog(); } } private void ShowNativeGameLog() { //IL_00a4: 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) PlayerConnectionLog val = Object.FindFirstObjectByType(); if ((Object)(object)val == (Object)null) { Debug.LogWarning((object)"[PairPlayerStartLog] PlayerConnectionLog was not found."); return; } if ((Object)(object)val.text == (Object)null) { Debug.LogWarning((object)"[PairPlayerStartLog] PlayerConnectionLog text was not found."); return; } string localizedMessage = GetLocalizedMessage(); string text = "" + localizedMessage + ""; RemoveCurrentLogMessage(val); currentDisplayedColoredText = text; TextMeshProUGUI text2 = val.text; ((TMP_Text)text2).text = ((TMP_Text)text2).text + text + "\n"; if (Object.op_Implicit((Object)(object)val.sfxJoin)) { val.sfxJoin.Play(default(Vector3)); } else { Debug.LogWarning((object)"[PairPlayerStartLog] PEAK join sound was not found."); } nativeLogExpireTime = Time.realtimeSinceStartup + 8f; if (nativeLogCoroutine == null) { nativeLogCoroutine = ((MonoBehaviour)this).StartCoroutine(NativeLogTimeoutRoutine()); } } private void RemoveCurrentLogMessage(PlayerConnectionLog playerLog) { if (!((Object)(object)playerLog == (Object)null) && !((Object)(object)playerLog.text == (Object)null) && !string.IsNullOrEmpty(currentDisplayedColoredText)) { string oldValue = currentDisplayedColoredText + "\n"; ((TMP_Text)playerLog.text).text = ((TMP_Text)playerLog.text).text.Replace(oldValue, ""); } } private IEnumerator NativeLogTimeoutRoutine() { while (Time.realtimeSinceStartup < nativeLogExpireTime) { yield return null; } PlayerConnectionLog playerLog = Object.FindFirstObjectByType(); if ((Object)(object)playerLog != (Object)null && (Object)(object)playerLog.text != (Object)null) { RemoveCurrentLogMessage(playerLog); } currentDisplayedColoredText = ""; nativeLogCoroutine = null; } } public static class OnlyEven { [HarmonyPatch(typeof(AirportCheckInKiosk), "StartGame", new Type[] { typeof(int) })] private static class AirportCheckInKiosk_StartGame_Patch { private static bool Prefix() { if (CanStartGame()) { return true; } ShowBlockedMessage("Game start"); return false; } } [HarmonyPatch(typeof(AirportCheckInKiosk), "LoadIslandMaster", new Type[] { typeof(int), typeof(byte[]) })] private static class AirportCheckInKiosk_LoadIslandMaster_Patch { private static bool Prefix() { if (CanStartGame()) { return true; } ShowBlockedMessage("Master scene load"); return false; } } private const string HarmonyId = "com.peak.coopmod.onlyeven"; private static Harmony harmony; private static bool initialized; public static ConfigEntry AllowOnePlayer; public static ConfigEntry AllowThreePlayers; public static void Initialize(CoopMod plugin) { //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Expected O, but got Unknown if (!initialized) { if ((Object)(object)plugin == (Object)null) { Debug.LogError((object)"[OnlyEven] CoopMod instance is null."); return; } AllowOnePlayer = ((BaseUnityPlugin)plugin).Config.Bind("Player Count", "Allow 1 Player", false, "1명인 상태에서도 게임 시작을 허용합니다."); AllowThreePlayers = ((BaseUnityPlugin)plugin).Config.Bind("Player Count", "Allow 3 Players", false, "3명인 상태에서도 게임 시작을 허용합니다."); harmony = new Harmony("com.peak.coopmod.onlyeven"); harmony.CreateClassProcessor(typeof(AirportCheckInKiosk_StartGame_Patch)).Patch(); harmony.CreateClassProcessor(typeof(AirportCheckInKiosk_LoadIslandMaster_Patch)).Patch(); initialized = true; Debug.Log((object)"[OnlyEven] Initialized."); Debug.Log((object)("[OnlyEven] Allow 1 Player: " + AllowOnePlayer.Value)); Debug.Log((object)("[OnlyEven] Allow 3 Players: " + AllowThreePlayers.Value)); } } public static void Shutdown() { if (initialized) { if (harmony != null) { harmony.UnpatchSelf(); harmony = null; } AllowOnePlayer = null; AllowThreePlayers = null; initialized = false; Debug.Log((object)"[OnlyEven] Shutdown."); } } public static int GetCurrentPlayerCount() { if (!PhotonNetwork.InRoom || PhotonNetwork.CurrentRoom == null) { return 0; } return PhotonNetwork.CurrentRoom.PlayerCount; } public static bool CanStartGame() { int currentPlayerCount = GetCurrentPlayerCount(); if (currentPlayerCount >= 2 && currentPlayerCount % 2 == 0) { return true; } if (currentPlayerCount == 1 && AllowOnePlayer != null && AllowOnePlayer.Value) { return true; } if (currentPlayerCount == 3 && AllowThreePlayers != null && AllowThreePlayers.Value) { return true; } return false; } private static void ShowBlockedMessage(string source) { Debug.Log((object)("[OnlyEven] " + source + " blocked. PlayerCount=" + GetCurrentPlayerCount())); PairPlayerStartLog.ShowEvenPlayerRequired(); } } public static class Piggyback { public enum RolePreferenceMode : byte { Random, Climber, Carrier } [HarmonyPatch(typeof(CharacterCarrying), "RPCA_StartCarry", new Type[] { typeof(PhotonView) })] private static class CharacterCarrying_RPCA_StartCarry_Patch { [HarmonyPostfix] [HarmonyPriority(0)] private static void Postfix(CharacterCarrying __instance, PhotonView targetView) { if (initialPairingWindow && !((Object)(object)__instance == (Object)null) && !((Object)(object)targetView == (Object)null)) { Character component = ((Component)__instance).GetComponent(); Character component2 = ((Component)targetView).GetComponent(); if (CharacterReady(component) && CharacterReady(component2) && !((Object)(object)component.data.carriedPlayer != (Object)(object)component2) && component2.data.isCarried && !((Object)(object)component2.data.carrier != (Object)(object)component)) { RegisterLockedPair(component, component2); MakeRiderAlive(component2); } } } } [HarmonyPatch(typeof(CharacterCarrying), "Update")] private static class CharacterCarrying_Update_Patch { [HarmonyPrefix] [HarmonyPriority(800)] private static bool Prefix(CharacterCarrying __instance) { if ((Object)(object)__instance == (Object)null) { return true; } Character component = ((Component)__instance).GetComponent(); if ((Object)(object)component == (Object)null || (Object)(object)component.data == (Object)null) { return true; } Character carriedPlayer = component.data.carriedPlayer; if (!IsLockedPair(component, carriedPlayer)) { return true; } if (ShouldAllowRelease(component, carriedPlayer)) { return true; } return false; } } [HarmonyPatch(typeof(CharacterCarrying), "Drop", new Type[] { typeof(Character) })] private static class CharacterCarrying_Drop_Patch { [HarmonyPrefix] [HarmonyPriority(800)] private static bool Prefix(CharacterCarrying __instance, Character target) { if ((Object)(object)__instance == (Object)null || (Object)(object)target == (Object)null) { return true; } Character component = ((Component)__instance).GetComponent(); if (!IsLockedPair(component, target)) { return true; } return ShouldAllowRelease(component, target); } } [HarmonyPatch(typeof(CharacterCarrying), "RPCA_Drop", new Type[] { typeof(PhotonView) })] private static class CharacterCarrying_RPCA_Drop_Patch { [HarmonyPrefix] [HarmonyPriority(800)] private static bool Prefix(CharacterCarrying __instance, PhotonView targetView) { if ((Object)(object)__instance == (Object)null || (Object)(object)targetView == (Object)null) { return true; } Character component = ((Component)__instance).GetComponent(); Character component2 = ((Component)targetView).GetComponent(); if (!IsLockedPair(component, component2)) { return true; } return ShouldAllowRelease(component, component2); } [HarmonyPostfix] [HarmonyPriority(0)] private static void Postfix(CharacterCarrying __instance, PhotonView targetView) { if (!((Object)(object)__instance == (Object)null) && !((Object)(object)targetView == (Object)null)) { Character component = ((Component)__instance).GetComponent(); Character component2 = ((Component)targetView).GetComponent(); if (!((Object)(object)component2 == (Object)null) && !((Object)(object)component2.data == (Object)null) && (!component2.data.isCarried || !((Object)(object)component2.data.carrier == (Object)(object)component))) { RemoveLockedPair(component, component2); } } } } private const string HarmonyId = "com.peak.coopmod.piggyback"; private const float CharacterSpawnTimeout = 30f; private const string RolePreferencePropertyKey = "CoopMod.RolePreference"; public static ConfigEntry RolePreference; private static Harmony harmony; private static CoopMod plugin; private static Coroutine assignmentCoroutine; private static bool initialPairingWindow; private static readonly Dictionary LockedRiderToCarrier = new Dictionary(); public static void Initialize(CoopMod owner) { //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Expected O, but got Unknown //IL_00cc: Unknown result type (might be due to invalid IL or missing references) if (harmony == null && !((Object)(object)owner == (Object)null)) { plugin = owner; RolePreference = ((BaseUnityPlugin)plugin).Config.Bind("Co-op Role", "Role Preference", RolePreferenceMode.Random, "역할 배정 선호도입니다. Random은 무작위, Climber는 등반자만, Carrier는 운반자만 배정됩니다."); RolePreference.SettingChanged += OnRolePreferenceChanged; PublishLocalRolePreference(); harmony = new Harmony("com.peak.coopmod.piggyback"); Patch(typeof(CharacterCarrying_RPCA_StartCarry_Patch)); Patch(typeof(CharacterCarrying_Update_Patch)); Patch(typeof(CharacterCarrying_Drop_Patch)); Patch(typeof(CharacterCarrying_RPCA_Drop_Patch)); SceneManager.sceneLoaded += OnSceneLoaded; HandleSceneLoaded(SceneManager.GetActiveScene()); } } public static void Shutdown() { SceneManager.sceneLoaded -= OnSceneLoaded; StopAssignmentCoroutine(); LockedRiderToCarrier.Clear(); initialPairingWindow = false; if (RolePreference != null) { RolePreference.SettingChanged -= OnRolePreferenceChanged; RolePreference = null; } if (harmony != null) { harmony.UnpatchSelf(); harmony = null; } plugin = null; } private static void Patch(Type patchType) { harmony.CreateClassProcessor(patchType).Patch(); } private static void OnSceneLoaded(Scene scene, LoadSceneMode mode) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) HandleSceneLoaded(scene); } private static void HandleSceneLoaded(Scene scene) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) StopAssignmentCoroutine(); LockedRiderToCarrier.Clear(); initialPairingWindow = false; if (!((Object)(object)plugin == (Object)null) && IsGameplayScene(scene)) { initialPairingWindow = true; assignmentCoroutine = ((MonoBehaviour)plugin).StartCoroutine(WaitForPlayersAndAssignTeams()); } } private static void StopAssignmentCoroutine() { if ((Object)(object)plugin != (Object)null && assignmentCoroutine != null) { ((MonoBehaviour)plugin).StopCoroutine(assignmentCoroutine); } assignmentCoroutine = null; } private static bool IsGameplayScene(Scene scene) { if (!((Scene)(ref scene)).IsValid()) { return false; } return ((Scene)(ref scene)).name.Contains("Island") || ((Scene)(ref scene)).name.Contains("Level_"); } private static bool IsOnShore() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Invalid comparison between Unknown and I4 if (!GameHandler.IsOnIsland) { return false; } return (int)MapHandler.CurrentSegmentNumber == 0; } private static IEnumerator WaitForPlayersAndAssignTeams() { float timeoutTime = Time.realtimeSinceStartup + 30f; while (Time.realtimeSinceStartup < timeoutTime) { if ((Object)(object)plugin == (Object)null) { assignmentCoroutine = null; yield break; } if (!PhotonNetwork.InRoom || PhotonNetwork.CurrentRoom == null) { yield return null; continue; } PublishLocalRolePreference(); if (!GameHandler.IsOnIsland) { yield return null; continue; } if (!IsOnShore()) { initialPairingWindow = false; assignmentCoroutine = null; yield break; } int playerCount = PhotonNetwork.CurrentRoom.PlayerCount; if (playerCount != 2 && playerCount != 4) { initialPairingWindow = false; assignmentCoroutine = null; yield break; } if (!PhotonNetwork.IsMasterClient) { assignmentCoroutine = null; yield break; } if (AllPlayerCharactersReady() && AllRolePreferencesReady()) { AssignTeamsByPreference(); assignmentCoroutine = null; yield break; } yield return null; } initialPairingWindow = false; assignmentCoroutine = null; } private static bool AllPlayerCharactersReady() { if (!PhotonNetwork.InRoom || PhotonNetwork.CurrentRoom == null) { return false; } Player[] playerList = PhotonNetwork.PlayerList; if (playerList == null || playerList.Length != PhotonNetwork.CurrentRoom.PlayerCount) { return false; } if (playerList.Length != 2 && playerList.Length != 4) { return false; } Character character = default(Character); for (int i = 0; i < playerList.Length; i++) { if (!PlayerHandler.TryGetCharacter(playerList[i].ActorNumber, ref character)) { return false; } if (!CharacterReady(character)) { return false; } } return true; } private static bool CharacterReady(Character character) { return (Object)(object)character != (Object)null && (Object)(object)character.data != (Object)null && character.refs != null && (Object)(object)character.refs.carriying != (Object)null && (Object)(object)((MonoBehaviourPun)character).photonView != (Object)null && (Object)(object)character.player != (Object)null; } private static void OnRolePreferenceChanged(object sender, EventArgs e) { PublishLocalRolePreference(); } private static void PublishLocalRolePreference() { //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_00ac: Expected O, but got Unknown //IL_00ae: Expected O, but got Unknown if (RolePreference != null && PhotonNetwork.InRoom && PhotonNetwork.LocalPlayer != null) { byte value = (byte)RolePreference.Value; if (PhotonNetwork.LocalPlayer.CustomProperties == null || !((Dictionary)(object)PhotonNetwork.LocalPlayer.CustomProperties).TryGetValue((object)"CoopMod.RolePreference", out object value2) || ((!(value2 is byte) || (byte)value2 != value) && (!(value2 is int) || (int)value2 != value))) { Hashtable val = new Hashtable(); ((Dictionary)val).Add((object)"CoopMod.RolePreference", (object)value); Hashtable val2 = val; PhotonNetwork.LocalPlayer.SetCustomProperties(val2, (Hashtable)null, (WebFlags)null); } } } private static bool AllRolePreferencesReady() { if (!PhotonNetwork.InRoom || PhotonNetwork.CurrentRoom == null) { return false; } Player[] playerList = PhotonNetwork.PlayerList; if (playerList == null || playerList.Length == 0) { return false; } for (int i = 0; i < playerList.Length; i++) { if (playerList[i] == null || playerList[i].CustomProperties == null || !((Dictionary)(object)playerList[i].CustomProperties).ContainsKey((object)"CoopMod.RolePreference")) { return false; } } return true; } private static RolePreferenceMode GetRolePreference(Player player) { if (player == null || player.CustomProperties == null) { return RolePreferenceMode.Random; } if (!((Dictionary)(object)player.CustomProperties).TryGetValue((object)"CoopMod.RolePreference", out object value)) { return RolePreferenceMode.Random; } if (value is byte b && b <= 2) { return (RolePreferenceMode)b; } if (value is int num && num >= 0 && num <= 2) { return (RolePreferenceMode)num; } return RolePreferenceMode.Random; } private static void Shuffle(List values, Random random) { if (values != null && random != null) { for (int num = values.Count - 1; num > 0; num--) { int index = random.Next(num + 1); int value = values[num]; values[num] = values[index]; values[index] = value; } } } private static void AssignTeamsByPreference() { if (!PhotonNetwork.IsMasterClient || !PhotonNetwork.InRoom || PhotonNetwork.CurrentRoom == null) { return; } Player[] playerList = PhotonNetwork.PlayerList; if (playerList == null || (playerList.Length != 2 && playerList.Length != 4)) { return; } int num = playerList.Length / 2; List list = new List(num); List list2 = new List(num); List list3 = new List(playerList.Length); for (int i = 0; i < playerList.Length; i++) { switch (GetRolePreference(playerList[i])) { case RolePreferenceMode.Carrier: list.Add(playerList[i].ActorNumber); break; case RolePreferenceMode.Climber: list2.Add(playerList[i].ActorNumber); break; default: list3.Add(playerList[i].ActorNumber); break; } } if (list.Count > num || list2.Count > num) { initialPairingWindow = false; return; } int num2 = num - list.Count; int num3 = num - list2.Count; if (num2 + num3 != list3.Count) { initialPairingWindow = false; return; } Random random = new Random(Environment.TickCount ^ PhotonNetwork.ServerTimestamp); Shuffle(list3, random); for (int j = 0; j < num2; j++) { list.Add(list3[j]); } for (int k = num2; k < list3.Count; k++) { list2.Add(list3[k]); } Shuffle(list, random); Shuffle(list2, random); Character val = default(Character); Character val2 = default(Character); for (int l = 0; l < num; l++) { if (PlayerHandler.TryGetCharacter(list[l], ref val) && PlayerHandler.TryGetCharacter(list2[l], ref val2) && CharacterReady(val) && CharacterReady(val2) && !((Object)(object)val == (Object)(object)val2) && !((Object)(object)val.data.carriedPlayer != (Object)null) && !val2.data.isCarried && !((Object)(object)val2.data.carrier != (Object)null) && !val.data.dead && !val2.data.dead) { ((MonoBehaviourPun)val).photonView.RPC("RPCA_StartCarry", (RpcTarget)0, new object[1] { ((MonoBehaviourPun)val2).photonView }); } } } private static int GetActorNumber(Character character) { if ((Object)(object)character == (Object)null || (Object)(object)((MonoBehaviourPun)character).photonView == (Object)null || ((MonoBehaviourPun)character).photonView.Owner == null) { return -1; } return ((MonoBehaviourPun)character).photonView.Owner.ActorNumber; } private static void RegisterLockedPair(Character carrier, Character rider) { if (!CharacterReady(carrier) || !CharacterReady(rider)) { return; } int actorNumber = GetActorNumber(carrier); int actorNumber2 = GetActorNumber(rider); if (actorNumber > 0 && actorNumber2 > 0 && actorNumber != actorNumber2) { LockedRiderToCarrier[actorNumber2] = actorNumber; int expectedPairCount = GetExpectedPairCount(); if (expectedPairCount > 0 && LockedRiderToCarrier.Count >= expectedPairCount) { initialPairingWindow = false; } } } private static void RemoveLockedPair(Character carrier, Character rider) { if ((Object)(object)rider == (Object)null) { return; } int actorNumber = GetActorNumber(rider); if (actorNumber <= 0 || !LockedRiderToCarrier.TryGetValue(actorNumber, out var value)) { return; } if ((Object)(object)carrier != (Object)null) { int actorNumber2 = GetActorNumber(carrier); if (actorNumber2 > 0 && value != actorNumber2) { return; } } LockedRiderToCarrier.Remove(actorNumber); } private static bool IsLockedPair(Character carrier, Character rider) { if ((Object)(object)carrier == (Object)null || (Object)(object)rider == (Object)null) { return false; } int actorNumber = GetActorNumber(carrier); int actorNumber2 = GetActorNumber(rider); if (actorNumber <= 0 || actorNumber2 <= 0) { return false; } if (!LockedRiderToCarrier.TryGetValue(actorNumber2, out var value)) { return false; } return value == actorNumber; } private static int GetExpectedPairCount() { if (!PhotonNetwork.InRoom || PhotonNetwork.CurrentRoom == null) { return 0; } return PhotonNetwork.CurrentRoom.PlayerCount switch { 2 => 1, 4 => 2, _ => 0, }; } private static Character ResolveCharacter(Component component) { if ((Object)(object)component == (Object)null) { return null; } Character component2 = component.GetComponent(); if ((Object)(object)component2 != (Object)null) { return component2; } return component.GetComponentInParent(); } private static void MakeRiderAlive(Character rider) { if (!((Object)(object)rider == (Object)null) && !((Object)(object)rider.data == (Object)null) && !rider.data.dead) { rider.data.deathTimer = 0f; rider.data.passOutValue = 0f; rider.data.passedOutOnTheBeach = 0f; rider.data.fallSeconds = 0f; rider.data.passedOut = false; rider.data.fullyPassedOut = false; rider.data.ragdollControlClamp = 1f; rider.data.currentRagdollControll = 1f; } } private static bool ShouldAllowRelease(Character carrier, Character rider) { if ((Object)(object)carrier == (Object)null || (Object)(object)rider == (Object)null || (Object)(object)carrier.data == (Object)null || (Object)(object)rider.data == (Object)null) { return true; } if (carrier.data.dead || rider.data.dead) { return true; } if (!rider.data.isCarried) { return true; } if ((Object)(object)rider.data.carrier != (Object)(object)carrier) { return true; } if ((Object)(object)carrier.data.carriedPlayer != (Object)(object)rider) { return true; } return false; } } public static class Rolechanger { private sealed class PairActors { public int CarrierActor; public int RiderActor; } [HarmonyPatch(typeof(Campfire), "Light_Rpc", new Type[] { typeof(bool), typeof(float) })] private static class Campfire_LightRpc_Patch { [HarmonyPostfix] [HarmonyPriority(0)] private static void Postfix(Campfire __instance, bool updateSegment) { if (!((Object)(object)__instance == (Object)null) && updateSegment && PhotonNetwork.InRoom && PhotonNetwork.IsMasterClient) { PhotonView component = ((Component)__instance).GetComponent(); if (!((Object)(object)component == (Object)null) && component.ViewID > 0) { RequestCampfireShuffle(component.ViewID); } } } } [HarmonyPatch(typeof(CharacterCarrying), "Update")] private static class CharacterCarrying_Update_Patch { [HarmonyPrefix] [HarmonyPriority(800)] private static bool Prefix(CharacterCarrying __instance) { if ((Object)(object)__instance == (Object)null) { return true; } Character component = ((Component)__instance).GetComponent(); if ((Object)(object)component == (Object)null || (Object)(object)component.data == (Object)null) { return true; } Character carriedPlayer = component.data.carriedPlayer; if (!IsLockedPair(component, carriedPlayer)) { return true; } return ShouldAllowRelease(component, carriedPlayer); } } [HarmonyPatch(typeof(CharacterCarrying), "Drop", new Type[] { typeof(Character) })] private static class CharacterCarrying_Drop_Patch { [HarmonyPrefix] [HarmonyPriority(800)] private static bool Prefix(CharacterCarrying __instance, Character target) { if ((Object)(object)__instance == (Object)null || (Object)(object)target == (Object)null) { return true; } Character component = ((Component)__instance).GetComponent(); if (!IsLockedPair(component, target)) { return true; } return ShouldAllowRelease(component, target); } } [HarmonyPatch(typeof(CharacterCarrying), "RPCA_Drop", new Type[] { typeof(PhotonView) })] private static class CharacterCarrying_RPCA_Drop_Patch { [HarmonyPrefix] [HarmonyPriority(800)] private static bool Prefix(CharacterCarrying __instance, PhotonView targetView) { if ((Object)(object)__instance == (Object)null || (Object)(object)targetView == (Object)null) { return true; } Character component = ((Component)__instance).GetComponent(); Character component2 = ((Component)targetView).GetComponent(); if (!IsLockedPair(component, component2)) { return true; } return ShouldAllowRelease(component, component2); } } private const string HarmonyId = "com.peak.coopmod.rolechanger"; private const byte SwapEventCode = 194; private const byte ShuffleAction = 1; private static Harmony harmony; private static CoopMod plugin; private static RolechangerRuntime runtime; private static readonly Dictionary LockedRiderToCarrier = new Dictionary(); private static readonly Random random = new Random(); public static void Initialize(CoopMod owner) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown if (harmony == null && !((Object)(object)owner == (Object)null)) { plugin = owner; harmony = new Harmony("com.peak.coopmod.rolechanger"); Patch(typeof(Campfire_LightRpc_Patch)); Patch(typeof(CharacterCarrying_Update_Patch)); Patch(typeof(CharacterCarrying_Drop_Patch)); Patch(typeof(CharacterCarrying_RPCA_Drop_Patch)); runtime = ((Component)owner).gameObject.GetComponent(); if ((Object)(object)runtime == (Object)null) { runtime = ((Component)owner).gameObject.AddComponent(); } runtime.InitializeRuntime(); } } public static void Shutdown() { LockedRiderToCarrier.Clear(); if ((Object)(object)runtime != (Object)null) { runtime.ShutdownRuntime(); Object.Destroy((Object)(object)runtime); runtime = null; } if (harmony != null) { harmony.UnpatchSelf(); harmony = null; } plugin = null; } private static void Patch(Type patchType) { harmony.CreateClassProcessor(patchType).Patch(); } internal static void RequestCampfireShuffle(int campfireViewId) { if (!((Object)(object)runtime == (Object)null)) { runtime.RequestCampfireShuffle(campfireViewId); } } internal static void HandleSwapEvent(EventData photonEvent) { if (photonEvent == null || photonEvent.Code != 194 || !(photonEvent.CustomData is byte[] array) || array.Length < 9) { return; } int offset = 0; byte b = array[offset++]; if (b != 1) { return; } int num = ReadInt32(array, ref offset); int num2 = ReadInt32(array, ref offset); if (num <= 0 || num2 <= 0 || array.Length != 9 + num2 * 8) { return; } List list = new List(num2); for (int i = 0; i < num2; i++) { int num3 = ReadInt32(array, ref offset); int num4 = ReadInt32(array, ref offset); if (num3 <= 0 || num4 <= 0 || num3 == num4) { return; } list.Add(new PairActors { CarrierActor = num3, RiderActor = num4 }); } ApplyAssignment(list); } internal static bool TryShuffleAndBroadcast(int campfireViewId) { if (!PhotonNetwork.InRoom || !PhotonNetwork.IsMasterClient || campfireViewId <= 0) { return false; } if (!TryGetCurrentPlayersAndPairs(out var characters, out var pairs)) { return false; } if (characters.Count < 2 || characters.Count % 2 != 0) { return false; } List newPairs; if (characters.Count == 2) { PairActors pairActors = pairs[0]; newPairs = new List { new PairActors { CarrierActor = pairActors.RiderActor, RiderActor = pairActors.CarrierActor } }; } else if (!TryCreateRandomGlobalPairs(characters, pairs, out newPairs)) { return false; } if (!ApplyAssignment(newPairs)) { return false; } BroadcastAssignment(campfireViewId, newPairs); return true; } internal static void RemovePairsForActor(int actorNumber) { if (actorNumber <= 0 || LockedRiderToCarrier.Count == 0) { return; } List list = null; foreach (KeyValuePair item in LockedRiderToCarrier) { if (item.Key == actorNumber || item.Value == actorNumber) { if (list == null) { list = new List(); } list.Add(item.Key); } } if (list != null) { for (int i = 0; i < list.Count; i++) { LockedRiderToCarrier.Remove(list[i]); } } } internal static void ClearPairs() { LockedRiderToCarrier.Clear(); } private static bool TryGetCurrentPlayersAndPairs(out List characters, out List pairs) { characters = new List(); pairs = new List(); if (!PhotonNetwork.InRoom || PhotonNetwork.CurrentRoom == null) { return false; } Player[] playerList = PhotonNetwork.PlayerList; if (playerList == null || playerList.Length < 2 || playerList.Length % 2 != 0) { return false; } Dictionary dictionary = new Dictionary(); Character val2 = default(Character); foreach (Player val in playerList) { if (val == null) { return false; } if (!PlayerHandler.TryGetCharacter(val.ActorNumber, ref val2) || !CharacterReady(val2) || val2.data.dead) { return false; } characters.Add(val2); dictionary[val.ActorNumber] = val2; } HashSet hashSet = new HashSet(); for (int j = 0; j < characters.Count; j++) { Character val3 = characters[j]; int actorNumber = GetActorNumber(val3); if (actorNumber <= 0) { return false; } if (!hashSet.Contains(actorNumber)) { Character val4 = null; Character val5 = null; if ((Object)(object)val3.data.carriedPlayer != (Object)null) { val4 = val3; val5 = val3.data.carriedPlayer; } else if (val3.data.isCarried && (Object)(object)val3.data.carrier != (Object)null) { val4 = val3.data.carrier; val5 = val3; } if (!CharacterReady(val4) || !CharacterReady(val5) || (Object)(object)val4.data.carriedPlayer != (Object)(object)val5 || !val5.data.isCarried || (Object)(object)val5.data.carrier != (Object)(object)val4) { return false; } int actorNumber2 = GetActorNumber(val4); int actorNumber3 = GetActorNumber(val5); if (actorNumber2 <= 0 || actorNumber3 <= 0 || actorNumber2 == actorNumber3 || !dictionary.ContainsKey(actorNumber2) || !dictionary.ContainsKey(actorNumber3) || hashSet.Contains(actorNumber2) || hashSet.Contains(actorNumber3)) { return false; } hashSet.Add(actorNumber2); hashSet.Add(actorNumber3); pairs.Add(new PairActors { CarrierActor = actorNumber2, RiderActor = actorNumber3 }); } } return hashSet.Count == characters.Count && pairs.Count * 2 == characters.Count; } private static bool TryCreateRandomGlobalPairs(List characters, List oldPairs, out List newPairs) { newPairs = null; if (characters == null || oldPairs == null || characters.Count < 4 || characters.Count % 2 != 0) { return false; } List list = new List(characters.Count); for (int i = 0; i < characters.Count; i++) { int actorNumber = GetActorNumber(characters[i]); if (actorNumber <= 0) { return false; } list.Add(actorNumber); } HashSet hashSet = new HashSet(); for (int j = 0; j < oldPairs.Count; j++) { PairActors pairActors = oldPairs[j]; hashSet.Add(MakePairKey(pairActors.CarrierActor, pairActors.RiderActor)); } for (int k = 0; k < 128; k++) { List list2 = new List(list); Shuffle(list2); bool flag = true; List list3 = new List(list2.Count / 2); for (int l = 0; l < list2.Count; l += 2) { int num = list2[l]; int num2 = list2[l + 1]; if (hashSet.Contains(MakePairKey(num, num2))) { flag = false; break; } list3.Add(new PairActors { CarrierActor = num, RiderActor = num2 }); } if (flag) { newPairs = list3; return true; } } return false; } private static void Shuffle(List values) { for (int num = values.Count - 1; num > 0; num--) { int index; lock (random) { index = random.Next(0, num + 1); } int value = values[num]; values[num] = values[index]; values[index] = value; } } private static long MakePairKey(int firstActor, int secondActor) { int num = Mathf.Min(firstActor, secondActor); int num2 = Mathf.Max(firstActor, secondActor); return ((long)num << 32) | (uint)num2; } private static bool ApplyAssignment(List pairs) { //IL_01a7: Unknown result type (might be due to invalid IL or missing references) if (pairs == null || pairs.Count == 0) { return false; } Dictionary dictionary = new Dictionary(); HashSet hashSet = new HashSet(); Character val = default(Character); Character val2 = default(Character); for (int i = 0; i < pairs.Count; i++) { PairActors pairActors = pairs[i]; if (pairActors == null || pairActors.CarrierActor <= 0 || pairActors.RiderActor <= 0 || pairActors.CarrierActor == pairActors.RiderActor || hashSet.Contains(pairActors.CarrierActor) || hashSet.Contains(pairActors.RiderActor)) { return false; } if (!PlayerHandler.TryGetCharacter(pairActors.CarrierActor, ref val) || !PlayerHandler.TryGetCharacter(pairActors.RiderActor, ref val2) || !CharacterReady(val) || !CharacterReady(val2)) { return false; } hashSet.Add(pairActors.CarrierActor); hashSet.Add(pairActors.RiderActor); dictionary[pairActors.CarrierActor] = val; dictionary[pairActors.RiderActor] = val2; } List characters = new List(dictionary.Values); ClearCurrentCarriedStates(characters); LockedRiderToCarrier.Clear(); Latejoin.ClearPairs(); for (int j = 0; j < pairs.Count; j++) { PairActors pairActors2 = pairs[j]; Character val3 = dictionary[pairActors2.CarrierActor]; Character rider = dictionary[pairActors2.RiderActor]; if ((Object)(object)val3.refs.items != (Object)null) { val3.refs.items.EquipSlot(Optionable.None); } ApplyCarriedState(val3, rider); LockedRiderToCarrier[pairActors2.RiderActor] = pairActors2.CarrierActor; } return true; } private static void ClearCurrentCarriedStates(List characters) { if (characters == null) { return; } HashSet hashSet = new HashSet(); for (int i = 0; i < characters.Count; i++) { Character val = characters[i]; if (CharacterReady(val) && val.data.isCarried && !((Object)(object)val.data.carrier == (Object)null)) { int actorNumber = GetActorNumber(val); if (actorNumber > 0 && hashSet.Add(actorNumber)) { ClearCarriedState(val.data.carrier, val); } } } for (int j = 0; j < characters.Count; j++) { Character val2 = characters[j]; if (!CharacterReady(val2)) { continue; } Character carriedPlayer = val2.data.carriedPlayer; if (CharacterReady(carriedPlayer)) { int actorNumber2 = GetActorNumber(carriedPlayer); if (actorNumber2 > 0 && hashSet.Add(actorNumber2)) { ClearCarriedState(val2, carriedPlayer); } } } } private static void ClearCarriedState(Character carrier, Character rider) { if ((Object)(object)carrier == (Object)null || (Object)(object)rider == (Object)null || (Object)(object)carrier.data == (Object)null || (Object)(object)rider.data == (Object)null) { return; } if (rider.refs != null) { if ((Object)(object)rider.refs.ragdoll != (Object)null) { rider.refs.ragdoll.ToggleCollision(true); } if ((Object)(object)rider.refs.animator != (Object)null) { rider.refs.animator.SetBool("IsCarried", false); } } rider.data.isCarried = false; rider.data.carrier = null; if ((Object)(object)carrier.data.carriedPlayer == (Object)(object)rider) { carrier.data.carriedPlayer = null; } } private static void ApplyCarriedState(Character carrier, Character rider) { if ((Object)(object)carrier == (Object)null || (Object)(object)rider == (Object)null || (Object)(object)carrier.data == (Object)null || (Object)(object)rider.data == (Object)null) { return; } if (rider.refs != null) { if ((Object)(object)rider.refs.ragdoll != (Object)null) { rider.refs.ragdoll.ToggleCollision(false); } if ((Object)(object)rider.refs.animator != (Object)null) { rider.refs.animator.SetBool("IsCarried", true); } if ((Object)(object)rider.refs.afflictions != (Object)null) { rider.refs.afflictions.SubtractStatus((STATUSTYPE)14, 1f, true, false); rider.refs.afflictions.SubtractStatus((STATUSTYPE)11, 1f, true, false); } } rider.data.deathTimer = 0f; rider.data.passOutValue = 0f; rider.data.passedOutOnTheBeach = 0f; rider.data.fallSeconds = 0f; rider.data.passedOut = false; rider.data.fullyPassedOut = false; rider.data.ragdollControlClamp = 1f; rider.data.currentRagdollControll = 1f; rider.data.isCarried = true; rider.data.carrier = carrier; carrier.data.carriedPlayer = rider; } private static void BroadcastAssignment(int campfireViewId, List pairs) { //IL_009c: 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_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Expected O, but got Unknown //IL_00b0: Unknown result type (might be due to invalid IL or missing references) if (PhotonNetwork.InRoom && pairs != null && pairs.Count != 0) { byte[] array = new byte[9 + pairs.Count * 8]; int offset = 0; array[offset++] = 1; WriteInt32(array, ref offset, campfireViewId); WriteInt32(array, ref offset, pairs.Count); for (int i = 0; i < pairs.Count; i++) { PairActors pairActors = pairs[i]; WriteInt32(array, ref offset, pairActors.CarrierActor); WriteInt32(array, ref offset, pairActors.RiderActor); } RaiseEventOptions val = new RaiseEventOptions { Receivers = (ReceiverGroup)0 }; PhotonNetwork.RaiseEvent((byte)194, (object)array, val, SendOptions.SendReliable); } } private static bool CharacterReady(Character character) { return (Object)(object)character != (Object)null && (Object)(object)character.data != (Object)null && character.refs != null && (Object)(object)character.refs.carriying != (Object)null && (Object)(object)character.refs.ragdoll != (Object)null && (Object)(object)((MonoBehaviourPun)character).photonView != (Object)null && (Object)(object)character.player != (Object)null; } private static int GetActorNumber(Character character) { if ((Object)(object)character == (Object)null || (Object)(object)((MonoBehaviourPun)character).photonView == (Object)null || ((MonoBehaviourPun)character).photonView.Owner == null) { return -1; } return ((MonoBehaviourPun)character).photonView.Owner.ActorNumber; } private static bool IsLockedPair(Character carrier, Character rider) { if ((Object)(object)carrier == (Object)null || (Object)(object)rider == (Object)null) { return false; } int actorNumber = GetActorNumber(carrier); int actorNumber2 = GetActorNumber(rider); if (actorNumber <= 0 || actorNumber2 <= 0) { return false; } if (!LockedRiderToCarrier.TryGetValue(actorNumber2, out var value)) { return false; } return value == actorNumber; } private static bool ShouldAllowRelease(Character carrier, Character rider) { if ((Object)(object)carrier == (Object)null || (Object)(object)rider == (Object)null || (Object)(object)carrier.data == (Object)null || (Object)(object)rider.data == (Object)null) { return true; } if (carrier.data.dead || rider.data.dead) { return true; } if (!rider.data.isCarried) { return true; } if ((Object)(object)rider.data.carrier != (Object)(object)carrier) { return true; } if ((Object)(object)carrier.data.carriedPlayer != (Object)(object)rider) { return true; } return false; } private static void WriteInt32(byte[] buffer, ref int offset, int value) { buffer[offset++] = (byte)value; buffer[offset++] = (byte)(value >> 8); buffer[offset++] = (byte)(value >> 16); buffer[offset++] = (byte)(value >> 24); } private static int ReadInt32(byte[] buffer, ref int offset) { int result = buffer[offset] | (buffer[offset + 1] << 8) | (buffer[offset + 2] << 16) | (buffer[offset + 3] << 24); offset += 4; return result; } } public sealed class RolechangerRuntime : MonoBehaviourPunCallbacks, IOnEventCallback { private const float RetryInterval = 0.25f; private bool runtimeInitialized; private int pendingCampfireViewId = -1; private int lastProcessedCampfireViewId = -1; private float nextRetryTime; internal void InitializeRuntime() { if (!runtimeInitialized) { runtimeInitialized = true; SceneManager.sceneLoaded += OnSceneLoaded; } } internal void ShutdownRuntime() { if (runtimeInitialized) { SceneManager.sceneLoaded -= OnSceneLoaded; pendingCampfireViewId = -1; lastProcessedCampfireViewId = -1; runtimeInitialized = false; } } public override void OnEnable() { ((MonoBehaviourPunCallbacks)this).OnEnable(); } public override void OnDisable() { ((MonoBehaviourPunCallbacks)this).OnDisable(); } public void OnEvent(EventData photonEvent) { Rolechanger.HandleSwapEvent(photonEvent); } public override void OnLeftRoom() { pendingCampfireViewId = -1; lastProcessedCampfireViewId = -1; Rolechanger.ClearPairs(); } public override void OnPlayerLeftRoom(Player otherPlayer) { if (otherPlayer != null) { Rolechanger.RemovePairsForActor(otherPlayer.ActorNumber); } } public override void OnMasterClientSwitched(Player newMasterClient) { if (PhotonNetwork.IsMasterClient) { pendingCampfireViewId = -1; lastProcessedCampfireViewId = -1; } } private void OnSceneLoaded(Scene scene, LoadSceneMode mode) { pendingCampfireViewId = -1; lastProcessedCampfireViewId = -1; Rolechanger.ClearPairs(); } internal void RequestCampfireShuffle(int campfireViewId) { if (PhotonNetwork.InRoom && PhotonNetwork.IsMasterClient && campfireViewId > 0 && campfireViewId != lastProcessedCampfireViewId) { pendingCampfireViewId = campfireViewId; nextRetryTime = 0f; } } private void Update() { if (!runtimeInitialized || pendingCampfireViewId < 0 || !PhotonNetwork.InRoom || !PhotonNetwork.IsMasterClient) { return; } float realtimeSinceStartup = Time.realtimeSinceStartup; if (!(realtimeSinceStartup < nextRetryTime)) { nextRetryTime = realtimeSinceStartup + 0.25f; if (Rolechanger.TryShuffleAndBroadcast(pendingCampfireViewId)) { lastProcessedCampfireViewId = pendingCampfireViewId; pendingCampfireViewId = -1; } } } } public static class SeparateRole { [StructLayout(LayoutKind.Explicit)] private struct FloatIntUnion { [FieldOffset(0)] public float FloatValue; [FieldOffset(0)] public int IntValue; } private struct CarrierPitonProxyState { public Character Carrier; public Character Climber; public CharacterItems CarrierItems; public bool Applied; public Optionable OriginalSelectedSlot; public Optionable OriginalLastSelectedSlot; public int OriginalClimbingSpikeCount; } private struct ClimberPitonUiProxyState { public Character Climber; public bool Applied; public bool OriginalIsClimbing; public bool OriginalIsRopeClimbing; public bool OriginalIsVineClimbing; public bool OriginalSecondaryWasPressed; public bool OriginalSecondaryIsPressed; public bool OriginalSecondaryWasReleased; } private struct PitonUpdateProxyState { public CarrierPitonProxyState CarrierState; public ClimberPitonUiProxyState ClimberState; } private sealed class RemoteUpperBodyInput { public int SourceActor = -1; public int TargetActor = -1; public int Sequence = -1; public Vector2 MovementInput = Vector2.zero; public bool PrimaryHeld; public bool SecondaryHeld; public float ReceivedTime = -100f; } [HarmonyPatch(typeof(CharacterInput), "Sample", new Type[] { typeof(bool) })] private static class CharacterInput_Sample_Patch { [HarmonyPostfix] [HarmonyPriority(0)] private static void Postfix(CharacterInput __instance) { Character localCharacter = Character.localCharacter; if ((Object)(object)localCharacter == (Object)null || (Object)(object)localCharacter.input != (Object)(object)__instance) { return; } if (IsCarrier(localCharacter)) { ApplyClimberInputToCarrier(__instance, localCharacter); Character val = (((Object)(object)localCharacter.data != (Object)null) ? localCharacter.data.carriedPlayer : null); if ((Object)(object)val != (Object)null && (Object)(object)val.data != (Object)null && (val.data.isRopeClimbing || val.data.isVineClimbing)) { __instance.jumpWasPressed = false; __instance.jumpIsPressed = false; } } else if (IsClimber(localCharacter)) { if (__instance.interactWasPressed && !__instance.interactIsPressed) { __instance.interactIsPressed = true; } __instance.useSecondaryWasPressed = false; __instance.useSecondaryIsPressed = false; __instance.useSecondaryWasReleased = false; ClearClimberCharacterInput(__instance, localCharacter); } } } [HarmonyPatch(typeof(CharacterInput), "SelectSlotWasPressed")] private static class CharacterInput_SelectSlotWasPressed_Patch { [HarmonyPrefix] [HarmonyPriority(800)] private static bool Prefix(CharacterInput __instance, int key, ref bool __result) { Character localCharacter = Character.localCharacter; if ((Object)(object)localCharacter == (Object)null || (Object)(object)localCharacter.input != (Object)(object)__instance) { return true; } if (IsClimber(localCharacter)) { return true; } if (!IsCarrier(localCharacter)) { return true; } __result = false; return false; } } [HarmonyPatch(typeof(CharacterInput), "SelectSlotIsPressed")] private static class CharacterInput_SelectSlotIsPressed_Patch { [HarmonyPrefix] [HarmonyPriority(800)] private static bool Prefix(CharacterInput __instance, int key, ref bool __result) { Character localCharacter = Character.localCharacter; if ((Object)(object)localCharacter == (Object)null || (Object)(object)localCharacter.input != (Object)(object)__instance) { return true; } if (IsClimber(localCharacter)) { return true; } if (!IsCarrier(localCharacter)) { return true; } __result = false; return false; } } [HarmonyPatch(typeof(Interaction), "DoInteractableRaycasts")] private static class Interaction_DoInteractableRaycasts_CarrierOrigin_Patch { [HarmonyPrefix] [HarmonyPriority(800)] private static bool Prefix(Interaction __instance, ref IInteractible interactableResult, float overrideDistance, bool ignoreInteractable) { //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0085: 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_00d9: 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_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_0122: 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_023c: Unknown result type (might be due to invalid IL or missing references) //IL_023e: Unknown result type (might be due to invalid IL or missing references) //IL_024b: 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_025b: Unknown result type (might be due to invalid IL or missing references) //IL_0270: 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_02a9: 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_01ca: Unknown result type (might be due to invalid IL or missing references) //IL_030b: Unknown result type (might be due to invalid IL or missing references) //IL_0310: Unknown result type (might be due to invalid IL or missing references) //IL_0312: Unknown result type (might be due to invalid IL or missing references) //IL_0317: Unknown result type (might be due to invalid IL or missing references) //IL_0365: Unknown result type (might be due to invalid IL or missing references) //IL_036c: Unknown result type (might be due to invalid IL or missing references) //IL_0378: Unknown result type (might be due to invalid IL or missing references) //IL_037d: Unknown result type (might be due to invalid IL or missing references) Character localCharacter = Character.localCharacter; if ((Object)(object)__instance == (Object)null || (Object)(object)localCharacter == (Object)null || !localCharacter.IsLocal || !IsClimber(localCharacter) || (Object)(object)localCharacter.data == (Object)null) { return true; } Character carrier = localCharacter.data.carrier; if ((Object)(object)carrier == (Object)null || (Object)(object)carrier.data == (Object)null) { return true; } Vector3 lookDirection = localCharacter.data.lookDirection; if (((Vector3)(ref lookDirection)).sqrMagnitude < 1E-06f) { interactableResult = null; return false; } ((Vector3)(ref lookDirection)).Normalize(); float num = ((overrideDistance == -1f) ? __instance.distance : overrideDistance); if (TryGetStuckInteractable(localCharacter, carrier, lookDirection, out interactableResult)) { return false; } Vector3 head = carrier.Head; Ray val = default(Ray); ((Ray)(ref val))..ctor(head, lookDirection); int num2 = HelperFunctions.LineCheckAll(((Ray)(ref val)).origin, ((Ray)(ref val)).origin + ((Ray)(ref val)).direction * num, (LayerType)0, interactionRayHitCache, 0f, (QueryTriggerInteraction)2); IInteractible val2 = null; RaycastHit val3 = default(RaycastHit); ((RaycastHit)(ref val3)).distance = float.MaxValue; Item currentItem = localCharacter.data.currentItem; float num3 = num; Item val5 = default(Item); for (int i = 0; i < num2; i++) { RaycastHit val4 = interactionRayHitCache[i]; if (!((Object)(object)((RaycastHit)(ref val4)).collider == (Object)null) && !(((RaycastHit)(ref val4)).distance >= num3) && !IsPairCollider(((RaycastHit)(ref val4)).collider, localCharacter, carrier) && (!Item.TryGetItemFromCollider(((RaycastHit)(ref val4)).collider, ref val5) || !((Object)(object)val5 != (Object)null) || !((Object)(object)val5 == (Object)(object)currentItem))) { num3 = ((RaycastHit)(ref val4)).distance; val3 = val4; } } if ((Object)(object)((RaycastHit)(ref val3)).collider != (Object)null) { IInteractible componentInParent = ((Component)((RaycastHit)(ref val3)).collider).GetComponentInParent(); if (componentInParent != null && (ignoreInteractable || componentInParent.IsInteractible(localCharacter))) { val2 = componentInParent; } } if (val2 == null) { float num4 = float.MaxValue; int num5 = Physics.SphereCastNonAlloc(head + lookDirection * (__instance.area / 2f), __instance.area, lookDirection, __instance.sphereCastResults, Mathf.Min(((RaycastHit)(ref val3)).distance, num), LayerMask.op_Implicit(HelperFunctions.GetMask((LayerType)0)), (QueryTriggerInteraction)2); int num6 = Mathf.Min(num5, __instance.sphereCastResults.Length); Item val7 = default(Item); for (int j = 0; j < num6; j++) { RaycastHit val6 = __instance.sphereCastResults[j]; if ((Object)(object)((RaycastHit)(ref val6)).collider == (Object)null || IsPairCollider(((RaycastHit)(ref val6)).collider, localCharacter, carrier) || (Item.TryGetItemFromCollider(((RaycastHit)(ref val6)).collider, ref val7) && (Object)(object)val7 != (Object)null && (Object)(object)val7 == (Object)(object)currentItem)) { continue; } float num7 = Vector3.Angle(((RaycastHit)(ref val6)).point - head, lookDirection); if (num7 >= num4) { continue; } IInteractible componentInParent2 = ((Component)((RaycastHit)(ref val6)).collider).GetComponentInParent(); if (componentInParent2 != null && (ignoreInteractable || componentInParent2.IsInteractible(localCharacter))) { RaycastHit val8 = HelperFunctions.LineCheck(((Ray)(ref val)).origin, ((RaycastHit)(ref val6)).point, (LayerType)1, 0f, (QueryTriggerInteraction)2); if (!((Object)(object)((RaycastHit)(ref val8)).collider != (Object)null) || ((Component)((RaycastHit)(ref val8)).collider).GetComponentInParent() == componentInParent2) { num4 = num7; val2 = componentInParent2; } } } } interactableResult = val2; return false; } } [HarmonyPatch(typeof(CharacterItems), "UpdateClimbingSpikeUse")] private static class CharacterItems_UpdateClimbingSpikeUse_PitonProxyPatch { [HarmonyPrefix] [HarmonyPriority(800)] private static bool Prefix(CharacterItems __instance, out PitonUpdateProxyState __state) { __state = default(PitonUpdateProxyState); Character val = ResolveCharacter((Component)(object)__instance); if ((Object)(object)val == (Object)null) { return true; } if (IsClimber(val)) { if (!val.IsLocal) { return false; } __state.ClimberState = BeginClimberPitonUiProxy(__instance); return true; } if (IsCarrier(val)) { if (!val.IsLocal) { return false; } __state.CarrierState = BeginCarrierPitonProxy(__instance); return true; } return true; } [HarmonyFinalizer] [HarmonyPriority(0)] private static Exception Finalizer(Exception __exception, PitonUpdateProxyState __state) { EndClimberPitonUiProxy(__state.ClimberState); EndCarrierPitonProxy(__state.CarrierState); return __exception; } } [HarmonyPatch(typeof(CharacterItems), "HammerClimbingSpike")] private static class CharacterItems_HammerClimbingSpike_ClimberUiOnlyPatch { [HarmonyPrefix] [HarmonyPriority(800)] private static bool Prefix(CharacterItems __instance) { Character val = ResolveCharacter((Component)(object)__instance); if ((Object)(object)val == (Object)null) { return true; } if (IsClimber(val)) { return false; } return true; } } [HarmonyPatch(typeof(UI_UseItemProgress), "UpdateFillAmount")] private static class UI_UseItemProgress_CarrierPitonSuppressPatch { [HarmonyPrefix] [HarmonyPriority(800)] private static bool Prefix(UI_UseItemProgress __instance, ref bool __result) { Character localCharacter = Character.localCharacter; if ((Object)(object)localCharacter == (Object)null || !IsCarrier(localCharacter) || localCharacter.refs == null || (Object)(object)localCharacter.refs.items == (Object)null || localCharacter.refs.items.climbingSpikeCastProgress <= 0f) { return true; } Item val = (((Object)(object)localCharacter.data != (Object)null) ? localCharacter.data.currentItem : null); if ((Object)(object)val != (Object)null && val.shouldShowCastProgress && val.progress > 0f) { __instance.fill.fillAmount = val.progress; __result = true; return false; } if ((Object)(object)Interaction.instance != (Object)null && Interaction.instance.currentHeldInteractible != null && Interaction.instance.constantInteractableProgress > 0f) { __instance.fill.fillAmount = Interaction.instance.constantInteractableProgress; __result = true; return false; } __result = false; return false; } } [HarmonyPatch(typeof(ClimbHandle), "Interact", new Type[] { typeof(Character) })] private static class ClimbHandle_Interact_CarrierPitonGrabPatch { [HarmonyPrefix] [HarmonyPriority(800)] private static bool Prefix(ClimbHandle __instance, Character interactor) { if ((Object)(object)__instance == (Object)null || (Object)(object)interactor == (Object)null || __instance.isPickaxe || !IsClimber(interactor)) { return true; } if (!interactor.IsLocal) { return false; } if ((Object)(object)__instance.hanger != (Object)null) { return false; } return !RequestCarrierPitonGrab(__instance, interactor); } } [HarmonyPatch(typeof(Player), "EmptySlot", new Type[] { typeof(Optionable) })] private static class Player_EmptySlot_PitonProxyPatch { [HarmonyPrefix] [HarmonyPriority(800)] private static bool Prefix(Player __instance, Optionable slot) { //IL_005d: Unknown result type (might be due to invalid IL or missing references) if (!pitonProxyActive || (Object)(object)pitonProxyCarrier == (Object)null || (Object)(object)pitonProxyClimber == (Object)null || (Object)(object)pitonProxyCarrier.player != (Object)(object)__instance || (Object)(object)pitonProxyClimber.player == (Object)null) { return true; } pitonProxyClimber.player.EmptySlot(slot); if (pitonProxyClimber.refs != null && (Object)(object)pitonProxyClimber.refs.items != (Object)null) { pitonProxyClimber.refs.items.UpdateClimbingSpikeCount(pitonProxyClimber.player.itemSlots); } if ((Object)(object)((MonoBehaviourPun)pitonProxyClimber).photonView != (Object)null) { ((MonoBehaviourPun)pitonProxyClimber).photonView.RPC("EquipSlotRpc", (RpcTarget)0, new object[2] { -1, -1 }); } if (pitonProxyClimber.refs != null && (Object)(object)pitonProxyClimber.refs.afflictions != (Object)null) { pitonProxyClimber.refs.items.RefreshAllCharacterCarryWeight(); } if ((Object)(object)pitonProxyClimber.data != (Object)null) { pitonProxyClimber.data.lastConsumedItem = Time.time; } return false; } } [HarmonyPatch(typeof(CharacterItems), "DoUsing")] private static class CharacterItems_DoUsing_RolePatch { [HarmonyPrefix] [HarmonyPriority(800)] private static bool Prefix(CharacterItems __instance) { Character character = ResolveCharacter((Component)(object)__instance); return !IsCarrier(character); } } [HarmonyPatch(typeof(CharacterItems), "DoDropping")] private static class CharacterItems_DoDropping_RolePatch { [HarmonyPrefix] [HarmonyPriority(800)] private static bool Prefix(CharacterItems __instance) { Character character = ResolveCharacter((Component)(object)__instance); return !IsCarrier(character); } } [HarmonyPatch(typeof(CharacterItems), "DoSwitching")] private static class CharacterItems_DoSwitching_RolePatch { [HarmonyPrefix] [HarmonyPriority(800)] private static bool Prefix(CharacterItems __instance) { Character val = ResolveCharacter((Component)(object)__instance); if (IsCarrier(val)) { return false; } if (!IsClimber(val) || (Object)(object)val.data == (Object)null) { return true; } Character carrier = val.data.carrier; if ((Object)(object)carrier == (Object)null || (Object)(object)carrier.data == (Object)null) { return true; } return !carrier.data.isClimbing; } } [HarmonyPatch(typeof(Character), "CheckMovement")] private static class Character_CheckMovement_Patch { [HarmonyPostfix] [HarmonyPriority(0)] private static void Postfix(Character __instance, ref bool __result) { if (IsClimber(__instance)) { __result = false; } } } [HarmonyPatch(typeof(CharacterClimbing), "CanClimb")] private static class CharacterClimbing_CanClimb_Patch { [HarmonyPostfix] [HarmonyPriority(0)] private static void Postfix(CharacterClimbing __instance, ref bool __result) { Character character = ResolveCharacter((Component)(object)__instance); if (IsClimber(character)) { __result = false; } } } [HarmonyPatch(typeof(CharacterClimbing), "StartClimbRpc", new Type[] { typeof(Vector3), typeof(Vector3) })] private static class CharacterClimbing_StartClimbRpc_Patch { [HarmonyPrefix] [HarmonyPriority(800)] private static bool Prefix(CharacterClimbing __instance) { Character character = ResolveCharacter((Component)(object)__instance); return !IsClimber(character); } } [HarmonyPatch(typeof(CharacterMovement), "JumpRpc", new Type[] { typeof(bool) })] private static class CharacterMovement_JumpRpc_Patch { [HarmonyPrefix] [HarmonyPriority(800)] private static bool Prefix(CharacterMovement __instance) { Character character = ResolveCharacter((Component)(object)__instance); return !IsClimber(character); } } [HarmonyPatch(typeof(CharacterRopeHandling), "Update")] private static class CharacterRopeHandling_Update_TransportPatch { [HarmonyPrefix] [HarmonyPriority(800)] private static bool Prefix(CharacterRopeHandling __instance) { Character val = ResolveCharacter((Component)(object)__instance); if (!IsClimber(val)) { return true; } if (val.IsLocal && (Object)(object)val.data != (Object)null && val.data.isRopeClimbing && (Object)(object)val.input != (Object)null && val.input.jumpWasPressed && (Object)(object)((MonoBehaviourPun)val).photonView != (Object)null) { ((MonoBehaviourPun)val).photonView.RPC("StopRopeClimbingRpc", (RpcTarget)0, new object[1] { true }); } return false; } } [HarmonyPatch(typeof(CharacterRopeHandling), "FixedUpdate")] private static class CharacterRopeHandling_FixedUpdate_TransportPatch { [HarmonyPrefix] [HarmonyPriority(800)] private static bool Prefix(CharacterRopeHandling __instance) { Character character = ResolveCharacter((Component)(object)__instance); return !IsClimber(character); } } [HarmonyPatch(typeof(CharacterRopeHandling), "GrabRopeRpc", new Type[] { typeof(PhotonView), typeof(int) })] private static class CharacterRopeHandling_GrabRopeRpc_TransportPatch { [HarmonyPostfix] [HarmonyPriority(0)] private static void Postfix(CharacterRopeHandling __instance, PhotonView __0, int __1) { Character val = ResolveCharacter((Component)(object)__instance); if (IsClimber(val) && !((Object)(object)val.data == (Object)null)) { Character carrier = val.data.carrier; if (!((Object)(object)carrier == (Object)null) && carrier.IsLocal && !((Object)(object)carrier.data == (Object)null) && !((Object)(object)((MonoBehaviourPun)carrier).photonView == (Object)null) && !((Object)(object)__0 == (Object)null) && (!carrier.data.isRopeClimbing || !((Object)(object)carrier.data.heldRope == (Object)(object)val.data.heldRope))) { ((MonoBehaviourPun)carrier).photonView.RPC("GrabRopeRpc", (RpcTarget)0, new object[2] { __0, __1 }); } } } } [HarmonyPatch(typeof(CharacterRopeHandling), "StopRopeClimbingRpc", new Type[] { typeof(bool) })] private static class CharacterRopeHandling_StopRopeClimbingRpc_TransportPatch { [HarmonyPostfix] [HarmonyPriority(0)] private static void Postfix(CharacterRopeHandling __instance, bool __0) { Character val = ResolveCharacter((Component)(object)__instance); if ((Object)(object)val == (Object)null || (Object)(object)val.data == (Object)null) { return; } if (IsClimber(val)) { Character carrier = val.data.carrier; if ((Object)(object)carrier != (Object)null && carrier.IsLocal && (Object)(object)carrier.data != (Object)null && carrier.data.isRopeClimbing && (Object)(object)((MonoBehaviourPun)carrier).photonView != (Object)null) { ((MonoBehaviourPun)carrier).photonView.RPC("StopRopeClimbingRpc", (RpcTarget)0, new object[1] { __0 }); } } else if (IsCarrier(val) && val.IsLocal) { Character carriedPlayer = val.data.carriedPlayer; if ((Object)(object)carriedPlayer != (Object)null && (Object)(object)carriedPlayer.data != (Object)null && carriedPlayer.data.isRopeClimbing && (Object)(object)((MonoBehaviourPun)carriedPlayer).photonView != (Object)null) { ((MonoBehaviourPun)carriedPlayer).photonView.RPC("StopRopeClimbingRpc", (RpcTarget)0, new object[1] { __0 }); } } } } [HarmonyPatch(typeof(CharacterVineClimbing), "Update")] private static class CharacterVineClimbing_Update_TransportPatch { [HarmonyPrefix] [HarmonyPriority(800)] private static bool Prefix(CharacterVineClimbing __instance) { Character val = ResolveCharacter((Component)(object)__instance); if (!IsClimber(val)) { return true; } if (val.IsLocal && (Object)(object)val.data != (Object)null && val.data.isVineClimbing && (Object)(object)val.input != (Object)null && val.input.jumpWasPressed && (Object)(object)((MonoBehaviourPun)val).photonView != (Object)null) { ((MonoBehaviourPun)val).photonView.RPC("StopVineClimbingRpc", (RpcTarget)0, new object[1] { true }); } return false; } } [HarmonyPatch(typeof(CharacterVineClimbing), "FixedUpdate")] private static class CharacterVineClimbing_FixedUpdate_TransportPatch { [HarmonyPrefix] [HarmonyPriority(800)] private static bool Prefix(CharacterVineClimbing __instance) { Character character = ResolveCharacter((Component)(object)__instance); return !IsClimber(character); } } [HarmonyPatch(typeof(CharacterVineClimbing), "GrabVineRpc", new Type[] { typeof(PhotonView), typeof(int) })] private static class CharacterVineClimbing_GrabVineRpc_TransportPatch { [HarmonyPostfix] [HarmonyPriority(0)] private static void Postfix(CharacterVineClimbing __instance, PhotonView __0, int __1) { Character val = ResolveCharacter((Component)(object)__instance); if (IsClimber(val) && !((Object)(object)val.data == (Object)null)) { Character carrier = val.data.carrier; if (!((Object)(object)carrier == (Object)null) && carrier.IsLocal && !((Object)(object)carrier.data == (Object)null) && !((Object)(object)((MonoBehaviourPun)carrier).photonView == (Object)null) && !((Object)(object)__0 == (Object)null) && (!carrier.data.isVineClimbing || !((Object)(object)carrier.data.heldVine == (Object)(object)val.data.heldVine))) { ((MonoBehaviourPun)carrier).photonView.RPC("GrabVineRpc", (RpcTarget)0, new object[2] { __0, __1 }); } } } } [HarmonyPatch(typeof(CharacterVineClimbing), "StopVineClimbingRpc", new Type[] { typeof(bool) })] private static class CharacterVineClimbing_StopVineClimbingRpc_TransportPatch { [HarmonyPostfix] [HarmonyPriority(0)] private static void Postfix(CharacterVineClimbing __instance, bool __0) { Character val = ResolveCharacter((Component)(object)__instance); if ((Object)(object)val == (Object)null || (Object)(object)val.data == (Object)null) { return; } if (IsClimber(val)) { Character carrier = val.data.carrier; if ((Object)(object)carrier != (Object)null && carrier.IsLocal && (Object)(object)carrier.data != (Object)null && carrier.data.isVineClimbing && (Object)(object)((MonoBehaviourPun)carrier).photonView != (Object)null) { ((MonoBehaviourPun)carrier).photonView.RPC("StopVineClimbingRpc", (RpcTarget)0, new object[1] { __0 }); } } else if (IsCarrier(val) && val.IsLocal) { Character carriedPlayer = val.data.carriedPlayer; if ((Object)(object)carriedPlayer != (Object)null && (Object)(object)carriedPlayer.data != (Object)null && carriedPlayer.data.isVineClimbing && (Object)(object)((MonoBehaviourPun)carriedPlayer).photonView != (Object)null) { ((MonoBehaviourPun)carriedPlayer).photonView.RPC("StopVineClimbingRpc", (RpcTarget)0, new object[1] { __0 }); } } } } [HarmonyPatch(typeof(CharacterCarrying), "Update")] private static class CharacterCarrying_PassOutLock_Patch { [HarmonyPrefix] [HarmonyPriority(800)] private static bool Prefix(CharacterCarrying __instance) { Character val = ResolveCharacter((Component)(object)__instance); if (!IsCarrier(val)) { return true; } Character carriedPlayer = val.data.carriedPlayer; if ((Object)(object)carriedPlayer == (Object)null || (Object)(object)carriedPlayer.data == (Object)null) { return true; } if (val.data.dead || carriedPlayer.data.dead) { return true; } if (val.data.passedOut || val.data.fullyPassedOut || carriedPlayer.data.passedOut || carriedPlayer.data.fullyPassedOut) { return false; } return true; } } private const string HarmonyId = "com.peak.coopmod.separaterole"; private const byte UpperBodyInputEventCode = 185; private const byte PitonGrabEventCode = 198; private const int PitonGrabPayloadLength = 12; private const float RemoteInputTimeout = 0.5f; private const float RemoteHeldInputTimeout = 3f; private const float InputSendInterval = 1f / 30f; private const float InputHeartbeatInterval = 0.15f; private const int InputPayloadLength = 22; private static readonly RaycastHit[] interactionRayHitCache = (RaycastHit[])(object)new RaycastHit[64]; private static Harmony harmony; private static SeparateRoleRuntime runtime; public static ConfigEntry HideCarrierBody; public static ConfigEntry HideCarrierHead; public static ConfigEntry HideCarrierFace; public static ConfigEntry HideCarrierHat; public static ConfigEntry HideCarrierSash; public static ConfigEntry HideCarrierCostumes; public static ConfigEntry HideCarrierSpecialRenderers; private static Character visibilityCarrier; private static float nextVisibilityRefreshTime; private static RemoteUpperBodyInput remoteInput = new RemoteUpperBodyInput(); private static byte pendingActionEdges; private static bool pitonProxyActive; private static Character pitonProxyCarrier; private static Character pitonProxyClimber; internal static byte PitonGrabEventCodeLocal => 198; internal static int PitonGrabPayloadLengthLocal => 12; internal static byte UpperBodyInputEventCodeLocal => 185; internal static float InputSendIntervalLocal => 1f / 30f; internal static float InputHeartbeatIntervalLocal => 0.15f; internal static int InputPayloadLengthLocal => 22; public static void Initialize(CoopMod plugin) { //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Expected O, but got Unknown if (harmony == null && !((Object)(object)plugin == (Object)null)) { HideCarrierBody = ((BaseUnityPlugin)plugin).Config.Bind("Climber View", "Hide Carrier Body", true, "등반자 화면에서 운반자의 몸통, 팔, 다리와 하체 의상을 숨깁니다. PEAK에서는 몸통/팔/다리가 하나의 스킨드 메시로 묶여 있습니다."); HideCarrierHead = ((BaseUnityPlugin)plugin).Config.Bind("Climber View", "Hide Carrier Head", true, "등반자 화면에서 운반자의 머리 메시를 숨깁니다."); HideCarrierFace = ((BaseUnityPlugin)plugin).Config.Bind("Climber View", "Hide Carrier Face", true, "등반자 화면에서 운반자의 눈, 입, 얼굴 액세서리를 숨깁니다."); HideCarrierHat = ((BaseUnityPlugin)plugin).Config.Bind("Climber View", "Hide Carrier Hat", true, "등반자 화면에서 운반자의 모자를 숨깁니다."); HideCarrierSash = ((BaseUnityPlugin)plugin).Config.Bind("Climber View", "Hide Carrier Sash", true, "등반자 화면에서 운반자의 띠/새시를 숨깁니다."); HideCarrierCostumes = ((BaseUnityPlugin)plugin).Config.Bind("Climber View", "Hide Carrier Costumes", true, "등반자 화면에서 운반자의 추가 코스튬 렌더러를 숨깁니다."); HideCarrierSpecialRenderers = ((BaseUnityPlugin)plugin).Config.Bind("Climber View", "Hide Carrier Special Renderers", true, "등반자 화면에서 운반자의 블라인드, 치킨, 스켈레톤 등 특수 렌더러를 숨깁니다."); harmony = new Harmony("com.peak.coopmod.separaterole"); Patch(typeof(CharacterInput_Sample_Patch)); Patch(typeof(CharacterInput_SelectSlotWasPressed_Patch)); Patch(typeof(CharacterInput_SelectSlotIsPressed_Patch)); Patch(typeof(Interaction_DoInteractableRaycasts_CarrierOrigin_Patch)); Patch(typeof(CharacterItems_DoUsing_RolePatch)); Patch(typeof(CharacterItems_UpdateClimbingSpikeUse_PitonProxyPatch)); Patch(typeof(CharacterItems_HammerClimbingSpike_ClimberUiOnlyPatch)); Patch(typeof(UI_UseItemProgress_CarrierPitonSuppressPatch)); Patch(typeof(ClimbHandle_Interact_CarrierPitonGrabPatch)); Patch(typeof(Player_EmptySlot_PitonProxyPatch)); Patch(typeof(CharacterItems_DoDropping_RolePatch)); Patch(typeof(CharacterItems_DoSwitching_RolePatch)); Patch(typeof(Character_CheckMovement_Patch)); Patch(typeof(CharacterClimbing_CanClimb_Patch)); Patch(typeof(CharacterClimbing_StartClimbRpc_Patch)); Patch(typeof(CharacterMovement_JumpRpc_Patch)); Patch(typeof(CharacterRopeHandling_Update_TransportPatch)); Patch(typeof(CharacterRopeHandling_FixedUpdate_TransportPatch)); Patch(typeof(CharacterRopeHandling_GrabRopeRpc_TransportPatch)); Patch(typeof(CharacterRopeHandling_StopRopeClimbingRpc_TransportPatch)); Patch(typeof(CharacterVineClimbing_Update_TransportPatch)); Patch(typeof(CharacterVineClimbing_FixedUpdate_TransportPatch)); Patch(typeof(CharacterVineClimbing_GrabVineRpc_TransportPatch)); Patch(typeof(CharacterVineClimbing_StopVineClimbingRpc_TransportPatch)); Patch(typeof(CharacterCarrying_PassOutLock_Patch)); runtime = ((Component)plugin).gameObject.GetComponent(); if ((Object)(object)runtime == (Object)null) { runtime = ((Component)plugin).gameObject.AddComponent(); } runtime.Activate(); ResetRemoteInput(); visibilityCarrier = null; nextVisibilityRefreshTime = 0f; } } public static void Shutdown() { if ((Object)(object)runtime != (Object)null) { runtime.Deactivate(); Object.Destroy((Object)(object)runtime); runtime = null; } if (harmony != null) { harmony.UnpatchSelf(); harmony = null; } RestoreCarrierVisibility(); HideCarrierBody = null; HideCarrierHead = null; HideCarrierFace = null; HideCarrierHat = null; HideCarrierSash = null; HideCarrierCostumes = null; HideCarrierSpecialRenderers = null; ResetRemoteInput(); } private static void Patch(Type patchType) { harmony.CreateClassProcessor(patchType).Patch(); } private static Character ResolveCharacter(Component component) { if ((Object)(object)component == (Object)null) { return null; } Character component2 = component.GetComponent(); if ((Object)(object)component2 != (Object)null) { return component2; } return component.GetComponentInParent(); } public static bool IsCarrier(Character character) { if ((Object)(object)character == (Object)null || (Object)(object)character.data == (Object)null) { return false; } Character carriedPlayer = character.data.carriedPlayer; if ((Object)(object)carriedPlayer == (Object)null || (Object)(object)carriedPlayer.data == (Object)null) { return false; } return carriedPlayer.data.isCarried && (Object)(object)carriedPlayer.data.carrier == (Object)(object)character; } public static bool IsClimber(Character character) { if ((Object)(object)character == (Object)null || (Object)(object)character.data == (Object)null || !character.data.isCarried) { return false; } Character carrier = character.data.carrier; if ((Object)(object)carrier == (Object)null || (Object)(object)carrier.data == (Object)null) { return false; } return (Object)(object)carrier.data.carriedPlayer == (Object)(object)character; } private static bool IsCarrierMovementAuthorityActive(Character character) { return (Object)(object)character != (Object)null && (Object)(object)character.data != (Object)null && (character.data.isClimbing || character.data.isRopeClimbing || character.data.isVineClimbing); } private static bool CanClimberSendInput(Character character) { return (Object)(object)character != (Object)null && (Object)(object)character.data != (Object)null && IsClimber(character) && !character.data.dead && !character.data.passedOut && !character.data.fullyPassedOut; } private static bool CanCarrierReceiveInput(Character character) { return (Object)(object)character != (Object)null && (Object)(object)character.data != (Object)null && IsCarrier(character) && !character.data.dead && !character.data.passedOut && !character.data.fullyPassedOut; } private static bool CanUseGameplayInput() { if ((Object)(object)GUIManager.instance == (Object)null) { return false; } return !GUIManager.instance.windowBlockingInput && !GUIManager.instance.wheelActive; } private static int GetActorNumber(Character character) { if ((Object)(object)character == (Object)null || (Object)(object)((MonoBehaviourPun)character).photonView == (Object)null || ((MonoBehaviourPun)character).photonView.Owner == null) { return -1; } return ((MonoBehaviourPun)character).photonView.Owner.ActorNumber; } private static void ClearClimberCharacterInput(CharacterInput input, Character character) { //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)input == (Object)null)) { bool flag = (Object)(object)character != (Object)null && (Object)(object)character.data != (Object)null && (character.data.isRopeClimbing || character.data.isVineClimbing); bool jumpWasPressed = flag && input.jumpWasPressed; bool jumpIsPressed = flag && input.jumpIsPressed; input.movementInput = Vector2.zero; input.jumpWasPressed = jumpWasPressed; input.jumpIsPressed = jumpIsPressed; input.sprintWasPressed = false; input.sprintIsPressed = false; input.sprintToggleWasPressed = false; input.sprintToggleIsPressed = false; input.crouchWasPressed = false; input.crouchIsPressed = false; input.crouchToggleWasPressed = false; } } private static void WriteInt32(byte[] buffer, ref int offset, int value) { buffer[offset++] = (byte)value; buffer[offset++] = (byte)(value >> 8); buffer[offset++] = (byte)(value >> 16); buffer[offset++] = (byte)(value >> 24); } private static int ReadInt32(byte[] buffer, ref int offset) { int result = buffer[offset] | (buffer[offset + 1] << 8) | (buffer[offset + 2] << 16) | (buffer[offset + 3] << 24); offset += 4; return result; } private static void WriteSingle(byte[] buffer, ref int offset, float value) { FloatIntUnion floatIntUnion = new FloatIntUnion { FloatValue = value }; WriteInt32(buffer, ref offset, floatIntUnion.IntValue); } private static float ReadSingle(byte[] buffer, ref int offset) { FloatIntUnion floatIntUnion = new FloatIntUnion { IntValue = ReadInt32(buffer, ref offset) }; return floatIntUnion.FloatValue; } private static void ResetRemoteInput() { remoteInput = new RemoteUpperBodyInput(); pendingActionEdges = 0; pitonProxyActive = false; pitonProxyCarrier = null; pitonProxyClimber = null; } private static bool RemoteInputIsValid(Character carrier) { if (!CanCarrierReceiveInput(carrier)) { return false; } if (Time.realtimeSinceStartup - remoteInput.ReceivedTime > 0.5f) { return false; } int actorNumber = GetActorNumber(carrier); Character carriedPlayer = carrier.data.carriedPlayer; int actorNumber2 = GetActorNumber(carriedPlayer); return actorNumber > 0 && actorNumber2 > 0 && remoteInput.TargetActor == actorNumber && remoteInput.SourceActor == actorNumber2; } private static bool RemoteHeldInputIsValid(Character carrier) { if (!CanCarrierReceiveInput(carrier)) { return false; } if (Time.realtimeSinceStartup - remoteInput.ReceivedTime > 3f) { return false; } int actorNumber = GetActorNumber(carrier); Character carriedPlayer = carrier.data.carriedPlayer; int actorNumber2 = GetActorNumber(carriedPlayer); return actorNumber > 0 && actorNumber2 > 0 && remoteInput.TargetActor == actorNumber && remoteInput.SourceActor == actorNumber2; } private static void ApplyClimberInputToCarrier(CharacterInput input, Character carrier) { //IL_003b: 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) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)input == (Object)null || (Object)(object)carrier == (Object)null) { return; } bool flag = RemoteInputIsValid(carrier); bool flag2 = RemoteHeldInputIsValid(carrier); byte b = pendingActionEdges; pendingActionEdges = 0; input.lookInput = Vector2.zero; input.interactWasPressed = false; input.interactIsPressed = false; input.interactWasReleased = false; input.usePrimaryWasPressed = false; input.usePrimaryIsPressed = false; input.usePrimaryWasReleased = false; input.useSecondaryWasPressed = false; input.useSecondaryIsPressed = false; input.useSecondaryWasReleased = false; input.dropWasPressed = false; input.dropIsPressed = false; input.dropWasReleased = false; input.selectSlotForwardWasPressed = false; input.selectSlotBackwardWasPressed = false; input.unselectSlotWasPressed = false; input.selectBackpackWasPressed = false; input.pingWasPressed = false; input.emoteIsPressed = false; input.spectateLeftWasPressed = false; input.spectateRightWasPressed = false; if (!((Object)(object)carrier.data == (Object)null)) { Character carriedPlayer = carrier.data.carriedPlayer; if ((Object)(object)carriedPlayer != (Object)null && (Object)(object)carriedPlayer.data != (Object)null) { carrier.data.lookValues = carriedPlayer.data.lookValues; } if (IsCarrierMovementAuthorityActive(carrier)) { input.movementInput = (flag ? remoteInput.MovementInput : Vector2.zero); } if (flag) { input.usePrimaryWasPressed = (b & 1) != 0; input.usePrimaryIsPressed = flag2 && remoteInput.PrimaryHeld; input.usePrimaryWasReleased = (b & 2) != 0; input.useSecondaryWasPressed = (b & 4) != 0; input.useSecondaryIsPressed = flag2 && remoteInput.SecondaryHeld; input.useSecondaryWasReleased = (b & 8) != 0; } } } private static bool RequestCarrierPitonGrab(ClimbHandle handle, Character climber) { if ((Object)(object)runtime == (Object)null || (Object)(object)handle == (Object)null || (Object)(object)climber == (Object)null || !climber.IsLocal || !IsClimber(climber) || (Object)(object)climber.data == (Object)null || handle.isPickaxe) { return false; } Character carrier = climber.data.carrier; if ((Object)(object)carrier == (Object)null || (Object)(object)carrier.data == (Object)null) { return false; } PhotonView component = ((Component)handle).GetComponent(); if ((Object)(object)component == (Object)null || component.ViewID <= 0) { return false; } runtime.SendPitonGrabRequest(climber, carrier, component.ViewID); return true; } internal static void HandlePitonGrabEvent(EventData photonEvent) { if (photonEvent == null || photonEvent.Code != 198 || !(photonEvent.CustomData is byte[] array) || array.Length < 12) { return; } Character localCharacter = Character.localCharacter; if ((Object)(object)localCharacter == (Object)null || !localCharacter.IsLocal || !IsCarrier(localCharacter) || (Object)(object)localCharacter.data == (Object)null) { return; } int offset = 0; int num = ReadInt32(array, ref offset); int num2 = ReadInt32(array, ref offset); int num3 = ReadInt32(array, ref offset); int actorNumber = GetActorNumber(localCharacter); Character carriedPlayer = localCharacter.data.carriedPlayer; int actorNumber2 = GetActorNumber(carriedPlayer); if (num2 != actorNumber || num != actorNumber2) { return; } PhotonView photonView = PhotonNetwork.GetPhotonView(num3); if (!((Object)(object)photonView == (Object)null)) { ClimbHandle component = ((Component)photonView).GetComponent(); if (!((Object)(object)component == (Object)null) && !component.isPickaxe && !((Object)(object)component.hanger != (Object)null) && localCharacter.refs != null && !((Object)(object)localCharacter.refs.climbing == (Object)null) && localCharacter.refs.climbing.canInteractWithPiton) { component.Interact(localCharacter); } } } internal static void RuntimeUpdate() { Character localCharacter = Character.localCharacter; if (PhotonNetwork.InRoom && PhotonNetwork.CurrentRoom != null && !((Object)(object)localCharacter == (Object)null) && localCharacter.IsLocal && CanClimberSendInput(localCharacter)) { Character carrier = localCharacter.data.carrier; if (!((Object)(object)carrier == (Object)null) && !((Object)(object)carrier.data == (Object)null)) { runtime.SendUpperBodyInput(localCharacter, carrier); } } } internal static void HandleInputEvent(EventData photonEvent) { //IL_0183: Unknown result type (might be due to invalid IL or missing references) //IL_0185: Unknown result type (might be due to invalid IL or missing references) if (photonEvent.Code != 185 || !(photonEvent.CustomData is byte[] array) || array.Length < 22) { return; } Character localCharacter = Character.localCharacter; if ((Object)(object)localCharacter == (Object)null || !localCharacter.IsLocal || !IsCarrier(localCharacter)) { return; } int offset = 0; int num = ReadInt32(array, ref offset); int num2 = ReadInt32(array, ref offset); int num3 = ReadInt32(array, ref offset); int actorNumber = GetActorNumber(localCharacter); Character carriedPlayer = localCharacter.data.carriedPlayer; int actorNumber2 = GetActorNumber(carriedPlayer); if (num2 == actorNumber && num == actorNumber2) { if (remoteInput.SourceActor != num || remoteInput.TargetActor != num2) { remoteInput = new RemoteUpperBodyInput(); remoteInput.SourceActor = num; remoteInput.TargetActor = num2; } if (num3 > remoteInput.Sequence) { Vector2 movementInput = default(Vector2); ((Vector2)(ref movementInput))..ctor(ReadSingle(array, ref offset), ReadSingle(array, ref offset)); byte b = array[offset++]; byte b2 = array[offset++]; remoteInput.SourceActor = num; remoteInput.TargetActor = num2; remoteInput.Sequence = num3; remoteInput.MovementInput = movementInput; remoteInput.PrimaryHeld = (b & 1) != 0; remoteInput.SecondaryHeld = (b & 2) != 0; pendingActionEdges |= b2; remoteInput.ReceivedTime = Time.realtimeSinceStartup; } } } private static bool IsPairCollider(Collider collider, Character climber, Character carrier) { if ((Object)(object)collider == (Object)null) { return false; } Character componentInParent = ((Component)collider).GetComponentInParent(); return (Object)(object)componentInParent != (Object)null && ((Object)(object)componentInParent == (Object)(object)climber || (Object)(object)componentInParent == (Object)(object)carrier); } private static bool TryFindThorn(Character owner, bool searchBelow, out IInteractible result) { //IL_00c3: 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_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) result = null; if ((Object)(object)owner == (Object)null || owner.refs == null || (Object)(object)owner.refs.afflictions == (Object)null || owner.refs.afflictions.physicalThorns == null) { return false; } foreach (ThornOnMe physicalThorn in owner.refs.afflictions.physicalThorns) { if ((Object)(object)physicalThorn == (Object)null || !physicalThorn.stuckIn || !physicalThorn.ICanAlwaysRemove) { continue; } if (searchBelow) { if (physicalThorn.Center().y > owner.Center.y) { continue; } } else if (physicalThorn.Center().y < owner.Center.y) { continue; } result = (IInteractible)(object)physicalThorn; return true; } return false; } private static bool TryGetStuckInteractable(Character climber, Character carrier, Vector3 lookDirection, out IInteractible result) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0080: 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_014f: 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) result = null; if ((Object)(object)climber == (Object)null || (Object)(object)climber.data == (Object)null) { return false; } float num = Vector3.Angle(Vector3.down, lookDirection); if (num <= 10f) { foreach (StickyItemComponent aLL_STUCK_ITEM in StickyItemComponent.ALL_STUCK_ITEMS) { if ((Object)(object)aLL_STUCK_ITEM != (Object)null && (Object)(object)((ItemComponent)aLL_STUCK_ITEM).item != (Object)null && ((ItemComponent)aLL_STUCK_ITEM).item.Center().y <= climber.Center.y) { result = (IInteractible)(object)((ItemComponent)aLL_STUCK_ITEM).item; return true; } } if (TryFindThorn(climber, searchBelow: true, out result)) { return true; } if (TryFindThorn(carrier, searchBelow: true, out result)) { return true; } } else if (num >= 170f) { foreach (StickyItemComponent aLL_STUCK_ITEM2 in StickyItemComponent.ALL_STUCK_ITEMS) { if ((Object)(object)aLL_STUCK_ITEM2 != (Object)null && (Object)(object)((ItemComponent)aLL_STUCK_ITEM2).item != (Object)null && ((ItemComponent)aLL_STUCK_ITEM2).item.Center().y >= climber.Center.y) { result = (IInteractible)(object)((ItemComponent)aLL_STUCK_ITEM2).item; return true; } } if (TryFindThorn(climber, searchBelow: false, out result)) { return true; } if (TryFindThorn(carrier, searchBelow: false, out result)) { return true; } } return false; } private static bool HasUsablePiton(Character climber) { if ((Object)(object)climber == (Object)null || (Object)(object)climber.player == (Object)null || climber.player.itemSlots == null) { return false; } ItemSlot[] itemSlots = climber.player.itemSlots; IntItemData val2 = default(IntItemData); foreach (ItemSlot val in itemSlots) { if (val != null && !val.IsEmpty() && !((Object)(object)val.prefab == (Object)null)) { ClimbingSpikeComponent component = ((Component)val.prefab).GetComponent(); if (!((Object)(object)component == (Object)null) && (val.data == null || !val.data.TryGetDataEntry((DataEntryKey)1, ref val2) || val2 == null || val2.Value <= 0)) { return true; } } } return false; } private static bool IsPitonCurrentItem(Character climber) { if ((Object)(object)climber == (Object)null || (Object)(object)climber.data == (Object)null || (Object)(object)climber.data.currentItem == (Object)null) { return false; } return (Object)(object)((Component)climber.data.currentItem).GetComponent() != (Object)null; } private static ClimberPitonUiProxyState BeginClimberPitonUiProxy(CharacterItems items) { ClimberPitonUiProxyState result = default(ClimberPitonUiProxyState); Character val = ResolveCharacter((Component)(object)items); if ((Object)(object)val == (Object)null || !val.IsLocal || !IsClimber(val) || (Object)(object)val.data == (Object)null || (Object)(object)val.input == (Object)null) { return result; } Character carrier = val.data.carrier; if ((Object)(object)carrier == (Object)null || (Object)(object)carrier.data == (Object)null) { return result; } result.Climber = val; result.Applied = true; result.OriginalIsClimbing = val.data.isClimbing; result.OriginalIsRopeClimbing = val.data.isRopeClimbing; result.OriginalIsVineClimbing = val.data.isVineClimbing; result.OriginalSecondaryWasPressed = val.input.useSecondaryWasPressed; result.OriginalSecondaryIsPressed = val.input.useSecondaryIsPressed; result.OriginalSecondaryWasReleased = val.input.useSecondaryWasReleased; val.data.isClimbing = carrier.data.isClimbing; val.data.isRopeClimbing = carrier.data.isRopeClimbing; val.data.isVineClimbing = carrier.data.isVineClimbing; bool flag = CanUseGameplayInput(); val.input.useSecondaryWasPressed = flag && CharacterInput.action_useSecondary != null && CharacterInput.action_useSecondary.WasPressedThisFrame(); val.input.useSecondaryIsPressed = flag && CharacterInput.action_useSecondary != null && CharacterInput.action_useSecondary.IsPressed(); val.input.useSecondaryWasReleased = flag && CharacterInput.action_useSecondary != null && CharacterInput.action_useSecondary.WasReleasedThisFrame(); return result; } private static void EndClimberPitonUiProxy(ClimberPitonUiProxyState state) { if (state.Applied && !((Object)(object)state.Climber == (Object)null) && !((Object)(object)state.Climber.data == (Object)null) && !((Object)(object)state.Climber.input == (Object)null)) { state.Climber.data.isClimbing = state.OriginalIsClimbing; state.Climber.data.isRopeClimbing = state.OriginalIsRopeClimbing; state.Climber.data.isVineClimbing = state.OriginalIsVineClimbing; state.Climber.input.useSecondaryWasPressed = state.OriginalSecondaryWasPressed; state.Climber.input.useSecondaryIsPressed = state.OriginalSecondaryIsPressed; state.Climber.input.useSecondaryWasReleased = state.OriginalSecondaryWasReleased; } } private static CarrierPitonProxyState BeginCarrierPitonProxy(CharacterItems items) { //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_0105: Unknown result type (might be due to invalid IL or missing references) //IL_010a: 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) CarrierPitonProxyState result = default(CarrierPitonProxyState); Character val = ResolveCharacter((Component)(object)items); if ((Object)(object)val == (Object)null || !val.IsLocal || !IsCarrier(val) || (Object)(object)val.data == (Object)null || (Object)(object)val.player == (Object)null || val.refs == null || (Object)(object)val.refs.items == (Object)null) { return result; } Character carriedPlayer = val.data.carriedPlayer; if ((Object)(object)carriedPlayer == (Object)null || (Object)(object)carriedPlayer.data == (Object)null || (Object)(object)carriedPlayer.player == (Object)null || carriedPlayer.refs == null || (Object)(object)carriedPlayer.refs.items == (Object)null || !HasUsablePiton(carriedPlayer)) { return result; } result.Carrier = val; result.Climber = carriedPlayer; result.CarrierItems = items; result.Applied = true; result.OriginalSelectedSlot = items.currentSelectedSlot; result.OriginalLastSelectedSlot = items.lastSelectedSlot; result.OriginalClimbingSpikeCount = val.data.climbingSpikeCount; items.UpdateClimbingSpikeCount(carriedPlayer.player.itemSlots); items.currentSelectedSlot = carriedPlayer.refs.items.currentSelectedSlot; items.lastSelectedSlot = carriedPlayer.refs.items.lastSelectedSlot; pitonProxyActive = true; pitonProxyCarrier = val; pitonProxyClimber = carriedPlayer; return result; } private static void EndCarrierPitonProxy(CarrierPitonProxyState state) { //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005e: 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) if (!state.Applied || (Object)(object)state.Carrier == (Object)null || (Object)(object)state.Carrier.data == (Object)null || (Object)(object)state.CarrierItems == (Object)null) { pitonProxyActive = false; pitonProxyCarrier = null; pitonProxyClimber = null; return; } state.CarrierItems.currentSelectedSlot = state.OriginalSelectedSlot; state.CarrierItems.lastSelectedSlot = state.OriginalLastSelectedSlot; state.Carrier.data.climbingSpikeCount = state.OriginalClimbingSpikeCount; pitonProxyActive = false; pitonProxyCarrier = null; pitonProxyClimber = null; } internal static void UpdateCarrierVisibilityForClimber() { Character localCharacter = Character.localCharacter; if ((Object)(object)localCharacter == (Object)null || !localCharacter.IsLocal || !IsClimber(localCharacter) || (Object)(object)localCharacter.data == (Object)null) { RestoreCarrierVisibility(); return; } Character carrier = localCharacter.data.carrier; if ((Object)(object)carrier == (Object)null || (Object)(object)carrier.data == (Object)null || carrier.refs == null || (Object)(object)carrier.refs.hideTheBody == (Object)null) { RestoreCarrierVisibility(); return; } if ((Object)(object)visibilityCarrier != (Object)(object)carrier) { RestoreCarrierVisibility(); visibilityCarrier = carrier; nextVisibilityRefreshTime = 0f; } if (!(Time.unscaledTime < nextVisibilityRefreshTime)) { nextVisibilityRefreshTime = Time.unscaledTime + 1f; ApplyCarrierVisibility(carrier); } } private static void RestoreCarrierVisibility() { if ((Object)(object)visibilityCarrier == (Object)null || visibilityCarrier.refs == null || (Object)(object)visibilityCarrier.refs.hideTheBody == (Object)null) { visibilityCarrier = null; nextVisibilityRefreshTime = 0f; } else { visibilityCarrier.refs.hideTheBody.Refresh(); visibilityCarrier = null; nextVisibilityRefreshTime = 0f; } } private static void ApplyCarrierVisibility(Character carrier) { if ((Object)(object)carrier == (Object)null || carrier.refs == null || (Object)(object)carrier.refs.hideTheBody == (Object)null) { return; } HideTheBody hideTheBody = carrier.refs.hideTheBody; CustomizationRefs refs = hideTheBody.refs; hideTheBody.Refresh(); if (HideCarrierBody != null && HideCarrierBody.Value) { SetRendererHidden(hideTheBody, (Renderer)(object)hideTheBody.body); if ((Object)(object)refs != (Object)null) { SetRendererHidden(hideTheBody, (Renderer)(object)refs.mainRenderer); SetRendererHidden(hideTheBody, refs.shorts); SetRendererHidden(hideTheBody, refs.skirt); } } if (HideCarrierHead != null && HideCarrierHead.Value) { SetRendererHidden(hideTheBody, hideTheBody.headRend); } if (HideCarrierFace != null && HideCarrierFace.Value) { if ((Object)(object)hideTheBody.face != (Object)null) { HideRendererArray(hideTheBody, ((Component)hideTheBody.face).GetComponentsInChildren(true)); } if ((Object)(object)refs != (Object)null) { HideRendererArray(hideTheBody, refs.EyeRenderers); SetRendererHidden(hideTheBody, refs.mouthRenderer); SetRendererHidden(hideTheBody, refs.accessoryRenderer); if ((Object)(object)refs.thirdEye != (Object)null) { SetRendererHidden(hideTheBody, refs.thirdEye.GetComponent()); } } } if (HideCarrierHat != null && HideCarrierHat.Value && (Object)(object)refs != (Object)null) { HideRendererArray(hideTheBody, refs.playerHats); } if (HideCarrierSash != null && HideCarrierSash.Value) { SetRendererHidden(hideTheBody, (Renderer)(object)hideTheBody.sash); if ((Object)(object)refs != (Object)null) { SetRendererHidden(hideTheBody, refs.sashRenderer); } } if (HideCarrierCostumes != null && HideCarrierCostumes.Value) { Renderer[] costumes = (Renderer[])(object)hideTheBody.costumes; HideRendererArray(hideTheBody, costumes); } if (HideCarrierSpecialRenderers != null && HideCarrierSpecialRenderers.Value && (Object)(object)refs != (Object)null) { SetRendererHidden(hideTheBody, refs.blindRenderer); SetRendererHidden(hideTheBody, refs.chickenRenderer); SetRendererHidden(hideTheBody, refs.skeletonRenderer); } } private static void HideRendererArray(HideTheBody hide, Renderer[] renderers) { if (!((Object)(object)hide == (Object)null) && renderers != null) { for (int i = 0; i < renderers.Length; i++) { SetRendererHidden(hide, renderers[i]); } } } private static void SetRendererHidden(HideTheBody hide, Renderer renderer) { if (!((Object)(object)hide == (Object)null) && !((Object)(object)renderer == (Object)null)) { hide.SetShowing(renderer, 1f); } } internal static bool IsPitonCurrentItemLocal(Character climber) { return IsPitonCurrentItem(climber); } internal static void WriteInt32Local(byte[] buffer, ref int offset, int value) { WriteInt32(buffer, ref offset, value); } internal static void WriteSingleLocal(byte[] buffer, ref int offset, float value) { WriteSingle(buffer, ref offset, value); } } [DefaultExecutionOrder(-10000)] public sealed class SeparateRoleRuntime : MonoBehaviour, IOnEventCallback { private bool active; private int currentCarrierActor = -1; private int inputSequence; private float nextInputSendTime; private float nextInputHeartbeatTime; private bool hasSentInputState; private Vector2 lastSentMovementInput = Vector2.zero; private byte lastSentInputFlags; private readonly int[] inputTargetActors = new int[1]; private readonly RaiseEventOptions inputRaiseEventOptions = new RaiseEventOptions(); public void Activate() { if (!active) { PhotonNetwork.AddCallbackTarget((object)this); ResetCounters(); active = true; } } public void Deactivate() { if (active) { PhotonNetwork.RemoveCallbackTarget((object)this); active = false; ResetCounters(); } } private void ResetCounters() { //IL_002d: 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) currentCarrierActor = -1; inputSequence = 0; nextInputSendTime = 0f; nextInputHeartbeatTime = 0f; hasSentInputState = false; lastSentMovementInput = Vector2.zero; lastSentInputFlags = 0; inputTargetActors[0] = -1; inputRaiseEventOptions.TargetActors = inputTargetActors; } private void Update() { if (active) { SeparateRole.RuntimeUpdate(); } } private void LateUpdate() { if (active) { SeparateRole.UpdateCarrierVisibilityForClimber(); } } internal void SendUpperBodyInput(Character climber, Character carrier) { //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: 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_01de: Unknown result type (might be due to invalid IL or missing references) //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_02bb: Unknown result type (might be due to invalid IL or missing references) //IL_02cb: Unknown result type (might be due to invalid IL or missing references) //IL_0337: Unknown result type (might be due to invalid IL or missing references) //IL_0330: Unknown result type (might be due to invalid IL or missing references) //IL_034a: Unknown result type (might be due to invalid IL or missing references) //IL_034b: Unknown result type (might be due to invalid IL or missing references) if (!active || !PhotonNetwork.InRoom || PhotonNetwork.CurrentRoom == null || (Object)(object)climber == (Object)null || (Object)(object)carrier == (Object)null || (Object)(object)climber.data == (Object)null || (Object)(object)carrier.data == (Object)null) { return; } int actorNumberLocal = GetActorNumberLocal(climber); int actorNumberLocal2 = GetActorNumberLocal(carrier); if (actorNumberLocal <= 0 || actorNumberLocal2 <= 0) { return; } if (currentCarrierActor != actorNumberLocal2) { ResetCounters(); currentCarrierActor = actorNumberLocal2; } bool flag = CanUseGameplayInputLocal(); Vector2 val = ((flag && IsCarrierMovementAuthorityActiveLocal(carrier)) ? ReadMovementInputLocal() : Vector2.zero); bool flag2 = (Object)(object)climber.data.currentItem == (Object)null || carrier.data.isClimbing; bool flag3 = (Object)(object)climber.data.currentItem == (Object)null || SeparateRole.IsPitonCurrentItemLocal(climber); byte b = 0; if (flag && flag2 && IsPressed(CharacterInput.action_usePrimary)) { b |= 1; } if (flag && flag3 && IsPressed(CharacterInput.action_useSecondary)) { b |= 2; } byte b2 = 0; if (flag && flag2 && WasPressed(CharacterInput.action_usePrimary)) { b2 |= 1; } if (flag && flag2 && WasReleased(CharacterInput.action_usePrimary)) { b2 |= 2; } if (flag && flag3 && WasPressed(CharacterInput.action_useSecondary)) { b2 |= 4; } if (flag && flag3 && WasReleased(CharacterInput.action_useSecondary)) { b2 |= 8; } bool flag4 = b != lastSentInputFlags; Vector2 val2 = val - lastSentMovementInput; bool flag5 = ((Vector2)(ref val2)).sqrMagnitude > 0.0004f; float realtimeSinceStartup = Time.realtimeSinceStartup; bool flag6 = flag4 || b2 != 0; bool flag7 = IsCarrierMovementAuthorityActiveLocal(carrier); bool flag8 = ((Vector2)(ref val)).sqrMagnitude > 0.0004f; if (!hasSentInputState || flag6 || (flag7 && realtimeSinceStartup >= nextInputSendTime && (flag5 || flag8)) || (b != 0 && realtimeSinceStartup >= nextInputHeartbeatTime)) { inputSequence++; byte[] array = new byte[SeparateRole.InputPayloadLengthLocal]; int offset = 0; SeparateRole.WriteInt32Local(array, ref offset, actorNumberLocal); SeparateRole.WriteInt32Local(array, ref offset, actorNumberLocal2); SeparateRole.WriteInt32Local(array, ref offset, inputSequence); SeparateRole.WriteSingleLocal(array, ref offset, val.x); SeparateRole.WriteSingleLocal(array, ref offset, val.y); array[offset++] = b; array[offset++] = b2; if (inputTargetActors[0] != actorNumberLocal2) { inputTargetActors[0] = actorNumberLocal2; inputRaiseEventOptions.TargetActors = inputTargetActors; } PhotonNetwork.RaiseEvent(SeparateRole.UpperBodyInputEventCodeLocal, (object)array, inputRaiseEventOptions, flag6 ? SendOptions.SendReliable : SendOptions.SendUnreliable); hasSentInputState = true; lastSentMovementInput = val; lastSentInputFlags = b; nextInputSendTime = realtimeSinceStartup + SeparateRole.InputSendIntervalLocal; nextInputHeartbeatTime = realtimeSinceStartup + SeparateRole.InputHeartbeatIntervalLocal; } } internal void SendPitonGrabRequest(Character climber, Character carrier, int handleViewID) { //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Expected O, but got Unknown //IL_00af: Unknown result type (might be due to invalid IL or missing references) if (active && PhotonNetwork.InRoom && PhotonNetwork.CurrentRoom != null && !((Object)(object)climber == (Object)null) && !((Object)(object)carrier == (Object)null) && handleViewID > 0) { int actorNumberLocal = GetActorNumberLocal(climber); int actorNumberLocal2 = GetActorNumberLocal(carrier); if (actorNumberLocal > 0 && actorNumberLocal2 > 0) { byte[] array = new byte[SeparateRole.PitonGrabPayloadLengthLocal]; int offset = 0; SeparateRole.WriteInt32Local(array, ref offset, actorNumberLocal); SeparateRole.WriteInt32Local(array, ref offset, actorNumberLocal2); SeparateRole.WriteInt32Local(array, ref offset, handleViewID); int[] targetActors = new int[1] { actorNumberLocal2 }; RaiseEventOptions val = new RaiseEventOptions { TargetActors = targetActors }; PhotonNetwork.RaiseEvent(SeparateRole.PitonGrabEventCodeLocal, (object)array, val, SendOptions.SendReliable); } } } public void OnEvent(EventData photonEvent) { if (active) { SeparateRole.HandleInputEvent(photonEvent); SeparateRole.HandlePitonGrabEvent(photonEvent); } } private static int GetActorNumberLocal(Character character) { if ((Object)(object)character == (Object)null || (Object)(object)((MonoBehaviourPun)character).photonView == (Object)null || ((MonoBehaviourPun)character).photonView.Owner == null) { return -1; } return ((MonoBehaviourPun)character).photonView.Owner.ActorNumber; } private static bool IsCarrierMovementAuthorityActiveLocal(Character character) { return (Object)(object)character != (Object)null && (Object)(object)character.data != (Object)null && (character.data.isClimbing || character.data.isRopeClimbing || character.data.isVineClimbing); } private static bool CanUseGameplayInputLocal() { if ((Object)(object)GUIManager.instance == (Object)null) { return false; } return !GUIManager.instance.windowBlockingInput && !GUIManager.instance.wheelActive; } private static Vector2 ReadMovementInputLocal() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_003f: 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) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_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_008d: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: 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_00c8: 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_00b5: 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_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: 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) Vector2 val = Vector2.zero; if (CharacterInput.action_move != null) { val += CharacterInput.action_move.ReadValue(); } if (CharacterInput.action_moveForward != null && CharacterInput.action_moveForward.IsPressed()) { val += Vector2.up; } if (CharacterInput.action_moveBackward != null && CharacterInput.action_moveBackward.IsPressed()) { val -= Vector2.up; } if (CharacterInput.action_moveRight != null && CharacterInput.action_moveRight.IsPressed()) { val += Vector2.right; } if (CharacterInput.action_moveLeft != null && CharacterInput.action_moveLeft.IsPressed()) { val -= Vector2.right; } return Vector2.ClampMagnitude(val, 1f); } private static bool IsPressed(InputAction action) { return action != null && action.IsPressed(); } private static bool WasPressed(InputAction action) { return action != null && action.WasPressedThisFrame(); } private static bool WasReleased(InputAction action) { return action != null && action.WasReleasedThisFrame(); } private void OnDestroy() { Deactivate(); } } public static class ShareAlive { [HarmonyPatch(typeof(CharacterCarrying), "RPCA_StartCarry", new Type[] { typeof(PhotonView) })] private static class CharacterCarrying_RPCA_StartCarry_Patch { [HarmonyPostfix] private static void Postfix(CharacterCarrying __instance, PhotonView targetView) { if (initialized && !((Object)(object)__instance == (Object)null) && !((Object)(object)targetView == (Object)null)) { Character component = ((Component)__instance).GetComponent(); Character component2 = ((Component)targetView).GetComponent(); if (!((Object)(object)component == (Object)null) && !((Object)(object)component2 == (Object)null) && !((Object)(object)component.data == (Object)null) && !((Object)(object)component2.data == (Object)null) && !((Object)(object)component.data.carriedPlayer != (Object)(object)component2) && component2.data.isCarried && !((Object)(object)component2.data.carrier != (Object)(object)component)) { RegisterPair(component, component2); } } } } [HarmonyPatch(typeof(Character), "RPCA_ReviveAtPosition", new Type[] { typeof(Vector3), typeof(bool), typeof(int) })] private static class Character_RPCA_ReviveAtPosition_Patch { [HarmonyPostfix] private static void Postfix(Character __instance, Vector3 position, bool applyStatus, int statueSegment) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) if (initialized) { ShareReviveAtPosition(__instance, position, applyStatus, statueSegment); } } } private const string HarmonyId = "com.peak.coopmod.sharealive"; private const byte ReviveEventCode = 189; private static Harmony harmony; private static ShareAliveRuntime runtime; private static bool initialized = false; private static bool applyingRemoteEvent = false; private static readonly Dictionary PartnerByActor = new Dictionary(); public static void Initialize(CoopMod plugin) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Expected O, but got Unknown if (!initialized && !((Object)(object)plugin == (Object)null)) { PartnerByActor.Clear(); applyingRemoteEvent = false; harmony = new Harmony("com.peak.coopmod.sharealive"); harmony.CreateClassProcessor(typeof(CharacterCarrying_RPCA_StartCarry_Patch)).Patch(); harmony.CreateClassProcessor(typeof(Character_RPCA_ReviveAtPosition_Patch)).Patch(); runtime = ((Component)plugin).gameObject.GetComponent(); if ((Object)(object)runtime == (Object)null) { runtime = ((Component)plugin).gameObject.AddComponent(); } runtime.Activate(); SceneManager.sceneLoaded += OnSceneLoaded; initialized = true; CaptureExistingPairs(); } } public static void Shutdown() { if (initialized) { SceneManager.sceneLoaded -= OnSceneLoaded; if ((Object)(object)runtime != (Object)null) { runtime.Deactivate(); Object.Destroy((Object)(object)runtime); runtime = null; } if (harmony != null) { harmony.UnpatchSelf(); harmony = null; } PartnerByActor.Clear(); applyingRemoteEvent = false; initialized = false; } } private static void OnSceneLoaded(Scene scene, LoadSceneMode mode) { PartnerByActor.Clear(); applyingRemoteEvent = false; } private static int GetActorNumber(Character character) { if ((Object)(object)character == (Object)null || (Object)(object)((MonoBehaviourPun)character).photonView == (Object)null || ((MonoBehaviourPun)character).photonView.Owner == null) { return -1; } return ((MonoBehaviourPun)character).photonView.Owner.ActorNumber; } private static void RegisterPair(Character carrier, Character climber) { if (!((Object)(object)carrier == (Object)null) && !((Object)(object)climber == (Object)null) && !((Object)(object)carrier == (Object)(object)climber)) { int actorNumber = GetActorNumber(carrier); int actorNumber2 = GetActorNumber(climber); if (actorNumber > 0 && actorNumber2 > 0) { PartnerByActor[actorNumber] = actorNumber2; PartnerByActor[actorNumber2] = actorNumber; } } } private static void CaptureExistingPairs() { List allPlayerCharacters = PlayerHandler.GetAllPlayerCharacters(); if (allPlayerCharacters == null) { return; } for (int i = 0; i < allPlayerCharacters.Count; i++) { Character val = allPlayerCharacters[i]; if (!((Object)(object)val == (Object)null) && !((Object)(object)val.data == (Object)null)) { Character carriedPlayer = val.data.carriedPlayer; if (!((Object)(object)carriedPlayer == (Object)null) && !((Object)(object)carriedPlayer.data == (Object)null) && carriedPlayer.data.isCarried && !((Object)(object)carriedPlayer.data.carrier != (Object)(object)val)) { RegisterPair(val, carriedPlayer); } } } } private static bool TryGetPartner(Character character, out Character partner) { partner = null; if ((Object)(object)character == (Object)null) { return false; } int actorNumber = GetActorNumber(character); if (actorNumber > 0 && PartnerByActor.TryGetValue(actorNumber, out var value) && value > 0 && PlayerHandler.TryGetCharacter(value, ref partner) && (Object)(object)partner != (Object)null) { return true; } if ((Object)(object)character.data == (Object)null) { partner = null; return false; } Character carriedPlayer = character.data.carriedPlayer; if ((Object)(object)carriedPlayer != (Object)null && (Object)(object)carriedPlayer.data != (Object)null && carriedPlayer.data.isCarried && (Object)(object)carriedPlayer.data.carrier == (Object)(object)character) { partner = carriedPlayer; RegisterPair(character, carriedPlayer); return true; } if (character.data.isCarried) { Character carrier = character.data.carrier; if ((Object)(object)carrier != (Object)null && (Object)(object)carrier.data != (Object)null && (Object)(object)carrier.data.carriedPlayer == (Object)(object)character) { partner = carrier; RegisterPair(carrier, character); return true; } } partner = null; return false; } private static bool NeedsRevive(Character character) { if ((Object)(object)character == (Object)null || (Object)(object)character.data == (Object)null) { return false; } return character.data.dead || character.data.fullyPassedOut; } private static bool IsAlive(Character character) { if ((Object)(object)character == (Object)null || (Object)(object)character.data == (Object)null) { return false; } return !character.data.dead && !character.data.fullyPassedOut; } private static void SendToPartner(Character sender, Character partner, object[] payload) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Expected O, but got Unknown //IL_0066: Unknown result type (might be due to invalid IL or missing references) if (PhotonNetwork.InRoom && PhotonNetwork.CurrentRoom != null && !((Object)(object)sender == (Object)null) && !((Object)(object)partner == (Object)null) && payload != null) { int actorNumber = GetActorNumber(partner); if (actorNumber > 0) { RaiseEventOptions val = new RaiseEventOptions(); val.TargetActors = new int[1] { actorNumber }; RaiseEventOptions val2 = val; PhotonNetwork.RaiseEvent((byte)189, (object)payload, val2, SendOptions.SendReliable); } } } private static void ShareReviveAtPosition(Character revivedCharacter, Vector3 position, bool applyStatus, int statueSegment) { //IL_0092: 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_00ae: Unknown result type (might be due to invalid IL or missing references) if (!applyingRemoteEvent && !((Object)(object)revivedCharacter == (Object)null) && revivedCharacter.IsLocal && IsAlive(revivedCharacter) && TryGetPartner(revivedCharacter, out var partner) && NeedsRevive(partner)) { int actorNumber = GetActorNumber(revivedCharacter); int actorNumber2 = GetActorNumber(partner); if (actorNumber > 0 && actorNumber2 > 0) { SendToPartner(revivedCharacter, partner, new object[7] { actorNumber, actorNumber2, position.x, position.y, position.z, applyStatus, statueSegment }); } } } internal static void HandlePhotonEvent(EventData photonEvent) { //IL_0138: Unknown result type (might be due to invalid IL or missing references) if (!initialized || photonEvent.Code != 189 || !(photonEvent.CustomData is object[] array) || array.Length < 7 || PhotonNetwork.LocalPlayer == null) { return; } int num = (int)array[0]; int num2 = (int)array[1]; if (PhotonNetwork.LocalPlayer.ActorNumber != num2) { return; } Character localCharacter = Character.localCharacter; if ((Object)(object)localCharacter == (Object)null || !localCharacter.IsLocal || !NeedsRevive(localCharacter) || (Object)(object)((MonoBehaviourPun)localCharacter).photonView == (Object)null || !TryGetPartner(localCharacter, out var partner) || GetActorNumber(partner) != num) { return; } Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor((float)array[2], (float)array[3], (float)array[4]); bool flag = (bool)array[5]; int num3 = (int)array[6]; applyingRemoteEvent = true; try { ((MonoBehaviourPun)localCharacter).photonView.RPC("RPCA_ReviveAtPosition", (RpcTarget)0, new object[3] { val, flag, num3 }); } finally { applyingRemoteEvent = false; } } } public sealed class ShareAliveRuntime : MonoBehaviour, IOnEventCallback { private bool active = false; public void Activate() { if (!active) { PhotonNetwork.AddCallbackTarget((object)this); active = true; } } public void Deactivate() { if (active) { PhotonNetwork.RemoveCallbackTarget((object)this); active = false; } } public void OnEvent(EventData photonEvent) { if (active) { ShareAlive.HandlePhotonEvent(photonEvent); } } private void OnDestroy() { Deactivate(); } } public static class ShareDeath { [HarmonyPatch(typeof(CharacterInput), "Sample", new Type[] { typeof(bool) })] [HarmonyAfter(new string[] { "com.peak.coopmod.separaterole" })] private static class CharacterInput_Sample_DeathHold_Patch { [HarmonyPostfix] [HarmonyPriority(0)] private static void Postfix(CharacterInput __instance) { Character localCharacter = Character.localCharacter; if (!((Object)(object)localCharacter == (Object)null) && localCharacter.IsLocal && !((Object)(object)localCharacter.input != (Object)(object)__instance) && !((Object)(object)localCharacter.data == (Object)null) && !localCharacter.data.dead && localCharacter.data.fullyPassedOut && IsCarrier(localCharacter) && CharacterInput.action_interact != null) { __instance.interactWasPressed = CharacterInput.action_interact.WasPressedThisFrame(); __instance.interactIsPressed = CharacterInput.action_interact.IsPressed(); __instance.interactWasReleased = CharacterInput.action_interact.WasReleasedThisFrame(); } } } [HarmonyPatch(typeof(CharacterCarrying), "RPCA_StartCarry", new Type[] { typeof(PhotonView) })] private static class CharacterCarrying_RPCA_StartCarry_Patch { [HarmonyPostfix] private static void Postfix(CharacterCarrying __instance, PhotonView targetView) { if (!((Object)(object)__instance == (Object)null) && !((Object)(object)targetView == (Object)null)) { Character component = ((Component)__instance).GetComponent(); Character component2 = ((Component)targetView).GetComponent(); if (!((Object)(object)component == (Object)null) && !((Object)(object)component2 == (Object)null) && !((Object)(object)component.data == (Object)null) && !((Object)(object)component2.data == (Object)null)) { RegisterPair(component, component2); } } } } [HarmonyPatch(typeof(Character), "RPCA_Die")] private static class Character_RPCA_Die_Patch { [HarmonyPrefix] [HarmonyPriority(800)] private static void Prefix(Character __instance) { SendSharedDeath(__instance); } } private const string HarmonyId = "com.peak.coopmod.sharedeath"; private const byte DeathEventCode = 188; private static Harmony harmony; private static ShareDeathRuntime runtime; private static readonly Dictionary PartnerByActor = new Dictionary(); private static readonly HashSet SuppressNextDeathSend = new HashSet(); public static void Initialize(CoopMod plugin) { //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Expected O, but got Unknown if (harmony == null && !((Object)(object)plugin == (Object)null)) { PartnerByActor.Clear(); SuppressNextDeathSend.Clear(); harmony = new Harmony("com.peak.coopmod.sharedeath"); harmony.CreateClassProcessor(typeof(CharacterCarrying_RPCA_StartCarry_Patch)).Patch(); harmony.CreateClassProcessor(typeof(Character_RPCA_Die_Patch)).Patch(); harmony.CreateClassProcessor(typeof(CharacterInput_Sample_DeathHold_Patch)).Patch(); runtime = ((Component)plugin).gameObject.GetComponent(); if ((Object)(object)runtime == (Object)null) { runtime = ((Component)plugin).gameObject.AddComponent(); } runtime.Activate(); } } public static void Shutdown() { if ((Object)(object)runtime != (Object)null) { runtime.Deactivate(); Object.Destroy((Object)(object)runtime); runtime = null; } PartnerByActor.Clear(); SuppressNextDeathSend.Clear(); if (harmony != null) { harmony.UnpatchSelf(); harmony = null; } } internal static void RuntimeUpdate() { Character localCharacter = Character.localCharacter; if (!((Object)(object)localCharacter == (Object)null) && localCharacter.IsLocal && !((Object)(object)localCharacter.data == (Object)null) && TryGetDirectPartner(localCharacter, out var partner)) { RegisterPair(localCharacter, partner); } } private static int GetActorNumber(Character character) { if ((Object)(object)character == (Object)null || (Object)(object)((MonoBehaviourPun)character).photonView == (Object)null || ((MonoBehaviourPun)character).photonView.Owner == null) { return -1; } return ((MonoBehaviourPun)character).photonView.Owner.ActorNumber; } private static void RegisterPair(Character first, Character second) { if (!((Object)(object)first == (Object)null) && !((Object)(object)second == (Object)null) && !((Object)(object)first == (Object)(object)second)) { int actorNumber = GetActorNumber(first); int actorNumber2 = GetActorNumber(second); if (actorNumber > 0 && actorNumber2 > 0) { PartnerByActor[actorNumber] = actorNumber2; PartnerByActor[actorNumber2] = actorNumber; } } } private static bool TryGetDirectPartner(Character character, out Character partner) { partner = null; if ((Object)(object)character == (Object)null || (Object)(object)character.data == (Object)null) { return false; } if (character.data.isCarried) { Character carrier = character.data.carrier; if ((Object)(object)carrier != (Object)null && (Object)(object)carrier.data != (Object)null && (Object)(object)carrier.data.carriedPlayer == (Object)(object)character) { partner = carrier; return true; } } Character carriedPlayer = character.data.carriedPlayer; if ((Object)(object)carriedPlayer != (Object)null && (Object)(object)carriedPlayer.data != (Object)null && carriedPlayer.data.isCarried && (Object)(object)carriedPlayer.data.carrier == (Object)(object)character) { partner = carriedPlayer; return true; } return false; } private static bool TryGetPartner(Character character, out Character partner) { partner = null; if ((Object)(object)character == (Object)null) { return false; } if (TryGetDirectPartner(character, out partner)) { RegisterPair(character, partner); return true; } int actorNumber = GetActorNumber(character); if (actorNumber <= 0 || !PartnerByActor.TryGetValue(actorNumber, out var value)) { return false; } if (!PlayerHandler.TryGetCharacter(value, ref partner) || (Object)(object)partner == (Object)null) { partner = null; return false; } return true; } private static void SendSharedDeath(Character dyingCharacter) { //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Expected O, but got Unknown //IL_00fa: Unknown result type (might be due to invalid IL or missing references) if (!PhotonNetwork.InRoom || (Object)(object)dyingCharacter == (Object)null || (Object)(object)dyingCharacter.data == (Object)null || !dyingCharacter.IsLocal || dyingCharacter.data.dead) { return; } int actorNumber = GetActorNumber(dyingCharacter); if (actorNumber > 0 && !SuppressNextDeathSend.Remove(actorNumber) && TryGetPartner(dyingCharacter, out var partner) && !((Object)(object)partner == (Object)null) && !((Object)(object)partner.data == (Object)null) && !partner.data.dead) { int actorNumber2 = GetActorNumber(partner); if (actorNumber2 > 0) { RaiseEventOptions val = new RaiseEventOptions(); val.TargetActors = new int[1] { actorNumber2 }; RaiseEventOptions val2 = val; PhotonNetwork.RaiseEvent((byte)188, (object)new object[2] { actorNumber, actorNumber2 }, val2, SendOptions.SendReliable); } } } internal static void HandlePhotonEvent(EventData photonEvent) { if (photonEvent.Code != 188 || !(photonEvent.CustomData is object[] array) || array.Length < 2) { return; } int num = (int)array[0]; int num2 = (int)array[1]; if (PhotonNetwork.LocalPlayer == null || PhotonNetwork.LocalPlayer.ActorNumber != num2) { return; } Character localCharacter = Character.localCharacter; if (!((Object)(object)localCharacter == (Object)null) && localCharacter.IsLocal && !((Object)(object)localCharacter.data == (Object)null) && !localCharacter.data.dead && !((Object)(object)((MonoBehaviourPun)localCharacter).photonView == (Object)null)) { int actorNumber = GetActorNumber(localCharacter); if (actorNumber == num2 && TryGetPartner(localCharacter, out var partner) && !((Object)(object)partner == (Object)null) && GetActorNumber(partner) == num) { SuppressNextDeathSend.Add(actorNumber); ((MonoBehaviourPun)localCharacter).photonView.RPC("RPCA_Die", (RpcTarget)0, Array.Empty()); } } } private static bool IsCarrier(Character character) { if ((Object)(object)character == (Object)null || (Object)(object)character.data == (Object)null) { return false; } Character carriedPlayer = character.data.carriedPlayer; if ((Object)(object)carriedPlayer == (Object)null || (Object)(object)carriedPlayer.data == (Object)null) { return false; } return carriedPlayer.data.isCarried && (Object)(object)carriedPlayer.data.carrier == (Object)(object)character; } } public sealed class ShareDeathRuntime : MonoBehaviour, IOnEventCallback { private bool active; public void Activate() { if (!active) { PhotonNetwork.AddCallbackTarget((object)this); active = true; } } public void Deactivate() { if (active) { PhotonNetwork.RemoveCallbackTarget((object)this); active = false; } } private void Update() { if (active) { ShareDeath.RuntimeUpdate(); } } public void OnEvent(EventData photonEvent) { if (active) { ShareDeath.HandlePhotonEvent(photonEvent); } } private void OnDestroy() { Deactivate(); } } public static class ShareInventory { private struct SelectedSlotMirrorState { public Character Carrier; public bool Applied; public Optionable OriginalSelectedSlot; } private struct BackpackRenderMirrorState { public Character Carrier; public Character Climber; public bool Applied; } [HarmonyPatch(typeof(Campfire), "Light_Rpc", new Type[] { typeof(bool), typeof(float) })] private static class Campfire_LightRpc_SafeDrop_Patch { [HarmonyPrefix] [HarmonyPriority(800)] private static void Prefix(Campfire __instance, bool updateSegment) { if (updateSegment) { if ((Object)(object)GUIManager.instance != (Object)null && GUIManager.instance.wheelActive) { GUIManager.instance.CloseBackpackWheel(); } SafeDropAllClimberInventories(__instance); } } } [HarmonyPatch(typeof(Item), "IsInteractible", new Type[] { typeof(Character) })] private static class Item_IsInteractible_CarrierBlock_Patch { [HarmonyPostfix] [HarmonyPriority(0)] private static void Postfix(Character interactor, ref bool __result) { if (IsCarrier(interactor)) { __result = false; } } } [HarmonyPatch(typeof(Item), "Interact", new Type[] { typeof(Character) })] private static class Item_Interact_CarrierBlock_Patch { [HarmonyPrefix] [HarmonyPriority(800)] private static bool Prefix(Character interactor) { return !IsCarrier(interactor); } } [HarmonyPatch(typeof(BackpackOnBackVisuals), "IsInteractible", new Type[] { typeof(Character) })] private static class BackpackOnBackVisuals_IsInteractible_CarrierBlock_Patch { [HarmonyPostfix] [HarmonyPriority(0)] private static void Postfix(Character interactor, ref bool __result) { if (IsCarrier(interactor)) { __result = false; } } } [HarmonyPatch(typeof(BackpackOnBackVisuals), "Interact_CastFinished", new Type[] { typeof(Character) })] private static class BackpackOnBackVisuals_InteractCastFinished_CarrierBlock_Patch { [HarmonyPrefix] [HarmonyPriority(800)] private static bool Prefix(Character interactor) { return !IsCarrier(interactor); } } [HarmonyPatch(typeof(Player), "SyncInventoryRPC", new Type[] { typeof(byte[]), typeof(bool) })] private static class Player_SyncInventoryRPC_Refresh_Patch { [HarmonyPostfix] [HarmonyPriority(0)] private static void Postfix(Player __instance) { RefreshInventory(__instance); } } [HarmonyPatch(typeof(GUIManager), "UpdateItems")] private static class GUIManager_UpdateItems_CarrierSharedHud_Patch { [HarmonyPostfix] [HarmonyPriority(0)] private static void Postfix(GUIManager __instance) { MirrorClimberInventoryToCarrierHud(__instance); } } [HarmonyPatch(typeof(InventoryItemUI), "SetItem", new Type[] { typeof(ItemSlot) })] private static class InventoryItemUI_SetItem_CarrierBackpackMirror_Patch { [HarmonyPrefix] [HarmonyPriority(800)] private static void Prefix(InventoryItemUI __instance, out BackpackRenderMirrorState __state) { __state = default(BackpackRenderMirrorState); if (carrierUiMirrorActive && !((Object)(object)__instance == (Object)null) && __instance.isBackpack && !((Object)(object)carrierUiMirrorCarrier == (Object)null) && !((Object)(object)carrierUiMirrorClimber == (Object)null) && !((Object)(object)carrierUiMirrorCarrier.data == (Object)null) && !((Object)(object)carrierUiMirrorCarrier.data.carriedPlayer != (Object)(object)carrierUiMirrorClimber)) { __state.Carrier = carrierUiMirrorCarrier; __state.Climber = carrierUiMirrorClimber; __state.Applied = true; carrierUiMirrorCarrier.data.carriedPlayer = null; } } [HarmonyFinalizer] [HarmonyPriority(0)] private static Exception Finalizer(Exception __exception, BackpackRenderMirrorState __state) { if (__state.Applied && (Object)(object)__state.Carrier != (Object)null && (Object)(object)__state.Carrier.data != (Object)null && (Object)(object)__state.Carrier.data.carriedPlayer == (Object)null) { __state.Carrier.data.carriedPlayer = __state.Climber; } return __exception; } } [HarmonyPatch(typeof(InventoryItemUI), "SetSelected")] private static class InventoryItemUI_SetSelected_CarrierSelectionMirror_Patch { [HarmonyPrefix] [HarmonyPriority(800)] private static void Prefix(out SelectedSlotMirrorState __state) { //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) __state = default(SelectedSlotMirrorState); if (carrierUiMirrorActive && !((Object)(object)carrierUiMirrorCarrier == (Object)null) && !((Object)(object)carrierUiMirrorClimber == (Object)null) && carrierUiMirrorCarrier.refs != null && !((Object)(object)carrierUiMirrorCarrier.refs.items == (Object)null) && carrierUiMirrorClimber.refs != null && !((Object)(object)carrierUiMirrorClimber.refs.items == (Object)null)) { __state.Carrier = carrierUiMirrorCarrier; __state.Applied = true; __state.OriginalSelectedSlot = carrierUiMirrorCarrier.refs.items.currentSelectedSlot; carrierUiMirrorCarrier.refs.items.currentSelectedSlot = carrierUiMirrorClimber.refs.items.currentSelectedSlot; } } [HarmonyFinalizer] [HarmonyPriority(0)] private static Exception Finalizer(Exception __exception, SelectedSlotMirrorState __state) { //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) if (__state.Applied && (Object)(object)__state.Carrier != (Object)null && __state.Carrier.refs != null && (Object)(object)__state.Carrier.refs.items != (Object)null) { __state.Carrier.refs.items.currentSelectedSlot = __state.OriginalSelectedSlot; } return __exception; } } [HarmonyPatch(typeof(Dynamite), "TestLightWick")] private static class Dynamite_TestLightWick_SafeDrop_Patch { [HarmonyPrefix] [HarmonyPriority(800)] private static bool Prefix(Dynamite __instance) { if ((Object)(object)__instance == (Object)null) { return true; } return !IsSafeDropped(((ItemComponent)__instance).item); } } [HarmonyPatch(typeof(EventOnItemCollision), "OnCollisionEnter")] private static class EventOnItemCollision_OnCollisionEnter_SafeDrop_Patch { [HarmonyPrefix] [HarmonyPriority(800)] private static bool Prefix(EventOnItemCollision __instance, Collision collision) { if ((Object)(object)__instance == (Object)null) { return true; } Item componentInParent = ((Component)__instance).GetComponentInParent(); if (IsSafeDropped(componentInParent)) { return false; } if (collision == null) { return true; } Item componentInParent2 = collision.gameObject.GetComponentInParent(); return !IsSafeDropped(componentInParent2); } } [HarmonyPatch(typeof(Breakable), "OnCollisionEnter")] private static class Breakable_OnCollisionEnter_SafeDrop_Patch { [HarmonyPrefix] [HarmonyPriority(800)] private static bool Prefix(Breakable __instance) { if ((Object)(object)__instance == (Object)null) { return true; } Item component = ((Component)__instance).GetComponent(); return !IsSafeDropped(component); } } [HarmonyPatch(typeof(ShelfShroom), "OnCollisionEnter")] private static class ShelfShroom_OnCollisionEnter_SafeDrop_Patch { [HarmonyPrefix] [HarmonyPriority(800)] private static bool Prefix(ShelfShroom __instance) { if ((Object)(object)__instance == (Object)null) { return true; } Item component = ((Component)__instance).GetComponent(); return !IsSafeDropped(component); } } private const string HarmonyId = "com.peak.coopmod.shareinventory"; private const byte SafeMarkerEventCode = 196; private static Harmony harmony; private static ShareInventoryRuntime runtime; private static bool carrierUiMirrorActive; private static Character carrierUiMirrorCarrier; private static Character carrierUiMirrorClimber; private static readonly HashSet processedCampfires = new HashSet(); public static void Initialize(CoopMod plugin) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown if (harmony == null && !((Object)(object)plugin == (Object)null)) { harmony = new Harmony("com.peak.coopmod.shareinventory"); Patch(typeof(Campfire_LightRpc_SafeDrop_Patch)); Patch(typeof(Item_IsInteractible_CarrierBlock_Patch)); Patch(typeof(Item_Interact_CarrierBlock_Patch)); Patch(typeof(BackpackOnBackVisuals_IsInteractible_CarrierBlock_Patch)); Patch(typeof(BackpackOnBackVisuals_InteractCastFinished_CarrierBlock_Patch)); Patch(typeof(Player_SyncInventoryRPC_Refresh_Patch)); Patch(typeof(GUIManager_UpdateItems_CarrierSharedHud_Patch)); Patch(typeof(InventoryItemUI_SetItem_CarrierBackpackMirror_Patch)); Patch(typeof(InventoryItemUI_SetSelected_CarrierSelectionMirror_Patch)); Patch(typeof(Dynamite_TestLightWick_SafeDrop_Patch)); Patch(typeof(EventOnItemCollision_OnCollisionEnter_SafeDrop_Patch)); Patch(typeof(Breakable_OnCollisionEnter_SafeDrop_Patch)); Patch(typeof(ShelfShroom_OnCollisionEnter_SafeDrop_Patch)); runtime = ((Component)plugin).gameObject.GetComponent(); if ((Object)(object)runtime == (Object)null) { runtime = ((Component)plugin).gameObject.AddComponent(); } runtime.Activate(); ResetSceneState(); } } public static void Shutdown() { if ((Object)(object)runtime != (Object)null) { runtime.Deactivate(); Object.Destroy((Object)(object)runtime); runtime = null; } if (harmony != null) { harmony.UnpatchSelf(); harmony = null; } ResetSceneState(); } private static void Patch(Type patchType) { harmony.CreateClassProcessor(patchType).Patch(); } internal static void ResetSceneState() { processedCampfires.Clear(); carrierUiMirrorActive = false; carrierUiMirrorCarrier = null; carrierUiMirrorClimber = null; } private static bool IsCarrier(Character character) { if ((Object)(object)character == (Object)null || (Object)(object)character.data == (Object)null) { return false; } Character carriedPlayer = character.data.carriedPlayer; if ((Object)(object)carriedPlayer == (Object)null || (Object)(object)carriedPlayer.data == (Object)null) { return false; } return carriedPlayer.data.isCarried && (Object)(object)carriedPlayer.data.carrier == (Object)(object)character; } private static bool IsClimber(Character character) { if ((Object)(object)character == (Object)null || (Object)(object)character.data == (Object)null || !character.data.isCarried) { return false; } Character carrier = character.data.carrier; if ((Object)(object)carrier == (Object)null || (Object)(object)carrier.data == (Object)null) { return false; } return (Object)(object)carrier.data.carriedPlayer == (Object)(object)character; } private static bool TryGetLocalCarrierPair(out Character carrier, out Character climber) { carrier = Character.localCharacter; climber = null; if ((Object)(object)carrier == (Object)null || !carrier.IsLocal || !IsCarrier(carrier) || (Object)(object)carrier.data == (Object)null) { carrier = null; return false; } climber = carrier.data.carriedPlayer; if ((Object)(object)climber == (Object)null || (Object)(object)climber.data == (Object)null || !climber.data.isCarried || (Object)(object)climber.data.carrier != (Object)(object)carrier) { carrier = null; climber = null; return false; } return true; } private static void MirrorClimberInventoryToCarrierHud(GUIManager gui) { if ((Object)(object)gui == (Object)null || !TryGetLocalCarrierPair(out var carrier, out var climber) || (Object)(object)climber.player == (Object)null || climber.refs == null || (Object)(object)climber.refs.items == (Object)null) { return; } carrierUiMirrorActive = true; carrierUiMirrorCarrier = carrier; carrierUiMirrorClimber = climber; try { for (int i = 0; i < gui.items.Length; i++) { if (i < climber.player.itemSlots.Length) { gui.items[i].SetItem(climber.player.itemSlots[i]); } else { gui.items[i].Clear(); } gui.items[i].SetSelected(); } gui.backpack.SetItem((ItemSlot)(object)climber.player.backpackSlot); gui.backpack.SetSelected(); ItemSlot itemSlot = climber.player.GetItemSlot((byte)250); if (itemSlot != null && !itemSlot.IsEmpty()) { ((Component)gui.temporaryItem).gameObject.SetActive(true); gui.temporaryItem.SetItem(itemSlot); gui.temporaryItem.SetSelected(); } else { ((Component)gui.temporaryItem).gameObject.SetActive(false); gui.temporaryItem.Clear(); } } finally { carrierUiMirrorActive = false; carrierUiMirrorCarrier = null; carrierUiMirrorClimber = null; } } private static void SafeDropAllClimberInventories(Campfire campfire) { if (!PhotonNetwork.InRoom || !PhotonNetwork.IsMasterClient || (Object)(object)campfire == (Object)null) { return; } PhotonView component = ((Component)campfire).GetComponent(); if ((Object)(object)component == (Object)null) { return; } int viewID = component.ViewID; if (!processedCampfires.Add(viewID)) { return; } List allPlayerCharacters = PlayerHandler.GetAllPlayerCharacters(); if (allPlayerCharacters == null) { return; } for (int i = 0; i < allPlayerCharacters.Count; i++) { Character val = allPlayerCharacters[i]; if (IsClimber(val)) { SafeDropAllItems(val); } } } private static void SafeDropAllItems(Character climber) { //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) if ((Object)(object)climber == (Object)null || (Object)(object)climber.player == (Object)null || climber.refs == null || (Object)(object)climber.refs.items == (Object)null) { return; } Player player = climber.player; CharacterItems items = climber.refs.items; if ((Object)(object)((MonoBehaviourPun)climber).photonView != (Object)null) { ((MonoBehaviourPun)climber).photonView.RPC("EquipSlotRpc", (RpcTarget)0, new object[2] { -1, -1 }); } items.currentSelectedSlot = Optionable.None; int dropIndex = 0; BackpackSlot backpackSlot = player.backpackSlot; if (backpackSlot != null && !((ItemSlot)backpackSlot).IsEmpty()) { SafeDropBackpackContents(climber, backpackSlot, ref dropIndex); } ItemSlot[] itemSlots = player.itemSlots; if (itemSlots != null) { foreach (ItemSlot val in itemSlots) { if (val != null && !val.IsEmpty() && SpawnSafeWorldItem(climber, val, ref dropIndex)) { val.EmptyOut(); } } } if (player.tempFullSlot != null && !player.tempFullSlot.IsEmpty() && SpawnSafeWorldItem(climber, player.tempFullSlot, ref dropIndex)) { player.tempFullSlot.EmptyOut(); } if (backpackSlot != null && !((ItemSlot)backpackSlot).IsEmpty() && SpawnSafeWorldItem(climber, (ItemSlot)(object)backpackSlot, ref dropIndex)) { ((ItemSlot)backpackSlot).EmptyOut(); } SyncInventory(player); if ((Object)(object)climber.refs.afflictions != (Object)null) { climber.refs.items.RefreshAllCharacterCarryWeight(); } } private static void SafeDropBackpackContents(Character climber, BackpackSlot backpackSlot, ref int dropIndex) { BackpackData val = default(BackpackData); if ((Object)(object)climber == (Object)null || backpackSlot == null || ((ItemSlot)backpackSlot).data == null || !((ItemSlot)backpackSlot).data.TryGetDataEntry((DataEntryKey)7, ref val) || val == null || val.itemSlots == null) { return; } for (int i = 0; i < val.itemSlots.Length; i++) { ItemSlot val2 = val.itemSlots[i]; if (val2 != null && !val2.IsEmpty() && SpawnSafeWorldItem(climber, val2, ref dropIndex)) { val2.EmptyOut(); } } } private static bool SpawnSafeWorldItem(Character climber, ItemSlot slot, ref int dropIndex) { //IL_004b: 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_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_007b: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0166: 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_012f: 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) if (!PhotonNetwork.IsMasterClient || (Object)(object)climber == (Object)null || slot == null || slot.IsEmpty()) { return false; } string prefabName = slot.GetPrefabName(); if (string.IsNullOrEmpty(prefabName)) { return false; } Vector3 safeDropPosition = GetSafeDropPosition(climber, dropIndex); Quaternion val = Quaternion.Euler(0f, (float)dropIndex * 47f % 360f, 0f); GameObject val2 = PhotonNetwork.Instantiate("0_Items/" + prefabName, safeDropPosition, val, (byte)0, (object[])null); if ((Object)(object)val2 == (Object)null) { return false; } Item component = val2.GetComponent(); PhotonView component2 = val2.GetComponent(); if ((Object)(object)component == (Object)null || (Object)(object)component2 == (Object)null) { return false; } ShareInventorySafeDropMarker component3 = val2.GetComponent(); if ((Object)(object)component3 == (Object)null) { val2.AddComponent(); } PrepareSafeItemData(slot, component); component2.RPC("SetItemInstanceDataRPC", (RpcTarget)0, new object[1] { slot.data }); if ((Object)(object)component.rig != (Object)null) { component.rig.linearVelocity = Vector3.zero; component.rig.angularVelocity = Vector3.zero; } component2.RPC("SetKinematicAndResetSyncData", (RpcTarget)3, new object[3] { true, safeDropPosition, val }); BroadcastSafeMarker(component2.ViewID); dropIndex++; return true; } private static void PrepareSafeItemData(ItemSlot slot, Item item) { if (slot == null || (Object)(object)item == (Object)null || slot.data == null) { return; } Dynamite component = ((Component)item).GetComponent(); if (!((Object)(object)component == (Object)null)) { BoolItemData val = default(BoolItemData); if (slot.data.TryGetDataEntry((DataEntryKey)3, ref val) && val != null) { val.Value = false; } FloatItemData val2 = default(FloatItemData); if (slot.data.TryGetDataEntry((DataEntryKey)10, ref val2) && val2 != null) { val2.Value = component.startingFuseTime; } } } private static Vector3 GetSafeDropPosition(Character climber, int index) { //IL_0002: 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_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0058: 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_005f: 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_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_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0077: 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_0086: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: 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_00c8: 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_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: 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) Vector3 center = climber.Center; int num = index / 6; int num2 = index % 6; float num3 = 1.25f + (float)num * 0.75f; float num4 = (float)num2 * 60f + (float)num * 30f; Vector3 val = Quaternion.Euler(0f, num4, 0f) * Vector3.forward * num3; Vector3 val2 = center + val; Vector3 val3 = val2 + Vector3.up * 3f; RaycastHit val4 = default(RaycastHit); if (Physics.Raycast(val3, Vector3.down, ref val4, 8f, LayerMask.op_Implicit(HelperFunctions.GetMask((LayerType)1)), (QueryTriggerInteraction)1)) { return ((RaycastHit)(ref val4)).point + Vector3.up * 0.08f; } return val2 + Vector3.up * 0.25f; } private static void SyncInventory(Player player) { //IL_0054: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)player == (Object)null) && !((Object)(object)((MonoBehaviourPun)player).photonView == (Object)null) && player.itemSlots != null && player.backpackSlot != null && player.tempFullSlot != null) { InventorySyncData val = default(InventorySyncData); ((InventorySyncData)(ref val))..ctor(player.itemSlots, player.backpackSlot, player.tempFullSlot); byte[] array = IBinarySerializable.ToManagedArray(val); ((MonoBehaviourPun)player).photonView.RPC("SyncInventoryRPC", (RpcTarget)1, new object[2] { array, false }); RefreshInventory(player); } } private static void RefreshInventory(Player player) { //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)player == (Object)null)) { player.itemsChangedAction?.Invoke(player.itemSlots); if (!((Object)(object)player.character == (Object)null) && player.character.refs != null && !((Object)(object)player.character.refs.items == (Object)null) && !HasAnyItem(player)) { player.character.refs.items.currentSelectedSlot = Optionable.None; } } } private static bool HasAnyItem(Player player) { if ((Object)(object)player == (Object)null) { return false; } if (player.itemSlots != null) { for (int i = 0; i < player.itemSlots.Length; i++) { ItemSlot val = player.itemSlots[i]; if (val != null && !val.IsEmpty()) { return true; } } } if (player.tempFullSlot != null && !player.tempFullSlot.IsEmpty()) { return true; } return player.backpackSlot != null && !((ItemSlot)player.backpackSlot).IsEmpty(); } private static bool IsSafeDropped(Item item) { return (Object)(object)item != (Object)null && (Object)(object)((Component)item).GetComponent() != (Object)null; } private static void BroadcastSafeMarker(int viewID) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Expected O, but got Unknown //IL_0047: Unknown result type (might be due to invalid IL or missing references) if (PhotonNetwork.InRoom && PhotonNetwork.IsMasterClient && viewID > 0) { byte[] array = new byte[4]; int offset = 0; WriteInt32(array, ref offset, viewID); RaiseEventOptions val = new RaiseEventOptions { Receivers = (ReceiverGroup)0 }; PhotonNetwork.RaiseEvent((byte)196, (object)array, val, SendOptions.SendReliable); } } internal static void HandleEvent(EventData photonEvent) { if (photonEvent != null && photonEvent.Code == 196 && photonEvent.CustomData is byte[] array && array.Length >= 4) { int offset = 0; int num = ReadInt32(array, ref offset); PhotonView photonView = PhotonNetwork.GetPhotonView(num); if (!((Object)(object)photonView == (Object)null) && !((Object)(object)((Component)photonView).gameObject == (Object)null) && (Object)(object)((Component)photonView).gameObject.GetComponent() == (Object)null) { ((Component)photonView).gameObject.AddComponent(); } } } private static void WriteInt32(byte[] buffer, ref int offset, int value) { buffer[offset++] = (byte)value; buffer[offset++] = (byte)(value >> 8); buffer[offset++] = (byte)(value >> 16); buffer[offset++] = (byte)(value >> 24); } private static int ReadInt32(byte[] buffer, ref int offset) { int result = buffer[offset] | (buffer[offset + 1] << 8) | (buffer[offset + 2] << 16) | (buffer[offset + 3] << 24); offset += 4; return result; } } public sealed class ShareInventorySafeDropMarker : MonoBehaviour { } [DefaultExecutionOrder(-8500)] public sealed class ShareInventoryRuntime : MonoBehaviour, IOnEventCallback { private bool active; private int sceneHandle = int.MinValue; public void Activate() { //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) if (!active) { PhotonNetwork.AddCallbackTarget((object)this); Scene activeScene = SceneManager.GetActiveScene(); sceneHandle = ((Scene)(ref activeScene)).handle; active = true; } } public void Deactivate() { if (active) { PhotonNetwork.RemoveCallbackTarget((object)this); active = false; } } private void Update() { //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) if (active) { Scene activeScene = SceneManager.GetActiveScene(); int handle = ((Scene)(ref activeScene)).handle; if (handle != sceneHandle) { sceneHandle = handle; ShareInventory.ResetSceneState(); } } } public void OnEvent(EventData photonEvent) { if (active) { ShareInventory.HandleEvent(photonEvent); } } private void OnDestroy() { Deactivate(); } } public static class ShareStamina { private enum StaminaAction : byte { Delta = 1, FullSync, SharedStatusSync, CarrierStatusDelta, SharedAfflictionApply, SharedAfflictionRemove, CarriedSpatialAfflictionApply, CarriedSpatialAfflictionRemove, PetrifySync } private struct StaminaSnapshot { public bool Track; public float Current; public float Extra; } private struct PetrifySnapshot { public bool Track; public Character Character; public int Amount; } private struct PassiveStatusSnapshotState { public bool Applied; public CharacterAfflictions Afflictions; public float Drowsy; public float Cold; public float Hunger; public float Poison; public float Hot; public float Spores; } [HarmonyPatch(typeof(Character), "UseStamina", new Type[] { typeof(float), typeof(bool), typeof(bool) })] private static class CharacterUseStaminaPatch { [HarmonyPrefix] private static void Prefix(Character __instance, out StaminaSnapshot __state) { __state = CaptureSnapshot(__instance); if (__state.Track) { useStaminaDepth++; } } [HarmonyPostfix] private static void Postfix(Character __instance, StaminaSnapshot __state) { try { SendSnapshotDelta(__instance, __state); } finally { if (__state.Track && useStaminaDepth > 0) { useStaminaDepth--; } } } } [HarmonyPatch(typeof(Character), "CanRegenStamina")] private static class CharacterCanRegenStaminaPatch { [HarmonyPostfix] private static void Postfix(Character __instance, ref bool __result) { if (!((Object)(object)__instance == (Object)null) && __instance.IsLocal && suppressSendDepth <= 0 && TryGetPartner(__instance, out var _) && IsClimber(__instance)) { __result = false; } } } [HarmonyPatch(typeof(Character), "AddStamina", new Type[] { typeof(float) })] private static class CharacterAddStaminaPatch { [HarmonyPrefix] private static void Prefix(Character __instance, out StaminaSnapshot __state) { __state = CaptureSnapshot(__instance); if (__state.Track) { addStaminaDepth++; } } [HarmonyPostfix] private static void Postfix(Character __instance, StaminaSnapshot __state) { try { SendSnapshotDelta(__instance, __state); } finally { if (__state.Track && addStaminaDepth > 0) { addStaminaDepth--; } } } } [HarmonyPatch(typeof(Character), "ClampStamina")] private static class CharacterClampStaminaPatch { [HarmonyPrefix] private static void Prefix(Character __instance, out StaminaSnapshot __state) { __state = CaptureSnapshot(__instance); } [HarmonyPostfix] private static void Postfix(Character __instance, StaminaSnapshot __state) { if (addStaminaDepth <= 0 && useStaminaDepth <= 0) { SendSnapshotDelta(__instance, __state); } } } [HarmonyPatch(typeof(Character), "SetExtraStamina", new Type[] { typeof(float) })] private static class CharacterSetExtraStaminaPatch { [HarmonyPrefix] private static void Prefix(Character __instance, out StaminaSnapshot __state) { __state = CaptureSnapshot(__instance); } [HarmonyPostfix] private static void Postfix(Character __instance, StaminaSnapshot __state) { SendSnapshotDelta(__instance, __state); } } [HarmonyPatch(typeof(Character), "AddExtraStamina", new Type[] { typeof(float) })] private static class CharacterAddExtraStaminaPatch { [HarmonyPrefix] private static void Prefix(Character __instance, out StaminaSnapshot __state) { __state = CaptureSnapshot(__instance); } [HarmonyPostfix] private static void Postfix(Character __instance, StaminaSnapshot __state) { SendSnapshotDelta(__instance, __state); } } [HarmonyPatch(typeof(CharacterData), "SetPetrify", new Type[] { typeof(int) })] private static class CharacterDataSetPetrifyPatch { [HarmonyPrefix] [HarmonyPriority(800)] private static void Prefix(CharacterData __instance, out PetrifySnapshot __state) { __state = CapturePetrifySnapshot(__instance); } [HarmonyPostfix] [HarmonyPriority(0)] private static void Postfix(CharacterData __instance, PetrifySnapshot __state) { SendPetrifyIfChanged(__instance, __state); } } [HarmonyPatch(typeof(CharacterAfflictions), "UpdateNormalStatuses")] private static class CharacterAfflictionsUpdateNormalStatusesPatch { [HarmonyPrefix] [HarmonyPriority(800)] private static void Prefix(CharacterAfflictions __instance, out PassiveStatusSnapshotState __state) { __state = default(PassiveStatusSnapshotState); if (TryGetLocalAfflictionsCharacter(__instance, out var character) && IsCarrier(character)) { __state.Applied = true; __state.Afflictions = __instance; __state.Drowsy = __instance.GetCurrentStatus((STATUSTYPE)6); __state.Cold = __instance.GetCurrentStatus((STATUSTYPE)2); __state.Hunger = __instance.GetCurrentStatus((STATUSTYPE)1); __state.Poison = __instance.GetCurrentStatus((STATUSTYPE)3); __state.Hot = __instance.GetCurrentStatus((STATUSTYPE)8); __state.Spores = __instance.GetCurrentStatus((STATUSTYPE)10); } } [HarmonyPostfix] [HarmonyPriority(0)] private static void Postfix(PassiveStatusSnapshotState __state) { if (__state.Applied && !((Object)(object)__state.Afflictions == (Object)null)) { RestorePassiveStatus(__state.Afflictions, (STATUSTYPE)6, __state.Drowsy); RestorePassiveStatus(__state.Afflictions, (STATUSTYPE)2, __state.Cold); RestorePassiveStatus(__state.Afflictions, (STATUSTYPE)1, __state.Hunger); RestorePassiveStatus(__state.Afflictions, (STATUSTYPE)3, __state.Poison); RestorePassiveStatus(__state.Afflictions, (STATUSTYPE)8, __state.Hot); RestorePassiveStatus(__state.Afflictions, (STATUSTYPE)10, __state.Spores); } } } [HarmonyPatch(typeof(CharacterAfflictions), "SetStatus", new Type[] { typeof(STATUSTYPE), typeof(float), typeof(bool) })] private static class CharacterAfflictionsSetStatusWeightPatch { [HarmonyPrefix] [HarmonyPriority(800)] private static void Prefix(CharacterAfflictions __instance, STATUSTYPE statusType, ref float amount) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Invalid comparison between Unknown and I4 if ((int)statusType == 7 && TryGetLocalAfflictionsCharacter(__instance, out var character) && IsCarrier(character) && TryGetPartner(character, out var partner) && partner.refs != null && !((Object)(object)partner.refs.afflictions == (Object)null)) { amount = partner.refs.afflictions.GetCurrentStatus((STATUSTYPE)7); } } } [HarmonyPatch(typeof(CharacterAfflictions), "AddAffliction")] private static class CharacterAfflictionsAddAfflictionCarriedBypassPatch { [HarmonyPrefix] [HarmonyPriority(800)] private static void Prefix(CharacterAfflictions __instance, out Character __state) { __state = null; if (TryGetLocalAfflictionsCharacter(__instance, out var character) && IsClimber(character) && !((Object)(object)character.data == (Object)null) && character.data.isCarried) { __state = character; character.data.isCarried = false; } } [HarmonyFinalizer] [HarmonyPriority(0)] private static Exception Finalizer(Exception __exception, Character __state) { if ((Object)(object)__state != (Object)null && (Object)(object)__state.data != (Object)null) { __state.data.isCarried = true; } return __exception; } } [HarmonyPatch(typeof(CharacterAfflictions), "LastAddedStatus", new Type[] { typeof(STATUSTYPE) })] private static class CharacterAfflictionsLastAddedStatusPatch { [HarmonyPostfix] private static void Postfix(CharacterAfflictions __instance, STATUSTYPE statusType, ref float __result) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) if (TryGetLocalAfflictionsCharacter(__instance, out var character) && IsClimber(character)) { int sharedStatusIndex = GetSharedStatusIndex(statusType); if (sharedStatusIndex >= 0 && syncedLastAddedTimes[sharedStatusIndex] > __result) { __result = syncedLastAddedTimes[sharedStatusIndex]; } } } } private const string HarmonyId = "com.peak.coopmod.sharestamina"; private const byte StaminaEventCode = 187; private const float ValueEpsilon = 0.0001f; private const float ClimberCanonicalSyncInterval = 0.35f; private const float PairResyncDuration = 1.5f; private const float PairResyncInterval = 0.15f; private static Harmony harmony; private static ShareStaminaRuntime runtime; private static bool initialized = false; private static int currentPartnerActor = -1; private static bool currentRoleIsCarrier = false; private static float pairResyncUntil = -1f; private static float nextPairResyncTime = 0f; private static float nextClimberCanonicalSyncTime = 0f; private static int suppressSendDepth = 0; private static int addStaminaDepth = 0; private static int useStaminaDepth = 0; private static bool hasSharedStatusBaseline = false; private static readonly Dictionary lastClimberAfflictionData = new Dictionary(); private static readonly Dictionary lastCarrierSpatialAfflictionData = new Dictionary(); private static readonly HashSet spatialAfflictionTypesReceived = new HashSet(); private static readonly HashSet spatialAfflictionsOwnedByShare = new HashSet(); private static readonly HashSet spatialAfflictionRemovalSuppressOnce = new HashSet(); private static readonly HashSet mirroredAfflictionTypes = new HashSet(); private static readonly HashSet mirroredAfflictionsOwnedByShare = new HashSet(); private static readonly STATUSTYPE[] SharedStatusTypes; private static readonly float[] lastSharedStatusValues; private static readonly float[] syncedLastAddedTimes; public static void Initialize(CoopMod plugin) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown if (!initialized && !((Object)(object)plugin == (Object)null)) { harmony = new Harmony("com.peak.coopmod.sharestamina"); harmony.CreateClassProcessor(typeof(CharacterUseStaminaPatch)).Patch(); harmony.CreateClassProcessor(typeof(CharacterCanRegenStaminaPatch)).Patch(); harmony.CreateClassProcessor(typeof(CharacterAddStaminaPatch)).Patch(); harmony.CreateClassProcessor(typeof(CharacterClampStaminaPatch)).Patch(); harmony.CreateClassProcessor(typeof(CharacterSetExtraStaminaPatch)).Patch(); harmony.CreateClassProcessor(typeof(CharacterAddExtraStaminaPatch)).Patch(); harmony.CreateClassProcessor(typeof(CharacterDataSetPetrifyPatch)).Patch(); harmony.CreateClassProcessor(typeof(CharacterAfflictionsUpdateNormalStatusesPatch)).Patch(); harmony.CreateClassProcessor(typeof(CharacterAfflictionsSetStatusWeightPatch)).Patch(); harmony.CreateClassProcessor(typeof(CharacterAfflictionsLastAddedStatusPatch)).Patch(); harmony.CreateClassProcessor(typeof(CharacterAfflictionsAddAfflictionCarriedBypassPatch)).Patch(); runtime = ((Component)plugin).gameObject.GetComponent(); if ((Object)(object)runtime == (Object)null) { runtime = ((Component)plugin).gameObject.AddComponent(); } runtime.Activate(); currentPartnerActor = -1; currentRoleIsCarrier = false; pairResyncUntil = -1f; nextPairResyncTime = 0f; nextClimberCanonicalSyncTime = 0f; suppressSendDepth = 0; addStaminaDepth = 0; useStaminaDepth = 0; ResetSharedStatusState(); initialized = true; } } public static void Shutdown() { if (initialized) { if ((Object)(object)runtime != (Object)null) { runtime.Deactivate(); Object.Destroy((Object)(object)runtime); runtime = null; } if (harmony != null) { harmony.UnpatchSelf(); harmony = null; } currentPartnerActor = -1; currentRoleIsCarrier = false; pairResyncUntil = -1f; nextPairResyncTime = 0f; nextClimberCanonicalSyncTime = 0f; suppressSendDepth = 0; addStaminaDepth = 0; useStaminaDepth = 0; ResetSharedStatusState(); initialized = false; } } internal static void RuntimeUpdate() { if (!initialized) { return; } Character localCharacter = Character.localCharacter; if ((Object)(object)localCharacter == (Object)null || !localCharacter.IsLocal) { ResetPartnerState(); return; } if (!TryGetPartner(localCharacter, out var partner)) { ResetPartnerState(); return; } int actorNumber = GetActorNumber(partner); if (actorNumber <= 0) { ResetPartnerState(); return; } bool flag = IsCarrier(localCharacter); bool flag2 = currentPartnerActor != actorNumber || currentRoleIsCarrier != flag; float realtimeSinceStartup = Time.realtimeSinceStartup; if (flag2) { currentPartnerActor = actorNumber; currentRoleIsCarrier = flag; pairResyncUntil = realtimeSinceStartup + 1.5f; nextPairResyncTime = realtimeSinceStartup + 0.15f; nextClimberCanonicalSyncTime = realtimeSinceStartup + 0.35f; ResetSharedStatusState(); CaptureSharedStatusBaseline(localCharacter); if (!flag) { NormalizeSharedStamina(localCharacter, partner); SendFullSync(localCharacter, partner); SendSharedStatusSync(localCharacter, partner, GetAllSharedStatusMask()); SendPetrifySync(localCharacter, partner); } RefreshStaminaBar(); } if (realtimeSinceStartup <= pairResyncUntil && realtimeSinceStartup >= nextPairResyncTime) { if (!flag) { NormalizeSharedStamina(localCharacter, partner); SendFullSync(localCharacter, partner); SendSharedStatusSync(localCharacter, partner, GetAllSharedStatusMask()); SendPetrifySync(localCharacter, partner); } nextPairResyncTime = realtimeSinceStartup + 0.15f; } if (!flag && realtimeSinceStartup >= nextClimberCanonicalSyncTime) { NormalizeSharedStamina(localCharacter, partner); SendFullSync(localCharacter, partner); nextClimberCanonicalSyncTime = realtimeSinceStartup + 0.35f; } if (flag) { SendCarrierStatusDeltasIfChanged(localCharacter, partner); SendCarrierSpatialAfflictionsIfChanged(localCharacter, partner); CleanupExpiredMirroredAfflictions(localCharacter); } else { SendClimberStatusesIfChanged(localCharacter, partner); SendClimberAfflictionsIfChanged(localCharacter, partner); } } internal static void HandlePhotonEvent(EventData photonEvent) { if (!initialized || photonEvent == null || photonEvent.Code != 187 || !(photonEvent.CustomData is object[] array) || array.Length < 3 || PhotonNetwork.LocalPlayer == null) { return; } byte b = (byte)array[0]; int num = (int)array[1]; int num2 = (int)array[2]; if (PhotonNetwork.LocalPlayer.ActorNumber != num2) { return; } Character localCharacter = Character.localCharacter; if ((Object)(object)localCharacter == (Object)null || !localCharacter.IsLocal || (Object)(object)localCharacter.data == (Object)null || !TryGetPartner(localCharacter, out var partner) || GetActorNumber(partner) != num) { return; } StaminaAction staminaAction = (StaminaAction)b; bool flag = false; int num3 = 0; suppressSendDepth++; try { switch (staminaAction) { case StaminaAction.Delta: { if (array.Length < 6) { return; } flag = true; float currentDelta = (float)array[3]; float extraDelta = (float)array[4]; bool resetUseTimer = (bool)array[5]; ApplyDelta(localCharacter, partner, currentDelta, extraDelta, resetUseTimer); break; } case StaminaAction.FullSync: { if (array.Length < 6 || !IsCarrier(localCharacter) || !IsClimber(partner)) { return; } flag = true; float currentStamina = (float)array[3]; float extraStamina = (float)array[4]; float sinceUseStamina = (float)array[5]; ApplyFullSync(localCharacter, partner, currentStamina, extraStamina, sinceUseStamina); break; } case StaminaAction.SharedStatusSync: ApplySharedStatusSync(localCharacter, array); break; case StaminaAction.CarrierStatusDelta: num3 = ApplyCarrierStatusDelta(localCharacter, array); break; case StaminaAction.SharedAfflictionApply: ApplySharedAffliction(localCharacter, array); break; case StaminaAction.SharedAfflictionRemove: RemoveSharedAffliction(localCharacter, array); break; case StaminaAction.CarriedSpatialAfflictionApply: ApplyCarriedSpatialAffliction(localCharacter, array); break; case StaminaAction.CarriedSpatialAfflictionRemove: RemoveCarriedSpatialAffliction(localCharacter, array); break; case StaminaAction.PetrifySync: { if (array.Length < 4) { return; } flag = true; int petrifyAmount = (int)array[3]; ApplyPetrifySync(localCharacter, partner, petrifyAmount); break; } } } finally { suppressSendDepth--; } if (num3 != 0 && IsClimber(localCharacter)) { SendSharedStatusSync(localCharacter, partner, num3); } if (flag && IsCarrier(localCharacter)) { SendFullSync(localCharacter, partner); } } private static void ResetPartnerState() { currentPartnerActor = -1; currentRoleIsCarrier = false; pairResyncUntil = -1f; nextPairResyncTime = 0f; nextClimberCanonicalSyncTime = 0f; ResetSharedStatusState(); } private static void ResetSharedStatusState() { hasSharedStatusBaseline = false; lastClimberAfflictionData.Clear(); lastCarrierSpatialAfflictionData.Clear(); spatialAfflictionTypesReceived.Clear(); spatialAfflictionsOwnedByShare.Clear(); spatialAfflictionRemovalSuppressOnce.Clear(); mirroredAfflictionTypes.Clear(); mirroredAfflictionsOwnedByShare.Clear(); for (int i = 0; i < lastSharedStatusValues.Length; i++) { lastSharedStatusValues[i] = 0f; syncedLastAddedTimes[i] = 0f; } } private static int GetAllSharedStatusMask() { return (1 << SharedStatusTypes.Length) - 1; } private static int GetSharedStatusIndex(STATUSTYPE statusType) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Invalid comparison between I4 and Unknown for (int i = 0; i < SharedStatusTypes.Length; i++) { if ((int)SharedStatusTypes[i] == (int)statusType) { return i; } } return -1; } private static bool IsSharedStatus(STATUSTYPE statusType) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return GetSharedStatusIndex(statusType) >= 0; } private static bool TryGetLocalAfflictionsCharacter(CharacterAfflictions afflictions, out Character character) { character = null; if ((Object)(object)afflictions == (Object)null) { return false; } character = afflictions.character; if ((Object)(object)character == (Object)null) { character = ((Component)afflictions).GetComponent(); } return (Object)(object)character != (Object)null && character.IsLocal; } private static void CaptureSharedStatusBaseline(Character character) { if ((Object)(object)character == (Object)null || character.refs == null || (Object)(object)character.refs.afflictions == (Object)null) { hasSharedStatusBaseline = false; return; } CharacterAfflictions afflictions = character.refs.afflictions; for (int i = 0; i < SharedStatusTypes.Length; i++) { lastSharedStatusValues[i] = afflictions.GetCurrentStatus(SharedStatusTypes[i]); } hasSharedStatusBaseline = true; } private static void UpdateSharedStatusBaseline(Character character, int mask) { if ((Object)(object)character == (Object)null || character.refs == null || (Object)(object)character.refs.afflictions == (Object)null) { return; } CharacterAfflictions afflictions = character.refs.afflictions; for (int i = 0; i < SharedStatusTypes.Length; i++) { if ((mask & (1 << i)) != 0) { lastSharedStatusValues[i] = afflictions.GetCurrentStatus(SharedStatusTypes[i]); } } hasSharedStatusBaseline = true; } private static void SendClimberStatusesIfChanged(Character climber, Character carrier) { if (suppressSendDepth > 0 || (Object)(object)climber == (Object)null || climber.refs == null || (Object)(object)climber.refs.afflictions == (Object)null) { return; } if (!hasSharedStatusBaseline) { CaptureSharedStatusBaseline(climber); SendSharedStatusSync(climber, carrier, GetAllSharedStatusMask()); return; } int num = 0; CharacterAfflictions afflictions = climber.refs.afflictions; for (int i = 0; i < SharedStatusTypes.Length; i++) { float currentStatus = afflictions.GetCurrentStatus(SharedStatusTypes[i]); if (Mathf.Abs(currentStatus - lastSharedStatusValues[i]) > 0.0001f) { num |= 1 << i; } } if (num != 0) { SendSharedStatusSync(climber, carrier, num); UpdateSharedStatusBaseline(climber, num); } } private static void SendCarrierStatusDeltasIfChanged(Character carrier, Character climber) { //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Invalid comparison between Unknown and I4 //IL_0086: 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_009f: Unknown result type (might be due to invalid IL or missing references) if (suppressSendDepth > 0 || (Object)(object)carrier == (Object)null || carrier.refs == null || (Object)(object)carrier.refs.afflictions == (Object)null) { return; } if (!hasSharedStatusBaseline) { CaptureSharedStatusBaseline(carrier); return; } CharacterAfflictions afflictions = carrier.refs.afflictions; int num = 0; float[] array = new float[SharedStatusTypes.Length]; for (int i = 0; i < SharedStatusTypes.Length; i++) { STATUSTYPE val = SharedStatusTypes[i]; if ((int)val == 7 || ShouldSuppressCarrierStatusDelta(val)) { lastSharedStatusValues[i] = afflictions.GetCurrentStatus(val); continue; } float currentStatus = afflictions.GetCurrentStatus(val); float num2 = currentStatus - lastSharedStatusValues[i]; if (!(Mathf.Abs(num2) <= 0.0001f)) { num |= 1 << i; array[i] = num2; lastSharedStatusValues[i] = currentStatus; } } if (num != 0) { SendCarrierStatusDelta(carrier, climber, num, array); } } private static void SendSharedStatusSync(Character sender, Character partner, int mask) { if ((Object)(object)sender == (Object)null || sender.refs == null || (Object)(object)sender.refs.afflictions == (Object)null || mask == 0) { return; } int actorNumber = GetActorNumber(sender); int actorNumber2 = GetActorNumber(partner); if (actorNumber > 0 && actorNumber2 > 0) { object[] array = new object[4 + SharedStatusTypes.Length]; array[0] = (byte)3; array[1] = actorNumber; array[2] = actorNumber2; array[3] = mask; CharacterAfflictions afflictions = sender.refs.afflictions; for (int i = 0; i < SharedStatusTypes.Length; i++) { array[4 + i] = afflictions.GetCurrentStatus(SharedStatusTypes[i]); } SendToPartner(sender, partner, array); } } private static void SendCarrierStatusDelta(Character sender, Character partner, int mask, float[] deltas) { if ((Object)(object)sender == (Object)null || (Object)(object)partner == (Object)null || deltas == null || mask == 0) { return; } int actorNumber = GetActorNumber(sender); int actorNumber2 = GetActorNumber(partner); if (actorNumber > 0 && actorNumber2 > 0) { object[] array = new object[4 + SharedStatusTypes.Length]; array[0] = (byte)4; array[1] = actorNumber; array[2] = actorNumber2; array[3] = mask; for (int i = 0; i < SharedStatusTypes.Length; i++) { array[4 + i] = deltas[i]; } SendToPartner(sender, partner, array); } } private static void ApplySharedStatusSync(Character character, object[] payload) { //IL_0078: 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_0089: Invalid comparison between Unknown and I4 //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)character == (Object)null || character.refs == null || (Object)(object)character.refs.afflictions == (Object)null || payload == null || payload.Length < 4 + SharedStatusTypes.Length) { return; } int num = (int)payload[3]; CharacterAfflictions afflictions = character.refs.afflictions; for (int i = 0; i < SharedStatusTypes.Length; i++) { if ((num & (1 << i)) != 0) { STATUSTYPE val = SharedStatusTypes[i]; float value = (float)payload[4 + i]; if ((int)val != 7 || IsCarrier(character)) { ApplySyncedStatusValue(afflictions, val, value); lastSharedStatusValues[i] = afflictions.GetCurrentStatus(val); } } } hasSharedStatusBaseline = true; } private static int ApplyCarrierStatusDelta(Character character, object[] payload) { //IL_0085: 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_008a: Invalid comparison between Unknown and I4 //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) if (!IsClimber(character) || character.refs == null || (Object)(object)character.refs.afflictions == (Object)null || payload == null || payload.Length < 4 + SharedStatusTypes.Length) { return 0; } int num = (int)payload[3]; CharacterAfflictions afflictions = character.refs.afflictions; int num2 = 0; for (int i = 0; i < SharedStatusTypes.Length; i++) { if ((num & (1 << i)) == 0) { continue; } STATUSTYPE val = SharedStatusTypes[i]; if ((int)val == 7) { continue; } float num3 = (float)payload[4 + i]; if (!(Mathf.Abs(num3) <= 0.0001f)) { float currentStatus = afflictions.GetCurrentStatus(val); float value = currentStatus + num3; if (num3 > 0.0001f) { syncedLastAddedTimes[i] = Time.time; } ApplySyncedStatusValue(afflictions, val, value); lastSharedStatusValues[i] = afflictions.GetCurrentStatus(val); num2 |= 1 << i; } } hasSharedStatusBaseline = true; return num2; } private static void ApplySyncedStatusValue(CharacterAfflictions afflictions, STATUSTYPE statusType, float value) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Invalid comparison between Unknown and I4 //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0056: 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) //IL_0074: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)afflictions == (Object)null) { return; } float currentStatus = afflictions.GetCurrentStatus(statusType); float num = value - currentStatus; if (Mathf.Abs(num) <= 0.0001f) { return; } if ((int)statusType == 7) { afflictions.SetStatus(statusType, value, true); return; } afflictions.AdjustStatus(statusType, num, true); float currentStatus2 = afflictions.GetCurrentStatus(statusType); if (Mathf.Abs(currentStatus2 - value) > 0.0001f) { afflictions.SetStatus(statusType, value, true); } } private static bool ShouldMirrorAffliction(AfflictionType type) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Invalid comparison between Unknown and I4 //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Invalid comparison between Unknown and I4 //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Invalid comparison between Unknown and I4 //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Invalid comparison between Unknown and I4 //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Invalid comparison between Unknown and I4 //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Invalid comparison between Unknown and I4 //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Invalid comparison between Unknown and I4 //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Invalid comparison between Unknown and I4 //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Invalid comparison between Unknown and I4 //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Invalid comparison between Unknown and I4 //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Invalid comparison between Unknown and I4 //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Invalid comparison between Unknown and I4 //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Invalid comparison between Unknown and I4 //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Invalid comparison between Unknown and I4 //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Invalid comparison between Unknown and I4 //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Invalid comparison between Unknown and I4 return (int)type == 1 || (int)type == 2 || (int)type == 4 || (int)type == 5 || (int)type == 9 || (int)type == 13 || (int)type == 14 || (int)type == 16 || (int)type == 17 || (int)type == 18 || (int)type == 19 || (int)type == 20 || (int)type == 21 || (int)type == 23 || (int)type == 25 || (int)type == 24; } private static bool ShouldMirrorSpatialAffliction(AfflictionType type) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0004: Invalid comparison between Unknown and I4 return (int)type == 13; } private static bool ShouldSuppressCarrierStatusDelta(STATUSTYPE statusType) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Invalid comparison between Unknown and I4 //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Invalid comparison between Unknown and I4 if ((int)statusType == 2 && mirroredAfflictionTypes.Contains(5)) { return true; } if ((int)statusType == 6 && mirroredAfflictionTypes.Contains(2)) { return true; } return false; } private static byte[] SerializeAffliction(Affliction affliction) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) if (affliction == null) { return null; } return IBinarySerializable.ToManagedArray(new AfflictionSyncData { afflictions = new List { affliction } }); } private static Affliction DeserializeAffliction(byte[] data) { //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_0024: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) if (data == null || data.Length == 0) { return null; } AfflictionSyncData fromManagedArray = IBinarySerializable.GetFromManagedArray(data); if (fromManagedArray.afflictions == null || fromManagedArray.afflictions.Count == 0) { return null; } return fromManagedArray.afflictions[0]; } private static bool ByteArraysEqual(byte[] first, byte[] second) { if (first == second) { return true; } if (first == null || second == null || first.Length != second.Length) { return false; } for (int i = 0; i < first.Length; i++) { if (first[i] != second[i]) { return false; } } return true; } private static void SendClimberAfflictionsIfChanged(Character climber, Character carrier) { //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0093: 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_00c1: Expected I4, but got Unknown if (suppressSendDepth > 0 || (Object)(object)climber == (Object)null || climber.refs == null || (Object)(object)climber.refs.afflictions == (Object)null || (Object)(object)carrier == (Object)null) { return; } Dictionary dictionary = new Dictionary(); List afflictionList = climber.refs.afflictions.afflictionList; if (afflictionList != null) { for (int i = 0; i < afflictionList.Count; i++) { Affliction val = afflictionList[i]; if (val == null) { continue; } AfflictionType afflictionType = val.GetAfflictionType(); if (!ShouldMirrorAffliction(afflictionType)) { continue; } byte[] array = SerializeAffliction(val); if (array != null) { int num = (int)afflictionType; dictionary[num] = array; if (!spatialAfflictionTypesReceived.Contains(num) && (!lastClimberAfflictionData.TryGetValue(num, out var value) || !ByteArraysEqual(value, array))) { SendSharedAfflictionApply(climber, carrier, array); } } } } List list = new List(); foreach (KeyValuePair lastClimberAfflictionDatum in lastClimberAfflictionData) { if (!dictionary.ContainsKey(lastClimberAfflictionDatum.Key)) { list.Add(lastClimberAfflictionDatum.Key); } } for (int j = 0; j < list.Count; j++) { if (!spatialAfflictionRemovalSuppressOnce.Remove(list[j])) { if (spatialAfflictionTypesReceived.Remove(list[j])) { spatialAfflictionsOwnedByShare.Remove(list[j]); } else { SendSharedAfflictionRemove(climber, carrier, list[j]); } } } lastClimberAfflictionData.Clear(); foreach (KeyValuePair item in dictionary) { lastClimberAfflictionData[item.Key] = item.Value; } } private static void SendCarrierSpatialAfflictionsIfChanged(Character carrier, Character climber) { //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008e: 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_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Expected I4, but got Unknown if (suppressSendDepth > 0 || (Object)(object)carrier == (Object)null || carrier.refs == null || (Object)(object)carrier.refs.afflictions == (Object)null || (Object)(object)climber == (Object)null) { return; } Dictionary dictionary = new Dictionary(); List afflictionList = carrier.refs.afflictions.afflictionList; if (afflictionList != null) { for (int i = 0; i < afflictionList.Count; i++) { Affliction val = afflictionList[i]; if (val == null) { continue; } AfflictionType afflictionType = val.GetAfflictionType(); if (!ShouldMirrorSpatialAffliction(afflictionType)) { continue; } byte[] array = SerializeAffliction(val); if (array != null) { int key = (int)afflictionType; dictionary[key] = array; if (!lastCarrierSpatialAfflictionData.TryGetValue(key, out var value) || !ByteArraysEqual(value, array)) { SendCarriedSpatialAfflictionApply(carrier, climber, array); } } } } List list = new List(); foreach (KeyValuePair lastCarrierSpatialAfflictionDatum in lastCarrierSpatialAfflictionData) { if (!dictionary.ContainsKey(lastCarrierSpatialAfflictionDatum.Key)) { list.Add(lastCarrierSpatialAfflictionDatum.Key); } } for (int j = 0; j < list.Count; j++) { SendCarriedSpatialAfflictionRemove(carrier, climber, list[j]); } lastCarrierSpatialAfflictionData.Clear(); foreach (KeyValuePair item in dictionary) { lastCarrierSpatialAfflictionData[item.Key] = item.Value; } } private static void SendCarriedSpatialAfflictionApply(Character sender, Character partner, byte[] data) { if (!((Object)(object)sender == (Object)null) && !((Object)(object)partner == (Object)null) && data != null) { int actorNumber = GetActorNumber(sender); int actorNumber2 = GetActorNumber(partner); if (actorNumber > 0 && actorNumber2 > 0) { SendToPartner(sender, partner, new object[4] { (byte)7, actorNumber, actorNumber2, data }); } } } private static void SendCarriedSpatialAfflictionRemove(Character sender, Character partner, int type) { if (!((Object)(object)sender == (Object)null) && !((Object)(object)partner == (Object)null)) { int actorNumber = GetActorNumber(sender); int actorNumber2 = GetActorNumber(partner); if (actorNumber > 0 && actorNumber2 > 0) { SendToPartner(sender, partner, new object[4] { (byte)8, actorNumber, actorNumber2, type }); } } } private static void SendSharedAfflictionApply(Character sender, Character partner, byte[] data) { if (!((Object)(object)sender == (Object)null) && !((Object)(object)partner == (Object)null) && data != null) { int actorNumber = GetActorNumber(sender); int actorNumber2 = GetActorNumber(partner); if (actorNumber > 0 && actorNumber2 > 0) { SendToPartner(sender, partner, new object[4] { (byte)5, actorNumber, actorNumber2, data }); } } } private static void SendSharedAfflictionRemove(Character sender, Character partner, int type) { if (!((Object)(object)sender == (Object)null) && !((Object)(object)partner == (Object)null)) { int actorNumber = GetActorNumber(sender); int actorNumber2 = GetActorNumber(partner); if (actorNumber > 0 && actorNumber2 > 0) { SendToPartner(sender, partner, new object[4] { (byte)6, actorNumber, actorNumber2, type }); } } } private static void ApplySharedAffliction(Character character, object[] payload) { //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Expected I4, but got Unknown //IL_007f: Unknown result type (might be due to invalid IL or missing references) if (!IsCarrier(character) || character.refs == null || (Object)(object)character.refs.afflictions == (Object)null || payload == null || payload.Length < 4) { return; } byte[] data = payload[3] as byte[]; Affliction val = DeserializeAffliction(data); if (val == null) { return; } AfflictionType afflictionType = val.GetAfflictionType(); if (ShouldMirrorAffliction(afflictionType)) { int item = (int)afflictionType; Affliction val2 = default(Affliction); bool flag = character.refs.afflictions.HasAfflictionType(afflictionType, ref val2); character.refs.afflictions.AddAffliction(val, true); mirroredAfflictionTypes.Add(item); if (!flag) { mirroredAfflictionsOwnedByShare.Add(item); } } } private static void ApplyCarriedSpatialAffliction(Character character, object[] payload) { //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Expected I4, but got Unknown //IL_007f: Unknown result type (might be due to invalid IL or missing references) if (!IsClimber(character) || character.refs == null || (Object)(object)character.refs.afflictions == (Object)null || payload == null || payload.Length < 4) { return; } byte[] data = payload[3] as byte[]; Affliction val = DeserializeAffliction(data); if (val == null) { return; } AfflictionType afflictionType = val.GetAfflictionType(); if (ShouldMirrorSpatialAffliction(afflictionType)) { int item = (int)afflictionType; Affliction val2 = default(Affliction); bool flag = character.refs.afflictions.HasAfflictionType(afflictionType, ref val2); character.refs.afflictions.AddAffliction(val, true); spatialAfflictionTypesReceived.Add(item); if (!flag) { spatialAfflictionsOwnedByShare.Add(item); } } } private static void RemoveCarriedSpatialAffliction(Character character, object[] payload) { //IL_0046: 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_0095: Unknown result type (might be due to invalid IL or missing references) if (!IsClimber(character) || character.refs == null || (Object)(object)character.refs.afflictions == (Object)null || payload == null || payload.Length < 4) { return; } int num = (int)payload[3]; AfflictionType val = (AfflictionType)num; if (!ShouldMirrorSpatialAffliction(val)) { return; } spatialAfflictionTypesReceived.Remove(num); if (spatialAfflictionsOwnedByShare.Remove(num)) { spatialAfflictionRemovalSuppressOnce.Add(num); Affliction val2 = default(Affliction); if (character.refs.afflictions.HasAfflictionType(val, ref val2) && val2 != null) { character.refs.afflictions.RemoveAffliction(val2, true, false); } } } private static void RemoveSharedAffliction(Character character, object[] payload) { //IL_0043: 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) if (IsCarrier(character) && character.refs != null && !((Object)(object)character.refs.afflictions == (Object)null) && payload != null && payload.Length >= 4) { int num = (int)payload[3]; AfflictionType val = (AfflictionType)num; mirroredAfflictionTypes.Remove(num); Affliction val2 = default(Affliction); if (mirroredAfflictionsOwnedByShare.Remove(num) && character.refs.afflictions.HasAfflictionType(val, ref val2) && val2 != null) { character.refs.afflictions.RemoveAffliction(val2, true, false); } } } private static void CleanupExpiredMirroredAfflictions(Character carrier) { if ((Object)(object)carrier == (Object)null || carrier.refs == null || (Object)(object)carrier.refs.afflictions == (Object)null || mirroredAfflictionTypes.Count == 0) { return; } List list = new List(); Affliction val = default(Affliction); foreach (int mirroredAfflictionType in mirroredAfflictionTypes) { if (!carrier.refs.afflictions.HasAfflictionType((AfflictionType)mirroredAfflictionType, ref val)) { list.Add(mirroredAfflictionType); } } for (int i = 0; i < list.Count; i++) { mirroredAfflictionTypes.Remove(list[i]); mirroredAfflictionsOwnedByShare.Remove(list[i]); } } private static bool IsCarrier(Character character) { if ((Object)(object)character == (Object)null || (Object)(object)character.data == (Object)null) { return false; } Character carriedPlayer = character.data.carriedPlayer; if ((Object)(object)carriedPlayer == (Object)null || (Object)(object)carriedPlayer.data == (Object)null) { return false; } return carriedPlayer.data.isCarried && (Object)(object)carriedPlayer.data.carrier == (Object)(object)character; } private static bool IsClimber(Character character) { if ((Object)(object)character == (Object)null || (Object)(object)character.data == (Object)null || !character.data.isCarried) { return false; } Character carrier = character.data.carrier; if ((Object)(object)carrier == (Object)null || (Object)(object)carrier.data == (Object)null) { return false; } return (Object)(object)carrier.data.carriedPlayer == (Object)(object)character; } private static bool TryGetPartner(Character character, out Character partner) { partner = null; if ((Object)(object)character == (Object)null || (Object)(object)character.data == (Object)null) { return false; } if (character.data.isCarried) { Character carrier = character.data.carrier; if ((Object)(object)carrier != (Object)null && (Object)(object)carrier.data != (Object)null && (Object)(object)carrier.data.carriedPlayer == (Object)(object)character) { partner = carrier; return true; } } Character carriedPlayer = character.data.carriedPlayer; if ((Object)(object)carriedPlayer != (Object)null && (Object)(object)carriedPlayer.data != (Object)null && carriedPlayer.data.isCarried && (Object)(object)carriedPlayer.data.carrier == (Object)(object)character) { partner = carriedPlayer; return true; } return false; } private static int GetActorNumber(Character character) { if ((Object)(object)character == (Object)null || (Object)(object)((MonoBehaviourPun)character).photonView == (Object)null || ((MonoBehaviourPun)character).photonView.Owner == null) { return -1; } return ((MonoBehaviourPun)character).photonView.Owner.ActorNumber; } private static float GetSharedMaxStamina(Character first, Character second) { if ((Object)(object)first == (Object)null) { return 0f; } float num = Mathf.Max(0f, first.GetMaxStamina()); if ((Object)(object)second == (Object)null) { return num; } float num2 = Mathf.Max(0f, second.GetMaxStamina()); return Mathf.Min(num, num2); } private static PetrifySnapshot CapturePetrifySnapshot(CharacterData data) { PetrifySnapshot result = default(PetrifySnapshot); if (suppressSendDepth > 0 || (Object)(object)data == (Object)null) { return result; } Character component = ((Component)data).GetComponent(); if ((Object)(object)component == (Object)null || !component.IsLocal || (Object)(object)component.data != (Object)(object)data) { return result; } if (!TryGetPartner(component, out var _)) { return result; } result.Track = true; result.Character = component; result.Amount = data.petrifyAmount; return result; } private static void SendPetrifyIfChanged(CharacterData data, PetrifySnapshot snapshot) { if (snapshot.Track && suppressSendDepth <= 0 && !((Object)(object)data == (Object)null) && !((Object)(object)snapshot.Character == (Object)null) && data.petrifyAmount != snapshot.Amount && TryGetPartner(snapshot.Character, out var partner)) { SendPetrifySync(snapshot.Character, partner); RefreshStaminaBar(); } } private static void SendPetrifySync(Character sender, Character partner) { if (!((Object)(object)sender == (Object)null) && !((Object)(object)sender.data == (Object)null) && !((Object)(object)partner == (Object)null)) { int actorNumber = GetActorNumber(sender); int actorNumber2 = GetActorNumber(partner); if (actorNumber > 0 && actorNumber2 > 0) { SendToPartner(sender, partner, new object[4] { (byte)9, actorNumber, actorNumber2, sender.data.petrifyAmount }); } } } private static void ApplyPetrifySync(Character character, Character partner, int petrifyAmount) { if (!((Object)(object)character == (Object)null) && !((Object)(object)character.data == (Object)null)) { character.data.SetPetrify(Mathf.Clamp(petrifyAmount, 0, 100)); NormalizeSharedStamina(character, partner); RefreshStaminaBar(); } } private static void NormalizeSharedStamina(Character character, Character partner) { if (!((Object)(object)character == (Object)null) && !((Object)(object)character.data == (Object)null)) { float sharedMaxStamina = GetSharedMaxStamina(character, partner); character.data.currentStamina = Mathf.Clamp(character.data.currentStamina, 0f, sharedMaxStamina); float num = Mathf.Clamp01(1f - (float)character.data.petrifyAmount * 0.01f); character.data.extraStamina = Mathf.Clamp(character.data.extraStamina, 0f, num); } } private static void ApplyDelta(Character character, Character partner, float currentDelta, float extraDelta, bool resetUseTimer) { if (!((Object)(object)character == (Object)null) && !((Object)(object)character.data == (Object)null)) { CharacterData data = character.data; data.currentStamina += currentDelta; CharacterData data2 = character.data; data2.extraStamina += extraDelta; NormalizeSharedStamina(character, partner); if (resetUseTimer) { character.data.sinceUseStamina = 0f; } RefreshStaminaBar(); } } private static void ApplyFullSync(Character character, Character partner, float currentStamina, float extraStamina, float sinceUseStamina) { if (!((Object)(object)character == (Object)null) && !((Object)(object)character.data == (Object)null)) { float sharedMaxStamina = GetSharedMaxStamina(character, partner); character.data.currentStamina = Mathf.Clamp(currentStamina, 0f, sharedMaxStamina); float num = Mathf.Clamp01(1f - (float)character.data.petrifyAmount * 0.01f); character.data.extraStamina = Mathf.Clamp(extraStamina, 0f, num); character.data.sinceUseStamina = Mathf.Max(0f, sinceUseStamina); RefreshStaminaBar(); } } private static void RefreshStaminaBar() { if ((Object)(object)GUIManager.instance != (Object)null && (Object)(object)GUIManager.instance.bar != (Object)null) { GUIManager.instance.bar.ChangeBar(); } } private static StaminaSnapshot CaptureSnapshot(Character character) { StaminaSnapshot result = default(StaminaSnapshot); if (suppressSendDepth > 0 || (Object)(object)character == (Object)null || (Object)(object)character.data == (Object)null || !character.IsLocal) { return result; } if (!TryGetPartner(character, out var _)) { return result; } result.Track = true; result.Current = character.data.currentStamina; result.Extra = character.data.extraStamina; return result; } private static void SendSnapshotDelta(Character character, StaminaSnapshot snapshot) { if (snapshot.Track && suppressSendDepth <= 0 && !((Object)(object)character == (Object)null) && !((Object)(object)character.data == (Object)null) && character.IsLocal && TryGetPartner(character, out var partner)) { NormalizeSharedStamina(character, partner); float num = character.data.currentStamina - snapshot.Current; float num2 = character.data.extraStamina - snapshot.Extra; if (!(Mathf.Abs(num) <= 0.0001f) || !(Mathf.Abs(num2) <= 0.0001f)) { bool resetUseTimer = num < -0.0001f || num2 < -0.0001f; SendDelta(character, partner, num, num2, resetUseTimer); RefreshStaminaBar(); } } } private static void SendToPartner(Character sender, Character partner, object[] payload) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Expected O, but got Unknown //IL_0066: Unknown result type (might be due to invalid IL or missing references) if (PhotonNetwork.InRoom && PhotonNetwork.CurrentRoom != null && !((Object)(object)sender == (Object)null) && !((Object)(object)partner == (Object)null) && payload != null) { int actorNumber = GetActorNumber(partner); if (actorNumber > 0) { RaiseEventOptions val = new RaiseEventOptions(); val.TargetActors = new int[1] { actorNumber }; RaiseEventOptions val2 = val; PhotonNetwork.RaiseEvent((byte)187, (object)payload, val2, SendOptions.SendReliable); } } } private static void SendDelta(Character sender, Character partner, float currentDelta, float extraDelta, bool resetUseTimer) { int actorNumber = GetActorNumber(sender); int actorNumber2 = GetActorNumber(partner); if (actorNumber > 0 && actorNumber2 > 0) { SendToPartner(sender, partner, new object[6] { (byte)1, actorNumber, actorNumber2, currentDelta, extraDelta, resetUseTimer }); } } private static void SendFullSync(Character sender, Character partner) { if (!((Object)(object)sender == (Object)null) && !((Object)(object)sender.data == (Object)null) && !((Object)(object)partner == (Object)null) && IsClimber(sender) && IsCarrier(partner)) { NormalizeSharedStamina(sender, partner); int actorNumber = GetActorNumber(sender); int actorNumber2 = GetActorNumber(partner); if (actorNumber > 0 && actorNumber2 > 0) { SendToPartner(sender, partner, new object[6] { (byte)2, actorNumber, actorNumber2, sender.data.currentStamina, sender.data.extraStamina, sender.data.sinceUseStamina }); } } } private static void RestorePassiveStatus(CharacterAfflictions afflictions, STATUSTYPE statusType, float value) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)afflictions == (Object)null) { return; } float currentStatus = afflictions.GetCurrentStatus(statusType); if (Mathf.Abs(currentStatus - value) <= 0.0001f) { return; } suppressSendDepth++; try { afflictions.SetStatus(statusType, value, true); } finally { suppressSendDepth--; } } static ShareStamina() { STATUSTYPE[] array = new STATUSTYPE[9]; RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/); SharedStatusTypes = (STATUSTYPE[])(object)array; lastSharedStatusValues = new float[9]; syncedLastAddedTimes = new float[9]; } } public sealed class ShareStaminaRuntime : MonoBehaviour, IOnEventCallback { private bool active = false; public void Activate() { if (!active) { PhotonNetwork.AddCallbackTarget((object)this); active = true; } } public void Deactivate() { if (active) { PhotonNetwork.RemoveCallbackTarget((object)this); active = false; } } private void Update() { if (active) { ShareStamina.RuntimeUpdate(); } } public void OnEvent(EventData photonEvent) { if (active) { ShareStamina.HandlePhotonEvent(photonEvent); } } private void OnDestroy() { Deactivate(); } }