Decompiled source of LethalNetworkAPI v3.3.1

BepInEx/plugins/LethalNetworkAPI/LethalNetworkAPI.dll

Decompiled 3 months ago
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: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: IgnoresAccessChecksTo("AmazingAssets.TerrainToMesh")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp-firstpass")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: IgnoresAccessChecksTo("ClientNetworkTransform")]
[assembly: IgnoresAccessChecksTo("DissonanceVoip")]
[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.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: AssemblyCompany("Xilophor")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Easily create networked mods.")]
[assembly: AssemblyFileVersion("3.3.1.0")]
[assembly: AssemblyInformationalVersion("3.3.1+eadeda895384f16cec4845c9d44533f19f84b2ee")]
[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)]
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.1")]
	[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.1 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.1"), (CompatibilityLevel)1, (VersionStrictness)2);
		}
	}
	[Obsolete("Use LNetworkEvent instead.")]
	public sealed class LethalClientEvent : LNetworkEventDepricated
	{
		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));
			}
		}

		private IEnumerator WaitAndInvokeEvent(float timeToWait, ulong originatorClientId)
		{
			if (timeToWait > 0f)
			{
				yield return (object)new WaitForSeconds(timeToWait);
			}
			ReceiveClientEvent(Identifier, originatorClientId);
		}
	}
	[Obsolete("Use LNetworkEvent instead.")]
	public sealed class LethalServerEvent : LNetworkEventDepricated
	{
		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));
			}
		}

		private IEnumerator WaitAndInvokeEvent(float timeToWait, ulong clientId)
		{
			if (timeToWait > 0f)
			{
				yield return (object)new WaitForSeconds(timeToWait);
			}
			this.OnReceived?.Invoke(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.1";
	}
}
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)
			{
				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
	{
	}
}
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();
	}
}