Decompiled source of CodeYapper v2.2.2

plugins/CodeTalker.dll

Decompiled a week ago
using System;
using System.Buffers.Binary;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using CodeTalker;
using CodeTalker.Networking;
using CodeTalker.Packets;
using K4os.Compression.LZ4;
using Microsoft.CodeAnalysis;
using Mirror;
using Newtonsoft.Json;
using Steamworks;
using UnityEngine;
using ZstdSharp;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyCompany("Robyn+Soggy_Pancake")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("2.2.2.0")]
[assembly: AssemblyInformationalVersion("2.2.2+e99f7b5d48c19da82d983d2513981f4f1ba84679")]
[assembly: AssemblyProduct("CodeTalker")]
[assembly: AssemblyTitle("CodeTalker")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("2.2.2.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;
		}
	}
}
internal enum PacketType : byte
{
	JSON,
	Binary
}
internal class PacketWrapper
{
	internal readonly byte[] PacketBytes;

	internal readonly ulong PacketSignature;

	internal readonly PacketType PacketType;

	internal readonly Compressors.CompressionType compression;

	internal readonly uint TargetNetId;

	internal PacketWrapper(string sig, Span<byte> rawData, PacketType packetType, Compressors.CompressionType compressionType = Compressors.CompressionType.None, CompressionLevel compressionLevel = CompressionLevel.Fastest, uint targetNetId = 0u)
	{
		Span<byte> span = CodeTalkerNetwork.CODE_TALKER_SIGNATURE;
		Span<byte> signature = Encoding.UTF8.GetBytes(sig);
		PacketType = packetType;
		PacketSignature = CodeTalkerNetwork.signatureHash(signature);
		if (compressionType != 0)
		{
			rawData = Compressors.Compress(rawData.ToArray(), compressionType, compressionLevel);
		}
		int num = span.Length + 8 + 5;
		PacketBytes = new byte[num + rawData.Length];
		Span<byte> span2 = new Span<byte>(PacketBytes);
		int num2 = 0;
		span.CopyTo(span2.Slice(num2));
		num2 += span.Length;
		BinaryPrimitives.WriteUInt64LittleEndian(span2.Slice(num2), PacketSignature);
		num2 += 8;
		span2[num2++] = (byte)((uint)(((int)compressionType << 4) & 0xF0) + (uint)(packetType & (PacketType)15));
		BinaryPrimitives.WriteUInt32LittleEndian(span2.Slice(num2), targetNetId);
		num2 += 4;
		rawData.CopyTo(span2.Slice(num2));
	}

	internal PacketWrapper(Span<byte> rawPacketData)
	{
		PacketSignature = BinaryPrimitives.ReadUInt64LittleEndian(rawPacketData);
		PacketType = (PacketType)(rawPacketData[8] & 0xFu);
		compression = (Compressors.CompressionType)((rawPacketData[8] >> 4) & 0xF);
		TargetNetId = BinaryPrimitives.ReadUInt32LittleEndian(rawPacketData.Slice(9, 4));
		PacketBytes = rawPacketData.Slice(13).ToArray();
		if (compression != 0)
		{
			PacketBytes = Compressors.Decompress(PacketBytes, compression);
		}
	}

	public override string ToString()
	{
		return $"[Type: {PacketType} Compression: {compression} Target: {TargetNetId}]";
	}
}
internal static class LCMPluginInfo
{
	public const string PLUGIN_GUID = "CodeTalker";

	public const string PLUGIN_NAME = "CodeTalker";

	public const string PLUGIN_VERSION = "2.2.2";
}
namespace CodeTalker
{
	[BepInPlugin("CodeTalker", "CodeTalker", "2.2.2")]
	public class CodeTalkerPlugin : BaseUnityPlugin
	{
		internal static ManualLogSource Log = null;

		internal static Callback<LobbyChatMsg_t>? onNetworkMessage;

		internal static Callback<SteamNetworkingMessagesSessionRequest_t>? onSNMRequest;

		internal static ConfigEntry<bool> EnablePacketDebugging = null;

		internal static ConfigEntry<bool> devMode = null;

		private static bool steamIntialized = false;

		private static IntPtr[] messagePtrBuffer = new IntPtr[10];

