Decompiled source of OnlineCoopBeta v0.1.1
BepInEx\patchers\SkulOnlineCoopV1.Preloader.dll
Decompiled a week agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using Microsoft.CodeAnalysis; using Mono.Cecil; using Mono.Cecil.Cil; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("SkulOnlineCoopV1.Preloader")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("SkulOnlineCoopV1.Preloader")] [assembly: AssemblyTitle("SkulOnlineCoopV1.Preloader")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace SkulOnlineCoopV1.Preloader { public static class PlayerContextPreloader { public static IEnumerable<string> TargetDLLs => new string[1] { "Assembly-CSharp.dll" }; public static void Patch(ref AssemblyDefinition assembly) { //IL_0178: Unknown result type (might be due to invalid IL or missing references) ModuleDefinition mainModule = assembly.MainModule; TypeDefinition val = mainModule.GetType("Level.LevelManager") ?? throw new InvalidOperationException("Skul Level.LevelManager was not found."); TypeDefinition val2 = mainModule.GetType("Characters.Character") ?? throw new InvalidOperationException("Skul Characters.Character was not found."); MethodDefinition val3 = ((IEnumerable<MethodDefinition>)val.Methods).Single((MethodDefinition method) => ((MemberReference)method).Name == "get_player" && ((MethodReference)method).Parameters.Count == 0); MethodDefinition val4 = AddResolver(mainModule, val, val2, val3); int num = 0; foreach (MethodDefinition item in from method in AllTypes((IEnumerable<TypeDefinition>)mainModule.Types).SelectMany((TypeDefinition type) => (IEnumerable<MethodDefinition>)type.Methods) where method.HasBody select method) { if (item.DeclaringType == val4.DeclaringType) { continue; } Instruction[] array = item.Body.Instructions.ToArray(); foreach (Instruction val5 in array) { object operand = val5.Operand; MethodReference val6 = (MethodReference)((operand is MethodReference) ? operand : null); if (val6 != null && !(((MemberReference)((MemberReference)val6).DeclaringType).FullName != ((MemberReference)val).FullName) && !(((MemberReference)val6).Name != ((MemberReference)val3).Name) && val6.Parameters.Count == 0 && !(((MemberReference)val6.ReturnType).FullName != ((MemberReference)val2).FullName)) { val5.OpCode = OpCodes.Call; val5.Operand = val4; num++; } } } Console.WriteLine($"[SkulOnlineCoopV1] Rewrote {num} LevelManager.player reads to PlayerExecutionContext.Resolve."); } private static MethodDefinition AddResolver(ModuleDefinition module, TypeDefinition levelManager, TypeDefinition character, MethodDefinition getter) { //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Expected O, but got Unknown //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Expected O, but got Unknown //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Expected O, but got Unknown //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Expected O, but got Unknown //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Expected O, but got Unknown //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_018a: Unknown result type (might be due to invalid IL or missing references) //IL_0191: Expected O, but got Unknown //IL_019d: Unknown result type (might be due to invalid IL or missing references) //IL_01b9: Unknown result type (might be due to invalid IL or missing references) //IL_01dd: Unknown result type (might be due to invalid IL or missing references) //IL_01e4: Expected O, but got Unknown //IL_01f2: Unknown result type (might be due to invalid IL or missing references) //IL_01fc: Expected O, but got Unknown //IL_01fc: Unknown result type (might be due to invalid IL or missing references) //IL_0214: Unknown result type (might be due to invalid IL or missing references) //IL_0230: 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_0268: Unknown result type (might be due to invalid IL or missing references) //IL_0296: Unknown result type (might be due to invalid IL or missing references) //IL_02b1: Unknown result type (might be due to invalid IL or missing references) //IL_02cd: Unknown result type (might be due to invalid IL or missing references) TypeDefinition type = module.GetType("SkulOnlineCoopV1.Runtime.PlayerExecutionContext"); if (type != null) { return ((IEnumerable<MethodDefinition>)type.Methods).Single((MethodDefinition method) => ((MemberReference)method).Name == "Resolve"); } TypeDefinition val = new TypeDefinition("SkulOnlineCoopV1.Runtime", "PlayerExecutionContext", (TypeAttributes)1048961, module.TypeSystem.Object); module.Types.Add(val); FieldDefinition val2 = new FieldDefinition("_activeCharacter", (FieldAttributes)17, (TypeReference)(object)character); val.Fields.Add(val2); MethodDefinition val3 = new MethodDefinition("SetCurrent", (MethodAttributes)22, module.TypeSystem.Void); ((MethodReference)val3).Parameters.Add(new ParameterDefinition("player", (ParameterAttributes)0, (TypeReference)(object)character)); val3.Body.Instructions.Add(Instruction.Create(OpCodes.Ldarg_0)); val3.Body.Instructions.Add(Instruction.Create(OpCodes.Stsfld, (FieldReference)(object)val2)); val3.Body.Instructions.Add(Instruction.Create(OpCodes.Ret)); val.Methods.Add(val3); MethodDefinition val4 = new MethodDefinition("ClearCurrent", (MethodAttributes)22, module.TypeSystem.Void); val4.Body.Instructions.Add(Instruction.Create(OpCodes.Ldnull)); val4.Body.Instructions.Add(Instruction.Create(OpCodes.Stsfld, (FieldReference)(object)val2)); val4.Body.Instructions.Add(Instruction.Create(OpCodes.Ret)); val.Methods.Add(val4); MethodDefinition val5 = new MethodDefinition("GetCurrent", (MethodAttributes)22, (TypeReference)(object)character); val5.Body.Instructions.Add(Instruction.Create(OpCodes.Ldsfld, (FieldReference)(object)val2)); val5.Body.Instructions.Add(Instruction.Create(OpCodes.Ret)); val.Methods.Add(val5); MethodDefinition val6 = new MethodDefinition("Resolve", (MethodAttributes)22, (TypeReference)(object)character); ((MethodReference)val6).Parameters.Add(new ParameterDefinition("manager", (ParameterAttributes)0, (TypeReference)(object)levelManager)); Instruction val7 = Instruction.Create(OpCodes.Pop); val6.Body.Instructions.Add(Instruction.Create(OpCodes.Ldsfld, (FieldReference)(object)val2)); val6.Body.Instructions.Add(Instruction.Create(OpCodes.Dup)); val6.Body.Instructions.Add(Instruction.Create(OpCodes.Brfalse_S, val7)); val6.Body.Instructions.Add(Instruction.Create(OpCodes.Ret)); val6.Body.Instructions.Add(val7); val6.Body.Instructions.Add(Instruction.Create(OpCodes.Ldarg_0)); val6.Body.Instructions.Add(Instruction.Create(OpCodes.Callvirt, (MethodReference)(object)getter)); val6.Body.Instructions.Add(Instruction.Create(OpCodes.Ret)); val.Methods.Add(val6); return val6; } private static IEnumerable<TypeDefinition> AllTypes(IEnumerable<TypeDefinition> roots) { foreach (TypeDefinition type in roots) { yield return type; foreach (TypeDefinition item in AllTypes((IEnumerable<TypeDefinition>)type.NestedTypes)) { yield return item; } } } } }
BepInEx\plugins\SkulOnlineCoopV1.Runtime.dll
Decompiled a week ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Logging; using Characters; using Characters.AI; using Characters.Actions; using Characters.Controllers; using Characters.Gear; using Characters.Gear.Items; using Characters.Gear.Quintessences; using Characters.Gear.Weapons; using Characters.Operations.Attack; using Characters.Operations.Fx; using Characters.Player; using Characters.Projectiles; using Data; using GameResources; using HarmonyLib; using Level; using Level.Npc; using Microsoft.CodeAnalysis; using Services; using Singletons; using Steamworks; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("SkulOnlineCoopV1.Runtime")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("SkulOnlineCoopV1.Runtime")] [assembly: AssemblyTitle("SkulOnlineCoopV1.Runtime")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace SkulOnlineCoopV1.Runtime { [BepInPlugin("com.codex.skul.onlinecoop.v1.runtime", "Skul Online Co-op v1 Runtime", "1.0.88")] public sealed class CoopRuntimePlugin : BaseUnityPlugin { private struct ReplicatedAnimatorState { internal int StateHash; internal float NormalizedTime; } private sealed class GearReferenceComparer : IEqualityComparer<Gear> { internal static readonly GearReferenceComparer Instance = new GearReferenceComparer(); public bool Equals(Gear? left, Gear? right) { return left == right; } public int GetHashCode(Gear gear) { return RuntimeHelpers.GetHashCode(gear); } } private readonly struct PendingStage { internal readonly int Chapter; internal readonly int Stage; internal readonly int Path; internal readonly int Node; internal readonly int Seed; internal PendingStage(int chapter, int stage, int path, int node, int seed) { Chapter = chapter; Stage = stage; Path = path; Node = node; Seed = seed; } } internal readonly struct DismantleReward { internal readonly uint DropId; internal readonly Type Type; internal readonly int Amount; internal DismantleReward(uint dropId, Type type, int amount) { //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) DropId = dropId; Type = type; Amount = amount; } } private readonly struct PendingClientWorldDrop { internal readonly byte Kind; internal readonly string Key; internal readonly Vector3 Position; internal readonly DroppedGear? Dropped; internal PendingClientWorldDrop(byte kind, string key, Vector3 position, DroppedGear? dropped) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) Kind = kind; Key = key; Position = position; Dropped = dropped; } } internal static ManualLogSource Log; private Callback<LobbyCreated_t>? _lobbyCreated; private Callback<LobbyEnter_t>? _lobbyEntered; private Callback<GameLobbyJoinRequested_t>? _joinRequested; private Callback<P2PSessionRequest_t>? _p2pRequested; private CSteamID _lobbyId; private float _nextTransformAt; private const int P2pChannel = 92; private const byte Protocol = 54; private const byte PlayerTransformPacket = 1; private const byte PlayerActionPacket = 2; private const byte WeaponStatePacket = 3; private const byte EnemySnapshotPacket = 4; private const byte ItemStatePacket = 5; private const byte EnemyDamageRequestPacket = 6; private const byte MapTransitionRequestPacket = 7; private const byte MapTransitionCommitPacket = 8; private const byte StageRequestPacket = 9; private const byte StageStatePacket = 10; private const byte PlayerHealthAuthorityPacket = 11; private const byte EnemyActionPacket = 12; private const byte WorldGearSpawnPacket = 13; private const byte WorldGearInteractionRequestPacket = 14; private const byte WorldGearDespawnPacket = 15; private const byte WorldGearSpawnRequestPacket = 16; private const byte WorldGearDismantleRewardRequestPacket = 17; private const byte WorldGearDismantleRewardGrantPacket = 18; private const byte WorldGearSpawnAcknowledgementPacket = 19; private const byte RewardObjectInteractionRequestPacket = 20; private const byte RewardObjectConsumedPacket = 21; private const byte GatesActivatedPacket = 22; private const byte CastleExitRequestPacket = 23; private const byte CastleExitCommitPacket = 24; private const byte EnemyLineTextPacket = 25; private float _nextEnemySnapshotAt; private float _nextHostEnemyTargetRefreshAt; private int _clientEnemyMapId; private float _nextClientEnemyCandidateRefreshAt; private float _nextWorldDropAt; private int _clientDropMapId; private bool _clientWorldAuthorityEstablished; private readonly HashSet<uint> _pendingWorldGearDrops = new HashSet<uint>(); private readonly HashSet<uint> _advertisedWorldGearDrops = new HashSet<uint>(); private readonly HashSet<Gear> _requestedClientWorldGear = new HashSet<Gear>(GearReferenceComparer.Instance); private readonly HashSet<Gear> _replicatedClientGear = new HashSet<Gear>(GearReferenceComparer.Instance); private readonly Dictionary<uint, PendingClientWorldDrop> _pendingClientWorldDrops = new Dictionary<uint, PendingClientWorldDrop>(); private uint _nextChestRewardGroupId; private readonly Dictionary<uint, HashSet<uint>> _chestRewardDropIds = new Dictionary<uint, HashSet<uint>>(); private readonly Dictionary<uint, HashSet<uint>> _chestRewardSelections = new Dictionary<uint, HashSet<uint>>(); private readonly HashSet<Chest> _trackedHostChests = new HashSet<Chest>(); private uint _nextClientWorldDropRequestId; private int _replicatedWorldGearCreationDepth; private int _replicatedNativeDropCallDepth; private readonly HashSet<ulong> _applyingReplicatedItems = new HashSet<ulong>(); private bool _advertiseFreshRunLocalItems; private PendingStage? _pendingStage; private PendingStage? _lastAppliedHostStage; private bool _applyingHostStage; private bool _applyingAuthoritativeCastleExit; private bool _resetPendingRun; private float _nextStageAdvertAt; private float _nextStageRequestAt; private bool _awaitingInitialHostStage; private uint _localStateSequence; private bool _steamReady; private float _nextSteamInitializationAttempt; private readonly Dictionary<int, ReplicatedAnimatorState> _enemyAnimatorStates = new Dictionary<int, ReplicatedAnimatorState>(); private readonly Dictionary<int, CharacterHealthBar> _generatedEnemyHealthBars = new Dictionary<int, CharacterHealthBar>(); private readonly Dictionary<uint, float> _replicatedEnemyHealth = new Dictionary<uint, float>(); private readonly Dictionary<int, float> _replicatedEnemyHealthBarExpiry = new Dictionary<int, float>(); private readonly HashSet<DroppedRandomWeaponBox> _openedRandomWeaponBoxes = new HashSet<DroppedRandomWeaponBox>(); private readonly HashSet<uint> _loggedUnboundEnemySnapshots = new HashSet<uint>(); private readonly List<Character> _clientEnemyCandidates = new List<Character>(); private string _lastAdvertisedWeaponState = string.Empty; private readonly HashSet<string> _loggedLocalActionDiagnostics = new HashSet<string>(); internal static CoopRuntimePlugin? Instance { get; private set; } internal CoopPlayerRegistry Players { get; } = new CoopPlayerRegistry(); internal CoopWorldRegistry World { get; } = new CoopWorldRegistry(); internal CoopDropRegistry Drops { get; } = new CoopDropRegistry(); private bool CreatingReplicatedWorldGear => _replicatedWorldGearCreationDepth > 0; private bool CreatingReplicatedNativeDrop => _replicatedNativeDropCallDepth > 0; internal bool IsHostAuthority => IsHost(); private void Awake() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown Instance = this; Log = ((BaseUnityPlugin)this).Logger; Harmony val = new Harmony("com.codex.skul.onlinecoop.v1.runtime"); foreach (Type item in from candidate in ((object)this).GetType().Assembly.GetTypes() where candidate.GetCustomAttributes(typeof(HarmonyPatch), inherit: false).Length != 0 select candidate) { try { val.CreateClassProcessor(item).Patch(); } catch (Exception arg) { ((BaseUnityPlugin)this).Logger.LogError((object)$"Skipped Harmony patch {item.FullName}: {arg}"); } } } private bool EnsureSteamReady() { if (_steamReady) { return true; } if (Time.unscaledTime < _nextSteamInitializationAttempt) { return false; } _nextSteamInitializationAttempt = Time.unscaledTime + 1f; try { _lobbyCreated = Callback<LobbyCreated_t>.Create((DispatchDelegate<LobbyCreated_t>)OnLobbyCreated); _lobbyEntered = Callback<LobbyEnter_t>.Create((DispatchDelegate<LobbyEnter_t>)OnLobbyEntered); _joinRequested = Callback<GameLobbyJoinRequested_t>.Create((DispatchDelegate<GameLobbyJoinRequested_t>)OnJoinRequested); _p2pRequested = Callback<P2PSessionRequest_t>.Create((DispatchDelegate<P2PSessionRequest_t>)OnP2pRequested); SteamNetworking.AllowP2PPacketRelay(true); _steamReady = true; ((BaseUnityPlugin)this).Logger.LogInfo((object)"Steamworks callbacks initialized."); return true; } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogDebug((object)("Steamworks not ready yet: " + ex.Message)); return false; } } private void Update() { if (EnsureSteamReady()) { if (Input.GetKeyDown((KeyCode)287)) { CreateOrInviteLobby(); } if (Input.GetKeyDown((KeyCode)288)) { RefreshStageSync(); } if (Input.GetKeyDown((KeyCode)289)) { ApplyPendingStage(); } if (Input.GetKeyDown((KeyCode)290)) { LeaveLobby(); } RegisterLobbyPlayersWhenReady(); AdvertiseLocalLoadoutIfChanged(); ResetClientEnemyRegistryForMapChange(); RefreshClientEnemyCandidates(); ReceivePackets(); KeepReplicatedEnemyHealthBarsVisible(); RequestInitialHostStageUntilReceived(); EnforceHostWorldDropAuthority(); DisableClientEnemySimulation(); RefreshHostEnemyTargets(); SendLocalTransform(); SendEnemySnapshots(); SendWorldGearSpawns(); AdvertiseHostStageWhenReady(); } } private void OnDestroy() { LeaveLobby(); } private void CreateOrInviteLobby() { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) if (_lobbyId.m_SteamID != 0L) { SteamFriends.ActivateGameOverlayInviteDialog(_lobbyId); return; } SteamMatchmaking.CreateLobby((ELobbyType)1, 2); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Creating v1 two-player Steam lobby."); } private void OnLobbyCreated(LobbyCreated_t callback) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Invalid comparison between Unknown and I4 //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_005c: 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_0075: 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_0015: Unknown result type (might be due to invalid IL or missing references) if ((int)callback.m_eResult != 1) { ((BaseUnityPlugin)this).Logger.LogError((object)$"Lobby creation failed: {callback.m_eResult}"); return; } _lobbyId = new CSteamID(callback.m_ulSteamIDLobby); SteamMatchmaking.SetLobbyData(_lobbyId, "skul_online_coop_v1", "1"); SteamMatchmaking.SetLobbyData(_lobbyId, "host", SteamUser.GetSteamID().m_SteamID.ToString()); SteamFriends.ActivateGameOverlayInviteDialog(_lobbyId); } private void OnJoinRequested(GameLobbyJoinRequested_t callback) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) SteamMatchmaking.JoinLobby(callback.m_steamIDLobby); } private void OnLobbyEntered(LobbyEnter_t callback) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_003e: 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) _lobbyId = new CSteamID(callback.m_ulSteamIDLobby); if (SteamMatchmaking.GetLobbyData(_lobbyId, "skul_online_coop_v1") != "1") { ((BaseUnityPlugin)this).Logger.LogWarning((object)"Not a Skul v1 lobby; leaving."); SteamMatchmaking.LeaveLobby(_lobbyId); _lobbyId = default(CSteamID); } else { _awaitingInitialHostStage = !IsHost(); _nextStageRequestAt = 0f; } } private void OnP2pRequested(P2PSessionRequest_t callback) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) if (IsLobbyMember(callback.m_steamIDRemote)) { SteamNetworking.AcceptP2PSessionWithUser(callback.m_steamIDRemote); } } private void RegisterLobbyPlayersWhenReady() { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) if (_lobbyId.m_SteamID == 0L) { return; } Character localPlayer = GetLocalPlayer(); if ((Object)(object)localPlayer == (Object)null) { return; } ulong steamID = SteamUser.GetSteamID().m_SteamID; Players.RegisterLocal(steamID, localPlayer); if (_advertiseFreshRunLocalItems) { ItemInventory val = localPlayer.playerComponents?.inventory?.item; if ((Object)(object)val != (Object)null) { SendLocalItems(val); SendLocalLoadout(localPlayer); _advertiseFreshRunLocalItems = false; ((BaseUnityPlugin)this).Logger.LogInfo((object)"Advertised clean local inventory/loadout for the new run."); } } int numLobbyMembers = SteamMatchmaking.GetNumLobbyMembers(_lobbyId); for (int i = 0; i < numLobbyMembers; i++) { ulong steamID2 = SteamMatchmaking.GetLobbyMemberByIndex(_lobbyId, i).m_SteamID; if (steamID2 != steamID && !Players.TryGet(steamID2, out Character _) && (Object)(object)Players.CreateRemotePlayer(steamID2, ((Component)localPlayer).transform.position + Vector3.right * 1.5f) != (Object)null) { SendLocalLoadout(localPlayer); ItemInventory val2 = localPlayer.playerComponents?.inventory?.item; if ((Object)(object)val2 != (Object)null) { SendLocalItems(val2); } } } } internal static Character? GetLocalPlayer() { try { Service instance = Singleton<Service>.Instance; object result; if (instance == null) { result = null; } else { LevelManager levelManager = instance.levelManager; result = ((levelManager != null) ? levelManager.player : null); } return (Character?)result; } catch { return null; } } internal void PrepareForNativeNewRun() { if (_lobbyId.m_SteamID == 0L) { return; } ulong[] array = Players.RemoteOwners(); foreach (ulong num in array) { if (!Players.TryGet(num, out Character character)) { continue; } ItemInventory val = character.playerComponents?.inventory?.item; if ((Object)(object)val == (Object)null) { continue; } _applyingReplicatedItems.Add(num); try { using (Players.Enter(num)) { val.RemoveAll(); } } finally { _applyingReplicatedItems.Remove(num); } } _lastAdvertisedWeaponState = string.Empty; _advertiseFreshRunLocalItems = true; ((BaseUnityPlugin)this).Logger.LogInfo((object)"Cleared remote native item inventories before the new run."); } private void SendLocalTransform() { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_0383: Unknown result type (might be due to invalid IL or missing references) //IL_0388: Unknown result type (might be due to invalid IL or missing references) //IL_038a: Unknown result type (might be due to invalid IL or missing references) //IL_0391: Unknown result type (might be due to invalid IL or missing references) //IL_039d: Unknown result type (might be due to invalid IL or missing references) if (_lobbyId.m_SteamID == 0L || Time.unscaledTime < _nextTransformAt) { return; } Character localPlayer = GetLocalPlayer(); if ((Object)(object)localPlayer == (Object)null) { return; } _nextTransformAt = Time.unscaledTime + 1f / 30f; Vector3 position = ((Component)localPlayer).transform.position; byte[] array = new byte[51]; array[0] = 1; array[1] = 54; Buffer.BlockCopy(BitConverter.GetBytes(++_localStateSequence), 0, array, 2, 4); Buffer.BlockCopy(BitConverter.GetBytes(position.x), 0, array, 6, 4); Buffer.BlockCopy(BitConverter.GetBytes(position.y), 0, array, 10, 4); array[14] = (byte)localPlayer.lookingDirection; Buffer.BlockCopy(BitConverter.GetBytes(position.z), 0, array, 15, 4); Animator characterAnimator = GetCharacterAnimator(localPlayer); AnimatorStateInfo val = (AnimatorStateInfo)(((Object)(object)characterAnimator == (Object)null) ? default(AnimatorStateInfo) : characterAnimator.GetCurrentAnimatorStateInfo(0)); Buffer.BlockCopy(BitConverter.GetBytes((!((Object)(object)characterAnimator == (Object)null)) ? ((AnimatorStateInfo)(ref val)).fullPathHash : 0), 0, array, 19, 4); Buffer.BlockCopy(BitConverter.GetBytes(((Object)(object)characterAnimator == (Object)null) ? 0f : ((AnimatorStateInfo)(ref val)).normalizedTime), 0, array, 23, 4); int value = 0; if ((Object)(object)characterAnimator != (Object)null) { AnimatorClipInfo[] currentAnimatorClipInfo = characterAnimator.GetCurrentAnimatorClipInfo(0); if (currentAnimatorClipInfo != null && currentAnimatorClipInfo.Length != 0 && (Object)(object)((AnimatorClipInfo)(ref currentAnimatorClipInfo[0])).clip != (Object)null) { value = Animator.StringToHash(((Object)((AnimatorClipInfo)(ref currentAnimatorClipInfo[0])).clip).name); } } Buffer.BlockCopy(BitConverter.GetBytes(value), 0, array, 27, 4); CharacterHealth health = localPlayer.health; Buffer.BlockCopy(BitConverter.GetBytes(((Object)(object)health == (Object)null) ? 0f : ((float)((Health)health).currentHealth)), 0, array, 31, 4); Buffer.BlockCopy(BitConverter.GetBytes(((Object)(object)health == (Object)null) ? 0f : ((float)((Health)health).maximumHealth)), 0, array, 35, 4); array[39] = (byte)(((Object)(object)health != (Object)null && ((Health)health).dead) ? 1 : 0); object obj = AccessTools.Field(typeof(CharacterAnimationController), "parameter")?.GetValue(localPlayer.animationController); array[40] = (byte)((obj != null && (bool)(AccessTools.Field(obj.GetType(), "walk")?.GetValue(obj) ?? ((object)false))) ? 1 : 0); array[41] = (byte)((obj != null && (bool)(AccessTools.Field(obj.GetType(), "grounded")?.GetValue(obj) ?? ((object)false))) ? 1 : 0); Buffer.BlockCopy(BitConverter.GetBytes((obj == null) ? 0f : ((float)(AccessTools.Field(obj.GetType(), "movementSpeed")?.GetValue(obj) ?? ((object)0f)))), 0, array, 42, 4); Buffer.BlockCopy(BitConverter.GetBytes((obj == null) ? 0f : ((float)(AccessTools.Field(obj.GetType(), "ySpeed")?.GetValue(obj) ?? ((object)0f)))), 0, array, 46, 4); array[50] = (byte)((obj != null && (bool)(AccessTools.Field(obj.GetType(), "flipX")?.GetValue(obj) ?? ((object)false))) ? 1 : 0); foreach (CSteamID item in LobbyMembers()) { if (item.m_SteamID != SteamUser.GetSteamID().m_SteamID) { SteamNetworking.SendP2PPacket(item, array, (uint)array.Length, (EP2PSend)1, 92); } } } private void ReceivePackets() { //IL_0032: 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_0107: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Unknown result type (might be due to invalid IL or missing references) //IL_024e: Unknown result type (might be due to invalid IL or missing references) //IL_0279: Unknown result type (might be due to invalid IL or missing references) //IL_029d: Unknown result type (might be due to invalid IL or missing references) //IL_0579: Unknown result type (might be due to invalid IL or missing references) //IL_046f: Unknown result type (might be due to invalid IL or missing references) //IL_03a7: Unknown result type (might be due to invalid IL or missing references) //IL_0523: Unknown result type (might be due to invalid IL or missing references) uint num = default(uint); uint num2 = default(uint); CSteamID val = default(CSteamID); while (SteamNetworking.IsP2PPacketAvailable(ref num, 92) && num != 0 && num <= 512) { byte[] array = new byte[num]; if (!SteamNetworking.ReadP2PPacket(array, num, ref num2, ref val, 92) || num2 != num || !IsLobbyMember(val) || array.Length < 2 || array[1] != 54) { continue; } if (array[0] == 9 && array.Length == 2 && IsHost()) { SendStageState(val); } else if (array[0] == 10 && array.Length == 22) { ReceiveStageState(array); } else if (array[0] == 11 && array.Length == 11 && !IsHost()) { ApplyHostPlayerHealth(array); } else if (array[0] == 12 && array.Length >= 21 && !IsHost()) { ApplyEnemyAction(array); } else if (array[0] == 13 && array.Length >= 16 && !IsHost()) { ReceiveWorldGearSpawn(array); } else if (array[0] == 16 && array.Length >= 16 && IsHost()) { ReceiveWorldGearSpawnRequest(val, array); } else if (array[0] == 19 && array.Length == 6 && !IsHost()) { ReceiveWorldGearSpawnAcknowledgement(array); } else if (array[0] == 14 && array.Length == 7 && IsHost()) { ApplyWorldGearInteractionRequest(val, array); } else if (array[0] == 15 && array.Length == 6 && !IsHost()) { ApplyWorldGearDespawn(array); } else if (array[0] == 20 && array.Length == 7 && IsHost()) { ApplyRewardObjectInteractionRequest(val, array); } else if (array[0] == 21 && array.Length == 7 && !IsHost()) { ApplyRewardObjectConsumed(array); } else if (array[0] == 22 && array.Length == 2 && !IsHost()) { ActivateClientMapGates(); } else if (array[0] == 23 && array.Length == 3 && IsHost()) { BeginHostCastleExit((Type)array[2]); } else if (array[0] == 24 && array.Length == 7 && !IsHost()) { ApplyHostCastleExit((Type)array[2], BitConverter.ToInt32(array, 3)); } else if (array[0] == 25 && array.Length >= 19 && !IsHost()) { ApplyEnemyLineText(array); } else { if (!Players.TryGet(val.m_SteamID, out Character _)) { continue; } if (array[0] == 1 && array.Length == 51) { Players.ApplyState(val.m_SteamID, BitConverter.ToUInt32(array, 2), new Vector3(BitConverter.ToSingle(array, 6), BitConverter.ToSingle(array, 10), BitConverter.ToSingle(array, 15)), (LookingDirection)array[14], BitConverter.ToInt32(array, 19), BitConverter.ToSingle(array, 23), BitConverter.ToInt32(array, 27), BitConverter.ToSingle(array, 31), BitConverter.ToSingle(array, 35), array[39] != 0, array[40] != 0, array[41] != 0, BitConverter.ToSingle(array, 42), BitConverter.ToSingle(array, 46), array[50] != 0); } else if (array[0] == 2 && array.Length >= 15) { byte b = array[8]; byte b2 = array[9]; byte b3 = array[14]; if (array.Length == 15 + b + b2 + b3) { short actionIndex = BitConverter.ToInt16(array, 10); short motionIndex = BitConverter.ToInt16(array, 12); string motionKey = Encoding.UTF8.GetString(array, 15, b); string weaponKey = ((b2 == 0) ? string.Empty : Encoding.UTF8.GetString(array, 15 + b, b2)); string actionPath = ((b3 == 0) ? string.Empty : Encoding.UTF8.GetString(array, 15 + b + b2, b3)); Players.ApplyAction(val.m_SteamID, motionKey, weaponKey, actionPath, actionIndex, motionIndex, BitConverter.ToSingle(array, 3), array[7] != 0, (LookingDirection)array[2]); } } else if (array[0] == 3 && array.Length >= 4) { byte selectedSlot = array[2]; byte b4 = array[3]; int num3 = 4; string[] array2 = new string[b4]; bool flag = b4 <= 2; int num4 = 0; while (flag && num4 < b4) { if (num3 >= array.Length || num3 + 1 + array[num3] > array.Length) { flag = false; break; } byte b5 = array[num3++]; array2[num4] = Encoding.UTF8.GetString(array, num3, b5); num3 += b5; num4++; } if (flag && num3 == array.Length) { Players.ApplyLoadout(val.m_SteamID, selectedSlot, array2); } } else if (array[0] == 5 && array.Length >= 11) { ulong num5 = BitConverter.ToUInt64(array, 2); byte b6 = array[10]; string[] array3 = new string[b6]; int num6 = 11; bool flag2 = num5 != 0; int num7 = 0; while (flag2 && num7 < b6) { if (num6 >= array.Length) { flag2 = false; break; } byte b7 = array[num6++]; if (num6 + b7 > array.Length) { flag2 = false; break; } array3[num7] = Encoding.UTF8.GetString(array, num6, b7); num6 += b7; num7++; } if (flag2 && num6 == array.Length && num5 != SteamUser.GetSteamID().m_SteamID) { ((MonoBehaviour)this).StartCoroutine(ApplyRemoteItems(num5, array3)); } } else if (array[0] == 4 && array.Length == 45 && !IsHost()) { ApplyEnemySnapshot(array); } else if (array[0] == 6 && array.Length == 25 && IsHost()) { ApplyClientEnemyDamage(val, array); } else if (array[0] == 7 && array.Length == 3 && IsHost()) { CommitMapTransition((NodeIndex)array[2]); } else if (array[0] == 8 && array.Length == 3) { ApplyMapTransition((NodeIndex)array[2]); } } } } internal void SendLocalWeapon(WeaponInventory inventory, Weapon weapon) { //IL_017a: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Unknown result type (might be due to invalid IL or missing references) Character localPlayer = GetLocalPlayer(); if (_lobbyId.m_SteamID == 0L || (Object)(object)((localPlayer == null) ? null : localPlayer.playerComponents?.inventory?.weapon) != (Object)(object)inventory || (Object)(object)weapon == (Object)null || !(AccessTools.Field(typeof(WeaponInventory), "weapons")?.GetValue(inventory) is Weapon[] array) || array.Length == 0) { return; } int num = Math.Min(array.Length, 2); string[] array2 = new string[num]; byte[][] array3 = new byte[num][]; int num2 = 4; for (int i = 0; i < num; i++) { array2[i] = (((Object)(object)array[i] == (Object)null) ? string.Empty : GetWeaponNetworkKey(array[i])); array3[i] = Encoding.UTF8.GetBytes(array2[i]); if (array3[i].Length > 255) { return; } num2 += 1 + array3[i].Length; } byte[] array4 = new byte[num2]; array4[0] = 3; array4[1] = 54; array4[2] = (byte)Mathf.Clamp(inventory.currentIndex, 0, num - 1); array4[3] = (byte)num; int num3 = 4; for (int j = 0; j < num; j++) { array4[num3++] = (byte)array3[j].Length; Buffer.BlockCopy(array3[j], 0, array4, num3, array3[j].Length); num3 += array3[j].Length; } foreach (CSteamID item in LobbyMembers()) { if (item.m_SteamID != SteamUser.GetSteamID().m_SteamID) { SteamNetworking.SendP2PPacket(item, array4, (uint)array4.Length, (EP2PSend)2, 92); } } } private void AdvertiseLocalLoadoutIfChanged() { if (_lobbyId.m_SteamID == 0L) { return; } Character? localPlayer = GetLocalPlayer(); WeaponInventory val = ((localPlayer == null) ? null : localPlayer.playerComponents?.inventory?.weapon); Weapon[] array = (((Object)(object)val == (Object)null) ? null : (AccessTools.Field(typeof(WeaponInventory), "weapons")?.GetValue(val) as Weapon[])); if ((Object)(object)val == (Object)null || array == null || array.Length == 0) { return; } int num = Math.Min(array.Length, 2); string[] array2 = new string[num]; for (int i = 0; i < num; i++) { array2[i] = (((Object)(object)array[i] == (Object)null) ? string.Empty : GetWeaponNetworkKey(array[i])); } string text = val.currentIndex + ":" + string.Join("|", array2); if (!string.Equals(text, _lastAdvertisedWeaponState, StringComparison.Ordinal)) { _lastAdvertisedWeaponState = text; Weapon val2 = val.polymorphOrCurrent ?? val.current; if ((Object)(object)val2 != (Object)null) { SendLocalWeapon(val, val2); } } } private void SendLocalLoadout(Character local) { WeaponInventory val = local.playerComponents?.inventory?.weapon; Weapon val2 = ((val != null) ? val.polymorphOrCurrent : null); if ((Object)(object)val2 != (Object)null) { SendLocalWeapon(val, val2); } } internal void SendLocalItems(ItemInventory inventory) { //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_018b: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Unknown result type (might be due to invalid IL or missing references) if (_lobbyId.m_SteamID == 0L || (Object)(object)inventory == (Object)null) { return; } object? obj = AccessTools.Field(typeof(ItemInventory), "_character")?.GetValue(inventory); Character val = (Character)((obj is Character) ? obj : null); if ((Object)(object)val == (Object)null || !Players.TryGetSteamId(val, out var steamId) || _applyingReplicatedItems.Contains(steamId)) { return; } List<Item> items = inventory.items; if (items == null || items.Count > 255) { return; } byte[][] array = new byte[items.Count][]; int num = 11; for (int i = 0; i < items.Count; i++) { Item val2 = items[i]; if ((Object)(object)val2 == (Object)null) { array[i] = Array.Empty<byte>(); num++; continue; } if (!TryGetItemNetworkKey(val2, out string key)) { return; } array[i] = Encoding.UTF8.GetBytes(key); if (array[i].Length > 255) { return; } num += 1 + array[i].Length; } byte[] array2 = new byte[num]; array2[0] = 5; array2[1] = 54; Buffer.BlockCopy(BitConverter.GetBytes(steamId), 0, array2, 2, 8); array2[10] = (byte)items.Count; int num2 = 11; for (int j = 0; j < array.Length; j++) { array2[num2++] = (byte)array[j].Length; Buffer.BlockCopy(array[j], 0, array2, num2, array[j].Length); num2 += array[j].Length; } foreach (CSteamID item in LobbyMembers()) { if (item.m_SteamID != SteamUser.GetSteamID().m_SteamID) { SteamNetworking.SendP2PPacket(item, array2, (uint)array2.Length, (EP2PSend)2, 92); } } } private IEnumerator ApplyRemoteItems(ulong owner, string[] keys) { if (!Players.TryGet(owner, out Character remote)) { yield break; } ItemInventory inventory = remote.playerComponents?.inventory?.item; GearResource resources = GearResource.instance; if ((Object)(object)inventory == (Object)null || (Object)(object)resources == (Object)null) { yield break; } _applyingReplicatedItems.Add(owner); try { using (Players.Enter(owner)) { inventory.RemoveAll(); } ItemReference val = default(ItemReference); foreach (string text in keys) { if (string.IsNullOrEmpty(text)) { continue; } if (!resources.TryGetItemReferenceByGuid(text, ref val) && !resources.TryGetItemReferenceByName(text, ref val)) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Remote item '" + text + "' could not be resolved.")); continue; } ItemRequest request = val.LoadAsync(); while (!((Request<Item>)(object)request).isDone) { yield return null; } if ((Object)(object)((Request<Item>)(object)request).asset != (Object)null) { using (Players.Enter(owner)) { inventory.TryEquip(((Request<Item>)(object)request).asset.Instantiate()); } } } using (Players.Enter(owner)) { PlayerComponents playerComponents = remote.playerComponents; if (playerComponents != null) { Inventory inventory2 = playerComponents.inventory; if (inventory2 != null) { inventory2.UpdateSynergy(); } } } } finally { _applyingReplicatedItems.Remove(owner); } } internal void SendLocalAction(Character character, Motion motion, float speedMultiplier, bool triggerOnStartAction) { //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_0255: Unknown result type (might be due to invalid IL or missing references) //IL_025a: Unknown result type (might be due to invalid IL or missing references) //IL_025c: Unknown result type (might be due to invalid IL or missing references) //IL_0263: Unknown result type (might be due to invalid IL or missing references) //IL_026f: Unknown result type (might be due to invalid IL or missing references) if (_lobbyId.m_SteamID == 0L || (Object)(object)character != (Object)(object)GetLocalPlayer() || (Object)(object)motion == (Object)null) { return; } byte[] bytes = Encoding.UTF8.GetBytes(motion.key ?? string.Empty); PlayerComponents playerComponents = character.playerComponents; object obj; if (playerComponents == null) { obj = null; } else { Inventory inventory = playerComponents.inventory; if (inventory == null) { obj = null; } else { WeaponInventory weapon = inventory.weapon; obj = ((weapon != null) ? weapon.polymorphOrCurrent : null); } } Weapon val = (Weapon)obj; byte[] array = (((Object)(object)val == (Object)null) ? Array.Empty<byte>() : Encoding.UTF8.GetBytes(GetWeaponNetworkKey(val))); TryGetMotionIdentity(character, motion, val, out string actionPath, out int motionIndex); byte[] bytes2 = Encoding.UTF8.GetBytes(actionPath); if (bytes.Length > 255 || array.Length > 255 || bytes2.Length > 255) { return; } TryGetMotionIndices(character, motion, out var actionIndex, out var motionIndex2); byte[] array2 = new byte[15 + bytes.Length + array.Length + bytes2.Length]; array2[0] = 2; array2[1] = 54; array2[2] = (byte)character.lookingDirection; Buffer.BlockCopy(BitConverter.GetBytes(speedMultiplier), 0, array2, 3, 4); array2[7] = (triggerOnStartAction ? ((byte)1) : ((byte)0)); array2[8] = (byte)bytes.Length; array2[9] = (byte)array.Length; Buffer.BlockCopy(BitConverter.GetBytes((short)actionIndex), 0, array2, 10, 2); Buffer.BlockCopy(BitConverter.GetBytes((short)motionIndex), 0, array2, 12, 2); array2[14] = (byte)bytes2.Length; Buffer.BlockCopy(bytes, 0, array2, 15, bytes.Length); if (array.Length != 0) { Buffer.BlockCopy(array, 0, array2, 15 + bytes.Length, array.Length); } if (bytes2.Length != 0) { Buffer.BlockCopy(bytes2, 0, array2, 15 + bytes.Length + array.Length, bytes2.Length); } string item = "sent|" + (motion.key ?? "<empty>") + "|" + actionIndex + ":" + motionIndex2; if (_loggedLocalActionDiagnostics.Add(item)) { ((BaseUnityPlugin)this).Logger.LogInfo((object)string.Format("Sent native local motion '{0}' path '{1}' [{2}] on weapon '{3}'.", motion.key ?? "<empty>", actionPath, motionIndex, ((val != null) ? ((Object)val).name : null) ?? "<none>")); } foreach (CSteamID item2 in LobbyMembers()) { if (item2.m_SteamID != SteamUser.GetSteamID().m_SteamID) { SteamNetworking.SendP2PPacket(item2, array2, (uint)array2.Length, (EP2PSend)2, 92); } } } internal void NotifyCharacterAction(Character character, Motion motion, float speedMultiplier, bool triggerOnStartAction) { if ((Object)(object)character == (Object)(object)GetLocalPlayer()) { SendLocalAction(character, motion, speedMultiplier, triggerOnStartAction); } else if (IsHost() && IsEnemy(character)) { SendEnemyAction(character, motion, speedMultiplier, triggerOnStartAction); } } private void SendEnemyAction(Character enemy, Motion motion, float speedMultiplier, bool triggerOnStartAction) { //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0114: 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) if (_lobbyId.m_SteamID == 0L || (Object)(object)motion == (Object)null || string.IsNullOrEmpty(motion.key)) { return; } byte[] bytes = Encoding.UTF8.GetBytes(motion.key); if (bytes.Length > 255) { return; } ulong steamId = 0uL; AIController val = ((Component)enemy).GetComponent<AIController>() ?? ((Component)enemy).GetComponentInChildren<AIController>(true); if ((Object)(object)((val != null) ? val.target : null) != (Object)null) { Players.TryGetSteamId(val.target, out steamId); } byte[] array = new byte[21 + bytes.Length]; array[0] = 12; array[1] = 54; Buffer.BlockCopy(BitConverter.GetBytes(World.GetOrAssignHostUnit(enemy)), 0, array, 2, 4); array[6] = (byte)enemy.lookingDirection; Buffer.BlockCopy(BitConverter.GetBytes(speedMultiplier), 0, array, 7, 4); array[11] = (triggerOnStartAction ? ((byte)1) : ((byte)0)); Buffer.BlockCopy(BitConverter.GetBytes(steamId), 0, array, 12, 8); array[20] = (byte)bytes.Length; Buffer.BlockCopy(bytes, 0, array, 21, bytes.Length); foreach (CSteamID item in LobbyMembers()) { if (item.m_SteamID != SteamUser.GetSteamID().m_SteamID) { SteamNetworking.SendP2PPacket(item, array, (uint)array.Length, (EP2PSend)2, 92); } } } private static bool TryGetMotionIndices(Character character, Motion motion, out int actionIndex, out int motionIndex) { actionIndex = -1; motionIndex = -1; if (!(AccessTools.Property(typeof(Character), "actions")?.GetValue(character, null) is IList list)) { return false; } for (int i = 0; i < list.Count; i++) { if (!(AccessTools.Property(list[i].GetType(), "motions")?.GetValue(list[i], null) is Array array)) { continue; } for (int j = 0; j < array.Length; j++) { if (array.GetValue(j) == motion) { actionIndex = i; motionIndex = j; return true; } } } return false; } internal static Motion? FindMotion(Character character, string motionKey, Weapon? preferredWeapon = null) { if (!(AccessTools.Property(typeof(Character), "actions")?.GetValue(character, null) is IList list) || string.IsNullOrEmpty(motionKey)) { return null; } for (int i = 0; i < list.Count; i++) { if (!(AccessTools.Property(list[i].GetType(), "motions")?.GetValue(list[i], null) is Array array)) { continue; } for (int j = 0; j < array.Length; j++) { object? value = array.GetValue(j); Motion val = (Motion)((value is Motion) ? value : null); if ((Object)(object)val != (Object)null && string.Equals(val.key, motionKey, StringComparison.Ordinal) && ((Object)(object)preferredWeapon == (Object)null || (Object)(object)((Component)val).GetComponentInParent<Weapon>() == (Object)(object)preferredWeapon)) { return val; } } } return null; } internal static Motion? FindMotion(Character character, int actionIndex, int motionIndex, Weapon? preferredWeapon) { if (!(AccessTools.Property(typeof(Character), "actions")?.GetValue(character, null) is IList list) || actionIndex < 0 || actionIndex >= list.Count || motionIndex < 0) { return null; } object obj = list[actionIndex]; if (obj == null) { return null; } if (!(AccessTools.Property(obj.GetType(), "motions")?.GetValue(obj, null) is Array array) || motionIndex >= array.Length) { return null; } object? value = array.GetValue(motionIndex); Motion val = (Motion)((value is Motion) ? value : null); if ((Object)(object)val == (Object)null || ((Object)(object)preferredWeapon != (Object)null && (Object)(object)((Component)val).GetComponentInParent<Weapon>() != (Object)(object)preferredWeapon)) { return null; } return val; } private static void TryGetMotionIdentity(Character character, Motion motion, Weapon? activeWeapon, out string actionPath, out int motionIndex) { actionPath = string.Empty; motionIndex = -1; Action action = motion.action; if ((Object)(object)action == (Object)null) { return; } Transform val = (((Object)(object)activeWeapon != (Object)null && ((Component)action).transform.IsChildOf(((Component)activeWeapon).transform)) ? ((Component)activeWeapon).transform : ((Component)character).transform); actionPath = (((Object)(object)val == (Object)(object)((activeWeapon != null) ? ((Component)activeWeapon).transform : null)) ? "W:" : "C:") + RelativeTransformPath(((Component)action).transform, val); if (!(AccessTools.Property(((object)action).GetType(), "motions")?.GetValue(action, null) is Array array)) { return; } for (int i = 0; i < array.Length; i++) { if (array.GetValue(i) == motion) { motionIndex = i; break; } } } internal static Motion? FindMotion(Character character, string actionPath, int motionIndex, Weapon? preferredWeapon) { if (string.IsNullOrEmpty(actionPath) || motionIndex < 0 || actionPath.Length < 3 || actionPath[1] != ':') { return null; } Transform val = ((actionPath[0] == 'W' && (Object)(object)preferredWeapon != (Object)null) ? ((Component)preferredWeapon).transform : ((Component)character).transform); string b = actionPath.Substring(2); Action[] componentsInChildren = ((Component)val).GetComponentsInChildren<Action>(true); foreach (Action val2 in componentsInChildren) { if (string.Equals(RelativeTransformPath(((Component)val2).transform, val), b, StringComparison.Ordinal) && AccessTools.Property(((object)val2).GetType(), "motions")?.GetValue(val2, null) is Array array && motionIndex < array.Length) { object? value = array.GetValue(motionIndex); return (Motion?)((value is Motion) ? value : null); } } return null; } private static string RelativeTransformPath(Transform target, Transform root) { if ((Object)(object)target == (Object)(object)root) { return "."; } Stack<string> stack = new Stack<string>(); Transform val = target; while ((Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)root) { stack.Push(((Object)val).name + "#" + val.GetSiblingIndex()); val = val.parent; } if (!((Object)(object)val == (Object)(object)root)) { return string.Empty; } return string.Join("/", stack.ToArray()); } private static CharacterAnimation? GetCharacterAnimation(Character character) { try { PlayerComponents playerComponents = character.playerComponents; object obj; if (playerComponents == null) { obj = null; } else { Inventory inventory = playerComponents.inventory; if (inventory == null) { obj = null; } else { WeaponInventory weapon = inventory.weapon; obj = ((weapon != null) ? weapon.polymorphOrCurrent : null); } } Weapon val = (Weapon)obj; if ((Object)(object)((val != null) ? val.characterAnimation : null) != (Object)null && (Object)(object)GetAnimationRenderer(val.characterAnimation) != (Object)null) { return val.characterAnimation; } return ((Component)character).GetComponentInChildren<CharacterAnimation>(true); } catch { return null; } } private static SpriteRenderer? GetAnimationRenderer(CharacterAnimation animation) { object? obj = AccessTools.Field(typeof(CharacterAnimation), "_spriteRenderer")?.GetValue(animation); return (SpriteRenderer?)((obj is SpriteRenderer) ? obj : null); } internal static Animator? GetCharacterAnimator(Character character) { CharacterAnimation characterAnimation = GetCharacterAnimation(character); if (!((Object)(object)characterAnimation == (Object)null)) { object? obj = AccessTools.Field(typeof(CharacterAnimation), "_animator")?.GetValue(characterAnimation); return (Animator?)((obj is Animator) ? obj : null); } return null; } private static string GetWeaponNetworkKey(Weapon weapon) { GearResource instance = GearResource.instance; WeaponReference val = default(WeaponReference); if ((Object)(object)instance != (Object)null && instance.TryGetWeaponReferenceByName(((Object)weapon).name, ref val)) { return ((GearReference)val).guid; } return ((Object)weapon).name; } private static bool TryGetItemNetworkKey(Item item, out string key) { GearResource instance = GearResource.instance; ItemReference val = default(ItemReference); if ((Object)(object)instance != (Object)null && instance.TryGetItemReferenceByName(((Object)item).name, ref val)) { key = ((GearReference)val).guid; return !string.IsNullOrEmpty(key); } key = (((Object)(object)item == (Object)null) ? string.Empty : ((Object)item).name); return !string.IsNullOrEmpty(key); } private IEnumerable<CSteamID> LobbyMembers() { int count = SteamMatchmaking.GetNumLobbyMembers(_lobbyId); for (int index = 0; index < count; index++) { yield return SteamMatchmaking.GetLobbyMemberByIndex(_lobbyId, index); } } private bool IsLobbyMember(CSteamID candidate) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) foreach (CSteamID item in LobbyMembers()) { if (item.m_SteamID == candidate.m_SteamID) { return true; } } return false; } internal bool IsRemoteCharacter(Character character) { return Players.IsRemote(character); } internal void NotifyHostRemotePlayerHealth(Health health) { //IL_008c: Unknown result type (might be due to invalid IL or missing references) if (_lobbyId.m_SteamID != 0L && IsHost()) { Character val = ((Component)health).GetComponent<Character>() ?? ((Component)health).GetComponentInParent<Character>(); if (!((Object)(object)val == (Object)null) && Players.TryGetOwner(val, out var steamId)) { byte[] array = new byte[11] { 11, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; Buffer.BlockCopy(BitConverter.GetBytes((float)health.currentHealth), 0, array, 2, 4); Buffer.BlockCopy(BitConverter.GetBytes((float)health.maximumHealth), 0, array, 6, 4); array[10] = (health.dead ? ((byte)1) : ((byte)0)); SteamNetworking.SendP2PPacket(new CSteamID(steamId), array, (uint)array.Length, (EP2PSend)2, 92); } } } internal void NotifyHostEnemyHealth(Health health) { if (_lobbyId.m_SteamID != 0L && IsHost()) { Character val = ((Component)health).GetComponent<Character>() ?? ((Component)health).GetComponentInParent<Character>(); if (!((Object)(object)val == (Object)null) && IsEnemy(val)) { SendEnemySnapshot(val, (EP2PSend)2, tookDamageEvent: true); } } } private static void ApplyHostPlayerHealth(byte[] packet) { Character? localPlayer = GetLocalPlayer(); CharacterHealth val = ((localPlayer != null) ? localPlayer.health : null); if (!((Object)(object)val == (Object)null)) { float num = BitConverter.ToSingle(packet, 6); float num2 = BitConverter.ToSingle(packet, 2); if (num > 0f && !float.IsNaN(num2) && !float.IsInfinity(num2)) { ((Health)val).SetHealth((double)Mathf.Clamp(num2, 0f, num), (double)num); } if (packet[10] != 0 && !((Health)val).dead) { ((Health)val).TryKill(); } } } internal bool IsHost() { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) if (_lobbyId.m_SteamID != 0L) { return SteamMatchmaking.GetLobbyData(_lobbyId, "host") == SteamUser.GetSteamID().m_SteamID.ToString(); } return false; } private void SendWorldGearSpawns() { //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_012b: 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) //IL_01b9: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_01d6: Unknown result type (might be due to invalid IL or missing references) //IL_01d8: Unknown result type (might be due to invalid IL or missing references) //IL_01df: Unknown result type (might be due to invalid IL or missing references) //IL_01eb: Unknown result type (might be due to invalid IL or missing references) if (!IsHost() || Time.unscaledTime < _nextWorldDropAt) { return; } _nextWorldDropAt = Time.unscaledTime + 1f / 30f; Drops.PruneDestroyed(); HashSet<uint> currentlyAlive = new HashSet<uint>(); DroppedGear[] array = Object.FindObjectsOfType<DroppedGear>(); foreach (DroppedGear val in array) { Gear gear = val.gear; if ((Object)(object)gear == (Object)null || !TryGetWorldGearKey(gear, out byte kind, out string key)) { continue; } byte[] bytes = Encoding.UTF8.GetBytes(key); if (bytes.Length == 0 || bytes.Length > 255) { continue; } Vector3 position = ((Component)val).transform.position; uint orAssignHostDrop = Drops.GetOrAssignHostDrop(val); currentlyAlive.Add(orAssignHostDrop); if (!_advertisedWorldGearDrops.Contains(orAssignHostDrop)) { ((BaseUnityPlugin)this).Logger.LogInfo((object)$"Host world scan registered drop {orAssignHostDrop}: '{key}' at {position}."); } byte[] array2 = new byte[25 + bytes.Length]; array2[0] = 13; array2[1] = 54; Buffer.BlockCopy(BitConverter.GetBytes(orAssignHostDrop), 0, array2, 2, 4); array2[6] = kind; Buffer.BlockCopy(BitConverter.GetBytes(position.x), 0, array2, 7, 4); Buffer.BlockCopy(BitConverter.GetBytes(position.y), 0, array2, 11, 4); array2[15] = (byte)bytes.Length; Buffer.BlockCopy(bytes, 0, array2, 16, bytes.Length); Buffer.BlockCopy(BitConverter.GetBytes(Drops.GetChestRewardGroup(orAssignHostDrop)), 0, array2, 16 + bytes.Length, 4); Buffer.BlockCopy(BitConverter.GetBytes(val.price), 0, array2, 20 + bytes.Length, 4); array2[24 + bytes.Length] = (byte)val.priceCurrency; foreach (CSteamID item in LobbyMembers()) { if (item.m_SteamID != SteamUser.GetSteamID().m_SteamID) { SteamNetworking.SendP2PPacket(item, array2, (uint)array2.Length, (EP2PSend)2, 92); } } } uint[] array3 = _advertisedWorldGearDrops.Where((uint item) => !currentlyAlive.Contains(item)).ToArray(); foreach (uint id in array3) { SendWorldGearDespawn(id); } _advertisedWorldGearDrops.UnionWith(currentlyAlive); } private static bool TryGetWorldGearKey(Gear gear, out byte kind, out string key) { GearResource instance = GearResource.instance; key = string.Empty; kind = 0; if ((Object)(object)instance == (Object)null) { return false; } Weapon val = (Weapon)(object)((gear is Weapon) ? gear : null); if (val != null) { kind = 0; key = GetWeaponNetworkKey(val); return !string.IsNullOrEmpty(key); } Item val2 = (Item)(object)((gear is Item) ? gear : null); if (val2 != null) { kind = 1; ItemReference val3 = default(ItemReference); if (instance.TryGetItemReferenceByName(((Object)val2).name, ref val3)) { key = ((GearReference)val3).guid; } return !string.IsNullOrEmpty(key); } Quintessence val4 = (Quintessence)(object)((gear is Quintessence) ? gear : null); if (val4 != null) { kind = 2; EssenceReference val5 = default(EssenceReference); if (instance.TryGetEssenceReferenceByName(((Object)val4).name, ref val5)) { key = ((GearReference)val5).guid; } return !string.IsNullOrEmpty(key); } return false; } private void ReceiveWorldGearSpawn(byte[] packet) { //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Unknown result type (might be due to invalid IL or missing references) byte b = packet[15]; if (b == 0 || packet.Length != 25 + b) { return; } Map instance = Map.Instance; int num = ((!((Object)(object)instance == (Object)null)) ? ((Object)instance).GetInstanceID() : 0); if (!_clientWorldAuthorityEstablished || _clientDropMapId != num) { _clientWorldAuthorityEstablished = true; _clientDropMapId = num; Drops.Clear(); _pendingWorldGearDrops.Clear(); _requestedClientWorldGear.Clear(); _replicatedClientGear.Clear(); DroppedGear[] array = Object.FindObjectsOfType<DroppedGear>(); for (int i = 0; i < array.Length; i++) { Object.Destroy((Object)(object)((Component)array[i]).gameObject); } } uint num2 = BitConverter.ToUInt32(packet, 2); if (num2 != 0) { byte kind = packet[6]; string key = Encoding.UTF8.GetString(packet, 16, b); Vector3 position = default(Vector3); ((Vector3)(ref position))..ctor(BitConverter.ToSingle(packet, 7), BitConverter.ToSingle(packet, 11), 0f); uint num3 = BitConverter.ToUInt32(packet, 16 + b); int num4 = BitConverter.ToInt32(packet, 20 + b); Type priceCurrency = (Type)packet[24 + b]; DroppedGear val = Drops.TryGetDrop(num2); if ((Object)(object)val != (Object)null) { ((Component)val).transform.position = position; val.price = Mathf.Max(0, num4); val.priceCurrency = priceCurrency; Drops.SetChestRewardGroup(num2, num3); } else if (!_pendingWorldGearDrops.Contains(num2)) { RetireMatchingTemporaryClientDrop(kind, key, position); _pendingWorldGearDrops.Add(num2); ((MonoBehaviour)this).StartCoroutine(CCreateWorldGearDrop(num2, kind, key, position, num3, Mathf.Max(0, num4), priceCurrency)); } } } private void ReceiveWorldGearSpawnRequest(CSteamID sender, byte[] packet) { //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) byte b = packet[15]; if (b == 0 || packet.Length != 16 + b) { return; } byte b2 = packet[2]; if (b2 <= 2) { uint num = BitConverter.ToUInt32(packet, 3); if (num != 0) { Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(BitConverter.ToSingle(packet, 7), BitConverter.ToSingle(packet, 11), 0f); string text = Encoding.UTF8.GetString(packet, 16, b); ((BaseUnityPlugin)this).Logger.LogInfo((object)$"Host accepted client world-drop request {num} from {sender.m_SteamID}: kind {b2}, key '{text}', at {val}."); ((MonoBehaviour)this).StartCoroutine(CCreateHostRequestedWorldGear(sender, num, b2, text, val)); } } } private IEnumerator CCreateHostRequestedWorldGear(CSteamID requester, uint requestId, byte kind, string key, Vector3 position) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_002b: 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) GearResource instance = GearResource.instance; Service instance2 = Singleton<Service>.Instance; LevelManager manager = ((instance2 != null) ? instance2.levelManager : null); if ((Object)(object)instance == (Object)null || (Object)(object)manager == (Object)null) { yield break; } Gear created = null; WeaponReference val = default(WeaponReference); ItemReference val2 = default(ItemReference); EssenceReference val3 = default(EssenceReference); if (kind == 0 && (instance.TryGetWeaponReferenceByGuid(key, ref val) || instance.TryGetWeaponReferenceByName(key, ref val))) { WeaponRequest request = val.LoadAsync(); while (!((Request<Weapon>)(object)request).isDone) { yield return null; } if ((Object)(object)((Request<Weapon>)(object)request).asset != (Object)null) { created = (Gear)(object)manager.DropWeapon(request, position); } } else if (kind == 1 && (instance.TryGetItemReferenceByGuid(key, ref val2) || instance.TryGetItemReferenceByName(key, ref val2))) { ItemRequest request2 = val2.LoadAsync(); while (!((Request<Item>)(object)request2).isDone) { yield return null; } if ((Object)(object)((Request<Item>)(object)request2).asset != (Object)null) { created = (Gear)(object)manager.DropItem(request2, position); } } else if (kind == 2 && (instance.TryGetEssenceReferenceByGuid(key, ref val3) || instance.TryGetEssenceReferenceByName(key, ref val3))) { EssenceRequest request3 = val3.LoadAsync(); while (!((Request<Quintessence>)(object)request3).isDone) { yield return null; } if ((Object)(object)((Request<Quintessence>)(object)request3).asset != (Object)null) { created = (Gear)(object)manager.DropQuintessence(request3, position); } } if ((Object)(object)created != (Object)null) { byte[] array = new byte[6] { 19, 54, 0, 0, 0, 0 }; Buffer.BlockCopy(BitConverter.GetBytes(requestId), 0, array, 2, 4); SteamNetworking.SendP2PPacket(requester, array, (uint)array.Length, (EP2PSend)2, 92); ((BaseUnityPlugin)this).Logger.LogInfo((object)$"Host created and acknowledged client world drop {requestId}: kind {kind}, key '{key}', at {position}."); ((MonoBehaviour)this).StartCoroutine(CTraceHostRequestedWorldDrop(requestId, created)); } else { ((BaseUnityPlugin)this).Logger.LogWarning((object)$"Host could not resolve requested world drop: kind {kind}, key '{key}'."); } } private IEnumerator CTraceHostRequestedWorldDrop(uint requestId, Gear created) { yield return null; TraceHostRequestedWorldDrop(requestId, created, "next-frame"); yield return (object)new WaitForSecondsRealtime(0.5f); TraceHostRequestedWorldDrop(requestId, created, "0.5s"); } private void TraceHostRequestedWorldDrop(uint requestId, Gear created, string phase) { //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) DroppedGear val = (((Object)(object)created == (Object)null) ? null : created.dropped); bool flag = (Object)(object)val != (Object)null && ((Component)val).gameObject.activeInHierarchy; bool flag2 = (Object)(object)val != (Object)null && (Object)(object)Map.Instance != (Object)null && (Object)(object)((Component)val).transform.parent == (Object)(object)((Component)Map.Instance).transform; Vector3 val2 = (((Object)(object)val == (Object)null) ? Vector3.zero : ((Component)val).transform.position); ((BaseUnityPlugin)this).Logger.LogInfo((object)$"Host client-drop {requestId} {phase}: gearAlive={(Object)(object)created != (Object)null}, droppedAlive={(Object)(object)val != (Object)null}, active={flag}, mapParent={flag2}, position={val2}."); } private void EnforceHostWorldDropAuthority() { if (_lobbyId.m_SteamID == 0L || IsHost() || !_clientWorldAuthorityEstablished) { return; } Character localPlayer = GetLocalPlayer(); DroppedGear[] array = Object.FindObjectsOfType<DroppedGear>(); foreach (DroppedGear val in array) { Gear val2 = val.gear ?? ((Component)val).GetComponent<Gear>(); if ((!((Object)(object)val2 != (Object)null) || !((Object)(object)val2.owner == (Object)(object)localPlayer)) && !Drops.TryGetDropId(val, out var _)) { Object.Destroy((Object)(object)((Component)val).gameObject); } } } internal bool HandleClientLocalWorldGearCreation(Gear gear, Vector3 position) { //IL_00bd: 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_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) if (_lobbyId.m_SteamID == 0L || IsHost() || CreatingReplicatedNativeDrop || (Object)(object)gear == (Object)null) { return false; } if (!_requestedClientWorldGear.Add(gear)) { return true; } if (!TryGetWorldGearKey(gear, out byte kind, out string key)) { return false; } byte[] bytes = Encoding.UTF8.GetBytes(key); if (bytes.Length == 0 || bytes.Length > 255) { return false; } uint num = ++_nextClientWorldDropRequestId; if (num == 0) { num = ++_nextClientWorldDropRequestId; } byte[] array = new byte[16 + bytes.Length]; array[0] = 16; array[1] = 54; array[2] = kind; Buffer.BlockCopy(BitConverter.GetBytes(num), 0, array, 3, 4); Buffer.BlockCopy(BitConverter.GetBytes(position.x), 0, array, 7, 4); Buffer.BlockCopy(BitConverter.GetBytes(position.y), 0, array, 11, 4); array[15] = (byte)bytes.Length; Buffer.BlockCopy(bytes, 0, array, 16, bytes.Length); foreach (CSteamID item in LobbyMembers()) { if (item.m_SteamID != SteamUser.GetSteamID().m_SteamID) { SteamNetworking.SendP2PPacket(item, array, (uint)array.Length, (EP2PSend)2, 92); } } _pendingClientWorldDrops[num] = new PendingClientWorldDrop(kind, key, position, gear.dropped); ((BaseUnityPlugin)this).Logger.LogInfo((object)$"Requested host world drop {num}: kind {kind}, key '{key}', at {position}."); return true; } internal void HandleClientNativeLevelManagerDrop(Gear gear, Vector3 position) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)gear == (Object)null) && _lobbyId.m_SteamID != 0L && !IsHost() && !CreatingReplicatedNativeDrop && HandleClientLocalWorldGearCreation(gear, position) && (Object)(object)gear.dropped != (Object)null) { ((MonoBehaviour)this).StartCoroutine(CHideTemporaryClientWorldDrop(gear.dropped)); } } internal void HandleClientWeaponReplacementDrop(Weapon displaced) { //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_0056: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)displaced == (Object)null || _lobbyId.m_SteamID == 0L || IsHost() || CreatingReplicatedNativeDrop) { return; } DroppedGear dropped = ((Gear)displaced).dropped; if ((Object)(object)dropped == (Object)null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"Native WeaponInventory.EquipAt returned a displaced weapon without DroppedGear."); return; } Vector3 position = ((Component)dropped).transform.position; bool flag = HandleClientLocalWorldGearCreation((Gear)(object)displaced, position); ((BaseUnityPlugin)this).Logger.LogInfo((object)$"Native WeaponInventory.EquipAt displaced '{((Object)displaced).name}': state={((Gear)displaced).state}, active={((Component)dropped).gameObject.activeInHierarchy}, requested={flag}, at {position}."); if (flag) { ((MonoBehaviour)this).StartCoroutine(CHideTemporaryClientWorldDrop(dropped)); } } internal void HandleClientGearDropped(Gear gear) { if (_lobbyId.m_SteamID != 0L && !IsHost() && !((Object)(object)gear == (Object)null)) { ((MonoBehaviour)this).StartCoroutine(CPromoteClientDroppedGearAfterNativeStateSettles(gear)); } } private IEnumerator CPromoteClientDroppedGearAfterNativeStateSettles(Gear gear) { yield return (object)new WaitForEndOfFrame(); if (!((Object)(object)gear == (Object)null) && !_replicatedClientGear.Contains(gear) && (int)gear.state == 0 && !((Object)(object)gear.dropped == (Object)null) && ((Component)gear.dropped).gameObject.activeInHierarchy) { if (gear.dropped.price > 0) { ((MonoBehaviour)this).StartCoroutine(CHideTemporaryClientWorldDrop(gear.dropped)); } else if (HandleClientLocalWorldGearCreation(gear, ((Component)gear.dropped).transform.position)) { ((MonoBehaviour)this).StartCoroutine(CHideTemporaryClientWorldDrop(gear.dropped)); } } } private IEnumerator CHideTemporaryClientWorldDrop(DroppedGear dropped) { yield return (object)new WaitForEndOfFrame(); if ((Object)(object)dropped != (Object)null && (Object)(object)((Component)dropped).gameObject != (Object)null) { ((Component)dropped).gameObject.SetActive(false); } } internal void ApplyRemoteAnimationParameters(CharacterAnimationController controller) { if (!((Object)(object)controller == (Object)null)) { Character componentInParent = ((Component)controller).GetComponentInParent<Character>(); if ((Object)(object)componentInParent != (Object)null) { Players.ApplyRemoteAnimationParameters(componentInParent, controller); } } } private void DisableClientEnemySimulation() { if (_lobbyId.m_SteamID == 0L || IsHost()) { return; } foreach (Character clientEnemyCandidate in _clientEnemyCandidates) { if ((Object)(object)clientEnemyCandidate == (Object)null) { continue; } AIController[] componentsInChildren = ((Component)clientEnemyCandidate).GetComponentsInChildren<AIController>(true); foreach (AIController val in componentsInChildren) { if (((Behaviour)val).enabled) { ((Behaviour)val).enabled = false; } } if ((Object)(object)clientEnemyCandidate.animationController != (Object)null && ((Behaviour)clientEnemyCandidate.animationController).enabled) { ((Behaviour)clientEnemyCandidate.animationController).enabled = false; } } } private void ResetClientEnemyRegistryForMapChange() { if (_lobbyId.m_SteamID != 0L && !IsHost()) { int num = ((!((Object)(object)Map.Instance == (Object)null)) ? ((Object)Map.Instance).GetInstanceID() : 0); if (num != 0 && num != _clientEnemyMapId) { _clientEnemyMapId = num; World.Clear(); _enemyAnimatorStates.Clear(); _replicatedEnemyHealthBarExpiry.Clear(); _replicatedEnemyHealth.Clear(); _loggedUnboundEnemySnapshots.Clear(); _clientEnemyCandidates.Clear(); _nextClientEnemyCandidateRefreshAt = 0f; ((BaseUnityPlugin)this).Logger.LogInfo((object)"Reset client enemy netId table for the newly loaded map."); } } } private void RefreshClientEnemyCandidates(bool force = false) { if (_lobbyId.m_SteamID == 0L || IsHost() || (!force && Time.unscaledTime < _nextClientEnemyCandidateRefreshAt)) { return; } _nextClientEnemyCandidateRefreshAt = Time.unscaledTime + 0.25f; _clientEnemyCandidates.Clear(); foreach (Character item in FindEnemies()) { if (!World.TryGetUnitId(item, out var _)) { _clientEnemyCandidates.Add(item); } } } private IEnumerator CCreateWorldGearDrop(uint id, byte kind, string key, Vector3 position, uint chestRewardGroup, int price, Type priceCurrency) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0025: 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) _replicatedWorldGearCreationDepth++; try { GearResource instance = GearResource.instance; Service instance2 = Singleton<Service>.Instance; LevelManager manager = ((instance2 != null) ? instance2.levelManager : null); if ((Object)(object)instance == (Object)null || (Object)(object)manager == (Object)null || id == 0) { yield break; } Gear created = null; WeaponReference val = default(WeaponReference); ItemReference val2 = default(ItemReference); EssenceReference val3 = default(EssenceReference); if (kind == 0 && (instance.TryGetWeaponReferenceByGuid(key, ref val) || instance.TryGetWeaponReferenceByName(key, ref val))) { WeaponRequest request = val.LoadAsync(); while (!((Request<Weapon>)(object)request).isDone) { yield return null; } if ((Object)(object)((Request<Weapon>)(object)request).asset != (Object)null) { _replicatedNativeDropCallDepth++; try { created = (Gear)(object)manager.DropWeapon(request, position); } finally { _replicatedNativeDropCallDepth--; } } } else if (kind == 1 && (instance.TryGetItemReferenceByGuid(key, ref val2) || instance.TryGetItemReferenceByName(key, ref val2))) { ItemRequest request2 = val2.LoadAsync(); while (!((Request<Item>)(object)request2).isDone) { yield return null; } if ((Object)(object)((Request<Item>)(object)request2).asset != (Object)null) { _replicatedNativeDropCallDepth++; try { created = (Gear)(object)manager.DropItem(request2, position); } finally { _replicatedNativeDropCallDepth--; } } } else if (kind == 2 && (instance.TryGetEssenceReferenceByGuid(key, ref val3) || instance.TryGetEssenceReferenceByName(key, ref val3))) { EssenceRequest request3 = val3.LoadAsync(); while (!((Request<Quintessence>)(object)request3).isDone) { yield return null; } if ((Object)(object)((Request<Quintessence>)(object)request3).asset != (Object)null) { _replicatedNativeDropCallDepth++; try { created = (Gear)(object)manager.DropQuintessence(request3, position); } finally { _replicatedNativeDropCallDepth--; } } } if (!((Object)(object)created == (Object)null) && !((Object)(object)Drops.TryGetDrop(id) != (Object)null)) { _replicatedClientGear.Add(created); Gear obj = created; if ((Object)(object)((obj != null) ? obj.dropped : null) != (Object)null) { created.dropped.price = price; created.dropped.priceCurrency = priceCurrency; Drops.RegisterClientDrop(id, created.dropped); Drops.SetChestRewardGroup(id, chestRewardGroup); } } } finally { CoopRuntimePlugin coopRuntimePlugin = this; coopRuntimePlugin._replicatedWorldGearCreationDepth--; coopRuntimePlugin._pendingWorldGearDrops.Remove(id); } } private void RetireMatchingTemporaryClientDrop(byte kind, string key, Vector3 position) { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) KeyValuePair<uint, PendingClientWorldDrop>[] array = _pendingClientWorldDrops.ToArray(); for (int i = 0; i < array.Length; i++) { KeyValuePair<uint, PendingClientWorldDrop> keyValuePair = array[i]; PendingClientWorldDrop value = keyValuePair.Value; if (value.Kind != kind || !string.Equals(value.Key, key, StringComparison.Ordinal)) { continue; } Vector3 val = value.Position - position; if (((Vector3)(ref val)).sqrMagnitude > 0.25f) { continue; } _pendingClientWorldDrops.Remove(keyValuePair.Key); if ((Object)(object)value.Dropped != (Object)null) { if ((Object)(object)value.Dropped.gear != (Object)null) { _requestedClientWorldGear.Remove(value.Dropped.gear); } Object.Destroy((Object)(object)((Component)value.Dropped).gameObject); } ((BaseUnityPlugin)this).Logger.LogInfo((object)("Retired temporary client world drop for host-issued '" + key + "'.")); break; } } private void ReceiveWorldGearSpawnAcknowledgement(byte[] packet) { uint num = BitConverter.ToUInt32(packet, 2); if (num == 0 || !_pendingClientWorldDrops.TryGetValue(num, out var value)) { return; } _pendingClientWorldDrops.Remove(num); if ((Object)(object)value.Dropped != (Object)null) { if ((Object)(object)value.Dropped.gear != (Object)null) { _requestedClientWorldGear.Remove(value.Dropped.gear); } Object.Destroy((Object)(object)((Component)value.Dropped).gameObject); } ((BaseUnityPlugin)this).Logger.LogInfo((object)$"Retired acknowledged temporary client world drop {num} for '{value.Key}'."); } internal bool RequestWorldGearInteraction(DroppedGear dropped, Character character, bool dismantle) { //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_0076: 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_0088: Unknown result type (might be due to invalid IL or missing references) if (_lobbyId.m_SteamID == 0L || IsHost() || (Object)(object)character != (Object)(object)GetLocalPlayer() || !Drops.TryGetDropId(dropped, out var id)) { return false; } if (dismantle) { return false; } byte[] array = new byte[7] { 14, 54, 0, 0, 0, 0, 0 }; Buffer.BlockCopy(BitConverter.GetBytes(id), 0, array, 2, 4); array[6] = (dismantle ? ((byte)1) : ((byte)0)); foreach (CSteamID item in LobbyMembers()) { if (item.m_SteamID != SteamUser.GetSteamID().m_SteamID) { SteamNetworking.SendP2PPacket(item, array, (uint)array.Length, (EP2PSend)2, 92); } } return false; } internal bool IsClientNetworkDrop(DroppedGear dropped) { uint id; if (_lobbyId.m_SteamID != 0L && !IsHost() && (Object)(object)dropped != (Object)null) { return Drops.TryGetDropId(dropped, out id); } return false; } internal bool TryGetNetworkDismantleReward(DroppedGear dropped, out DismantleReward reward) { reward = default(DismantleReward); if (_lobbyId.m_SteamID == 0L || (Object)(object)dropped == (Object)null || !Drops.TryGetDropId(dropped, out var id) || (Object)(object)dropped.gear == (Object)null) { return false; } return TryGetNetworkDismantleReward(dropped.gear, id, out reward); } private bool TryGetNetworkDismantleReward(Gear gear, uint dropId, out DismantleReward reward) { //IL_0050: 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_005a: 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_005d: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Invalid comparison between Unknown and I4 reward = default(DismantleReward); if (_lobbyId.m_SteamID == 0L || (Object)(object)gear == (Object)null) { return false; } Item val = (Item)(object)((gear is Item) ? gear : null); int num = ((val != null && ((Gear)val).destructible) ? WitchBonus.instance.soul.ancientAlchemy.GetGoldByDiscard(val) : gear.currencyByDiscard); Type currencyTypeByDiscard = gear.currencyTypeByDiscard; if (num <= 0 || ((int)currencyTypeByDiscard != 0 && (int)currencyTypeByDiscard != 2)) { return false; } reward = new DismantleReward(dropId, currencyTypeByDiscard, num); return true; } internal bool PrepareSharedWorldItemDismantle(DroppedGear dropped, Character actor) { return false; } internal bool PrepareSharedInventoryItemDismantle(Item item) { return false; } internal void NotifyNetworkDismantleReward(DismantleReward reward) { //IL_001d: 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_003d: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_005d: 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_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0105: 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) if (_lobbyId.m_SteamID == 0L || reward.Amount <= 0) { return; } Currency.currencies[reward.Type].Earn(reward.Amount); if (IsHost()) { byte[] array = BuildDismantleRewardPacket(18, reward.Type, reward.Amount); { foreach (CSteamID item in LobbyMembers()) { if (item.m_SteamID != SteamUser.GetSteamID().m_SteamID) { SteamNetworking.SendP2PPacket(item, array, (uint)array.Length, (EP2PSend)2, 92); } } return; } } byte[] array2 = new byte[11] { 17, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; Buffer.BlockCopy(BitConverter.GetBytes(reward.DropId), 0, array2, 2, 4); array2[6] = (byte)reward.Type; Buffer.BlockCopy(BitConverter.GetBytes(reward.Amount), 0, array2, 7, 4); foreach (CSteamID item2 in LobbyMembers()) { if (item2.m_SteamID != SteamUser.GetSteamID().m_SteamID) { SteamNetworking.SendP2PPacket(item2, array2, (uint)array2.Length, (EP2PSend)2, 92); } } } private void ReceiveDismantleRewardRequest(CSteamID sender, byte[] packet) { //IL_000b: 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_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Invalid comparison between Unknown and I4 uint num = BitConverter.ToUInt32(packet, 2); Type val = (Type)packet[6]; int num2 = BitConverter.ToInt32(packet, 7); if (Players.TryGet(sender.m_SteamID, out Character _) && (num == 0 || !((Object)(object)Drops.TryGetDrop(num) == (Object)null)) && num2 > 0 && num2 <= 100000 && ((int)val == 0 || (int)val == 2)) { Currency.currencies[val].Earn(num2); ((BaseUnityPlugin)this).Logger.LogInfo((object)$"Granted shared client dismantle reward to host: {val} {num2} for drop {num}."); } } private void ReceiveDismantleRewardGrant(byte[] packet) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Invalid comparison between Unknown and I4 Type val = (Type)packet[2]; int num = BitConverter.ToInt32(packet, 3); if (num > 0 && num <= 100000 && ((int)val == 0 || (int)val == 2)) { Currency.currencies[val].Earn(num); ((BaseUnityPlugin)this).Logger.LogInfo((object)$"Granted shared host dismantle reward to client: {val} {num}."); } } private static byte[] BuildDismantleRewardPacket(byte packetType, Type type, int amount) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) byte[] array = new byte[7] { packetType, 54, (byte)type, 0, 0, 0, 0 }; Buffer.BlockCopy(BitConverter.GetBytes(amount), 0, array, 3, 4); return array; } internal void NotifyClientWorldGearDismantled(DroppedGear dropped) { //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0067: 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) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) if (_lobbyId.m_SteamID == 0L || IsHost() || (Object)(object)dropped == (Object)null || !Drops.TryGetDropId(dropped, out var id)) { return; } byte[] array = new byte[7] { 14, 54, 0, 0, 0, 0, 0 }; Buffer.BlockCopy(BitConverter.GetBytes(id), 0, array, 2, 4); array[6] = 1; foreach (CSteamID item in LobbyMembers()) { if (item.m_SteamID != SteamUser.GetSteamID().m_SteamID) { SteamNetworking.SendP2PPacket(item, array, (uint)array.Length, (EP2PSend)2, 92); } } } private void ApplyWorldGearInteractionRequest(CSteamID sender, byte[] packet) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) uint num = BitConverter.ToUInt32(packet, 2); DroppedGear val = Drops.TryGetDrop(num); if ((Object)(object)val == (Object)null || !Players.TryGet(sender.m_SteamID, out Character _)) { return; } try { if (!TryResolveChestRewardSelection(num, destroyHostWorldCopy: true)) { SendWorldGearDespawn(num); Object.Destroy((Object)(object)((Component)val).gameObject); } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)$"Host could not process world-drop interaction {num}: {ex.Message}"); } } internal void NotifyWorldGearLooted(DroppedGear dropped) { if ((Object)(object)dropped != (Object)null && IsHost() && Drops.TryGetDropId(dropped, out var id) && !TryResolveChestRewardSelection(id, destroyHostWorldCopy: false)) { SendWorldGearDespawn(id); } } internal void NotifyWorldGearDestroyed(DroppedGear dropped) { if ((Object)(object)dropped != (Object)null && IsHost() && Drops.TryGetDropId(dropped, out var id)) { SendWorldGearDespawn(id); } } internal void NotifyWorldGearInteractionFinished(DroppedGear dropped) { if ((Object)(object)dropped != (Object)null && IsHost() && Drops.TryGetDropId(dropped, out var id)) { ((MonoBehaviour)this).StartCoroutine(CNotifyWorldGearDespawnIfConsumed(dropped, id)); } } private IEnumerator CNotifyWorldGearDespawnIfConsumed(DroppedGear dropped, uint id) { yield return (object)new WaitForEndOfFrame(); if (!TryResolveChestRewardSelection(id, destroyHostWorldCopy: false) && ((Object)(object)dropped == (Object)null || (Object)(object)dropped.gear == (Object)null) && !TryResolveChestRewardSelection(id, destroyHostWorldCopy: false)) { SendWorldGearDespawn(id); } } internal void NotifyHostChestOpened(Chest chest) { if ((Object)(object)chest != (Object)null && _lobbyId.m_SteamID != 0L && IsHost()) { ((MonoBehaviour)this).StartCoroutine(CRegisterHostChestRewards(chest)); } } private IEnumerator CRegisterHostChestRewards(Chest chest) { FieldInfo rewardsField = AccessTools.Field(typeof(Chest), "_rewards"); int frame = 0; while ((Object)(object)chest != (Object)null && frame < 300) { if (rewardsField?.GetValue(chest) is Gear[] array && array.Length == 3 && array.All((Gear gear) => (Object)(object)((gear != null) ? gear.dropped : null) != (Object)null)) { uint num = ++_nextChestRewardGroupId; if (num == 0) { num = ++_nextChestRewardGroupId; } HashSet<uint> hashSet = new HashSet<uint>(); Gear[] array2 = array; foreach (Gear val in array2) { uint orAssignHostDrop = Drops.GetOrAssignHostDrop(val.dropped); Drops.SetChestRewardGroup(orAssignHostDrop, num); hashSet.Add(orAssignHostDrop); } _chestRewardDropIds[num] = hashSet; _chestRewardSelections[num] = new HashSet<uint>(); _trackedHostChests.Add(chest); ((BaseUnityPlugin)this).Logger.LogInfo((object)$"Registered native chest reward group {num} with {hashSet.Count} drops; party limit is two pickups."); yield break; } yield return null; frame++; } ((BaseUnityPlugin)this).Logger.LogWarning((object)"Could not obtain Level.Chest._rewards after its native drop coroutine."); } internal bool ShouldRunNativeChestOnLoot(Chest chest) { if (_lobbyId.m_SteamID != 0L && IsHost() && !((Object)(object)chest == (Object)null)) { return !_trackedHostChests.Contains(chest); } return true; } private bool TryResolveChestRewardSelection(uint dropId, bool destroyHostWorldCopy) { uint chestRewardGroup = Drops.GetChestRewardGroup(dropId); if (chestRewardGroup == 0 || !_chestRewardDropIds.TryGetValue(chestRewardGroup, out HashSet<uint> value) || !_chestRewardSelections.TryGetValue(chestRewardGroup, out HashSet<uint> value2)) { return false; } if (!value2.Add(dropId)) { return true; } if (destroyHostWorldCopy) { DroppedGear val = Drops.TryGetDrop(dropId); if ((Object)(object)val != (Object)null) { Gear gear = val.gear; if ((Object)(object)((gear != null) ? gear.owner : null) == (Object)null) { Object.Destroy((Object)(object)((Component)val).gameObject); } } } SendWorldGearDespawn(dropId); ((BaseUnityPlugin)this).Logger.LogInfo((object)$"Chest reward group {chestRewardGroup}: selection {value2.Count}/2 (drop {dropId})."); if (value2.Count < 2) { return true; } foreach (uint item in value) { SendWorldGearDespawn(item); DroppedGear val2 = Drops.TryGetDrop(item); if ((Object)(object)val2 != (Object)null) { Gear gear2 = val2.gear; if ((Object)(object)((gear2 != null) ? gear2.owner : null) == (Object)null) { Object.Destroy((Object)(object)((Component)val2).gameObject); } } } _chestRewardDropIds.Remove(chestRewardGroup); _chestRewardSelections.Remove(chestRewardGroup); SendGatesActivated(); return true; } private void SendGatesActivated() { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: 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) byte[] array = new byte[2] { 22, 54 }; foreach (CSteamID item in LobbyMembers()) { if (item.m_SteamID != SteamUser.GetSteamID().m_SteamID) { SteamNetworking.SendP2PPacket(item, array, (uint)array.Length, (EP2PSend)2, 92); } } } private static void ActivateClientMapGates() { Map instance = Map.Instance; if ((Object)(object)instance == (Object)null) { return; } Gate[] componentsInChildren = ((Component)instance).GetComponentsInChildren<Gate>(true); foreach (Gate val in componentsInChildren) { if (((Component)val).gameObject.activeInHierarchy) { ((InteractiveObject)val).Activate(); } } } private void SendWorldGearDespawn(uint id) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) _advertisedWorldGearDrops.Remove(id); byte[] array = new byte[6] { 15, 54, 0, 0, 0, 0 }; Buffer.BlockCopy(BitConverter.GetBytes(id), 0, array, 2, 4); foreach (CSteamID item in LobbyMembers()) { if (item.m_SteamID != SteamUser.GetSteamID().m_SteamID) { SteamNetworking.SendP2PPacket(item, array, (uint)array.Length, (EP2PSend)2, 92); } } } private void ApplyWorldGearDespawn(byte[] packet) { uint id = BitConverter.ToUInt32(packet, 2); DroppedGear val = Drops.TryGetDrop(id); if ((Object)(object)val == (Object)null) { return; } Gear val2 = val.gear ?? ((Component)val).GetComponent<Gear>(); if ((Object)(object)val2 != (Object)null && (Object)(object)val2.owner != (Object)null) { Drops.Unregister(id, val); return; } if (((Component)val).gameObject.activeInHierarchy) { Object.Destroy((Object)(object)((Component)val).gameObject); } Drops.Unregister(id, val); } internal bool RequestRewardObjectInteraction(Component rewardObject, Character actor, byte kind) { //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_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) if (_lobbyId.m_SteamID == 0L || IsHost() || (Object)(object)rewardObject == (Object)null || (Object)(object)actor != (Object)(object)GetLocalPlayer()) { return false; } byte[] array = new byte[7] { 20, 54, kind, 0, 0, 0, 0 }; Buffer.BlockCopy(BitConverter.GetBytes(StableId(rewardObject.transform)), 0, array, 3, 4); foreach (CSteamID item in LobbyMembers()) { if (item.m_SteamID != SteamUser.GetSteamID().m_SteamID) { SteamNetworking.SendP2PPacket(item, array, (uint)array.Length, (EP2PSend)2, 92); } } return true; } internal void NotifyHostRewardObjectOpened(Component rewardObject, byte kind) { //IL_005c: 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_0062: 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) //IL_0074: Unknown result type (might be due to invalid IL or missing references) if (_lobbyId.m_SteamID == 0L || !IsHost() || (Object)(object)rewardObject == (Object)null) { return; } byte[] array = new byte[7] { 21, 54, kind, 0, 0, 0, 0 }; Buffer.BlockCopy(BitConverter.GetBytes(StableId(rewardObject.transform)), 0, array, 3, 4); foreach (CSteamID item in LobbyMembers()) { if (item.m_SteamID != SteamUser.GetSteamID().m_SteamID) { SteamNetworking.SendP2PPacket(item, array, (uint)array.Length, (EP2PSend)2, 92); } } } private void ApplyRewardObjectInteractionRequest(CSteamID sender, byte[] packet) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) if (!Players.TryGet(sender.m_SteamID, out Character character)) { return; } byte b = packet[2]; int signature = BitConverter.ToInt32(packet, 3); try { using (Players.Enter(sender.m_SteamID)) { switch (b) { case 1: { Chest? obj2 = ((IEnumerable<Chest>)Object.FindObjectsOfType<Chest>()).FirstOrDefault((Func<Chest, bool>)((Chest candidate) => ((Component)candidate).gameObject.activeInHierarchy && StableId(((Component)candidate).transform) == signature)); if (obj2 != null) { ((InteractiveObject)obj2).InteractWith(character); } break; } case 2: { DroppedRandomWeaponBox? obj = ((IEnumerable<DroppedRandomWeaponBox>)Object.FindObjectsOfType<DroppedRandomWeaponBox>()).FirstOrDefault((Func<DroppedRandomWeaponBox, bool>)((DroppedRandomWeaponBox candidate) => ((Component)candidate).gameObject.activeInHierarchy && StableId(((Component)candidate).transform) == signature)); if (obj != null) { ((InteractiveObject)obj).InteractWith(character); } break; } } } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Host could not open requested reward container: " + ex.Message)); } } private void ApplyRewardObjectConsumed(byte[] packet) { byte b = packet[2]; int signature = BitConverter.ToInt32(packet, 3); Component val = null; switch (b) { case 1: val = (Component)(object)((IEnumerable<Chest>)Object.FindObjectsOfType<Chest>()).FirstOrDefault((Func<Chest, bool>)((Chest candidate) => StableId(((Component)candidate).transform) == signature)); break; case 2: val = (Component)(object)((IEnumerable<DroppedRandomWeaponBox>)Object.FindObjectsOfType<DroppedRandomWeaponBox>()).FirstOrDefault((Func<DroppedRandomWeaponBox, bool>)((DroppedRandomWeaponBox candidate) => StableId(((Component)candidate).transform) == signature)); break; } if ((Object)(object)val != (Object)null) { val.gameObject.SetActive(false); } } internal void NotifyHostRandomWeaponBoxOpened(DroppedRandomWeaponBox box) { NotifyHostRewardObjectOpened((Component)(object)box, 2); if (_lobbyId.m_SteamID != 0L && IsHost() && !((Object)(object)box == (Object)null) && _openedRandomWeaponBoxes.Add(box)) { ((MonoBehaviour)this).StartCoroutine(CSpawnSecondNativeRandomWeapon(box)); } } private IEnumerator CSpawnSecondNativeRandomWeapon(DroppedRandomWeaponBox box) { yield return null; if ((Object)(object)box == (Object)null) { yield break; } object request = null; Vector3 dropPosition = default(Vector3); try { Random random = AccessTools.Field(typeof(DroppedRandomWeaponBox), "_random")?.GetValue(box) as Random; object obj = AccessTools.Field(typeof(DroppedRandomWeaponBox), "_rarityPossibilities")?.GetValue(box); object obj2 = AccessTools.Field(typeof(DroppedRandomWeaponBox), "_category")?.GetValue(box); object? obj3 = AccessTools.Field(typeof(DroppedRandomWeaponBox), "_dropPoint")?.GetValue(box); Transform val = (Transform)((obj3 is Transform) ? ob