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.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Logging; using GameNetcodeStuff; using HarmonyLib; using LethalNetworkAPI.Internal; using LethalNetworkAPI.Old; using LethalNetworkAPI.Old.Networking; using LethalNetworkAPI.Serializable; using LethalNetworkAPI.Utils; using LobbyCompatibility.Enums; using LobbyCompatibility.Features; using Microsoft.CodeAnalysis; using OdinSerializer; using Unity.Collections; using Unity.Netcode; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: RegisterFormatter(typeof(NetworkBehaviourReferenceFormatter), 0)] [assembly: RegisterFormatter(typeof(NetworkObjectReferenceFormatter), 0)] [assembly: IgnoresAccessChecksTo("AmazingAssets.TerrainToMesh")] [assembly: IgnoresAccessChecksTo("Assembly-CSharp-firstpass")] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: IgnoresAccessChecksTo("ClientNetworkTransform")] [assembly: IgnoresAccessChecksTo("com.olegknyazev.softmask")] [assembly: IgnoresAccessChecksTo("DissonanceVoip")] [assembly: IgnoresAccessChecksTo("EasyTextEffects")] [assembly: IgnoresAccessChecksTo("Facepunch Transport for Netcode for GameObjects")] [assembly: IgnoresAccessChecksTo("Facepunch.Steamworks.Win64")] [assembly: IgnoresAccessChecksTo("Unity.AI.Navigation")] [assembly: IgnoresAccessChecksTo("Unity.Animation.Rigging")] [assembly: IgnoresAccessChecksTo("Unity.Animation.Rigging.DocCodeExamples")] [assembly: IgnoresAccessChecksTo("Unity.Burst")] [assembly: IgnoresAccessChecksTo("Unity.Burst.Unsafe")] [assembly: IgnoresAccessChecksTo("Unity.Collections")] [assembly: IgnoresAccessChecksTo("Unity.Collections.LowLevel.ILSupport")] [assembly: IgnoresAccessChecksTo("Unity.InputSystem")] [assembly: IgnoresAccessChecksTo("Unity.InputSystem.ForUI")] [assembly: IgnoresAccessChecksTo("Unity.Jobs")] [assembly: IgnoresAccessChecksTo("Unity.Mathematics")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.Common")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.MetricTypes")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStats")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Component")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Configuration")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Implementation")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsReporting")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetworkProfiler.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetworkSolutionInterface")] [assembly: IgnoresAccessChecksTo("Unity.Netcode.Components")] [assembly: IgnoresAccessChecksTo("Unity.Netcode.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.Networking.Transport")] [assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Csg")] [assembly: IgnoresAccessChecksTo("Unity.ProBuilder")] [assembly: IgnoresAccessChecksTo("Unity.ProBuilder.KdTree")] [assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Poly2Tri")] [assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Stl")] [assembly: IgnoresAccessChecksTo("Unity.Profiling.Core")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.ShaderLibrary")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.HighDefinition.Config.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.HighDefinition.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.ShaderGraph.ShaderGraphLibrary")] [assembly: IgnoresAccessChecksTo("Unity.Services.Authentication")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Analytics")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Components")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Configuration")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Device")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Environments")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Environments.Internal")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Internal")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Networking")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Registration")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Scheduler")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Telemetry")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Threading")] [assembly: IgnoresAccessChecksTo("Unity.Services.QoS")] [assembly: IgnoresAccessChecksTo("Unity.Services.Relay")] [assembly: IgnoresAccessChecksTo("Unity.TextMeshPro")] [assembly: IgnoresAccessChecksTo("Unity.Timeline")] [assembly: IgnoresAccessChecksTo("Unity.VisualEffectGraph.Runtime")] [assembly: IgnoresAccessChecksTo("UnityEngine.ARModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.NVIDIAModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.UI")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("Xilophor")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Easily create networked mods.")] [assembly: AssemblyFileVersion("3.3.3.0")] [assembly: AssemblyInformationalVersion("3.3.3+672618aacde358537d7240242a5d0117aad12cf5")] [assembly: AssemblyProduct("LethalNetworkAPI")] [assembly: AssemblyTitle("LethalNetworkAPI")] [assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/Xilophor/LethalNetworkAPI")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("3.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] [CompilerGenerated] internal sealed class <>z__ReadOnlySingleElementList : IEnumerable, ICollection, IList, IEnumerable, IReadOnlyCollection, IReadOnlyList, ICollection, IList { private sealed class Enumerator : IDisposable, IEnumerator, IEnumerator { object IEnumerator.Current => _item; T IEnumerator.Current => _item; public Enumerator(T item) { _item = item; } bool IEnumerator.MoveNext() { if (!_moveNextCalled) { return _moveNextCalled = true; } return false; } void IEnumerator.Reset() { _moveNextCalled = false; } void IDisposable.Dispose() { } } int ICollection.Count => 1; bool ICollection.IsSynchronized => false; object ICollection.SyncRoot => this; object IList.this[int index] { get { if (index != 0) { throw new IndexOutOfRangeException(); } return _item; } set { throw new NotSupportedException(); } } bool IList.IsFixedSize => true; bool IList.IsReadOnly => true; int IReadOnlyCollection.Count => 1; T IReadOnlyList.this[int index] { get { if (index != 0) { throw new IndexOutOfRangeException(); } return _item; } } int ICollection.Count => 1; bool ICollection.IsReadOnly => true; T IList.this[int index] { get { if (index != 0) { throw new IndexOutOfRangeException(); } return _item; } set { throw new NotSupportedException(); } } public <>z__ReadOnlySingleElementList(T item) { _item = item; } IEnumerator IEnumerable.GetEnumerator() { return new Enumerator(_item); } void ICollection.CopyTo(Array array, int index) { array.SetValue(_item, index); } int IList.Add(object value) { throw new NotSupportedException(); } void IList.Clear() { throw new NotSupportedException(); } bool IList.Contains(object value) { return EqualityComparer.Default.Equals(_item, (T)value); } int IList.IndexOf(object value) { if (!EqualityComparer.Default.Equals(_item, (T)value)) { return -1; } return 0; } void IList.Insert(int index, object value) { throw new NotSupportedException(); } void IList.Remove(object value) { throw new NotSupportedException(); } void IList.RemoveAt(int index) { throw new NotSupportedException(); } IEnumerator IEnumerable.GetEnumerator() { return new Enumerator(_item); } void ICollection.Add(T item) { throw new NotSupportedException(); } void ICollection.Clear() { throw new NotSupportedException(); } bool ICollection.Contains(T item) { return EqualityComparer.Default.Equals(_item, item); } void ICollection.CopyTo(T[] array, int arrayIndex) { array[arrayIndex] = _item; } bool ICollection.Remove(T item) { throw new NotSupportedException(); } int IList.IndexOf(T item) { if (!EqualityComparer.Default.Equals(_item, item)) { return -1; } return 0; } void IList.Insert(int index, T item) { throw new NotSupportedException(); } void IList.RemoveAt(int index) { throw new NotSupportedException(); } } namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.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] [Microsoft.CodeAnalysis.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] [Microsoft.CodeAnalysis.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 LethalNetworkAPI { [BepInPlugin("LethalNetworkAPI", "LethalNetworkAPI", "3.3.3")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class LethalNetworkAPIPlugin : BaseUnityPlugin { private static Harmony _harmony; public static LethalNetworkAPIPlugin Instance { get; private set; } internal static ManualLogSource Logger { get; private set; } private void Awake() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown Instance = this; Logger = ((BaseUnityPlugin)this).Logger; _harmony = new Harmony("LethalNetworkAPI"); _harmony.PatchAll(); if (LobbyCompatibilityDep.Enabled) { LobbyCompatibilityDep.Initialize(); } Logger.LogInfo((object)"LethalNetworkAPI v3.3.3 has Loaded."); } } internal static class LobbyCompatibilityDep { private static bool? _enabled; public static bool Enabled { get { bool valueOrDefault = _enabled.GetValueOrDefault(); if (!_enabled.HasValue) { valueOrDefault = Chainloader.PluginInfos.ContainsKey("BMX.LobbyCompatibility"); _enabled = valueOrDefault; return valueOrDefault; } return valueOrDefault; } } [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] public static void Initialize() { PluginHelper.RegisterPlugin("LethalNetworkAPI", new Version("3.3.3"), (CompatibilityLevel)1, (VersionStrictness)2); } } [Obsolete("Use LNetworkEvent instead.")] public sealed class LethalClientEvent : LNetworkEventDepricated { [CompilerGenerated] private sealed class d__13 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public float timeToWait; public LethalClientEvent <>4__this; public ulong originatorClientId; object? IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object? IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__13(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Expected O, but got Unknown int num = <>1__state; LethalClientEvent lethalClientEvent = <>4__this; switch (num) { default: return false; case 0: <>1__state = -1; if (timeToWait > 0f) { <>2__current = (object)new WaitForSeconds(timeToWait); <>1__state = 1; return true; } break; case 1: <>1__state = -1; break; } lethalClientEvent.ReceiveClientEvent(lethalClientEvent.Identifier, originatorClientId); return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } public event Action? OnReceived; public event Action? OnReceivedFromClient; public LethalClientEvent(string identifier, Action? onReceived = null, Action? onReceivedFromClient = null) : base(identifier) { NetworkHandler.OnClientEvent += ReceiveClientEvent; NetworkHandler.OnSyncedClientEvent += ReceiveSyncedClientEvent; OnReceived += onReceived; OnReceivedFromClient += onReceivedFromClient; } public void InvokeServer() { if (!IsNetworkHandlerNull()) { NetworkHandler.Instance.EventServerRpc(Identifier); } } public void InvokeAllClients(bool includeLocalClient = true, bool waitForServerResponse = false) { if (!IsNetworkHandlerNull()) { NetworkHandler.Instance.EventServerRpc(Identifier, toOtherClients: true); if (includeLocalClient) { this.OnReceivedFromClient?.Invoke(NetworkManager.Singleton.LocalClientId); } } } public void InvokeAllClientsSynced() { //IL_000f: 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) if (!IsNetworkHandlerNull()) { NetworkTime localTime = NetworkManager.Singleton.LocalTime; double time = ((NetworkTime)(ref localTime)).Time; NetworkHandler.Instance.SyncedEventServerRpc(Identifier, time); ReceiveClientEvent(Identifier, NetworkManager.Singleton.LocalClientId); } } public void ClearSubscriptions() { this.OnReceived = delegate { }; this.OnReceivedFromClient = delegate { }; } private void ReceiveClientEvent(string identifier, ulong originatorClientId) { if (!(identifier != Identifier)) { if (originatorClientId == 99999) { this.OnReceived?.Invoke(); } else { this.OnReceivedFromClient?.Invoke(originatorClientId); } } } private void ReceiveSyncedClientEvent(string identifier, double time, ulong originatorClientId) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) if (!(identifier != Identifier) && NetworkHandler.Instance != null) { NetworkTime serverTime = NetworkManager.Singleton.ServerTime; double num = time - ((NetworkTime)(ref serverTime)).Time; ((MonoBehaviour)NetworkManager.Singleton).StartCoroutine(WaitAndInvokeEvent((float)num, originatorClientId)); } } [IteratorStateMachine(typeof(d__13))] private IEnumerator WaitAndInvokeEvent(float timeToWait, ulong originatorClientId) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__13(0) { <>4__this = this, timeToWait = timeToWait, originatorClientId = originatorClientId }; } } [Obsolete("Use LNetworkEvent instead.")] public sealed class LethalServerEvent : LNetworkEventDepricated { [CompilerGenerated] private sealed class d__10 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public float timeToWait; public LethalServerEvent <>4__this; public ulong clientId; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__10(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Expected O, but got Unknown int num = <>1__state; LethalServerEvent lethalServerEvent = <>4__this; switch (num) { default: return false; case 0: <>1__state = -1; if (timeToWait > 0f) { <>2__current = (object)new WaitForSeconds(timeToWait); <>1__state = 1; return true; } break; case 1: <>1__state = -1; break; } lethalServerEvent.OnReceived?.Invoke(clientId); return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } public event Action? OnReceived; public LethalServerEvent(string identifier, Action? onReceived = null) : base(identifier) { NetworkHandler.OnServerEvent += ReceiveServerEvent; NetworkHandler.OnSyncedServerEvent += ReceiveSyncedServerEvent; OnReceived += onReceived; } public void InvokeClient(ulong clientId) { if (!IsNetworkHandlerNull() && IsHostOrServer()) { NetworkHandler.Instance.EventClientRpc(Identifier, new ulong[1] { clientId }); } } public void InvokeClients(IEnumerable clientIds) { if (!IsNetworkHandlerNull() && IsHostOrServer()) { NetworkHandler.Instance.EventClientRpc(Identifier, clientIds.ToArray()); } } public void InvokeAllClients(bool receiveOnHost = true) { if (!IsNetworkHandlerNull() && IsHostOrServer()) { if (receiveOnHost) { NetworkHandler.Instance.EventClientRpc(Identifier, LNetworkUtils.AllConnectedClients); } else { NetworkHandler.Instance.EventClientRpc(Identifier, LNetworkUtils.OtherConnectedClients); } } } public void ClearSubscriptions() { this.OnReceived = delegate { }; } private void ReceiveServerEvent(string identifier, ulong originClientId) { if (!(identifier != Identifier)) { this.OnReceived?.Invoke(originClientId); } } private void ReceiveSyncedServerEvent(string identifier, double time, ulong originatorClientId) { //IL_0015: 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) if (!(identifier != Identifier)) { NetworkTime serverTime = NetworkManager.Singleton.ServerTime; double num = time - ((NetworkTime)(ref serverTime)).Time; ((MonoBehaviour)NetworkManager.Singleton).StartCoroutine(WaitAndInvokeEvent((float)num, originatorClientId)); } } [IteratorStateMachine(typeof(d__10))] private IEnumerator WaitAndInvokeEvent(float timeToWait, ulong clientId) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__10(0) { <>4__this = this, timeToWait = timeToWait, clientId = clientId }; } } [Obsolete("Deprecated Internal Class")] public abstract class LNetworkEventDepricated : LethalNetworkDeprecated { protected LNetworkEventDepricated(string identifier) : base("evt." + identifier, "Event") { } } [Obsolete] public static class LethalNetworkExtensions { public static PlayerControllerB? GetPlayerController(this ulong clientId) { return StartOfRound.Instance.allPlayerScripts[StartOfRound.Instance.ClientPlayerList[clientId]]; } [Obsolete("GetPlayerFromId is deprecated, please use GetPlayerController instead.")] public static PlayerControllerB? GetPlayerFromId(this ulong clientId) { return clientId.GetPlayerController(); } public static ulong GetClientId(this PlayerControllerB player) { return player.actualClientId; } [Obsolete] public static LethalNetworkVariable? GetNetworkVariable(this NetworkBehaviour networkBehaviour, string identifier, bool serverOwned = false) { return ((Component)networkBehaviour).gameObject.NetworkVariable(identifier, serverOwned); } [Obsolete] public static LethalNetworkVariable? GetNetworkVariable(this NetworkObject networkObject, string identifier, bool serverOwned = false) { return ((Component)networkObject).gameObject.NetworkVariable(identifier, serverOwned); } [Obsolete] public static LethalNetworkVariable? GetNetworkVariable(this GameObject gameObject, string identifier, bool serverOwned = false) { return gameObject.NetworkVariable(identifier, serverOwned); } [Obsolete] private static LethalNetworkVariable? NetworkVariable(this GameObject gameObject, string identifier, bool serverOwned) { string identifier2 = identifier; NetworkObject networkObjectComp = default(NetworkObject); if (!gameObject.TryGetComponent(ref networkObjectComp)) { LethalNetworkAPIPlugin.Logger.LogError((object)$"Unable to find the network object component. Are you adding variable \"{identifier2}\" to a network object?"); return null; } LethalNetworkVariable lethalNetworkVariable = (LethalNetworkVariable)NetworkHandler.Instance.ObjectNetworkVariableList.FirstOrDefault((ILethalNetVar i) => ((LethalNetworkVariable)i).Identifier == $"{identifier2}.{networkObjectComp.GlobalObjectIdHash}"); if (lethalNetworkVariable != null) { return lethalNetworkVariable; } lethalNetworkVariable = new LethalNetworkVariable($"{identifier2}.{networkObjectComp.GlobalObjectIdHash}", networkObjectComp, serverOwned, 3); NetworkHandler.Instance.ObjectNetworkVariableList.Add(lethalNetworkVariable); return lethalNetworkVariable; } } [Obsolete("Use LNetworkMessage instead.")] public sealed class LethalClientMessage : LNetworkMessageDeprecated { public event Action? OnReceived; public event Action? OnReceivedFromClient; [Obsolete("Use LNetworkMessage instead.")] public LethalClientMessage(string identifier, Action? onReceived = null, Action? onReceivedFromClient = null) : base(identifier) { NetworkHandler.OnClientMessage += ReceiveMessage; OnReceived += onReceived; OnReceivedFromClient += onReceivedFromClient; } public void SendServer(TData data) { if (!IsNetworkHandlerNull()) { NetworkHandler.Instance.MessageServerRpc(Identifier, LethalNetworkSerializer.Serialize(data)); } } public void SendAllClients(TData data, bool includeLocalClient = true, bool waitForServerResponse = false) { if (!IsNetworkHandlerNull()) { NetworkHandler.Instance.MessageServerRpc(Identifier, LethalNetworkSerializer.Serialize(data), toOtherClients: true); if (includeLocalClient) { this.OnReceivedFromClient?.Invoke(data, NetworkManager.Singleton.LocalClientId); } } } public void ClearSubscriptions() { this.OnReceived = delegate { }; this.OnReceivedFromClient = delegate { }; } private void ReceiveMessage(string identifier, byte[] data, ulong originatorClient) { if (!(identifier != Identifier)) { if (originatorClient == 99999) { this.OnReceived?.Invoke(LethalNetworkSerializer.Deserialize(data)); } else { this.OnReceivedFromClient?.Invoke(LethalNetworkSerializer.Deserialize(data), originatorClient); } } } } [Obsolete("Use LNetworkMessage instead.")] public class LethalServerMessage : LNetworkMessageDeprecated { public event Action? OnReceived; [Obsolete("Use LNetworkMessage instead.")] public LethalServerMessage(string identifier, Action? onReceived = null) : base(identifier) { NetworkHandler.OnServerMessage += ReceiveServerMessage; OnReceived += onReceived; } public void SendClient(TData data, ulong clientId) { if (!IsNetworkHandlerNull() && IsHostOrServer()) { NetworkHandler.Instance.MessageClientRpc(Identifier, LethalNetworkSerializer.Serialize(data), new ulong[1] { clientId }); } } public void SendClients(TData data, IEnumerable clientIds) { if (!IsNetworkHandlerNull() && IsHostOrServer()) { NetworkHandler.Instance.MessageClientRpc(Identifier, LethalNetworkSerializer.Serialize(data), clientIds.ToArray()); } } public void SendAllClients(TData data, bool receiveOnHost = true) { if (!IsNetworkHandlerNull() && IsHostOrServer()) { if (receiveOnHost) { NetworkHandler.Instance.MessageClientRpc(Identifier, LethalNetworkSerializer.Serialize(data), LNetworkUtils.AllConnectedClients); } else { NetworkHandler.Instance.MessageClientRpc(Identifier, LethalNetworkSerializer.Serialize(data), LNetworkUtils.OtherConnectedClients); } } } public void ClearSubscriptions() { this.OnReceived = delegate { }; } private void ReceiveServerMessage(string identifier, byte[] data, ulong originClientId) { if (!(identifier != Identifier)) { this.OnReceived?.Invoke(LethalNetworkSerializer.Deserialize(data), originClientId); } } } [Obsolete("Deprecated Internal Class.")] public abstract class LNetworkMessageDeprecated : LethalNetworkDeprecated { protected LNetworkMessageDeprecated(string identifier) : base("msg." + identifier, "Message") { } } internal interface ILethalNetVar { } [Obsolete("Use LNetworkVariable instead.")] public sealed class LethalNetworkVariable : LethalNetworkDeprecated, ILethalNetVar { private readonly bool _public; private readonly NetworkObject? _ownerObject; private bool _isDirty; private TData _value; public TData Value { get { return _value; } set { if (IsOwner && (value != null || _value != null) && (value == null || !value.Equals(_value))) { _value = value; _isDirty = true; this.OnValueChanged?.Invoke(_value); } } } private bool IsOwner { get { if (_public) { return true; } if ((Object)(object)NetworkManager.Singleton == (Object)null) { return true; } if (_ownerObject == null && NetworkManager.Singleton.IsServer) { return true; } if (_ownerObject != null) { return _ownerObject.OwnerClientId == NetworkManager.Singleton.LocalClientId; } return false; } } public event Action? OnValueChanged; public LethalNetworkVariable(string identifier) : this(identifier, (NetworkObject?)null, serverOwned: true, 2) { } internal LethalNetworkVariable(string identifier, NetworkObject? owner, bool serverOwned, int frameIndex) : base(identifier, "Variable", frameIndex + 1) { //IL_00bb: 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) _ownerObject = ((!serverOwned) ? owner : null); NetworkHandler.OnVariableUpdate += ReceiveUpdate; NetworkHandler.NetworkTick += OnNetworkTick; NetworkHandler.NetworkSpawn += delegate { if (!IsNetworkHandlerNull() && IsHostOrServer(log: false)) { NetworkHandler.OnPlayerJoin += OnPlayerJoin; NetworkHandler.NetworkDespawn += ClearSubscriptions; } }; NetworkHandler.GetVariableValue += delegate(string id, ulong clientId) { if (!(id != Identifier) && !IsNetworkHandlerNull() && IsHostOrServer()) { NetworkHandler.Instance.UpdateVariableClientRpc(Identifier, LethalNetworkSerializer.Serialize(_value), new ulong[1] { clientId }); } }; if (typeof(LethalNetworkVariable).GetCustomAttributes(typeof(PublicNetworkVariableAttribute), inherit: true).Any()) { _public = true; } if (!IsNetworkHandlerNull(log: false)) { if (IsHostOrServer()) { NetworkHandler.OnPlayerJoin += OnPlayerJoin; } else { NetworkHandler.Instance.GetVariableValueServerRpc(Identifier); } } } private void OnPlayerJoin(ulong clientId) { if (!IsNetworkHandlerNull() && IsHostOrServer()) { NetworkHandler.Instance.UpdateVariableClientRpc(Identifier, LethalNetworkSerializer.Serialize(_value), new ulong[1] { clientId }); } } private void ClearSubscriptions() { NetworkHandler.OnPlayerJoin -= OnPlayerJoin; NetworkHandler.NetworkDespawn -= ClearSubscriptions; } private void SendUpdate() { if (!IsNetworkHandlerNull() && IsOwner) { NetworkHandler.Instance.UpdateVariableServerRpc(Identifier, LethalNetworkSerializer.Serialize(_value)); } } private void ReceiveUpdate(string identifier, byte[] data) { if (!(identifier != Identifier)) { TData val = LethalNetworkSerializer.Deserialize(data); if (val != null) { _value = val; this.OnValueChanged?.Invoke(val); } } } private void OnNetworkTick() { if (_isDirty && _value != null) { SendUpdate(); _isDirty = false; } } } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)] public class PublicNetworkVariableAttribute : Attribute { } public sealed class LNetworkEvent { internal string Identifier { get; } public event Action? OnServerReceived = delegate { }; public event Action? OnClientReceived = delegate { }; public event Action? OnClientReceivedFromClient = delegate { }; public static LNetworkEvent Connect(string identifier, Action? onServerReceived = null, Action? onClientReceived = null, Action? onClientReceivedFromClient = null) { string text; try { text = LNetworkUtils.GetModGuid(2) + "." + identifier; } catch (Exception arg) { LethalNetworkAPIPlugin.Logger.LogError((object)("Unable to find Mod Guid! To still work, this Event will only use the given identifier. " + $"Warning: This may cause collision with another mod's NetworkEvent! Stack Trace: {arg}")); text = identifier; } if (!UnnamedMessageHandler.LNetworkEvents.TryGetValue(text, out LNetworkEvent value)) { return new LNetworkEvent(text, onServerReceived, onClientReceived, onClientReceivedFromClient); } value.OnServerReceived += onServerReceived; value.OnClientReceived += onClientReceived; value.OnClientReceivedFromClient += onClientReceivedFromClient; return value; } public static LNetworkEvent Create(string identifier, Action? onServerReceived = null, Action? onClientReceived = null, Action? onClientReceivedFromClient = null) { string identifier2; try { identifier2 = LNetworkUtils.GetModGuid(2) + "." + identifier; } catch (Exception arg) { LethalNetworkAPIPlugin.Logger.LogError((object)("Unable to find Mod Guid! To still work, this Event will only use the given identifier. " + $"Warning: This may cause collision with another mod's NetworkEvent! Stack Trace: {arg}")); identifier2 = identifier; } return new LNetworkEvent(identifier2, onServerReceived, onClientReceived, onClientReceivedFromClient); } private LNetworkEvent(string identifier, Action? onServerReceived = null, Action? onClientReceived = null, Action? onClientReceivedFromClient = null) { if (UnnamedMessageHandler.LNetworkEvents.TryGetValue(identifier, out LNetworkEvent _)) { throw new InvalidOperationException("An event with the identifier " + identifier + " already exists! Please use a different identifier."); } Identifier = identifier; OnServerReceived += onServerReceived; OnClientReceived += onClientReceived; OnClientReceivedFromClient += onClientReceivedFromClient; UnnamedMessageHandler.LNetworkEvents.Add(identifier, this); } internal void InvokeOnServerReceived(ulong clientId) { this.OnServerReceived?.Invoke(clientId); } internal void InvokeOnClientReceived() { this.OnClientReceived?.Invoke(); } internal void InvokeOnClientReceivedFromClient(ulong clientId) { this.OnClientReceivedFromClient?.Invoke(clientId); } public void ClearSubscriptions() { this.OnServerReceived = delegate { }; this.OnClientReceived = delegate { }; this.OnClientReceivedFromClient = delegate { }; } public void InvokeClient(ulong clientGuid) { InvokeClients(new ulong[1] { clientGuid }); } public void InvokeClient(int playerId) { InvokeClients(new ulong[1] { LNetworkUtils.GetClientGuid(playerId) }); } public void InvokeClients(ulong[] clientGuidArray) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) if (!LNetworkUtils.IsConnected) { throw new NetworkConfigurationException("Attempting to use LNetworkMessage method while not connected to a server."); } if (!LNetworkUtils.IsHostOrServer) { throw new InvalidOperationException("Attempting to use LNetworkMessage Server-Only method while not the host."); } if (clientGuidArray.Any()) { if (UnnamedMessageHandler.Instance == null) { throw new NetworkConfigurationException("The UnnamedMessageHandler is null. Shit's fucked! Please send this log to the LethalNetworkAPI developer."); } UnnamedMessageHandler.Instance.SendMessageToClients(new MessageData(Identifier, EMessageType.Event | EMessageType.ServerMessage), clientGuidArray); } } public void InvokeClients(int[] playerIdArray) { InvokeClients(playerIdArray.Select(LNetworkUtils.GetClientGuid).ToArray()); } public void InvokeClients() { InvokeClients(LNetworkUtils.AllConnectedClients); } public void InvokeServer() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) if (!LNetworkUtils.IsConnected) { throw new NetworkConfigurationException("Attempting to use LNetworkMessage method while not connected to a server."); } if (UnnamedMessageHandler.Instance == null) { throw new NetworkConfigurationException("The UnnamedMessageHandler is null. Shit's fucked! Please send this log to the LethalNetworkAPI developer."); } UnnamedMessageHandler.Instance.SendMessageToServer(new MessageData(Identifier, EMessageType.Event | EMessageType.ClientMessage)); } public void InvokeOtherClients(ulong[] clientGuidArray) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) if (!LNetworkUtils.IsConnected) { throw new NetworkConfigurationException("Attempting to use LNetworkMessage method while not connected to a server."); } if (clientGuidArray.Any()) { if (UnnamedMessageHandler.Instance == null) { throw new NetworkConfigurationException("The UnnamedMessageHandler is null. Shit's fucked! Please send this log to the LethalNetworkAPI developer."); } if (UnnamedMessageHandler.Instance.IsServer) { UnnamedMessageHandler.Instance.SendMessageToClients(new MessageData(Identifier, EMessageType.Event | EMessageType.ClientMessageToClient), clientGuidArray); } else { UnnamedMessageHandler.Instance.SendMessageToServer(new MessageData(Identifier, EMessageType.Event | EMessageType.ClientMessageToClient, null, clientGuidArray)); } } } public void InvokeOtherClients(int[] playerIdArray) { InvokeOtherClients(playerIdArray.Select(LNetworkUtils.GetClientGuid).ToArray()); } public void InvokeOtherClients() { InvokeOtherClients(LNetworkUtils.OtherConnectedClients); } } internal interface INetMessage { internal void InvokeOnServerReceived(object? data, ulong clientId); internal void InvokeOnClientReceived(object? data); internal void InvokeOnClientReceivedFromClient(object? data, ulong clientId); } public sealed class LNetworkMessage : INetMessage { internal string Identifier { get; } public event Action? OnServerReceived = delegate { }; public event Action? OnClientReceived = delegate { }; public event Action? OnClientReceivedFromClient = delegate { }; public static LNetworkMessage Connect(string identifier, Action? onServerReceived = null, Action? onClientReceived = null, Action? onClientReceivedFromClient = null) { string text; try { text = LNetworkUtils.GetModGuid(2) + "." + identifier; } catch (Exception arg) { LethalNetworkAPIPlugin.Logger.LogError((object)("Unable to find Mod Guid! To still work, this Message will only use the given identifier. " + $"Warning: This may cause collision with another mod's NetworkMessage! Stack Trace: {arg}")); text = identifier; } if (!UnnamedMessageHandler.LNetworkMessages.TryGetValue(text, out INetMessage value)) { return new LNetworkMessage(text, onServerReceived, onClientReceived, onClientReceivedFromClient); } LNetworkMessage lNetworkMessage = (LNetworkMessage)value; lNetworkMessage.OnServerReceived += onServerReceived; lNetworkMessage.OnClientReceived += onClientReceived; lNetworkMessage.OnClientReceivedFromClient += onClientReceivedFromClient; return lNetworkMessage; } public static LNetworkMessage Create(string identifier, Action? onServerReceived = null, Action? onClientReceived = null, Action? onClientReceivedFromClient = null) { string identifier2; try { identifier2 = LNetworkUtils.GetModGuid(2) + "." + identifier; } catch (Exception arg) { LethalNetworkAPIPlugin.Logger.LogError((object)("Unable to find Mod Guid! To still work, this Message will only use the given identifier. " + $"Warning: This may cause collision with another mod's NetworkMessage! Stack Trace: {arg}")); identifier2 = identifier; } return new LNetworkMessage(identifier2, onServerReceived, onClientReceived, onClientReceivedFromClient); } private LNetworkMessage(string identifier, Action? onServerReceived = null, Action? onClientReceived = null, Action? onClientReceivedFromClient = null) { if (UnnamedMessageHandler.LNetworkMessages.TryGetValue(identifier, out INetMessage _)) { throw new InvalidOperationException("A message with the identifier " + identifier + " already exists! Please use a different identifier."); } Identifier = identifier; OnServerReceived += onServerReceived; OnClientReceived += onClientReceived; OnClientReceivedFromClient += onClientReceivedFromClient; UnnamedMessageHandler.LNetworkMessages.Add(identifier, this); } void INetMessage.InvokeOnServerReceived(object? data, ulong clientId) { this.OnServerReceived?.Invoke((TData)data, clientId); } void INetMessage.InvokeOnClientReceived(object? data) { this.OnClientReceived?.Invoke((TData)data); } void INetMessage.InvokeOnClientReceivedFromClient(object? data, ulong clientId) { this.OnClientReceivedFromClient?.Invoke((TData)data, clientId); } public void ClearSubscriptions() { this.OnServerReceived = delegate { }; this.OnClientReceived = delegate { }; this.OnClientReceivedFromClient = delegate { }; } public void SendClient(TData data, ulong clientGuid) { SendClients(data, new ulong[1] { clientGuid }); } public void SendClient(TData data, int playerId) { SendClients(data, new ulong[1] { LNetworkUtils.GetClientGuid(playerId) }); } public void SendClients(TData data, ulong[] clientGuidArray) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) if (!LNetworkUtils.IsConnected) { throw new NetworkConfigurationException("Attempting to use LNetworkMessage method while not connected to a server."); } if (!LNetworkUtils.IsHostOrServer) { throw new InvalidOperationException("Attempting to use LNetworkMessage Server-Only method while not the host."); } if (clientGuidArray.Any()) { if (UnnamedMessageHandler.Instance == null) { throw new NetworkConfigurationException("The UnnamedMessageHandler is null. Shit's fucked! Please send this log to the LethalNetworkAPI developer."); } UnnamedMessageHandler.Instance.SendMessageToClients(new MessageData(Identifier, EMessageType.Message | EMessageType.ServerMessage, data), clientGuidArray); } } public void SendClients(TData data, int[] playerIdArray) { SendClients(data, playerIdArray.Select(LNetworkUtils.GetClientGuid).ToArray()); } public void SendClients(TData data) { SendClients(data, LNetworkUtils.AllConnectedClients); } public void SendServer(TData data) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) if (!LNetworkUtils.IsConnected) { throw new NetworkConfigurationException("Attempting to use LNetworkMessage method while not connected to a server."); } if (UnnamedMessageHandler.Instance == null) { throw new NetworkConfigurationException("The UnnamedMessageHandler is null. Shit's fucked! Please send this log to the LethalNetworkAPI developer."); } UnnamedMessageHandler.Instance.SendMessageToServer(new MessageData(Identifier, EMessageType.Message | EMessageType.ClientMessage, data)); } public void SendOtherClients(TData data, ulong[] clientGuidArray) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) if (!LNetworkUtils.IsConnected) { throw new NetworkConfigurationException("Attempting to use LNetworkMessage method while not connected to a server."); } if (clientGuidArray.Any()) { if (UnnamedMessageHandler.Instance == null) { throw new NetworkConfigurationException("The UnnamedMessageHandler is null. Shit's fucked! Please send this log to the LethalNetworkAPI developer."); } if (UnnamedMessageHandler.Instance.IsServer) { UnnamedMessageHandler.Instance.SendMessageToClients(new MessageData(Identifier, EMessageType.Message | EMessageType.ClientMessageToClient, data), clientGuidArray); } else { UnnamedMessageHandler.Instance.SendMessageToServer(new MessageData(Identifier, EMessageType.Message | EMessageType.ClientMessageToClient, data, clientGuidArray)); } } } public void SendOtherClients(TData data, int[] playerIdArray) { SendOtherClients(data, playerIdArray.Select(LNetworkUtils.GetClientGuid).ToArray()); } public void SendOtherClients(TData data) { SendOtherClients(data, LNetworkUtils.OtherConnectedClients); } } public class LNetworkVariable : LNetworkVariableBase { private TData _offlineValue; private TData _value; private TData _previousValue; internal bool Dirty { get; set; } public TData OfflineValue { get { return _offlineValue; } set { _offlineValue = value; if ((Object)(object)NetworkManager.Singleton == (Object)null) { ResetValue(); } } } public TData Value { get { return _value; } set { if (!object.Equals(_value, value)) { SetDirty(value: true); _previousValue = _value; _value = value; this.OnValueChanged?.Invoke(_previousValue, _value); } } } public event Action? OnValueChanged = delegate { }; private LNetworkVariable(string identifier, TData offlineValue, LNetworkVariableWritePerms writePerms, Action? onValueChanged) { if (UnnamedMessageHandler.LNetworkVariables.TryGetValue(identifier, out LNetworkVariableBase _)) { throw new InvalidOperationException("A variable with the identifier " + identifier + " already exists! Please use a different identifier."); } base.Identifier = identifier; base.WritePerms = writePerms; _offlineValue = offlineValue; _value = offlineValue; _previousValue = offlineValue; OnValueChanged += onValueChanged; UnnamedMessageHandler.VariableCheck += CheckForDirt; UnnamedMessageHandler.LNetworkVariables.Add(base.Identifier, this); UnnamedMessageHandler? instance = UnnamedMessageHandler.Instance; if (instance != null && instance.UnInitializedValues.TryGetValue(base.Identifier, out object value2)) { _value = (TData)value2; UnnamedMessageHandler.Instance.UnInitializedValues.Remove(base.Identifier); this.OnValueChanged?.Invoke(_previousValue, _value); _previousValue = _value; } } public static LNetworkVariable Connect(string identifier, TData offlineValue = default(TData), LNetworkVariableWritePerms writePerms = LNetworkVariableWritePerms.Server, Action? onValueChanged = null) { string text; try { text = LNetworkUtils.GetModGuid(2) + "." + identifier; } catch (Exception arg) { LethalNetworkAPIPlugin.Logger.LogError((object)("Unable to find Mod Guid! To still work, this Message will only use the given identifier. " + $"Warning: This may cause collision with another mod's NetworkMessage! Stack Trace: {arg}")); text = identifier; } if (!UnnamedMessageHandler.LNetworkVariables.TryGetValue(text, out LNetworkVariableBase value)) { return new LNetworkVariable(text, offlineValue, writePerms, onValueChanged); } LNetworkVariable lNetworkVariable = (LNetworkVariable)value; lNetworkVariable.OfflineValue = offlineValue; lNetworkVariable.OnValueChanged += onValueChanged; return lNetworkVariable; } public static LNetworkVariable Create(string identifier, TData defaultValue = default(TData), LNetworkVariableWritePerms writePerms = LNetworkVariableWritePerms.Server, Action? onValueChanged = null) { string identifier2; try { identifier2 = LNetworkUtils.GetModGuid(2) + "." + identifier; } catch (Exception arg) { LethalNetworkAPIPlugin.Logger.LogError((object)("Unable to find Mod Guid! To still work, this Message will only use the given identifier. " + $"Warning: This may cause collision with another mod's NetworkMessage! Stack Trace: {arg}")); identifier2 = identifier; } return new LNetworkVariable(identifier2, defaultValue, writePerms, onValueChanged); } private void CheckForDirt() { IsDirty(); } private void SetDirty(bool value) { if (value) { UnnamedMessageHandler.Instance?.DirtyBois.Add(this); } Dirty = value; } internal override bool IsDirty() { if (Dirty) { return true; } if (object.Equals(_previousValue, Value)) { return false; } if (!CanWrite()) { return false; } if (typeof(TData).IsByRef) { _previousValue = (TData)AccessTools.MakeDeepCopy((object)_value, typeof(TData), (Func)null, ""); } else { _previousValue = _value; } SetDirty(value: true); return true; } internal override void ResetValue() { _value = (_previousValue = _offlineValue); Dirty = false; } internal override void ResetDirty() { if (Dirty) { _previousValue = _value; Dirty = false; } } internal override object? GetValue() { return _value; } internal override void ReceiveUpdate(object? data) { TData val = (TData)data; if (!object.Equals(_value, val)) { this.OnValueChanged?.Invoke(_value, val); } _value = val; if (typeof(TData).IsByRef) { _previousValue = (TData)AccessTools.MakeDeepCopy((object)val, typeof(TData), (Func)null, ""); } else { _previousValue = val; } Dirty = false; } public void MakeDirty() { SetDirty(value: true); } public void UpdateOwner(params ulong[] clientGuidArray) { if (base.WritePerms != LNetworkVariableWritePerms.Owner) { throw new InvalidOperationException($"The variable `{base.Identifier}` does not allow changing ownership (writePerms: {base.WritePerms})."); } if ((Object)(object)NetworkManager.Singleton == (Object)null) { throw new InvalidOperationException("Cannot modify ownership of the variable `" + base.Identifier + "` while not connected to a server!"); } if (!NetworkManager.Singleton.IsServer && !NetworkManager.Singleton.IsHost) { LethalNetworkAPIPlugin.Logger.LogWarning((object)("Cannot modify ownership of the variable `" + base.Identifier + "` if not the host!")); } else { base.OwnerClients = clientGuidArray; } } public void UpdateOwner(params int[] playerIdArray) { if (base.WritePerms != LNetworkVariableWritePerms.Owner) { throw new InvalidOperationException($"The variable `{base.Identifier}` does not allow changing ownership (writePerms: {base.WritePerms})."); } if ((Object)(object)NetworkManager.Singleton == (Object)null) { throw new InvalidOperationException("Cannot modify ownership of the variable `" + base.Identifier + "` while not connected to a server!"); } if (!NetworkManager.Singleton.IsServer && !NetworkManager.Singleton.IsHost) { LethalNetworkAPIPlugin.Logger.LogWarning((object)("Cannot modify ownership of the variable `" + base.Identifier + "` if not the host!")); } else { base.OwnerClients = playerIdArray.Select(LNetworkUtils.GetClientGuid).ToArray(); } } public void Dispose() { UnnamedMessageHandler.LNetworkVariables.Remove(base.Identifier); UnnamedMessageHandler.Instance?.DirtyBois.Remove(this); this.OnValueChanged = null; } } public enum LNetworkVariableWritePerms { Server, Owner, Everyone } internal static class TextDefinitions { internal const string NotInLobbyMessage = "Unable to send the {0} with identifier \"{1}\" and data {{{2}}}. Is the player in a lobby?"; internal const string UnableToFindGuid = "Unable to find plugin info for calling mod for {0} with identifier \"{1}\". Are you using BepInEx? \n Stacktrace: {2}"; internal const string NotServerInfo = "The client {0} cannot use server methods. {1} Identifier: \"{2}\""; internal const string NotInLobbyEvent = "Unable to invoke the {0} with identifier \"{1}\". Is the player in a lobby?"; internal const string NetworkHandlerDoesNotExist = "The NetworkHandler does not exist. This shouldn't occur!"; internal const string TargetClientNotConnected = "The specified client {0} is not connected. {1} Identifier: \"{2}\""; internal const string TargetClientsNotConnected = "None of the specified clients {0} are connected. {1} Identifier: \"{2}\""; internal const string UnableToLocateNetworkObjectComponent = "Unable to find the network object component. Are you adding variable \"{0}\" to a network object?"; } public static class MyPluginInfo { public const string PLUGIN_GUID = "LethalNetworkAPI"; public const string PLUGIN_NAME = "LethalNetworkAPI"; public const string PLUGIN_VERSION = "3.3.3"; } } namespace LethalNetworkAPI.Utils { public static class LNetworkUtils { private static ulong[] _allClients; public static bool IsConnected { get { NetworkManager singleton = NetworkManager.Singleton; if (singleton == null) { return false; } return singleton.IsConnectedClient; } } public static bool IsHostOrServer { get { if (!NetworkManager.Singleton.IsHost) { return NetworkManager.Singleton.IsServer; } return true; } } public static ulong[] AllConnectedClients { get { if ((Object)(object)NetworkManager.Singleton == (Object)null) { return Array.Empty(); } if (NetworkManager.Singleton.IsServer || NetworkManager.Singleton.IsHost) { return NetworkManager.Singleton.ConnectedClientsIds.ToArray(); } return _allClients; } internal set { _allClients = value; } } public static ulong[] OtherConnectedClients => AllConnectedClientsExcept(NetworkManager.Singleton.LocalClientId); public static event Action OnNetworkStart; public static ulong[] AllConnectedClientsExcept(ulong clientId) { return AllConnectedClients.Where((ulong i) => i != clientId).ToArray(); } public static ulong[] AllConnectedClientsExcept(params ulong[] clientIds) { ulong[] clientIds2 = clientIds; return AllConnectedClients.Where((ulong i) => !clientIds2.Contains(i)).ToArray(); } public static ulong GetClientGuid(int playerId) { return StartOfRound.Instance.allPlayerScripts[playerId].actualClientId; } public static int GetPlayerId(ulong clientGuid) { return (int)StartOfRound.Instance.allPlayerScripts.First((PlayerControllerB player) => player.actualClientId == clientGuid).playerClientId; } internal static string GetModGuid(int frameIndex) { MethodBase method = new StackTrace().GetFrame(frameIndex).GetMethod(); Assembly assembly = method.ReflectedType.Assembly; Type type2 = AccessTools.GetTypesFromAssembly(assembly).First((Type type) => type.GetCustomAttributes(typeof(BepInPlugin), inherit: false).Any()); return MetadataHelper.GetMetadata(type2).GUID; } [MethodImpl(MethodImplOptions.NoInlining)] internal static void InvokeOnNetworkStart(ulong clientID) { NetworkManager singleton = NetworkManager.Singleton; if (clientID != ((singleton != null) ? new ulong?(singleton.LocalClientId) : null)) { return; } Delegate[] invocationList = LNetworkUtils.OnNetworkStart.GetInvocationList(); foreach (Delegate @delegate in invocationList) { try { @delegate.DynamicInvoke(IsHostOrServer); } catch (Exception ex) { LethalNetworkAPIPlugin.Logger.LogError((object)ex); } } } static LNetworkUtils() { LNetworkUtils.OnNetworkStart = delegate { }; _allClients = Array.Empty(); } } } namespace LethalNetworkAPI.Patches { [HarmonyPatch(typeof(NetworkManager))] [HarmonyPriority(500)] [HarmonyWrapSafe] internal static class NetworkManagerPatch { [HarmonyPatch("Initialize")] [HarmonyPostfix] public static void InitializePatch(NetworkManager __instance) { new UnnamedMessageHandler(); new NetworkHandler(); __instance.OnClientConnectedCallback += LNetworkUtils.InvokeOnNetworkStart; } [HarmonyPatch("ShutdownInternal")] [HarmonyPrefix] public static void ShutdownPatch(NetworkManager __instance) { __instance.OnClientConnectedCallback -= LNetworkUtils.InvokeOnNetworkStart; UnnamedMessageHandler.Instance?.Dispose(); NetworkHandler.Instance?.Dispose(); } } } namespace LethalNetworkAPI.Serializable { internal static class LethalNetworkSerializer { internal static byte[] Serialize(T value) { //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) //IL_005e: Unknown result type (might be due to invalid IL or missing references) if (value == null) { return Array.Empty(); } object obj = value; GameObject val = (GameObject)((obj is GameObject) ? obj : null); if (val != null) { return SerializationUtility.SerializeValue(NetworkObjectReference.op_Implicit(val), (DataFormat)0, (SerializationContext)null); } object obj2 = value; NetworkObject val2 = (NetworkObject)((obj2 is NetworkObject) ? obj2 : null); if (val2 != null) { return SerializationUtility.SerializeValue(NetworkObjectReference.op_Implicit(val2), (DataFormat)0, (SerializationContext)null); } object obj3 = value; NetworkBehaviour val3 = (NetworkBehaviour)((obj3 is NetworkBehaviour) ? obj3 : null); if (val3 != null) { return SerializationUtility.SerializeValue(NetworkBehaviourReference.op_Implicit(val3), (DataFormat)0, (SerializationContext)null); } return SerializationUtility.SerializeValue(value, (DataFormat)0, (SerializationContext)null); } internal static T Deserialize(byte[] data) { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) if (data.Length == 0) { return default(T); } T val = default(T); if (!(val is GameObject)) { if (!(val is NetworkObject)) { if (val is NetworkBehaviour) { return (T)(object)NetworkBehaviourReference.op_Implicit(SerializationUtility.DeserializeValue(data, (DataFormat)0, (DeserializationContext)null)); } return SerializationUtility.DeserializeValue(data, (DataFormat)0, (DeserializationContext)null); } return (T)(object)NetworkObjectReference.op_Implicit(SerializationUtility.DeserializeValue(data, (DataFormat)0, (DeserializationContext)null)); } return (T)(object)NetworkObjectReference.op_Implicit(SerializationUtility.DeserializeValue(data, (DataFormat)0, (DeserializationContext)null)); } } public class NetworkBehaviourReferenceFormatter : MinimalBaseFormatter { private static readonly Serializer UInt16Serializer = Serializer.Get(); private static readonly Serializer NetworkObjectReferenceSerializer = Serializer.Get(); protected override void Read(ref NetworkBehaviourReference value, IDataReader reader) { //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) value.m_NetworkObjectReference = NetworkObjectReferenceSerializer.ReadValue(reader); value.m_NetworkBehaviourId = UInt16Serializer.ReadValue(reader); } protected override void Write(ref NetworkBehaviourReference value, IDataWriter writer) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) NetworkObjectReferenceSerializer.WriteValue(value.m_NetworkObjectReference, writer); UInt16Serializer.WriteValue(value.m_NetworkBehaviourId, writer); } } internal class NetworkObjectReferenceFormatter : MinimalBaseFormatter { private static readonly Serializer UInt64Serializer = Serializer.Get(); protected override void Read(ref NetworkObjectReference value, IDataReader reader) { ((NetworkObjectReference)(ref value)).NetworkObjectId = UInt64Serializer.ReadValue(reader); } protected override void Write(ref NetworkObjectReference value, IDataWriter writer) { UInt64Serializer.WriteValue(((NetworkObjectReference)(ref value)).NetworkObjectId, writer); } } } namespace LethalNetworkAPI.Old { [Obsolete] public abstract class LethalNetworkDeprecated { internal readonly string Identifier; private readonly string _networkType; protected LethalNetworkDeprecated(string identifier, string networkType, int frameIndex = 3) { try { MethodBase method = new StackTrace().GetFrame(frameIndex).GetMethod(); Assembly assembly = method.ReflectedType.Assembly; Type type2 = AccessTools.GetTypesFromAssembly(assembly).First((Type type) => type.GetCustomAttributes(typeof(BepInPlugin), inherit: false).Any()); Identifier = MetadataHelper.GetMetadata(type2).GUID + "." + identifier; _networkType = networkType; } catch (Exception ex) { LethalNetworkAPIPlugin.Logger.LogError((object)ex); } } protected bool IsNetworkHandlerNull(bool log = true) { if (NetworkHandler.Instance != null) { return false; } if (log) { LethalNetworkAPIPlugin.Logger.LogError((object)$"Unable to invoke the {_networkType.ToLower()} with identifier \"{Identifier}\". Is the player in a lobby?"); } return true; } protected bool IsHostOrServer(bool log = true) { if ((Object)(object)NetworkManager.Singleton == (Object)null) { return false; } if (NetworkManager.Singleton.IsHost || NetworkManager.Singleton.IsServer) { return true; } if (log) { LethalNetworkAPIPlugin.Logger.LogError((object)$"The client {NetworkManager.Singleton.LocalClientId} cannot use server methods. {_networkType} Identifier: \"{Identifier}\""); } return false; } private bool DoClientsExist(IEnumerable clientIds, bool log = true) { if (clientIds.Any()) { return true; } if (log) { LethalNetworkAPIPlugin.Logger.LogError((object)$"None of the specified clients {clientIds} are connected. {_networkType} Identifier: \"{Identifier}\""); } return false; } private ClientRpcParams GenerateClientParams(IEnumerable clientIds, bool allExcept) { //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: 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_0108: 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_00e0: 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) ulong[] enumerable = (clientIds as ulong[]) ?? clientIds.ToArray(); NativeArray val = default(NativeArray); if (!enumerable.Any() && allExcept) { val..ctor(NetworkManager.Singleton.ConnectedClientsIds.Where((ulong i) => i != 0).ToArray(), (Allocator)4); } else if (allExcept) { val..ctor(NetworkManager.Singleton.ConnectedClientsIds.Where((ulong i) => enumerable.All((ulong j) => i != j)).ToArray(), (Allocator)4); } else { val..ctor(enumerable.Where((ulong i) => NetworkManager.Singleton.ConnectedClientsIds.Contains(i)).ToArray(), (Allocator)4); } if (!DoClientsExist((IEnumerable)(object)val)) { return default(ClientRpcParams); } ClientRpcParams result = default(ClientRpcParams); result.Send = new ClientRpcSendParams { TargetClientIdsNativeArray = val }; return result; } protected ClientRpcParams GenerateClientParams(IEnumerable clientIds) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) return GenerateClientParams(clientIds, allExcept: false); } protected ClientRpcParams GenerateClientParams(ulong clientId) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) return GenerateClientParams(new <>z__ReadOnlySingleElementList(clientId), allExcept: false); } protected ClientRpcParams GenerateClientParamsExcept(IEnumerable clientIds) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) return GenerateClientParams(clientIds, allExcept: true); } protected ClientRpcParams GenerateClientParamsExcept(ulong clientId) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) return GenerateClientParams(new <>z__ReadOnlySingleElementList(clientId), allExcept: true); } protected ClientRpcParams GenerateClientParamsExceptHost() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) return GenerateClientParams(Array.Empty(), allExcept: true); } } } namespace LethalNetworkAPI.Old.Networking { internal class NetworkHandler : IDisposable { internal readonly List ObjectNetworkVariableList = new List(); internal bool IsServer => UnnamedMessageHandler.Instance?.IsServer ?? false; internal static NetworkHandler? Instance { get; private set; } internal static event Action? NetworkSpawn; internal static event Action? NetworkDespawn; internal static event Action? NetworkTick; internal static event Action? OnPlayerJoin; internal static event Action? OnServerMessage; internal static event Action? OnClientMessage; internal static event Action? OnVariableUpdate; internal static event Action? GetVariableValue; internal static event Action? OnServerEvent; internal static event Action? OnClientEvent; internal static event Action? OnSyncedServerEvent; internal static event Action? OnSyncedClientEvent; private void SendMessageToServer(MessageData messageData) { UnnamedMessageHandler.Instance.SendMessageToServer(messageData, deprecatedMessage: true); } private void SendMessageToClients(MessageData messageData, ulong[] clientGuidArray) { UnnamedMessageHandler.Instance.SendMessageToClients(messageData, clientGuidArray, deprecatedMessage: true); } public NetworkHandler() { Instance = this; NetworkHandler.NetworkSpawn?.Invoke(); NetworkManager.Singleton.NetworkTickSystem.Tick += InvokeNetworkTick; NetworkManager.Singleton.OnClientConnectedCallback += OnClientConnectedCallback; } [MethodImpl(MethodImplOptions.NoInlining)] private void InvokeNetworkTick() { NetworkHandler.NetworkTick?.Invoke(); } public void Dispose() { NetworkHandler.NetworkDespawn?.Invoke(); NetworkHandler.OnPlayerJoin = delegate { }; NetworkHandler.NetworkDespawn = delegate { }; Instance = null; NetworkManager.Singleton.NetworkTickSystem.Tick -= InvokeNetworkTick; NetworkManager.Singleton.OnClientConnectedCallback -= OnClientConnectedCallback; } private void OnClientConnectedCallback(ulong client) { NetworkHandler.OnPlayerJoin?.Invoke(client); } public void ReadMessage(ulong clientId, FastBufferReader reader) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) string messageID = default(string); ((FastBufferReader)(ref reader)).ReadValueSafe(ref messageID, false); EMessageType messageType = default(EMessageType); ((FastBufferReader)(ref reader)).ReadValueSafe(ref messageType, default(ForEnums)); byte[] messageData = default(byte[]); ((FastBufferReader)(ref reader)).ReadValueSafe(ref messageData, default(ForPrimitives)); HandleMessage(clientId, messageID, messageType, messageData); } public void HandleMessage(ulong clientId, string messageID, EMessageType messageType, byte[] messageData) { switch (messageType) { case EMessageType.Event | EMessageType.ServerMessage: NetworkHandler.OnClientEvent?.Invoke(messageID, 99999uL); break; case EMessageType.Event | EMessageType.ClientMessage: NetworkHandler.OnServerEvent?.Invoke(messageID, clientId); break; case EMessageType.Event | EMessageType.ClientMessageToClient: if (IsServer) { UnnamedMessageHandler.Instance.SendMessageToClientsExcept(new MessageData(messageID, messageType, messageData), clientId, deprecatedMessage: true); } NetworkHandler.OnClientEvent?.Invoke(messageID, clientId); break; case EMessageType.SyncedEvent: if (IsServer) { UnnamedMessageHandler.Instance.SendMessageToClientsExcept(new MessageData(messageID, messageType, messageData), clientId, deprecatedMessage: true); } NetworkHandler.OnSyncedServerEvent?.Invoke(messageID, UnnamedMessageHandler.Deserialize(messageData), clientId); break; case EMessageType.Message | EMessageType.ServerMessage: NetworkHandler.OnClientMessage?.Invoke(messageID, messageData, 99999uL); break; case EMessageType.Message | EMessageType.ClientMessage: NetworkHandler.OnServerMessage?.Invoke(messageID, messageData, clientId); break; case EMessageType.Message | EMessageType.ClientMessageToClient: if (IsServer) { UnnamedMessageHandler.Instance.SendMessageToClientsExcept(new MessageData(messageID, messageType, messageData), clientId, deprecatedMessage: true); } NetworkHandler.OnClientMessage?.Invoke(messageID, messageData, clientId); break; case EMessageType.Variable | EMessageType.Request: NetworkHandler.GetVariableValue?.Invoke(messageID, clientId); break; case EMessageType.Variable: if (IsServer) { UnnamedMessageHandler.Instance.SendMessageToClientsExcept(new MessageData(messageID, messageType, messageData), clientId, deprecatedMessage: true); } NetworkHandler.OnVariableUpdate?.Invoke(messageID, messageData); break; default: throw new ArgumentOutOfRangeException(); } } internal void MessageServerRpc(string identifier, byte[] data, bool toOtherClients = false) { if (!toOtherClients) { SendMessageToServer(new MessageData(identifier, EMessageType.Message | EMessageType.ClientMessage, data)); } else if (IsServer) { SendMessageToClients(new MessageData(identifier, EMessageType.Message | EMessageType.ClientMessageToClient, data), LNetworkUtils.OtherConnectedClients); } else { SendMessageToServer(new MessageData(identifier, EMessageType.Message | EMessageType.ClientMessageToClient, data)); } } internal void MessageClientRpc(string identifier, byte[] data, ulong[] clientGuidArray) { SendMessageToClients(new MessageData(identifier, EMessageType.Message | EMessageType.ServerMessage, data), clientGuidArray); } internal void EventServerRpc(string identifier, bool toOtherClients = false) { if (!toOtherClients) { SendMessageToServer(new MessageData(identifier, EMessageType.Event | EMessageType.ClientMessage)); } else if (IsServer) { SendMessageToClients(new MessageData(identifier, EMessageType.Event | EMessageType.ClientMessageToClient), LNetworkUtils.OtherConnectedClients); } else { SendMessageToServer(new MessageData(identifier, EMessageType.Event | EMessageType.ClientMessageToClient)); } } internal void EventClientRpc(string identifier, ulong[] clientGuidArray) { SendMessageToClients(new MessageData(identifier, EMessageType.Event | EMessageType.ServerMessage), clientGuidArray); } internal void SyncedEventServerRpc(string identifier, double time) { if (IsServer) { SendMessageToClients(new MessageData(identifier, EMessageType.SyncedEvent, UnnamedMessageHandler.Serialize(time)), LNetworkUtils.OtherConnectedClients); } else { SendMessageToServer(new MessageData(identifier, EMessageType.SyncedEvent, UnnamedMessageHandler.Serialize(time))); } } [ServerRpc(RequireOwnership = false)] internal void UpdateVariableServerRpc(string identifier, byte[] data) { if (IsServer) { SendMessageToClients(new MessageData(identifier, EMessageType.Variable, data), LNetworkUtils.OtherConnectedClients); } else { SendMessageToServer(new MessageData(identifier, EMessageType.Variable, data)); } } [ClientRpc] internal void UpdateVariableClientRpc(string identifier, byte[] data, ulong[] clientGuidArray) { SendMessageToClients(new MessageData(identifier, EMessageType.Variable, data), clientGuidArray); } [ServerRpc(RequireOwnership = false)] internal void GetVariableValueServerRpc(string identifier, ServerRpcParams serverRpcParams = default(ServerRpcParams)) { SendMessageToServer(new MessageData(identifier, EMessageType.Variable | EMessageType.Request)); } } } namespace LethalNetworkAPI.Internal { [Flags] internal enum EMessageType { None = 0, Event = 1, Message = 2, Variable = 4, SyncedEvent = 8, ServerMessage = 0x10, ClientMessage = 0x20, ClientMessageToClient = 0x40, Request = 0x80, DataUpdate = 0x10, OwnershipUpdate = 0x20, UpdateClientList = 0x80 } public abstract class LNetworkVariableBase { internal string Identifier { get; init; } internal LNetworkVariableWritePerms WritePerms { get; init; } internal ulong[]? OwnerClients { get; set; } internal abstract void ReceiveUpdate(object? data); internal abstract void ResetValue(); internal abstract bool IsDirty(); internal abstract void ResetDirty(); internal abstract object? GetValue(); internal bool CanWrite() { return WritePerms switch { LNetworkVariableWritePerms.Owner => OwnerClients != null && OwnerClients.Contains(NetworkManager.Singleton.LocalClientId), LNetworkVariableWritePerms.Server => NetworkManager.Singleton.IsServer || NetworkManager.Singleton.IsHost, LNetworkVariableWritePerms.Everyone => true, _ => false, }; } } internal record MessageData([property: OdinSerialize] string Identifier, [property: OdinSerialize] EMessageType MessageType, [property: OdinSerialize] object? Data = null, [property: OdinSerialize] ulong[]? TargetClients = null); internal class UnnamedMessageHandler : IDisposable { private const string LibIdentifier = "LethalNetworkAPI"; private int _ticksSinceLastCheck; internal static UnnamedMessageHandler? Instance { get; private set; } internal static Dictionary LNetworkMessages { get; } = new Dictionary(); internal static Dictionary LNetworkEvents { get; } = new Dictionary(); internal static Dictionary LNetworkVariables { get; } = new Dictionary(); internal bool IsServer { get { if (!NetworkManager.IsServer) { return NetworkManager.IsHost; } return true; } } private NetworkManager NetworkManager { get; } private CustomMessagingManager CustomMessagingManager { get; } internal HashSet DirtyBois { get; } = new HashSet(); internal Dictionary UnInitializedValues { get; } = new Dictionary(); internal static event Action? VariableCheck; internal UnnamedMessageHandler() { //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Expected O, but got Unknown Instance = this; NetworkManager = NetworkManager.Singleton; CustomMessagingManager = NetworkManager.CustomMessagingManager; NetworkManager.NetworkTickSystem.Tick += CheckVariablesForChanges; CustomMessagingManager.OnUnnamedMessage += new UnnamedMessageDelegate(ReceiveMessage); if (IsServer) { NetworkManager.OnClientConnectedCallback += UpdateNewClientVariables; NetworkManager.OnClientDisconnectCallback += UpdateClientList; } } private void CheckVariablesForChanges() { if (_ticksSinceLastCheck++ > 9) { UnnamedMessageHandler.VariableCheck?.Invoke(); _ticksSinceLastCheck = 0; } UpdateVariables(); } private void UpdateVariables() { if (DirtyBois.Count == 0) { return; } foreach (LNetworkVariableBase dirtyBoi in DirtyBois) { if (IsServer) { SendMessageToClients(new MessageData(dirtyBoi.Identifier, EMessageType.Variable | EMessageType.ServerMessage, dirtyBoi.GetValue()), LNetworkUtils.OtherConnectedClients); } else { SendMessageToServer(new MessageData(dirtyBoi.Identifier, EMessageType.Variable | EMessageType.ServerMessage, dirtyBoi.GetValue())); } dirtyBoi.ResetDirty(); } DirtyBois.Clear(); } private void UpdateNewClientVariables(ulong newClient) { if (!IsServer || newClient == 0L) { return; } UpdateClientList(newClient); foreach (LNetworkVariableBase value in LNetworkVariables.Values) { SendMessageToClients(new MessageData(value.Identifier, EMessageType.Variable | EMessageType.ServerMessage, value.OwnerClients), new ulong[1] { newClient }); } } private void UpdateClientList(ulong changedClient) { if (IsServer) { SendMessageToClients(new MessageData("Internal.UpdateClientList", EMessageType.Request, LNetworkUtils.OtherConnectedClients), LNetworkUtils.AllConnectedClients); } } internal void SendMessageToClients(MessageData messageData, ulong[] clientGuidArray, bool deprecatedMessage = false) { //IL_00ba: Unknown result type (might be due to invalid IL or missing references) if (clientGuidArray.Any((ulong client) => client == NetworkManager.LocalClientId)) { clientGuidArray = clientGuidArray.Where((ulong client) => client != NetworkManager.LocalClientId).ToArray(); if (deprecatedMessage) { NetworkHandler.Instance.HandleMessage(NetworkManager.LocalClientId, messageData.Identifier, messageData.MessageType, ((byte[])messageData.Data) ?? Array.Empty()); } else { HandleMessage(NetworkManager.LocalClientId, messageData.Identifier, messageData.MessageType, messageData.Data, new ulong[1] { NetworkManager.LocalClientId }); } } if (clientGuidArray.Any()) { WriteMessageData(out var writer, messageData, deprecatedMessage); CustomMessagingManager.SendUnnamedMessage((IReadOnlyList)clientGuidArray, writer, (NetworkDelivery)4); ((FastBufferWriter)(ref writer)).Dispose(); } } internal void SendMessageToClientsExcept(MessageData messageData, ulong clientId, bool deprecatedMessage = false) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) WriteMessageData(out var writer, messageData, deprecatedMessage); ulong[] array = LNetworkUtils.AllConnectedClientsExcept(clientId, 0uL); if (array.Length != 0) { CustomMessagingManager.SendUnnamedMessage((IReadOnlyList)LNetworkUtils.AllConnectedClientsExcept(clientId, 0uL), writer, (NetworkDelivery)4); ((FastBufferWriter)(ref writer)).Dispose(); } } internal void SendMessageToServer(MessageData messageData, bool deprecatedMessage = false) { //IL_006a: Unknown result type (might be due to invalid IL or missing references) if (IsServer) { if (deprecatedMessage) { NetworkHandler.Instance.HandleMessage(0uL, messageData.Identifier, messageData.MessageType, ((byte[])messageData.Data) ?? Array.Empty()); } else { HandleMessage(0uL, messageData.Identifier, messageData.MessageType, messageData.Data, new ulong[1]); } } else { WriteMessageData(out var writer, messageData, deprecatedMessage); CustomMessagingManager.SendUnnamedMessage(0uL, writer, (NetworkDelivery)4); ((FastBufferWriter)(ref writer)).Dispose(); } } private void ReceiveMessage(ulong clientId, FastBufferReader reader) { //IL_004f: 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_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_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0088: 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_002b: Unknown result type (might be due to invalid IL or missing references) string text = default(string); try { ((FastBufferReader)(ref reader)).ReadValueSafe(ref text, false); } catch { return; } if (text == "LethalNetworkAPI.Old") { NetworkHandler.Instance?.ReadMessage(clientId, reader); } if (!(text != "LethalNetworkAPI")) { string messageID = default(string); ((FastBufferReader)(ref reader)).ReadValueSafe(ref messageID, false); EMessageType messageType = default(EMessageType); ((FastBufferReader)(ref reader)).ReadValueSafe(ref messageType, default(ForEnums)); ulong[] targetClients = default(ulong[]); ((FastBufferReader)(ref reader)).ReadValueSafe(ref targetClients, default(ForPrimitives)); byte[] serializedData = default(byte[]); ((FastBufferReader)(ref reader)).ReadValueSafe(ref serializedData, default(ForPrimitives)); byte[] serializedData2 = default(byte[]); ((FastBufferReader)(ref reader)).ReadValueSafe(ref serializedData2, default(ForPrimitives)); Type type = Deserialize(serializedData2); object messageData = ((type != null) ? Deserialize(serializedData) : null); HandleMessage(clientId, messageID, messageType, messageData, targetClients); } } private void HandleMessage(ulong clientId, string messageID, EMessageType messageType, object? messageData, ulong[] targetClients) { ulong[] clientGuidArray = targetClients.Where((ulong i) => i != 0L && i != clientId).ToArray(); switch (messageType) { case EMessageType.Event | EMessageType.ServerMessage: LNetworkEvents[messageID].InvokeOnClientReceived(); break; case EMessageType.Event | EMessageType.ClientMessage: LNetworkEvents[messageID].InvokeOnServerReceived(clientId); break; case EMessageType.Event | EMessageType.ClientMessageToClient: if (!IsServer) { LNetworkMessages[messageID].InvokeOnClientReceivedFromClient(messageData, clientId); break; } SendMessageToClients(new MessageData(messageID, messageType, messageData), clientGuidArray); if (targetClients.Any((ulong i) => i == 0)) { LNetworkEvents[messageID].InvokeOnClientReceivedFromClient(clientId); } break; case EMessageType.Message | EMessageType.ServerMessage: LNetworkMessages[messageID].InvokeOnClientReceived(messageData); break; case EMessageType.Message | EMessageType.ClientMessage: LNetworkMessages[messageID].InvokeOnServerReceived(messageData, clientId); break; case EMessageType.Message | EMessageType.ClientMessageToClient: if (!IsServer) { LNetworkMessages[messageID].InvokeOnClientReceivedFromClient(messageData, clientId); break; } SendMessageToClients(new MessageData(messageID, messageType, messageData), clientGuidArray); if (targetClients.Any((ulong i) => i == 0)) { LNetworkMessages[messageID].InvokeOnClientReceivedFromClient(messageData, clientId); } break; case EMessageType.Variable | EMessageType.ServerMessage: { if (!LNetworkVariables.TryGetValue(messageID, out LNetworkVariableBase lNetworkVariableBase)) { UnInitializedValues[messageID] = messageData; break; } if (IsServer) { if (!lNetworkVariableBase.CanWrite()) { break; } SendMessageToClients(new MessageData(messageID, messageType, messageData), clientGuidArray); } lNetworkVariableBase.ReceiveUpdate(messageData); break; } case EMessageType.Variable | EMessageType.ClientMessage: { LNetworkVariableBase lNetworkVariableBase = LNetworkVariables[messageID]; if (clientId == 0L && lNetworkVariableBase.WritePerms == LNetworkVariableWritePerms.Owner) { lNetworkVariableBase.OwnerClients = (ulong[])messageData; } break; } case EMessageType.Request: if (clientId == 0L && NetworkManager.LocalClientId != 0L) { LNetworkUtils.AllConnectedClients = CollectionExtensions.AddToArray(((ulong[])messageData) ?? new ulong[1] { NetworkManager.LocalClientId }, 0uL); } break; default: throw new ArgumentOutOfRangeException(); } } internal static byte[] Serialize(object? data) { return SerializationUtility.SerializeValue(data, (DataFormat)0, (SerializationContext)null); } internal static T Deserialize(byte[] serializedData) { return SerializationUtility.DeserializeValue(serializedData, (DataFormat)0, (DeserializationContext)null); } private static void WriteMessageData(out FastBufferWriter writer, MessageData messageData, bool deprecatedMessage) { //IL_0021: 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_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: 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_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) (byte[], byte[], int) tuple = SerializeDataAndGetSize(messageData, deprecatedMessage); byte[] item = tuple.Item1; byte[] item2 = tuple.Item2; int item3 = tuple.Item3; writer = new FastBufferWriter(item3, (Allocator)2, item3 + 8); if (!((FastBufferWriter)(ref writer)).TryBeginWrite(item3)) { throw new OutOfMemoryException($"The buffer is too small ({((FastBufferWriter)(ref writer)).MaxCapacity}) " + $"to write the message data ({item3}) @ {((FastBufferWriter)(ref writer)).Position}. Shit's hella fucked!"); } ((FastBufferWriter)(ref writer)).WriteValue(deprecatedMessage ? "LethalNetworkAPI.Old" : "LethalNetworkAPI", false); ((FastBufferWriter)(ref writer)).WriteValue(messageData.Identifier, false); EMessageType messageType = messageData.MessageType; ((FastBufferWriter)(ref writer)).WriteValue(ref messageType, default(ForEnums)); if (!deprecatedMessage) { ((FastBufferWriter)(ref writer)).WriteValue(messageData.TargetClients ?? Array.Empty(), default(ForPrimitives)); } ((FastBufferWriter)(ref writer)).WriteValue(item, default(ForPrimitives)); ((FastBufferWriter)(ref writer)).WriteValue(item2, default(ForPrimitives)); } private static (byte[], byte[], int) SerializeDataAndGetSize(MessageData messageData, bool deprecatedMessage) { //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) byte[] array = ((messageData.Data?.GetType() == typeof(byte[])) ? ((byte[])messageData.Data) : Serialize(messageData.Data)); byte[] array2 = Serialize(messageData.Data?.GetType()); int writeSize = FastBufferWriter.GetWriteSize(deprecatedMessage ? "LethalNetworkAPI.Old" : "LethalNetworkAPI", false); writeSize += FastBufferWriter.GetWriteSize(messageData.Identifier, false); int num = writeSize; EMessageType messageType = messageData.MessageType; writeSize = num + FastBufferWriter.GetWriteSize(ref messageType, default(ForStructs)); if (!deprecatedMessage) { writeSize += FastBufferWriter.GetWriteSize(messageData.TargetClients ?? Array.Empty(), -1, 0); } writeSize += FastBufferWriter.GetWriteSize(array, -1, 0); writeSize += FastBufferWriter.GetWriteSize(array2, -1, 0); if (writeSize > 65536) { LethalNetworkAPIPlugin.Logger.LogWarning((object)($"The serialized message size of '{messageData.Identifier}' is {writeSize} bytes. " + "This is larger than the recommended max size of 65536 bytes. The message may be dropped during transit.")); } return (array, array2, writeSize); } public void Dispose() { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Expected O, but got Unknown CustomMessagingManager.OnUnnamedMessage -= new UnnamedMessageDelegate(ReceiveMessage); if (NetworkManager.NetworkTickSystem != null) { NetworkManager.NetworkTickSystem.Tick -= CheckVariablesForChanges; } if (IsServer) { NetworkManager.OnClientConnectedCallback -= UpdateNewClientVariables; NetworkManager.OnClientDisconnectCallback -= UpdateClientList; } foreach (LNetworkVariableBase value in LNetworkVariables.Values) { value.ResetValue(); } } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } internal static class IsExternalInit { } }