		private void Awake()
		{
			Log = ((BaseUnityPlugin)this).Logger;
			EnablePacketDebugging = ((BaseUnityPlugin)this).Config.Bind<bool>("Debugging", "EnablePacketDebugging", false, "If CodeTalker should dump packet information (this will be on the debug channel, make sure that is enabled in BepInEx.cfg)");
			devMode = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "EnableDevMode", false, "If CodeTalker should log extremely verbosely. This should only be used when actively debugging codetalker!");
			Log.LogInfo((object)"Plugin CodeTalker version 2.2.2 is loaded!");
			onNetworkMessage = Callback<LobbyChatMsg_t>.Create((DispatchDelegate<LobbyChatMsg_t>)CodeTalkerNetwork.OnNetworkMessage);
			onSNMRequest = Callback<SteamNetworkingMessagesSessionRequest_t>.Create((DispatchDelegate<SteamNetworkingMessagesSessionRequest_t>)CodeTalkerNetwork.OnSteamSessionRequest);
			Callback<SteamRelayNetworkStatus_t>.Create((DispatchDelegate<SteamRelayNetworkStatus_t>)OnSteamNetworkInitialized);
			Log.LogMessage((object)"Created steam networking callbacks");
			CodeTalkerNetwork.dbg = EnablePacketDebugging.Value;
			CodeTalkerNetwork.dev = devMode.Value;
			byte[] array = new byte[64];
			new Random().NextBytes(array);
			foreach (Compressors.CompressionType value in Enum.GetValues(typeof(Compressors.CompressionType)))
			{
				if (value != 0)
				{
					byte[] data = Compressors.Compress(array, value);
					Compressors.Decompress(data, value);
				}
			}
		}

