Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of LethalNetworkAPI v3.3.3
BepInEx/plugins/LethalNetworkAPI/LethalNetworkAPI.dll
Decompiled 2 months agousing 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<T> : IEnumerable, ICollection, IList, IEnumerable<T>, IReadOnlyCollection<T>, IReadOnlyList<T>, ICollection<T>, IList<T> { private sealed class Enumerator : IDisposable, IEnumerator, IEnumerator<T> { object IEnumerator.Current => _item; T IEnumerator<T>.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<T>.Count => 1; T IReadOnlyList<T>.this[int index] { get { if (index != 0) { throw new IndexOutOfRangeException(); } return _item; } } int ICollection<T>.Count => 1; bool ICollection<T>.IsReadOnly => true; T IList<T>.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<T>.Default.Equals(_item, (T)value); } int IList.IndexOf(object value) { if (!EqualityComparer<T>.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<T> IEnumerable<T>.GetEnumerator() { return new Enumerator(_item); } void ICollection<T>.Add(T item) { throw new NotSupportedException(); } void ICollection<T>.Clear() { throw new NotSupportedException(); } bool ICollection<T>.Contains(T item) { return EqualityComparer<T>.Default.Equals(_item, item); } void ICollection<T>.CopyTo(T[] array, int arrayIndex) { array[arrayIndex] = _item; } bool ICollection<T>.Remove(T item) { throw new NotSupportedException(); } int IList<T>.IndexOf(T item) { if (!EqualityComparer<T>.Default.Equals(_item, item)) { return -1; } return 0; } void IList<T>.Insert(int index, T item) { throw new NotSupportedException(); } void IList<T>.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 <WaitAndInvokeEvent>d__13 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public float timeToWait; public LethalClientEvent <>4__this; public ulong originatorClientId; object? IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object? IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <WaitAndInvokeEvent>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<ulong>? OnReceivedFromClient; public LethalClientEvent(string identifier, Action? onReceived = null, Action<ulong>? 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(<WaitAndInvokeEvent>d__13))] private IEnumerator WaitAndInvokeEvent(float timeToWait, ulong originatorClientId) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <WaitAndInvokeEvent>d__13(0) { <>4__this = this, timeToWait = timeToWait, originatorClientId = originatorClientId }; } } [Obsolete("Use LNetworkEvent instead.")] public sealed class LethalServerEvent : LNetworkEventDepricated { [CompilerGenerated] private sealed class <WaitAndInvokeEvent>d__10 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public float timeToWait; public LethalServerEvent <>4__this; public ulong clientId; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <WaitAndInvokeEvent>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<ulong>? OnReceived; public LethalServerEvent(string identifier, Action<ulong>? 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<ulong> 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(<WaitAndInvokeEvent>d__10))] private IEnumerator WaitAndInvokeEvent(float timeToWait, ulong clientId) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <WaitAndInvokeEvent>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<TData>? GetNetworkVariable<TData>(this NetworkBehaviour networkBehaviour, string identifier, bool serverOwned = false) { return ((Component)networkBehaviour).gameObject.NetworkVariable<TData>(identifier, serverOwned); } [Obsolete] public static LethalNetworkVariable<TData>? GetNetworkVariable<TData>(this NetworkObject networkObject, string identifier, bool serverOwned = false) { return ((Component)networkObject).gameObject.NetworkVariable<TData>(identifier, serverOwned); } [Obsolete] public static LethalNetworkVariable<TData>? GetNetworkVariable<TData>(this GameObject gameObject, string identifier, bool serverOwned = false) { return gameObject.NetworkVariable<TData>(identifier, serverOwned); } [Obsolete] private static LethalNetworkVariable<TData>? NetworkVariable<TData>(this GameObject gameObject, string identifier, bool serverOwned) { string identifier2 = identifier; NetworkObject networkObjectComp = default(NetworkObject); if (!gameObject.TryGetComponent<NetworkObject>(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<TData> lethalNetworkVariable = (LethalNetworkVariable<TData>)NetworkHandler.Instance.ObjectNetworkVariableList.FirstOrDefault((ILethalNetVar i) => ((LethalNetworkVariable<TData>)i).Identifier == $"{identifier2}.{networkObjectComp.GlobalObjectIdHash}"); if (lethalNetworkVariable != null) { return lethalNetworkVariable; } lethalNetworkVariable = new LethalNetworkVariable<TData>($"{identifier2}.{networkObjectComp.GlobalObjectIdHash}", networkObjectComp, serverOwned, 3); NetworkHandler.Instance.ObjectNetworkVariableList.Add(lethalNetworkVariable); return lethalNetworkVariable; } } [Obsolete("Use LNetworkMessage instead.")] public sealed class LethalClientMessage<TData> : LNetworkMessageDeprecated { public event Action<TData>? OnReceived; public event Action<TData, ulong>? OnReceivedFromClient; [Obsolete("Use LNetworkMessage instead.")] public LethalClientMessage(string identifier, Action<TData>? onReceived = null, Action<TData, ulong>? 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<TData>(data)); } else { this.OnReceivedFromClient?.Invoke(LethalNetworkSerializer.Deserialize<TData>(data), originatorClient); } } } } [Obsolete("Use LNetworkMessage instead.")] public class LethalServerMessage<TData> : LNetworkMessageDeprecated { public event Action<TData, ulong>? OnReceived; [Obsolete("Use LNetworkMessage instead.")] public LethalServerMessage(string identifier, Action<TData, ulong>? 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<ulong> 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<TData>(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<TData> : 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<TData>? 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<TData>).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<TData>(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<ulong>? OnServerReceived = delegate { }; public event Action? OnClientReceived = delegate { }; public event Action<ulong>? OnClientReceivedFromClient = delegate { }; public static LNetworkEvent Connect(string identifier, Action<ulong>? onServerReceived = null, Action? onClientReceived = null, Action<ulong>? 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<ulong>? onServerReceived = null, Action? onClientReceived = null, Action<ulong>? 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<ulong>? onServerReceived = null, Action? onClientReceived = null, Action<ulong>? 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<TData> : INetMessage { internal string Identifier { get; } public event Action<TData, ulong>? OnServerReceived = delegate { }; public event Action<TData>? OnClientReceived = delegate { }; public event Action<TData, ulong>? OnClientReceivedFromClient = delegate { }; public static LNetworkMessage<TData> Connect(string identifier, Action<TData, ulong>? onServerReceived = null, Action<TData>? onClientReceived = null, Action<TData, ulong>? 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<TData>(text, onServerReceived, onClientReceived, onClientReceivedFromClient); } LNetworkMessage<TData> lNetworkMessage = (LNetworkMessage<TData>)value; lNetworkMessage.OnServerReceived += onServerReceived; lNetworkMessage.OnClientReceived += onClientReceived; lNetworkMessage.OnClientReceivedFromClient += onClientReceivedFromClient; return lNetworkMessage; } public static LNetworkMessage<TData> Create(string identifier, Action<TData, ulong>? onServerReceived = null, Action<TData>? onClientReceived = null, Action<TData, ulong>? 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<TData>(identifier2, onServerReceived, onClientReceived, onClientReceivedFromClient); } private LNetworkMessage(string identifier, Action<TData, ulong>? onServerReceived = null, Action<TData>? onClientReceived = null, Action<TData, ulong>? 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<TData> : 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<TData, TData>? OnValueChanged = delegate { }; private LNetworkVariable(string identifier, TData offlineValue, LNetworkVariableWritePerms writePerms, Action<TData, TData>? 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<TData> Connect(string identifier, TData offlineValue = default(TData), LNetworkVariableWritePerms writePerms = LNetworkVariableWritePerms.Server, Action<TData, TData>? 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<TData>(text, offlineValue, writePerms, onValueChanged); } LNetworkVariable<TData> lNetworkVariable = (LNetworkVariable<TData>)value; lNetworkVariable.OfflineValue = offlineValue; lNetworkVariable.OnValueChanged += onValueChanged; return lNetworkVariable; } public static LNetworkVariable<TData> Create(string identifier, TData defaultValue = default(TData), LNetworkVariableWritePerms writePerms = LNetworkVariableWritePerms.Server, Action<TData, TData>? 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<TData>(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<string, Traverse, Traverse, object>)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<string, Traverse, Traverse, object>)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<ulong>(); } 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<bool> 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<ulong>(); } } } 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>(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<byte>(); } object obj = value; GameObject val = (GameObject)((obj is GameObject) ? obj : null); if (val != null) { return SerializationUtility.SerializeValue<NetworkObjectReference>(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>(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>(NetworkBehaviourReference.op_Implicit(val3), (DataFormat)0, (SerializationContext)null); } return SerializationUtility.SerializeValue<T>(value, (DataFormat)0, (SerializationContext)null); } internal static T Deserialize<T>(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<NetworkBehaviourReference>(data, (DataFormat)0, (DeserializationContext)null)); } return SerializationUtility.DeserializeValue<T>(data, (DataFormat)0, (DeserializationContext)null); } return (T)(object)NetworkObjectReference.op_Implicit(SerializationUtility.DeserializeValue<NetworkObjectReference>(data, (DataFormat)0, (DeserializationContext)null)); } return (T)(object)NetworkObjectReference.op_Implicit(SerializationUtility.DeserializeValue<NetworkObjectReference>(data, (DataFormat)0, (DeserializationContext)null)); } } public class NetworkBehaviourReferenceFormatter : MinimalBaseFormatter<NetworkBehaviourReference> { private static readonly Serializer<ushort> UInt16Serializer = Serializer.Get<ushort>(); private static readonly Serializer<NetworkObjectReference> NetworkObjectReferenceSerializer = Serializer.Get<NetworkObjectReference>(); 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<NetworkObjectReference> { private static readonly Serializer<ulong> UInt64Serializer = Serializer.Get<ulong>(); 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<ulong> 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<ulong> 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<ulong> val = default(NativeArray<ulong>); 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<ulong>)(object)val)) { return default(ClientRpcParams); } ClientRpcParams result = default(ClientRpcParams); result.Send = new ClientRpcSendParams { TargetClientIdsNativeArray = val }; return result; } protected ClientRpcParams GenerateClientParams(IEnumerable<ulong> 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<ulong>(clientId), allExcept: false); } protected ClientRpcParams GenerateClientParamsExcept(IEnumerable<ulong> 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<ulong>(clientId), allExcept: true); } protected ClientRpcParams GenerateClientParamsExceptHost() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) return GenerateClientParams(Array.Empty<ulong>(), allExcept: true); } } } namespace LethalNetworkAPI.Old.Networking { internal class NetworkHandler : IDisposable { internal readonly List<ILethalNetVar> ObjectNetworkVariableList = new List<ILethalNetVar>(); 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<ulong>? OnPlayerJoin; internal static event Action<string, byte[], ulong>? OnServerMessage; internal static event Action<string, byte[], ulong>? OnClientMessage; internal static event Action<string, byte[]>? OnVariableUpdate; internal static event Action<string, ulong>? GetVariableValue; internal static event Action<string, ulong>? OnServerEvent; internal static event Action<string, ulong>? OnClientEvent; internal static event Action<string, double, ulong>? OnSyncedServerEvent; internal static event Action<string, double, ulong>? 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<EMessageType>(ref messageType, default(ForEnums)); byte[] messageData = default(byte[]); ((FastBufferReader)(ref reader)).ReadValueSafe<byte>(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<double>(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<string, INetMessage> LNetworkMessages { get; } = new Dictionary<string, INetMessage>(); internal static Dictionary<string, LNetworkEvent> LNetworkEvents { get; } = new Dictionary<string, LNetworkEvent>(); internal static Dictionary<string, LNetworkVariableBase> LNetworkVariables { get; } = new Dictionary<string, LNetworkVariableBase>(); internal bool IsServer { get { if (!NetworkManager.IsServer) { return NetworkManager.IsHost; } return true; } } private NetworkManager NetworkManager { get; } private CustomMessagingManager CustomMessagingManager { get; } internal HashSet<LNetworkVariableBase> DirtyBois { get; } = new HashSet<LNetworkVariableBase>(); internal Dictionary<string, object?> UnInitializedValues { get; } = new Dictionary<string, object>(); 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<byte>()); } 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<ulong>)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<ulong>)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<byte>()); } 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<EMessageType>(ref messageType, default(ForEnums)); ulong[] targetClients = default(ulong[]); ((FastBufferReader)(ref reader)).ReadValueSafe<ulong>(ref targetClients, default(ForPrimitives)); byte[] serializedData = default(byte[]); ((FastBufferReader)(ref reader)).ReadValueSafe<byte>(ref serializedData, default(ForPrimitives)); byte[] serializedData2 = default(byte[]); ((FastBufferReader)(ref reader)).ReadValueSafe<byte>(ref serializedData2, default(ForPrimitives)); Type type = Deserialize<Type>(serializedData2); object messageData = ((type != null) ? Deserialize<object>(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>(((ulong[])messageData) ?? new ulong[1] { NetworkManager.LocalClientId }, 0uL); } break; default: throw new ArgumentOutOfRangeException(); } } internal static byte[] Serialize(object? data) { return SerializationUtility.SerializeValue<object>(data, (DataFormat)0, (SerializationContext)null); } internal static T Deserialize<T>(byte[] serializedData) { return SerializationUtility.DeserializeValue<T>(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<EMessageType>(ref messageType, default(ForEnums)); if (!deprecatedMessage) { ((FastBufferWriter)(ref writer)).WriteValue<ulong>(messageData.TargetClients ?? Array.Empty<ulong>(), default(ForPrimitives)); } ((FastBufferWriter)(ref writer)).WriteValue<byte>(item, default(ForPrimitives)); ((FastBufferWriter)(ref writer)).WriteValue<byte>(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<EMessageType>(ref messageType, default(ForStructs)); if (!deprecatedMessage) { writeSize += FastBufferWriter.GetWriteSize<ulong>(messageData.TargetClients ?? Array.Empty<ulong>(), -1, 0); } writeSize += FastBufferWriter.GetWriteSize<byte>(array, -1, 0); writeSize += FastBufferWriter.GetWriteSize<byte>(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 { } }