Decompiled source of UnityNetworkMessages v2.0.0

UnityNetworkMessages.dll

Decompiled 10 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using OdinSerializer;
using OdinSerializer.Utilities;
using Unity.Collections;
using Unity.Netcode;
using UnityEngine;
using UnityNetMessages.Events;
using UnityNetMessages.Logging;
using UnityNetMessages.OdinSerializer;
using UnityNetMessages.Patches;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("UnityNetworkMessages")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("UnityNetworkMessages")]
[assembly: AssemblyTitle("UnityNetworkMessages")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace UnityNetMessages
{
	[BepInPlugin("Saradora.UnityNetworkMessages", "Unity Network Messagin", "2.0.0")]
	public class Plugin : BaseUnityPlugin
	{
		private readonly Harmony _harmonyInstance = new Harmony("Saradora.UnityNetworkMessages");

		private void Awake()
		{
			_harmonyInstance.PatchAll();
		}
	}
	public static class UnityNetworkMessages
	{
		public const string ModGuid = "Saradora.UnityNetworkMessages";

		public const string ModVersion = "2.0.0";

		public const string ModName = "Unity Network Messagin";
	}
	public static class Hashing
	{
		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private unsafe static uint Hash32(byte* input, int length, uint seed = 0u)
		{
			uint num = seed + 374761393;
			if (length >= 16)
			{
				uint num2 = seed - 1640531535 - 2048144777;
				uint num3 = seed + 2246822519u;
				uint num4 = seed;
				uint num5 = seed - 2654435761u;
				int num6 = length >> 4;
				for (int i = 0; i < num6; i++)
				{
					uint num7 = *(uint*)input;
					uint num8 = *(uint*)(input + 4);
					uint num9 = *(uint*)(input + 8);
					uint num10 = *(uint*)(input + 12);
					uint num11 = num2 + (uint)((int)num7 * -2048144777);
					num2 = ((num11 << 13) | (num11 >> 19)) * 2654435761u;
					uint num12 = num3 + (uint)((int)num8 * -2048144777);
					num3 = ((num12 << 13) | (num12 >> 19)) * 2654435761u;
					uint num13 = num4 + (uint)((int)num9 * -2048144777);
					num4 = ((num13 << 13) | (num13 >> 19)) * 2654435761u;
					uint num14 = num5 + (uint)((int)num10 * -2048144777);
					num5 = ((num14 << 13) | (num14 >> 19)) * 2654435761u;
					input += 16;
				}
				num = ((num2 << 1) | (num2 >> 31)) + ((num3 << 7) | (num3 >> 25)) + ((num4 << 12) | (num4 >> 20)) + ((num5 << 18) | (num5 >> 14));
			}
			uint num15 = num + (uint)length;
			for (length &= 0xF; length >= 4; length -= 4)
			{
				uint num16 = num15 + (uint)((int)(*(uint*)input) * -1028477379);
				num15 = ((num16 << 17) | (num16 >> 15)) * 668265263;
				input += 4;
			}
			while (length > 0)
			{
				uint num17 = num15 + (uint)(*input * 374761393);
				num15 = ((num17 << 11) | (num17 >> 21)) * 2654435761u;
				input++;
				length--;
			}
			int num18 = (int)(num15 ^ (num15 >> 15)) * -2048144777;
			int num19 = (num18 ^ (num18 >>> 13)) * -1028477379;
			return (uint)num19 ^ ((uint)num19 >> 16);
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public unsafe static uint Hash32(this byte[] buffer)
		{
			int length = buffer.Length;
			fixed (byte* input = buffer)
			{
				return Hash32(input, length);
			}
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static uint Hash32(this string text)
		{
			return Encoding.UTF8.GetBytes(text).Hash32();
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static uint Hash32(this Type type)
		{
			return type.FullName.Hash32();
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static uint Hash32<T>()
		{
			return typeof(T).Hash32();
		}
	}
}
namespace UnityNetMessages.Logging
{
	public static class Log
	{
		private static readonly Dictionary<Assembly, ManualLogSource> LOGSources = new Dictionary<Assembly, ManualLogSource>();

		public static void Print(object message)
		{
			GetLogger(Assembly.GetCallingAssembly()).LogInfo(message ?? "Null");
		}

		public static void Warning(object message)
		{
			GetLogger(Assembly.GetCallingAssembly()).LogWarning(message ?? "Null");
		}

		public static void Error(object message)
		{
			GetLogger(Assembly.GetCallingAssembly()).LogError(message ?? "Null");
		}

		public static void Exception(Exception exception)
		{
			GetLogger(Assembly.GetCallingAssembly()).LogError((object)(exception?.Message ?? "Null"));
		}

		private static ManualLogSource GetLogger(Assembly assembly)
		{
			if (LOGSources.TryGetValue(assembly, out var value))
			{
				return value;
			}
			LOGSources[assembly] = Logger.CreateLogSource(assembly.GetName().Name);
			return LOGSources[assembly];
		}
	}
}
namespace UnityNetMessages.OdinSerializer
{
	internal sealed class CachedMemoryStream : ICacheNotificationReceiver
	{
		public static int InitialCapacity = 1024;

		public static int MaxCapacity = 32768;

		private MemoryStream memoryStream;

		public MemoryStream MemoryStream
		{
			get
			{
				if (!memoryStream.CanRead)
				{
					memoryStream = new MemoryStream(InitialCapacity);
				}
				return memoryStream;
			}
		}

		public CachedMemoryStream()
		{
			memoryStream = new MemoryStream(InitialCapacity);
		}

		public void OnFreed()
		{
			memoryStream.SetLength(0L);
			memoryStream.Position = 0L;
			if (memoryStream.Capacity > MaxCapacity)
			{
				memoryStream.Capacity = MaxCapacity;
			}
		}

		public void OnClaimed()
		{
			memoryStream.SetLength(0L);
			memoryStream.Position = 0L;
		}

		public static Cache<CachedMemoryStream> Claim(int minCapacity)
		{
			Cache<CachedMemoryStream> val = Cache<CachedMemoryStream>.Claim();
			if (val.Value.MemoryStream.Capacity < minCapacity)
			{
				val.Value.MemoryStream.Capacity = minCapacity;
			}
			return val;
		}

		public static Cache<CachedMemoryStream> Claim(byte[] bytes = null)
		{
			Cache<CachedMemoryStream> val = Cache<CachedMemoryStream>.Claim();
			if (bytes != null)
			{
				val.Value.MemoryStream.Write(bytes, 0, bytes.Length);
				val.Value.MemoryStream.Position = 0L;
			}
			return val;
		}
	}
	public static class Serialization
	{
		public static T Deserialize<T>(byte[] bytes)
		{
			return (T)Deserialize(bytes, typeof(T));
		}

		public static object Deserialize(byte[] bytes, Type type)
		{
			Cache<CachedMemoryStream> val = CachedMemoryStream.Claim(bytes);
			try
			{
				Cache<BinaryDataReader> obj = Cache<BinaryDataReader>.Claim();
				BinaryDataReader value = obj.Value;
				((BaseDataReader)value).Stream = val.Value.MemoryStream;
				((BaseDataReader)value).Context = null;
				((BaseDataReader)value).PrepareNewSerializationSession();
				IDataReader val2 = (IDataReader)(object)value;
				IDisposable disposable = (IDisposable)obj;
				try
				{
					Cache<DeserializationContext> val3 = Cache<DeserializationContext>.Claim();
					try
					{
						val2.Context = Cache<DeserializationContext>.op_Implicit(val3);
						return Serializer.Get(type).ReadValueWeak(val2);
					}
					finally
					{
						((IDisposable)val3)?.Dispose();
					}
				}
				finally
				{
					disposable.Dispose();
				}
			}
			finally
			{
				((IDisposable)val)?.Dispose();
			}
		}
	}
}
namespace UnityNetMessages.Patches
{
	[HarmonyPatch(typeof(NetworkManager))]
	public static class NetworkManager_Patching
	{
		private static NetworkManager _currentSingleton;

		private static CustomMessagingManager _currentMessagingManager;

		[HarmonyPatch(/*Could not decode attribute arguments.*/)]
		[HarmonyPostfix]
		private static void Singleton_SetterPostfix(NetworkManager value)
		{
			if (!((Object)(object)_currentSingleton == (Object)(object)value))
			{
				if ((Object)(object)value == (Object)null)
				{
					CustomMessagingManager_SetterPostfix(null);
				}
				NetworkMessaging.TriggerSingletonChange(value);
				_currentSingleton = value;
			}
		}

		[HarmonyPatch(/*Could not decode attribute arguments.*/)]
		[HarmonyPostfix]
		private static void CustomMessagingManager_SetterPostfix(CustomMessagingManager value)
		{
			if (_currentMessagingManager != value)
			{
				NetworkMessaging.TriggerMessengerChange(value);
				_currentMessagingManager = value;
			}
		}
	}
	[HarmonyPatch(typeof(NetworkObject))]
	public static class NetworkObject_Patching
	{
		private static Dictionary<NetworkObject, Action<ulong>> _networkIdsEvents = new Dictionary<NetworkObject, Action<ulong>>();

		[HarmonyPatch(/*Could not decode attribute arguments.*/)]
		[HarmonyPostfix]
		private static void NetworkObjectId_SetterPostfix(ulong value, NetworkObject __instance)
		{
			if (_networkIdsEvents.ContainsKey(__instance))
			{
				_networkIdsEvents[__instance]?.Invoke(value);
			}
		}

		public static void RegisterToObjectIdChanges(this NetworkObject obj, Action<ulong> action)
		{
			if (!_networkIdsEvents.ContainsKey(obj))
			{
				_networkIdsEvents.Add(obj, action);
				return;
			}
			Dictionary<NetworkObject, Action<ulong>> networkIdsEvents = _networkIdsEvents;
			networkIdsEvents[obj] = (Action<ulong>)Delegate.Combine(networkIdsEvents[obj], action);
		}

		public static void UnregisterFromObjectIdChanges(this NetworkObject obj, Action<ulong> action)
		{
			if (_networkIdsEvents.ContainsKey(obj))
			{
				Dictionary<NetworkObject, Action<ulong>> networkIdsEvents = _networkIdsEvents;
				networkIdsEvents[obj] = (Action<ulong>)Delegate.Remove(networkIdsEvents[obj], action);
				if (_networkIdsEvents[obj] == null)
				{
					_networkIdsEvents.Remove(obj);
				}
			}
		}

		[HarmonyPatch("OnDestroy")]
		[HarmonyPrefix]
		private static void OnDestroy_Prefix(NetworkObject __instance)
		{
			if (_networkIdsEvents.ContainsKey(__instance))
			{
				_networkIdsEvents[__instance]?.Invoke(0uL);
				_networkIdsEvents.Remove(__instance);
			}
		}
	}
}
namespace UnityNetMessages.Events
{
	public class GlobalNetEvent : NetEventBase
	{
		private readonly uint _hash;

		public GlobalNetEvent(string name, bool assemblySpecific = false)
		{
			string text = name;
			if (assemblySpecific)
			{
				text = Assembly.GetCallingAssembly().GetName().Name + "+" + text;
			}
			_hash = text.Hash32();
			RegisterEvent<NetworkEvent>();
		}

		protected override uint? GetHash()
		{
			return _hash;
		}
	}
	public class GlobalNetMessage<T> : NetMessageBase<T>
	{
		private readonly uint _hash;

		public GlobalNetMessage(string name, bool assemblySpecific = false)
		{
			string text = name;
			if (assemblySpecific)
			{
				text = Assembly.GetCallingAssembly().GetName().Name + "+" + text;
			}
			_hash = text.Hash32();
			RegisterEvent<T>();
		}

		protected override uint? GetHash()
		{
			return _hash;
		}
	}
	[StructLayout(LayoutKind.Sequential, Size = 1)]
	internal struct NetworkEvent
	{
	}
	public class MessageHandler
	{
		private readonly List<WeakReference> _actions = new List<WeakReference>();

		public Type ReturnType { get; }

		public bool IsEmpty
		{
			get
			{
				if (_actions.Count <= 0)
				{
					return true;
				}
				foreach (WeakReference action in _actions)
				{
					if (action.IsAlive)
					{
						return false;
					}
				}
				return true;
			}
		}

		private MessageHandler(MessageReceiver action, Type returnType)
		{
			ReturnType = returnType;
			_actions.Add(new WeakReference(action));
		}

		public static MessageHandler Create<TReturnType>(MessageReceiver action)
		{
			return new MessageHandler(action, typeof(TReturnType));
		}

		public void Subscribe<TReturnType>(MessageReceiver action)
		{
			if (ReturnType != typeof(TReturnType))
			{
				throw new ArgumentException("Cannot create network event with type " + typeof(TReturnType).Name + " because an event with the same name already exists with a different type of " + ReturnType.Name + ".");
			}
			foreach (WeakReference action2 in _actions)
			{
				if (action2.Target == action)
				{
					return;
				}
			}
			_actions.Add(new WeakReference(action));
		}

		public void Unsubscribe(MessageReceiver action)
		{
			foreach (WeakReference action2 in _actions)
			{
				if (action2.IsAlive && action2.Target == action)
				{
					_actions.Remove(action2);
					break;
				}
			}
		}

		public void RaiseEvent(ulong clientId)
		{
			for (int num = _actions.Count - 1; num >= 0; num--)
			{
				WeakReference weakReference = _actions[num];
				if (!weakReference.IsAlive)
				{
					_actions.RemoveAt(num);
				}
				else
				{
					((MessageReceiver)weakReference.Target).Invoke(clientId, null);
				}
			}
		}

		public void RaiseMessage(ulong clientId, FastBufferReader buffer)
		{
			int num = ((FastBufferReader)(ref buffer)).Length - 1 - 4;
			if (num < 0)
			{
				return;
			}
			if (num == 0)
			{
				RaiseEvent(clientId);
			}
			object obj = null;
			if (!((FastBufferReader)(ref buffer)).TryBeginRead(num))
			{
				Log.Error("Couldn't read buffer");
				return;
			}
			byte[] bytes = new byte[num];
			((FastBufferReader)(ref buffer)).ReadBytes(ref bytes, num, 0);
			obj = Serialization.Deserialize(bytes, ReturnType);
			for (int num2 = _actions.Count - 1; num2 >= 0; num2--)
			{
				WeakReference weakReference = _actions[num2];
				if (!weakReference.IsAlive)
				{
					_actions.RemoveAt(num2);
				}
				else
				{
					((MessageReceiver)weakReference.Target).Invoke(clientId, obj);
				}
			}
		}
	}
	public abstract class MessageReceiver : IDisposable
	{
		private bool _disposed;

		internal void RegisterEvent<TReturnType>()
		{
			uint? hashInternal = GetHashInternal();
			if (!hashInternal.HasValue)
			{
				throw new NullReferenceException("Cannot register event as it is uninitialized.");
			}
			NetworkMessaging.RegisterEvent<TReturnType>(hashInternal.Value, this);
		}

		internal void UnregisterEvent()
		{
			uint? hashInternal = GetHashInternal();
			if (hashInternal.HasValue)
			{
				NetworkMessaging.UnregisterEvent(hashInternal.Value, this);
			}
		}

		internal void Invoke(ulong senderId, object data)
		{
			OnReceiveMessage(senderId, data);
		}

		protected abstract uint? GetHash();

		protected abstract void OnReceiveMessage(ulong senderId, object data);

		protected uint? GetHashInternal()
		{
			if (!_disposed)
			{
				return GetHash();
			}
			return null;
		}

		~MessageReceiver()
		{
			Dispose();
		}

		public void Dispose()
		{
			if (!_disposed)
			{
				_disposed = true;
				DoDispose();
			}
		}

		protected virtual void DoDispose()
		{
			UnregisterEvent();
		}
	}
	public abstract class NetEventBase : MessageReceiver
	{
		public event Action<ulong> EventReceived;

		public event Action<ulong> EventReceivedFromClient;

		public event Action EventReceivedFromServer;

		protected override void OnReceiveMessage(ulong senderId, object data)
		{
			this.EventReceived?.Invoke(senderId);
			if (senderId == NetworkMessaging.ServerClientId)
			{
				this.EventReceivedFromServer?.Invoke();
			}
			else
			{
				this.EventReceivedFromClient?.Invoke(senderId);
			}
		}

		private FastBufferWriter GetWriterAndHash(out uint outHash)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			uint? hash = GetHash();
			if (!hash.HasValue)
			{
				throw new NullReferenceException("Cannot send as it is uninitialized.");
			}
			FastBufferWriter writer = NetworkMessaging.GetWriter(EMessageType.Event, hash.Value, 0);
			outHash = hash.Value;
			return writer;
		}

		public void InvokeOnServer(NetworkDelivery delivery = 3)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			uint outHash;
			FastBufferWriter writerAndHash = GetWriterAndHash(out outHash);
			try
			{
				NetworkMessaging.TrySendMessageToServer<NetworkEvent>(outHash, writerAndHash, delivery);
			}
			finally
			{
				((IDisposable)(FastBufferWriter)(ref writerAndHash)).Dispose();
			}
		}

		public void InvokeOnClient(ulong clientId, NetworkDelivery delivery = 3)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: 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)
			uint outHash;
			FastBufferWriter writerAndHash = GetWriterAndHash(out outHash);
			try
			{
				NetworkMessaging.TrySendMessageToClient<NetworkEvent>(outHash, clientId, writerAndHash, delivery);
			}
			finally
			{
				((IDisposable)(FastBufferWriter)(ref writerAndHash)).Dispose();
			}
		}

		public void InvokeOnAllClients(bool includeHost = false, NetworkDelivery delivery = 3)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: 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)
			uint outHash;
			FastBufferWriter writerAndHash = GetWriterAndHash(out outHash);
			try
			{
				NetworkMessaging.TrySendMessageToAllClients<NetworkEvent>(outHash, writerAndHash, includeHost, delivery);
			}
			finally
			{
				((IDisposable)(FastBufferWriter)(ref writerAndHash)).Dispose();
			}
		}
	}
	public abstract class NetMessageBase<T> : MessageReceiver
	{
		public event Action<T, ulong> MessageReceived;

		public event Action<T, ulong> MessageReceivedFromClient;

		public event Action<T> MessageReceivedFromServer;

		protected override void OnReceiveMessage(ulong senderId, object data)
		{
			if (data is T)
			{
				T val = (T)data;
				this.MessageReceived?.Invoke(val, senderId);
				if (senderId == NetworkMessaging.ServerClientId)
				{
					this.MessageReceivedFromServer?.Invoke(val);
				}
				else
				{
					this.MessageReceivedFromClient?.Invoke(val, senderId);
				}
			}
		}

		private bool TryGetWriterAndHash(T data, out uint outHash, out FastBufferWriter outWriter)
		{
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			uint? hash = GetHash();
			if (!hash.HasValue)
			{
				throw new NullReferenceException("Cannot send as it is uninitialized.");
			}
			byte[] array;
			try
			{
				array = SerializationUtility.SerializeValue<T>(data, (DataFormat)0, (SerializationContext)null);
			}
			catch
			{
				Log.Exception(new Exception("Cannot serialize type " + data.GetType().Name));
				throw;
			}
			outWriter = NetworkMessaging.GetWriter(EMessageType.Data, hash.Value, array.Length);
			((FastBufferWriter)(ref outWriter)).WriteBytes(array, -1, 0);
			outHash = hash.Value;
			return true;
		}

		public void SendToServer(T data, NetworkDelivery delivery = 3)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			if (!TryGetWriterAndHash(data, out var outHash, out var outWriter))
			{
				return;
			}
			FastBufferWriter val = outWriter;
			try
			{
				NetworkMessaging.TrySendMessageToServer<T>(outHash, outWriter, delivery);
			}
			catch (Exception exception)
			{
				Log.Exception(exception);
			}
			finally
			{
				((IDisposable)(FastBufferWriter)(ref val)).Dispose();
			}
		}

		public void SendToClient(T data, ulong clientId, NetworkDelivery delivery = 3)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			if (!TryGetWriterAndHash(data, out var outHash, out var outWriter))
			{
				return;
			}
			FastBufferWriter val = outWriter;
			try
			{
				NetworkMessaging.TrySendMessageToClient<T>(outHash, clientId, outWriter, delivery);
			}
			catch (Exception exception)
			{
				Log.Exception(exception);
			}
			finally
			{
				((IDisposable)(FastBufferWriter)(ref val)).Dispose();
			}
		}

		public void SendToAllClients(T data, bool includeHost = false, NetworkDelivery delivery = 3)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			if (!TryGetWriterAndHash(data, out var outHash, out var outWriter))
			{
				return;
			}
			FastBufferWriter val = outWriter;
			try
			{
				NetworkMessaging.TrySendMessageToAllClients<T>(outHash, outWriter, includeHost, delivery);
			}
			catch (Exception exception)
			{
				Log.Exception(exception);
			}
			finally
			{
				((IDisposable)(FastBufferWriter)(ref val)).Dispose();
			}
		}
	}
	public enum EMessageType : byte
	{
		Event,
		Data
	}
	public static class NetworkMessaging
	{
		private static readonly Dictionary<uint, MessageHandler> _registeredMessages;

		private static CustomMessagingManager _messenger;

		private static readonly List<ulong> _clientIds;

		public static bool IsServer => NetworkManager.Singleton.IsServer;

		public static ulong ServerClientId => 0uL;

		public static IReadOnlyList<ulong> NonHostClientIds
		{
			get
			{
				IReadOnlyList<ulong> connectedClientsIds = NetworkManager.Singleton.ConnectedClientsIds;
				_clientIds.Clear();
				ulong num = 0uL;
				foreach (ulong item in connectedClientsIds)
				{
					if (item != num)
					{
						_clientIds.Add(item);
					}
				}
				return _clientIds;
			}
		}

		public static event Action<NetworkManager> SingletonChanged;

		public static event Action<CustomMessagingManager> MessagingManagerChanged;

		internal static void TriggerSingletonChange(NetworkManager singleton)
		{
			NetworkMessaging.SingletonChanged?.Invoke(singleton);
		}

		internal static void TriggerMessengerChange(CustomMessagingManager messenger)
		{
			NetworkMessaging.MessagingManagerChanged?.Invoke(messenger);
		}

		public static FastBufferWriter GetWriter(EMessageType messageType, uint hash, int size)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			FastBufferWriter result = default(FastBufferWriter);
			switch (messageType)
			{
			case EMessageType.Event:
				((FastBufferWriter)(ref result))..ctor(5, (Allocator)2, -1);
				((FastBufferWriter)(ref result)).WriteValue<EMessageType>(ref messageType, default(ForEnums));
				((FastBufferWriter)(ref result)).WriteValue<uint>(ref hash, default(ForPrimitives));
				break;
			case EMessageType.Data:
				((FastBufferWriter)(ref result))..ctor(5 + size, (Allocator)2, -1);
				((FastBufferWriter)(ref result)).WriteValue<EMessageType>(ref messageType, default(ForEnums));
				((FastBufferWriter)(ref result)).WriteValue<uint>(ref hash, default(ForPrimitives));
				break;
			default:
				((FastBufferWriter)(ref result))..ctor(1, (Allocator)2, -1);
				break;
			}
			return result;
		}

		static NetworkMessaging()
		{
			_registeredMessages = new Dictionary<uint, MessageHandler>();
			_clientIds = new List<ulong>();
			MessagingManagerChanged -= OnMessagingManagerChanged;
			MessagingManagerChanged += OnMessagingManagerChanged;
		}

		private static void OnMessagingManagerChanged(CustomMessagingManager instance)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Expected O, but got Unknown
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Expected O, but got Unknown
			if (_messenger != null)
			{
				_messenger.OnUnnamedMessage -= new UnnamedMessageDelegate(OnUnnamedMessageReceived);
			}
			_messenger = instance;
			if (_messenger != null)
			{
				_messenger.OnUnnamedMessage += new UnnamedMessageDelegate(OnUnnamedMessageReceived);
			}
		}

		private static void OnUnnamedMessageReceived(ulong clientId, FastBufferReader bufferReader)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			EMessageType eMessageType = EMessageType.Event;
			if (!((FastBufferReader)(ref bufferReader)).TryBeginReadValue<EMessageType>(ref eMessageType))
			{
				return;
			}
			((FastBufferReader)(ref bufferReader)).ReadValue<EMessageType>(ref eMessageType, default(ForEnums));
			uint key = 0u;
			MessageHandler value;
			switch (eMessageType)
			{
			case EMessageType.Event:
				if (((FastBufferReader)(ref bufferReader)).TryBeginReadValue<uint>(ref key))
				{
					((FastBufferReader)(ref bufferReader)).ReadValue<uint>(ref key, default(ForPrimitives));
					if (_registeredMessages.TryGetValue(key, out value))
					{
						value.RaiseEvent(clientId);
					}
				}
				break;
			case EMessageType.Data:
				if (((FastBufferReader)(ref bufferReader)).TryBeginReadValue<uint>(ref key))
				{
					((FastBufferReader)(ref bufferReader)).ReadValue<uint>(ref key, default(ForPrimitives));
					if (_registeredMessages.TryGetValue(key, out value))
					{
						value.RaiseMessage(clientId, bufferReader);
					}
				}
				break;
			}
		}

		public static void RegisterEvent<TReturnType>(uint hash, MessageReceiver action)
		{
			if (!_registeredMessages.ContainsKey(hash))
			{
				_registeredMessages[hash] = MessageHandler.Create<TReturnType>(action);
			}
			else
			{
				_registeredMessages[hash].Subscribe<TReturnType>(action);
			}
		}

		public static void UnregisterEvent(uint hash, MessageReceiver action)
		{
			if (_registeredMessages.ContainsKey(hash))
			{
				MessageHandler messageHandler = _registeredMessages[hash];
				messageHandler.Unsubscribe(action);
				if (messageHandler.IsEmpty)
				{
					_registeredMessages.Remove(hash);
				}
			}
		}

		public static void TrySendMessageToServer<TReturnType>(uint hash, FastBufferWriter writer, NetworkDelivery delivery = 3)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			if (IsServer)
			{
				Log.Warning("Message couldn't be sent because you are the server.");
			}
			else
			{
				TrySendMessageToClientInternal<TReturnType>(hash, ServerClientId, writer, delivery);
			}
		}

		public static void TrySendMessageToClient<TReturnType>(uint hash, ulong clientId, FastBufferWriter writer, NetworkDelivery delivery = 3)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			if (!IsServer)
			{
				Log.Warning("Message couldn't be sent because you are not the server.");
			}
			else
			{
				TrySendMessageToClientInternal<TReturnType>(hash, clientId, writer, delivery);
			}
		}

		public static void TrySendMessageToAllClients<TReturnType>(uint hash, FastBufferWriter writer, bool includeHost, NetworkDelivery delivery = 3)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			if (!IsServer)
			{
				Log.Warning("Message couldn't be sent because you are not the server.");
			}
			else if (ValidateHandler<TReturnType>(hash))
			{
				if (includeHost)
				{
					_messenger.SendUnnamedMessageToAll(writer, delivery);
				}
				else
				{
					_messenger.SendUnnamedMessage(NonHostClientIds, writer, delivery);
				}
			}
		}

		private static void TrySendMessageToClientInternal<TReturnType>(uint hash, ulong clientId, FastBufferWriter writer, NetworkDelivery delivery)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			if (ValidateHandler<TReturnType>(hash))
			{
				_messenger.SendUnnamedMessage(clientId, writer, delivery);
			}
		}

		private static bool ValidateHandler<TReturnType>(uint hash)
		{
			if (_messenger == null)
			{
				Log.Warning("Message couldn't be sent because messenger isn't active");
				return false;
			}
			if (!_registeredMessages.TryGetValue(hash, out var value))
			{
				Log.Warning("Message couldn't be sent because it wasn't registered to the messenger");
				return false;
			}
			if (value.ReturnType != typeof(TReturnType))
			{
				Log.Error("Message couldn't be sent because the registered event with the same name has a different return type.");
				return false;
			}
			return true;
		}
	}
	public class ObjectMessageLink<TReturnType>
	{
		private readonly string _baseName;

		private readonly NetworkObject _targetObject;

		private readonly MessageReceiver _messageReceiver;

		public uint? Hash { get; private set; }

		public ObjectMessageLink(string baseName, NetworkObject obj, MessageReceiver receiver)
		{
			Hash = null;
			_baseName = baseName;
			_targetObject = obj;
			_messageReceiver = receiver;
			RegisterNetworkObject();
			_targetObject.RegisterToObjectIdChanges(OnNetworkObjectIdChanged);
		}

		private void OnNetworkObjectIdChanged(ulong value)
		{
			if (value != 0L)
			{
				RegisterNetworkObject();
			}
			else
			{
				Dispose();
			}
		}

		private void RegisterNetworkObject()
		{
			if (_targetObject.NetworkObjectId != 0L)
			{
				if (Hash.HasValue)
				{
					UnregisterNetworkObject();
				}
				Hash = $"obj{_targetObject.NetworkObjectId}+{_baseName}".Hash32();
				_messageReceiver.RegisterEvent<TReturnType>();
			}
		}

		private void UnregisterNetworkObject()
		{
			if (Hash.HasValue)
			{
				_messageReceiver.UnregisterEvent();
				Hash = null;
			}
		}

		public void Dispose()
		{
			UnregisterNetworkObject();
			if ((Object)(object)_targetObject != (Object)null)
			{
				_targetObject.UnregisterFromObjectIdChanges(OnNetworkObjectIdChanged);
			}
		}
	}
	public class ObjectNetEvent : NetEventBase
	{
		private readonly ObjectMessageLink<NetworkEvent> _objectMessageLink;

		public ObjectNetEvent(string name, NetworkObject targetObject, bool assemblySpecific = false)
		{
			if ((Object)(object)targetObject == (Object)null)
			{
				throw new NullReferenceException("Cannot create an object event without a target object.");
			}
			if (assemblySpecific)
			{
				name = Assembly.GetCallingAssembly().GetName().Name + "+" + name;
			}
			_objectMessageLink = new ObjectMessageLink<NetworkEvent>(name, targetObject, this);
		}

		protected override uint? GetHash()
		{
			return _objectMessageLink.Hash;
		}

		protected override void DoDispose()
		{
			_objectMessageLink.Dispose();
		}
	}
	public class ObjectNetMessage<T> : NetMessageBase<T>
	{
		private readonly ObjectMessageLink<T> _objectMessageLink;

		public ObjectNetMessage(string name, NetworkObject targetObject, bool assemblySpecific = false)
		{
			if ((Object)(object)targetObject == (Object)null)
			{
				throw new NullReferenceException("Cannot create an object event without a target object.");
			}
			if (assemblySpecific)
			{
				name = Assembly.GetCallingAssembly().GetName().Name + "+" + name;
			}
			_objectMessageLink = new ObjectMessageLink<T>(name, targetObject, this);
		}

		protected override uint? GetHash()
		{
			return _objectMessageLink.Hash;
		}

		protected override void DoDispose()
		{
			_objectMessageLink.Dispose();
		}
	}
}