		private void OnSteamNetworkInitialized(SteamRelayNetworkStatus_t status)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Invalid comparison between Unknown and I4
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			if (!steamIntialized)
			{
				steamIntialized = (int)status.m_eAvail == 100;
				if (devMode.Value)
				{
					((BaseUnityPlugin)this).Logger.LogDebug((object)$"Steam Relay Network status update: {status.m_eAvail}");
				}
				if (steamIntialized)
				{
					SteamNetworkingUtils.InitRelayNetworkAccess();
				}
			}
		}

		private void Update()
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				int num = SteamNetworkingMessages.ReceiveMessagesOnChannel(0, messagePtrBuffer, messagePtrBuffer.Length);
				if (num <= 0)
				{
					return;
				}
				try
				{
					for (int i = 0; i < num; i++)
					{
						SteamNetworkingMessage_t val = Marshal.PtrToStructure<SteamNetworkingMessage_t>(messagePtrBuffer[i]);
						byte[] array = new byte[val.m_cbSize];
						if (devMode.Value)
						{
							Log.LogDebug((object)$"Recieved SNM packet of size {val.m_cbSize}");
						}
						try
						{
							Marshal.Copy(val.m_pData, array, 0, val.m_cbSize);
							Span<byte> span = new Span<byte>(array);
							if (CodeTalkerNetwork.signatureCheck(array, CodeTalkerNetwork.CODE_TALKER_SIGNATURE))
							{
								if (devMode.Value)
								{
									Log.LogDebug((object)("Got P2P message! " + CodeTalkerNetwork.BinaryToHexString(array)));
								}
								CodeTalkerNetwork.HandleNetworkMessage(((SteamNetworkingIdentity)(ref val.m_identityPeer)).GetSteamID(), span.Slice(CodeTalkerNetwork.CODE_TALKER_SIGNATURE.Length));
							}
						}
						catch
						{
						}
						SteamNetworkingMessage_t.Release(messagePtrBuffer[i]);
					}
				}
				catch (Exception ex)
				{
					((BaseUnityPlugin)this).Logger.LogError((object)("Error handling SteamNetworkingMessages message! " + ex));
				}
			}
			catch
			{
			}
		}
	}
	public static class Compressors
	{
		public enum CompressionType
		{
			None,
			Brotli,
			LZ4,
			ZStd,
			GZip
		}

		public static byte[] Compress(byte[] data, CompressionType type = CompressionType.Brotli, CompressionLevel level = CompressionLevel.Fastest)
		{
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Expected O, but got Unknown
			switch (type)
			{
			case CompressionType.Brotli:
			{
				MemoryStream memoryStream = new MemoryStream(data);
				MemoryStream memoryStream2 = new MemoryStream();
				BrotliStream brotliStream = new BrotliStream(memoryStream2, level);
				memoryStream.CopyTo(brotliStream);
				brotliStream.Close();
				brotliStream.DisposeAsync();
				return memoryStream2.ToArray();
			}
			case CompressionType.ZStd:
			{
				Compressor val = new Compressor((level == CompressionLevel.Fastest) ? 3 : 10);
				return val.Wrap((ReadOnlySpan<byte>)data).ToArray();
			}
			case CompressionType.GZip:
			{
				MemoryStream memoryStream = new MemoryStream(data);
				MemoryStream memoryStream2 = new MemoryStream();
				GZipStream gZipStream = new GZipStream(memoryStream2, level);
				memoryStream.CopyTo(gZipStream);
				gZipStream.Close();
				return memoryStream2.ToArray();
			}
			case CompressionType.LZ4:
				return LZ4Pickler.Pickle(data, (LZ4Level)((level != CompressionLevel.Fastest) ? 11 : 0));
			default:
				CodeTalkerPlugin.Log.LogError((object)$"[CodeTalker] Unknown compression type: {type}");
				return data;
			}
		}

		public static byte[] Decompress(byte[] data, CompressionType type = CompressionType.Brotli, CompressionLevel level = CompressionLevel.Fastest)
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Expected O, but got Unknown
			switch (type)
			{
			case CompressionType.Brotli:
			{
				BrotliStream brotliStream = new BrotliStream(new MemoryStream(data), CompressionMode.Decompress);
				MemoryStream memoryStream = new MemoryStream();
				brotliStream.CopyTo(memoryStream);
				return memoryStream.ToArray();
			}
			case CompressionType.ZStd:
			{
				Decompressor val = new Decompressor();
				return val.Unwrap((ReadOnlySpan<byte>)data, int.MaxValue).ToArray();
			}
			case CompressionType.GZip:
			{
				MemoryStream memoryStream = new MemoryStream();
				GZipStream gZipStream = new GZipStream(new MemoryStream(data), CompressionMode.Decompress);
				gZipStream.CopyTo(memoryStream);
				return memoryStream.ToArray();
			}
			case CompressionType.LZ4:
				return LZ4Pickler.Unpickle(data);
			default:
				CodeTalkerPlugin.Log.LogError((object)$"[CodeTalker] Unknown decompression type: {type}");
				return data;
			}
		}

		public static void CompressTest(byte[] rawBytes)
		{
			Stopwatch stopwatch = new Stopwatch();
			CompressionLevel compressionLevel = CompressionLevel.Fastest;
			long num = 1000000000 / Stopwatch.Frequency;
			foreach (CompressionType value in Enum.GetValues(typeof(CompressionType)))
			{
				if (value != 0)
				{
					Compress(rawBytes, value);
					Compress(rawBytes, value, CompressionLevel.Optimal);
				}
			}
			for (int i = 0; i < 2; i++)
			{
				CodeTalkerPlugin.Log.LogInfo((object)$"{compressionLevel}:");
				foreach (CompressionType value2 in Enum.GetValues(typeof(CompressionType)))
				{
					if (value2 != 0)
					{
						stopwatch.Start();
						byte[] array = Compress(rawBytes, value2, compressionLevel);
						stopwatch.Stop();
						CodeTalkerPlugin.Log.LogInfo((object)$"{value2}: {array.Length} bytes - ratio: {(float)rawBytes.Length / (float)array.Length} - time to compress: {stopwatch.ElapsedTicks * num / 1000}us");
						stopwatch.Reset();
					}
				}
				compressionLevel = CompressionLevel.Optimal;
			}
		}

		public static void CompressTest(PacketBase packet)
		{
			string s = JsonConvert.SerializeObject((object)packet, PacketSerializer.JSONOptions);
			byte[] bytes = Encoding.UTF8.GetBytes(s);
			CompressTest(bytes);
		}
	}
}
namespace CodeTalker.Packets
{
	public abstract class BinaryPacketBase
	{
		public abstract string PacketSignature { get; }

		public abstract byte[] Serialize();

		public abstract void Deserialize(byte[] data);
	}
	public abstract class PacketBase
	{
		[JsonProperty]
		public abstract string PacketSourceGUID { get; }
	}
	public class PacketHeader
	{
		public readonly ulong SenderID;

		public readonly uint TargetNetId;

		public bool SenderIsLobbyOwner => SteamMatchmaking.GetLobbyOwner(new CSteamID(SteamLobby._current._currentLobbyID)).m_SteamID == SenderID;

		public PacketHeader(ulong senderID, uint targetNetId = 0u)
		{
			SenderID = senderID;
			TargetNetId = targetNetId;
			base..ctor();
		}
	}
	public static class PacketSerializer
	{
		internal static readonly JsonSerializerSettings JSONOptions = new JsonSerializerSettings
		{
			TypeNameHandling = (TypeNameHandling)0,
			PreserveReferencesHandling = (PreserveReferencesHandling)1,
			Formatting = (Formatting)0,
			NullValueHandling = (NullValueHandling)1,
			DefaultValueHandling = (DefaultValueHandling)1
		};
	}
}
namespace CodeTalker.Networking
{
	public static class CodeTalkerNetwork
	{
		public delegate void PacketListener(PacketHeader header, PacketBase packet);

		public delegate void BinaryPacketListener(PacketHeader header, BinaryPacketBase packet);

		private struct BinaryListenerEntry
		{
			public BinaryPacketListener Listener;

			public Type PacketType;
		}

		private const ushort NETWORK_PACKET_VERSION = 4;

		internal static byte[] CODE_TALKER_SIGNATURE = Encoding.UTF8.GetBytes($"!CTN:PV{(ushort)4}!");

		private static readonly Dictionary<ulong, PacketListener> packetListeners = new Dictionary<ulong, PacketListener>();

		private static readonly Dictionary<ulong, Func<string, PacketBase>> packetDeserializers = new Dictionary<ulong, Func<string, PacketBase>>();

		private static ulong lastSkippedPacketSig = 0uL;

		private static readonly Dictionary<ulong, BinaryListenerEntry> binaryListeners = new Dictionary<ulong, BinaryListenerEntry>();

		internal static bool dbg = false;

		internal static bool dev = false;

		private static object? packet;

		private static Type? type;

		private static PacketWrapper? wrapper;

		internal static string GetTypeNameString(Type type)
		{
			return type.Assembly.GetName().Name + "," + (type.DeclaringType?.Name ?? "NONE") + ":" + (type.Namespace ?? "NONE") + "." + type.Name;
		}

		internal static bool signatureCheck(Span<byte> data, Span<byte> sig)
		{
			if (data.Length < sig.Length)
			{
				return false;
			}
			return data.Slice(0, sig.Length).SequenceEqual(sig);
		}

		internal static ulong signatureHash(Span<byte> signature)
		{
			ulong num = 14695981039346656037uL;
			Span<byte> span = signature;
			for (int i = 0; i < span.Length; i++)
			{
				byte b = span[i];
				num ^= b;
				num *= 1099511628211L;
			}
			return num;
		}

		public static bool RegisterListener<T>(PacketListener listener) where T : PacketBase
		{
			Type typeFromHandle = typeof(T);
			string typeNameString = GetTypeNameString(typeFromHandle);
			ulong key = signatureHash(Encoding.UTF8.GetBytes(typeNameString));
			if (packetListeners.ContainsKey(key))
			{
				CodeTalkerPlugin.Log.LogError((object)("Failed to register listener for type " + typeFromHandle.FullName + "! A listener for this type is already registered or a hash collision has occurred!"));
				return false;
			}
			packetListeners.Add(key, listener);
			packetDeserializers.Add(key, (string payload) => JsonConvert.DeserializeObject<T>(payload, PacketSerializer.JSONOptions));
			return true;
		}

		public static bool RegisterBinaryListener<T>(BinaryPacketListener listener) where T : BinaryPacketBase, new()
		{
			Type typeFromHandle = typeof(T);
			BinaryPacketBase binaryPacketBase = new T();
			if (binaryPacketBase.PacketSignature == string.Empty)
			{
				CodeTalkerPlugin.Log.LogError((object)("Failed to register binary Listener for type " + typeFromHandle.FullName + ", PacketSignature can't be empty!"));
				return false;
			}
			ulong key = signatureHash(Encoding.UTF8.GetBytes(binaryPacketBase.PacketSignature));
			if (binaryListeners.ContainsKey(key))
			{
				CodeTalkerPlugin.Log.LogError((object)("Failed to register listener for type " + binaryPacketBase.PacketSignature + "! A listener for this type is already registered or a hash collision has occurred!"));
				return false;
			}
			binaryListeners.Add(key, new BinaryListenerEntry
			{
				Listener = listener,
				PacketType = typeFromHandle
			});
			return true;
		}

		public static void SendNetworkPacket(PacketBase packet)
		{
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			string s = JsonConvert.SerializeObject((object)packet, PacketSerializer.JSONOptions);
			PacketWrapper packetWrapper = new PacketWrapper(GetTypeNameString(packet.GetType()), Encoding.UTF8.GetBytes(s), PacketType.JSON);
			if (packetWrapper.PacketBytes.Length > 4096)
			{
				CodeTalkerPlugin.Log.LogError((object)$"Failed to send packet of type {GetTypeNameString(packet.GetType())}, packet size exceeds maximum of 4kb! Size: {packetWrapper.PacketBytes.Length}");
			}
			else
			{
				SteamMatchmaking.SendLobbyChatMsg(new CSteamID(SteamLobby._current._currentLobbyID), packetWrapper.PacketBytes, packetWrapper.PacketBytes.Length);
			}
		}

		public static void SendNetworkPacket(BinaryPacketBase packet)
		{
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			byte[] array = packet.Serialize();
			PacketWrapper packetWrapper = new PacketWrapper(packet.PacketSignature, array, PacketType.Binary);
			if (packetWrapper.PacketBytes.Length > 4096)
			{
				CodeTalkerPlugin.Log.LogError((object)$"Failed to send binary packet of signature {packet.PacketSignature}, packet size exceeds maximum of 4kb! Size: {packetWrapper.PacketBytes.Length}");
			}
			else
			{
				SteamMatchmaking.SendLobbyChatMsg(new CSteamID(SteamLobby._current._currentLobbyID), packetWrapper.PacketBytes, packetWrapper.PacketBytes.Length);
			}
		}

		public static void SendNetworkPacket(PacketBase packet, Compressors.CompressionType compressionType = Compressors.CompressionType.None, CompressionLevel compressionLevel = CompressionLevel.Fastest)
		{
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			string s = JsonConvert.SerializeObject((object)packet, PacketSerializer.JSONOptions);
			PacketWrapper packetWrapper = new PacketWrapper(GetTypeNameString(packet.GetType()), Encoding.UTF8.GetBytes(s), PacketType.JSON, compressionType, compressionLevel);
			if (packetWrapper.PacketBytes.Length > 4096)
			{
				CodeTalkerPlugin.Log.LogError((object)$"Failed to send packet of type {GetTypeNameString(packet.GetType())}, packet size exceeds maximum of 4kb! Size: {packetWrapper.PacketBytes.Length}");
			}
			else
			{
				SteamMatchmaking.SendLobbyChatMsg(new CSteamID(SteamLobby._current._currentLobbyID), packetWrapper.PacketBytes, packetWrapper.PacketBytes.Length);
			}
		}

		public static void SendNetworkPacket(BinaryPacketBase packet, Compressors.CompressionType compressionType = Compressors.CompressionType.None, CompressionLevel compressionLevel = CompressionLevel.Fastest)
		{
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			byte[] array = packet.Serialize();
			PacketWrapper packetWrapper = new PacketWrapper(packet.PacketSignature, array, PacketType.Binary, compressionType, compressionLevel);
			if (packetWrapper.PacketBytes.Length > 4096)
			{
				CodeTalkerPlugin.Log.LogError((object)$"Failed to send binary packet of signature {packet.PacketSignature}, packet size exceeds maximum of 4kb! Size: {packetWrapper.PacketBytes.Length}");
			}
			else
			{
				SteamMatchmaking.SendLobbyChatMsg(new CSteamID(SteamLobby._current._currentLobbyID), packetWrapper.PacketBytes, packetWrapper.PacketBytes.Length);
			}
		}

		[Obsolete("Use SendNetworkPacket(BinaryPacketBase) instead")]
		public static void SendBinaryNetworkPacket(BinaryPacketBase packet)
		{
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			byte[] array = packet.Serialize();
			PacketWrapper packetWrapper = new PacketWrapper(packet.PacketSignature, array, PacketType.Binary);
			if (packetWrapper.PacketBytes.Length > 4096)
			{
				CodeTalkerPlugin.Log.LogError((object)$"Failed to send binary packet of signature {packet.PacketSignature}, packet size exceeds maximum of 4kb! Size: {packetWrapper.PacketBytes.Length}");
			}
			else
			{
				SteamMatchmaking.SendLobbyChatMsg(new CSteamID(SteamLobby._current._currentLobbyID), packetWrapper.PacketBytes, packetWrapper.PacketBytes.Length);
			}
		}

		public static void SendNetworkPacket(Player player, BinaryPacketBase packet, Compressors.CompressionType compressionType = Compressors.CompressionType.None, CompressionLevel compressionLevel = CompressionLevel.Fastest)
		{
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			if (player.Network_steamID == string.Empty || !ulong.TryParse(player.Network_steamID, out var result))
			{
				CodeTalkerPlugin.Log.LogError((object)("Unable to send a packet of type '" + packet.PacketSignature + "' to \"" + player.Network_nickname + "\" which has an empty or invalid steam id!"));
			}
			else
			{
				byte[] array = packet.Serialize();
				PacketWrapper wrappedPacket = new PacketWrapper(packet.PacketSignature, array, PacketType.Binary, compressionType, compressionLevel, ((NetworkBehaviour)player).netId);
				SendSteamNetworkingMessage(new CSteamID(result), wrappedPacket);
			}
		}

		public static void SendNetworkPacket(Player player, PacketBase packet, Compressors.CompressionType compressionType = Compressors.CompressionType.None, CompressionLevel compressionLevel = CompressionLevel.Fastest)
		{
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			if (player.Network_steamID == string.Empty || !ulong.TryParse(player.Network_steamID, out var result))
			{
				CodeTalkerPlugin.Log.LogError((object)("Unable to send a packet of type '" + packet.PacketSourceGUID + "' to \"" + player.Network_nickname + "\" which has an empty or invalid steam id!"));
			}
			else
			{
				string s = JsonConvert.SerializeObject((object)packet, PacketSerializer.JSONOptions);
				PacketWrapper wrappedPacket = new PacketWrapper(GetTypeNameString(packet.GetType()), Encoding.UTF8.GetBytes(s), PacketType.JSON, compressionType, compressionLevel, ((NetworkBehaviour)player).netId);
				SendSteamNetworkingMessage(new CSteamID(result), wrappedPacket);
			}
		}

		public static void SendNetworkPacket(ulong steamID, BinaryPacketBase packet, Compressors.CompressionType compressionType = Compressors.CompressionType.None, CompressionLevel compressionLevel = CompressionLevel.Fastest)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			byte[] array = packet.Serialize();
			PacketWrapper wrappedPacket = new PacketWrapper(packet.PacketSignature, array, PacketType.Binary, compressionType, compressionLevel);
			SendSteamNetworkingMessage(new CSteamID(steamID), wrappedPacket);
		}

		public static void SendNetworkPacket(ulong steamID, PacketBase packet, Compressors.CompressionType compressionType = Compressors.CompressionType.None, CompressionLevel compressionLevel = CompressionLevel.Fastest)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			string s = JsonConvert.SerializeObject((object)packet, PacketSerializer.JSONOptions);
			PacketWrapper wrappedPacket = new PacketWrapper(GetTypeNameString(packet.GetType()), Encoding.UTF8.GetBytes(s), PacketType.JSON, compressionType, compressionLevel);
			SendSteamNetworkingMessage(new CSteamID(steamID), wrappedPacket);
		}

		internal static void SendSteamNetworkingMessage(CSteamID id, PacketWrapper wrappedPacket)
		{
			//IL_0002: 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_0032: Unknown result type (might be due to invalid IL or missing references)
			SteamNetworkingIdentity val = default(SteamNetworkingIdentity);
			((SteamNetworkingIdentity)(ref val)).SetSteamID(id);
			GCHandle gCHandle = GCHandle.Alloc(wrappedPacket.PacketBytes, GCHandleType.Pinned);
			try
			{
				IntPtr intPtr = gCHandle.AddrOfPinnedObject();
				SteamNetworkingMessages.SendMessageToUser(ref val, intPtr, (uint)wrappedPacket.PacketBytes.Length, 0, 0);
			}
			catch
			{
			}
			gCHandle.Free();
		}

		internal static void OnNetworkMessage(LobbyChatMsg_t message)
		{
			//IL_0021: 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)
			//IL_002c: 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)
			if (dev)
			{
				CodeTalkerPlugin.Log.LogDebug((object)"Called back!");
			}
			byte[] array = new byte[4096];
			CSteamID senderID = default(CSteamID);
			EChatEntryType val = default(EChatEntryType);
			int lobbyChatEntry = SteamMatchmaking.GetLobbyChatEntry(new CSteamID(message.m_ulSteamIDLobby), (int)message.m_iChatID, ref senderID, array, 4096, ref val);
			Span<byte> span = new Span<byte>(array);
			if (signatureCheck(array, CODE_TALKER_SIGNATURE))
			{
				HandleNetworkMessage(senderID, span.Slice(CODE_TALKER_SIGNATURE.Length, lobbyChatEntry - CODE_TALKER_SIGNATURE.Length));
			}
		}

		internal static void OnSteamSessionRequest(SteamNetworkingMessagesSessionRequest_t request)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			if (dev)
			{
				CodeTalkerPlugin.Log.LogDebug((object)$"Accepting messages session request from {((SteamNetworkingIdentity)(ref request.m_identityRemote)).GetSteamID()}");
			}
			SteamNetworkingMessages.AcceptSessionWithUser(ref request.m_identityRemote);
		}

		internal static string BinaryToUtf8String(Span<byte> data)
		{
			return new string((from c in Encoding.UTF8.GetString(data)
				select (!char.IsControl(c) || c == '\r' || c == '\n') ? c : '\ufffd').ToArray());
		}

		internal static string BinaryToHexString(Span<byte> data)
		{
			return BitConverter.ToString(data.ToArray()).Replace("-", "");
		}

		private static void printWrapperInfo(CSteamID senderID, PacketWrapper wrapper, LogLevel level = 32)
		{
			//IL_0005: 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_0021: Unknown result type (might be due to invalid IL or missing references)
			CodeTalkerPlugin.Log.Log(level, (object)$"Sender: {senderID} Wrapper: {wrapper}");
			CodeTalkerPlugin.Log.Log(level, (object)("Message hex: " + BinaryToHexString(wrapper.PacketBytes)));
		}

		[DebuggerNonUserCode]
		internal static void ExecuteHandler(Delegate listener, CSteamID senderID, object packetObj)
		{
			//IL_0048: 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_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (packetObj is PacketBase packetBase)
				{
					if (dbg)
					{
						printWrapperInfo(senderID, wrapper, (LogLevel)32);
						CodeTalkerPlugin.Log.LogDebug((object)("Sending an event for \"" + GetTypeNameString(packetBase.GetType()) + "\""));
					}
					((PacketListener)listener)(new PacketHeader(senderID.m_SteamID), packetBase);
				}
				else if (packetObj is BinaryPacketBase binaryPacketBase)
				{
					if (dbg)
					{
						printWrapperInfo(senderID, wrapper, (LogLevel)32);
						CodeTalkerPlugin.Log.LogDebug((object)("Sending an event for \"" + binaryPacketBase.PacketSignature + "\""));
					}
					((BinaryPacketListener)listener)(new PacketHeader(senderID.m_SteamID), binaryPacketBase);
				}
			}
			catch (Exception arg2)
			{
				Dictionary<string, PluginInfo> pluginInfos = Chainloader.PluginInfos;
				PluginInfo val = pluginInfos.Values.Where((PluginInfo mod) => ((object)mod.Instance)?.GetType().Assembly == type?.Assembly).FirstOrDefault();
				string arg = ((val != null) ? $"{val.Metadata.Name} version {val.Metadata.Version}" : (type?.Assembly.GetName().Name ?? ""));
				CodeTalkerPlugin.Log.LogError((object)$"The following mod encountered an error while responding to a network packet, please do not report this as a CodeTalker error!\r\nMod: {arg}\r\nStackTrace:\r\n{arg2}");
			}
		}

		internal static void HandleNetworkMessage(CSteamID senderID, Span<byte> rawData)
		{
			//IL_02a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02da: Unknown result type (might be due to invalid IL or missing references)
			//IL_01be: Unknown result type (might be due to invalid IL or missing references)
			//IL_030f: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				wrapper = new PacketWrapper(rawData);
			}
			catch (Exception arg)
			{
				CodeTalkerPlugin.Log.LogError((object)$"Failed to create packet wrapper for valid packet!\nStackTrace: {arg}");
				return;
			}
			if (wrapper.TargetNetId != 0 && ((Object)(object)Player._mainPlayer == (Object)null || ((NetworkBehaviour)Player._mainPlayer).netId != wrapper.TargetNetId))
			{
				if (dev)
				{
					CodeTalkerPlugin.Log.LogDebug((object)$"Target netId doesn't match this client! Targeted netId: {wrapper.TargetNetId}");
				}
				return;
			}
			switch (wrapper.PacketType)
			{
			case PacketType.JSON:
			{
				if (dev)
				{
					CodeTalkerPlugin.Log.LogDebug((object)"Recieved JSON packet!");
				}
				if (!packetListeners.TryGetValue(wrapper.PacketSignature, out PacketListener value2))
				{
					if (dbg && wrapper.PacketSignature != lastSkippedPacketSig)
					{
						CodeTalkerPlugin.Log.LogDebug((object)$"Skipping packet of type: {wrapper.PacketSignature} because this client does not have it installed, this is safe!");
						lastSkippedPacketSig = wrapper.PacketSignature;
					}
					break;
				}
				try
				{
					PacketBase packetBase = packetDeserializers[wrapper.PacketSignature](Encoding.UTF8.GetString(wrapper.PacketBytes));
					if (packetBase == null)
					{
						break;
					}
					type = packetBase.GetType();
					packet = packetBase;
				}
				catch (Exception ex)
				{
					CodeTalkerPlugin.Log.LogError((object)$"Error while unwrapping a packet!\r\nException: {ex.GetType().Name}\r\nExpected Type: {wrapper.PacketSignature}");
					break;
				}
				if (dev)
				{
					CodeTalkerPlugin.Log.LogDebug((object)("Raw message: " + BinaryToHexString(rawData)));
				}
				ExecuteHandler(value2, senderID, packet);
				break;
			}
			case PacketType.Binary:
			{
				if (dev)
				{
					CodeTalkerPlugin.Log.LogDebug((object)"Recieved binary packet!");
				}
				if (!binaryListeners.TryGetValue(wrapper.PacketSignature, out var value))
				{
					if (dev && wrapper.PacketSignature != lastSkippedPacketSig)
					{
						CodeTalkerPlugin.Log.LogDebug((object)("Skipping binary packet of unknown signature hash: 0x" + wrapper.PacketSignature.ToString("x2") + " because this client does not have it installed, this is safe!"));
						lastSkippedPacketSig = wrapper.PacketSignature;
					}
					break;
				}
				try
				{
					type = value.PacketType;
					object obj = Activator.CreateInstance(type);
					if (!(obj is BinaryPacketBase binaryPacketBase))
					{
						throw new InvalidOperationException("Failed to create instance of binary packet type!");
					}
					packet = obj;
					try
					{
						binaryPacketBase.Deserialize(wrapper.PacketBytes);
					}
					catch (Exception arg2)
					{
						CodeTalkerPlugin.Log.LogError((object)$"Error while deserializing binary packet! THIS IS NOT A CODETALKER ISSUE! DO NOT REPORT THIS TO THE CODETALKER DEV!!\nStackTrace: {arg2}");
						printWrapperInfo(senderID, wrapper, (LogLevel)2);
						break;
					}
				}
				catch (Exception arg3)
				{
					CodeTalkerPlugin.Log.LogError((object)$"Error while creating binary packet instance! This should be reported to either codetalker or the plugin dev!\nStackTrace: {arg3}");
					printWrapperInfo(senderID, wrapper, (LogLevel)2);
					break;
				}
				if (dev)
				{
					CodeTalkerPlugin.Log.LogDebug((object)("Raw message: " + BinaryToHexString(rawData)));
				}
				ExecuteHandler(value.Listener, senderID, packet);
				break;
			}
			default:
				CodeTalkerPlugin.Log.LogError((object)$"UNKNOWN PACKET TYPE RECIEVED! THERE IS LIKELY A BUG IN CODEYAPPER. REPORT THIS TO @Soggy_Pancake! {wrapper}\nRecieved data: {BinaryToHexString(rawData)}");
				break;
			}
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}