Decompiled source of MyceliumNetworking v1.0.14

BepInEx/plugins/MyceliumNetworking/MyceliumNetworkingForCW.dll

Decompiled 6 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
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 Microsoft.CodeAnalysis;
using Steamworks;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: IgnoresAccessChecksTo("Ashley.MeshSplitter")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp-firstpass")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: IgnoresAccessChecksTo("com.rlabrecque.steamworks.net")]
[assembly: IgnoresAccessChecksTo("Discord")]
[assembly: IgnoresAccessChecksTo("HBAO.Demo.Universal.Runtime")]
[assembly: IgnoresAccessChecksTo("HBAO.Runtime")]
[assembly: IgnoresAccessChecksTo("HBAO.Universal.Runtime")]
[assembly: IgnoresAccessChecksTo("MeshSplit")]
[assembly: IgnoresAccessChecksTo("Photon3Unity3D")]
[assembly: IgnoresAccessChecksTo("PhotonChat")]
[assembly: IgnoresAccessChecksTo("PhotonRealtime")]
[assembly: IgnoresAccessChecksTo("PhotonUnityNetworking")]
[assembly: IgnoresAccessChecksTo("PhotonUnityNetworking.Utilities")]
[assembly: IgnoresAccessChecksTo("PhotonVoice.API")]
[assembly: IgnoresAccessChecksTo("PhotonVoice")]
[assembly: IgnoresAccessChecksTo("PhotonVoice.PUN")]
[assembly: IgnoresAccessChecksTo("pworld")]
[assembly: IgnoresAccessChecksTo("sc.posteffects.runtime")]
[assembly: IgnoresAccessChecksTo("Sirenix.OdinInspector.Attributes")]
[assembly: IgnoresAccessChecksTo("Sirenix.OdinInspector.Modules.Unity.Addressables")]
[assembly: IgnoresAccessChecksTo("Sirenix.OdinInspector.Modules.UnityLocalization")]
[assembly: IgnoresAccessChecksTo("Sirenix.Serialization.Config")]
[assembly: IgnoresAccessChecksTo("Sirenix.Serialization")]
[assembly: IgnoresAccessChecksTo("Sirenix.Utilities")]
[assembly: IgnoresAccessChecksTo("Tayx.Graphy")]
[assembly: IgnoresAccessChecksTo("Unity.Addressables")]
[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.InternalAPIEngineBridge.013")]
[assembly: IgnoresAccessChecksTo("Unity.Localization")]
[assembly: IgnoresAccessChecksTo("Unity.Mathematics")]
[assembly: IgnoresAccessChecksTo("Unity.PlayableGraphVisualizer")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipeline.Universal.ShaderLibrary")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.ShaderLibrary")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.ShaderGraph.ShaderGraphLibrary")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Universal.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Universal.Shaders")]
[assembly: IgnoresAccessChecksTo("Unity.ResourceManager")]
[assembly: IgnoresAccessChecksTo("Unity.ScriptableBuildPipeline")]
[assembly: IgnoresAccessChecksTo("Unity.Splines")]
[assembly: IgnoresAccessChecksTo("Unity.TextMeshPro")]
[assembly: IgnoresAccessChecksTo("Unity.Timeline")]
[assembly: IgnoresAccessChecksTo("UnityEngine.ARModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.NVIDIAModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.UI")]
[assembly: IgnoresAccessChecksTo("Zorro.Core.Runtime")]
[assembly: IgnoresAccessChecksTo("Zorro.PhotonUtility")]
[assembly: IgnoresAccessChecksTo("Zorro.Recorder")]
[assembly: IgnoresAccessChecksTo("Zorro.Settings.Runtime")]
[assembly: IgnoresAccessChecksTo("Zorro.UI.Runtime")]
[assembly: AssemblyCompany("RugbugRedfern")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.14.0")]
[assembly: AssemblyInformationalVersion("1.0.14+2efbc5cb2bb4d03a71c503581dbd17a763b97873")]
[assembly: AssemblyProduct("Mycelium Networking")]
[assembly: AssemblyTitle("MyceliumNetworkingForCW")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/RugbugRedfern/Mycelium-Networking-For-Content-Warning")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.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.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace MyceliumNetworking
{
	[AttributeUsage(AttributeTargets.Method)]
	public class CustomRPCAttribute : Attribute
	{
	}
	public class Message : IDisposable
	{
		private const int MYCELIUM_VERSION = 1;

		public byte MyceliumVersion;

		public int Mask;

		public uint ModID;

		public string MethodName;

		private List<byte> buffer;

		private byte[] readableBuffer;

		private int readPos;

		private Dictionary<Type, Action<Message, object>> WriteCasters = new Dictionary<Type, Action<Message, object>>
		{
			{
				typeof(byte),
				delegate(Message msg, object value)
				{
					msg.WriteByte((byte)value);
				}
			},
			{
				typeof(byte[]),
				delegate(Message msg, object value)
				{
					msg.WriteBytes((byte[])value);
				}
			},
			{
				typeof(bool),
				delegate(Message msg, object value)
				{
					msg.WriteBool((bool)value);
				}
			},
			{
				typeof(bool[]),
				delegate(Message msg, object value)
				{
					msg.WriteBools((bool[])value);
				}
			},
			{
				typeof(int),
				delegate(Message msg, object value)
				{
					msg.WriteInt((int)value);
				}
			},
			{
				typeof(uint),
				delegate(Message msg, object value)
				{
					msg.WriteUInt((uint)value);
				}
			},
			{
				typeof(short),
				delegate(Message msg, object value)
				{
					msg.WriteShort((short)value);
				}
			},
			{
				typeof(ushort),
				delegate(Message msg, object value)
				{
					msg.WriteUShort((ushort)value);
				}
			},
			{
				typeof(long),
				delegate(Message msg, object value)
				{
					msg.WriteLong((long)value);
				}
			},
			{
				typeof(ulong),
				delegate(Message msg, object value)
				{
					msg.WriteULong((ulong)value);
				}
			},
			{
				typeof(float),
				delegate(Message msg, object value)
				{
					msg.WriteFloat((float)value);
				}
			},
			{
				typeof(string),
				delegate(Message msg, object value)
				{
					msg.WriteString((string)value);
				}
			},
			{
				typeof(Vector3),
				delegate(Message msg, object value)
				{
					//IL_0002: Unknown result type (might be due to invalid IL or missing references)
					msg.WriteVector3((Vector3)value);
				}
			},
			{
				typeof(Quaternion),
				delegate(Message msg, object value)
				{
					//IL_0002: Unknown result type (might be due to invalid IL or missing references)
					msg.WriteQuaternion((Quaternion)value);
				}
			},
			{
				typeof(CSteamID),
				delegate(Message msg, object value)
				{
					msg.WriteULong(((CSteamID)value).m_SteamID);
				}
			}
		};

		private Dictionary<Type, Func<Message, object>> ReadCasters = new Dictionary<Type, Func<Message, object>>
		{
			{
				typeof(byte),
				(Message msg) => msg.ReadByte()
			},
			{
				typeof(byte[]),
				(Message msg) => msg.ReadBytes()
			},
			{
				typeof(bool),
				(Message msg) => msg.ReadBool()
			},
			{
				typeof(bool[]),
				(Message msg) => msg.ReadBools()
			},
			{
				typeof(int),
				(Message msg) => msg.ReadInt()
			},
			{
				typeof(uint),
				(Message msg) => msg.ReadUInt()
			},
			{
				typeof(short),
				(Message msg) => msg.ReadShort()
			},
			{
				typeof(ushort),
				(Message msg) => msg.ReadUShort()
			},
			{
				typeof(long),
				(Message msg) => msg.ReadLong()
			},
			{
				typeof(ulong),
				(Message msg) => msg.ReadULong()
			},
			{
				typeof(float),
				(Message msg) => msg.ReadFloat()
			},
			{
				typeof(string),
				(Message msg) => msg.ReadString()
			},
			{
				typeof(Vector3),
				(Message msg) => msg.ReadVector3()
			},
			{
				typeof(Quaternion),
				(Message msg) => msg.ReadQuaternion()
			},
			{
				typeof(CSteamID),
				(Message msg) => (CSteamID)msg.ReadULong()
			}
		};

		private bool disposed;

		public static int MaxSize { get; private set; } = 524288;


		public string GetDestination()
		{
			return $"{ModID}: {MethodName}";
		}

		public Message(uint modID, string methodName, int mask)
		{
			buffer = new List<byte>();
			readPos = 0;
			MyceliumVersion = 1;
			ModID = modID;
			MethodName = methodName;
			Mask = mask;
			WriteByte(MyceliumVersion);
			WriteUInt(ModID);
			WriteString(MethodName);
			WriteInt(Mask);
		}

		public Message(byte[] data)
		{
			buffer = new List<byte>();
			readPos = 0;
			SetBytes(data);
			MyceliumVersion = ReadByte();
			ModID = ReadUInt();
			MethodName = ReadString();
			Mask = ReadInt();
		}

		public void SetBytes(byte[] data)
		{
			buffer.AddRange(data);
			readableBuffer = buffer.ToArray();
		}

		public void WriteLength()
		{
			buffer.InsertRange(0, BitConverter.GetBytes(buffer.Count));
		}

		public byte[] ToArray()
		{
			readableBuffer = buffer.ToArray();
			return readableBuffer;
		}

		public int Length()
		{
			return buffer.Count;
		}

		public int UnreadLength()
		{
			return Length() - readPos;
		}

		public void Reset(bool shouldReset = true)
		{
			if (shouldReset)
			{
				buffer.Clear();
				readableBuffer = null;
				readPos = 0;
			}
			else
			{
				readPos -= 4;
			}
		}

		public Message WriteByte(byte value)
		{
			buffer.Add(value);
			return this;
		}

		public Message WriteBytes(byte[] value)
		{
			WriteInt(value.Length);
			buffer.AddRange(value);
			return this;
		}

		public Message WriteBools(bool[] value)
		{
			WriteInt(value.Length);
			byte[] array = new byte[value.Length];
			for (int i = 0; i < array.Length; i++)
			{
				array[i] = (value[i] ? ((byte)1) : ((byte)0));
			}
			buffer.AddRange(array);
			return this;
		}

		public Message WriteShort(short value)
		{
			buffer.AddRange(BitConverter.GetBytes(value));
			return this;
		}

		public Message WriteUShort(ushort value)
		{
			buffer.AddRange(BitConverter.GetBytes(value));
			return this;
		}

		public Message WriteInt(int value)
		{
			buffer.AddRange(BitConverter.GetBytes(value));
			return this;
		}

		public Message WriteUInt(uint value)
		{
			buffer.AddRange(BitConverter.GetBytes(value));
			return this;
		}

		public Message InsertInt(int value)
		{
			buffer.InsertRange(1, BitConverter.GetBytes(value));
			return this;
		}

		public Message WriteLong(long value)
		{
			buffer.AddRange(BitConverter.GetBytes(value));
			return this;
		}

		public Message WriteULong(ulong value)
		{
			buffer.AddRange(BitConverter.GetBytes(value));
			return this;
		}

		public Message WriteFloat(float value)
		{
			buffer.AddRange(BitConverter.GetBytes(value));
			return this;
		}

		public Message WriteBool(bool value)
		{
			buffer.AddRange(BitConverter.GetBytes(value));
			return this;
		}

		public Message WriteString(string value)
		{
			byte[] bytes = Encoding.UTF8.GetBytes(value);
			WriteInt(bytes.Length);
			buffer.AddRange(bytes);
			return this;
		}

		public Message WriteVector3(Vector3 value)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			WriteFloat(value.x);
			WriteFloat(value.y);
			WriteFloat(value.z);
			return this;
		}

		public Message WriteQuaternion(Quaternion value)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: 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)
			WriteFloat(value.x);
			WriteFloat(value.y);
			WriteFloat(value.z);
			WriteFloat(value.w);
			return this;
		}

		public void WriteObject(Type type, object value)
		{
			if (WriteCasters.TryGetValue(type, out var value2))
			{
				value2(this, value);
				return;
			}
			throw new Exception($"Could not write value of type '{type}' as it is unsupported!");
		}

		public byte ReadByte()
		{
			if (buffer.Count > readPos)
			{
				byte result = readableBuffer[readPos];
				readPos++;
				return result;
			}
			throw new Exception("Could not read value of type 'byte'!");
		}

		public byte[] ReadBytes()
		{
			int num = ReadInt();
			if (num == 0)
			{
				return new byte[0];
			}
			if (buffer.Count > readPos)
			{
				byte[] result = buffer.GetRange(readPos, num).ToArray();
				readPos += num;
				return result;
			}
			throw new Exception("Could not read value of type 'byte[]'!");
		}

		public bool[] ReadBools()
		{
			int num = ReadInt();
			if (buffer.Count > readPos)
			{
				bool[] array = new bool[num];
				for (int i = 0; i < num; i++)
				{
					byte b = buffer[readPos + i];
					array[i] = b == 1;
				}
				readPos += num;
				return array;
			}
			throw new Exception("Could not read value of type 'bool[]'!");
		}

		public short ReadShort()
		{
			if (buffer.Count > readPos)
			{
				short result = BitConverter.ToInt16(readableBuffer, readPos);
				readPos += 2;
				return result;
			}
			throw new Exception("Could not read value of type 'short'!");
		}

		public ushort ReadUShort()
		{
			if (buffer.Count > readPos)
			{
				ushort result = BitConverter.ToUInt16(readableBuffer, readPos);
				readPos += 2;
				return result;
			}
			throw new Exception("Could not read value of type 'short'!");
		}

		public int ReadInt()
		{
			if (buffer.Count > readPos)
			{
				int result = BitConverter.ToInt32(readableBuffer, readPos);
				readPos += 4;
				return result;
			}
			throw new Exception("Could not read value of type 'int'!");
		}

		public uint ReadUInt()
		{
			if (buffer.Count > readPos)
			{
				uint result = BitConverter.ToUInt32(readableBuffer, readPos);
				readPos += 4;
				return result;
			}
			throw new Exception("Could not read value of type 'uint'!");
		}

		public long ReadLong()
		{
			if (buffer.Count > readPos)
			{
				long result = BitConverter.ToInt64(readableBuffer, readPos);
				readPos += 8;
				return result;
			}
			throw new Exception("Could not read value of type 'long'!");
		}

		public ulong ReadULong()
		{
			if (buffer.Count > readPos)
			{
				ulong result = BitConverter.ToUInt64(readableBuffer, readPos);
				readPos += 8;
				return result;
			}
			throw new Exception("Could not read value of type 'ulong'!");
		}

		public float ReadFloat()
		{
			if (buffer.Count > readPos)
			{
				float result = BitConverter.ToSingle(readableBuffer, readPos);
				readPos += 4;
				return result;
			}
			throw new Exception("Could not read value of type 'float'!");
		}

		public bool ReadBool()
		{
			if (buffer.Count > readPos)
			{
				bool result = BitConverter.ToBoolean(readableBuffer, readPos);
				readPos++;
				return result;
			}
			throw new Exception("Could not read value of type 'bool'!");
		}

		public string ReadString()
		{
			try
			{
				int num = ReadInt();
				string @string = Encoding.UTF8.GetString(readableBuffer, readPos, num);
				if (@string.Length > 0)
				{
					readPos += num;
				}
				return @string;
			}
			catch
			{
				throw new Exception("Could not read value of type 'string'!");
			}
		}

		public Vector3 ReadVector3()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			return new Vector3(ReadFloat(), ReadFloat(), ReadFloat());
		}

		public Quaternion ReadQuaternion()
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			return new Quaternion(ReadFloat(), ReadFloat(), ReadFloat(), ReadFloat());
		}

		public object ReadObject(Type type)
		{
			if (ReadCasters.TryGetValue(type, out var value))
			{
				return value(this);
			}
			throw new Exception($"Could not read value of type '{type}' as it is unsupported!");
		}

		public int GetSize()
		{
			return readableBuffer.Length;
		}

		protected virtual void Dispose(bool disposing)
		{
			if (!disposed)
			{
				if (disposing)
				{
					buffer = null;
					readableBuffer = null;
					readPos = 0;
				}
				disposed = true;
			}
		}

		public void Dispose()
		{
			Dispose(disposing: true);
			GC.SuppressFinalize(this);
		}
	}
	public enum ReliableType
	{
		Unreliable,
		Reliable,
		UnreliableNoDelay
	}
	public static class MyceliumNetwork
	{
		private class MessageHandler
		{
			public object Target;

			public MethodInfo Method;

			public ParameterInfo[] Parameters;

			public bool TakesInfo;

			public int Mask;
		}

		private const int CHANNEL = 120;

		private static List<string> lobbyDataKeys = new List<string>();

		private static List<string> playerDataKeys = new List<string>();

		private static Dictionary<CSteamID, Dictionary<string, string>> lastPlayerData = new Dictionary<CSteamID, Dictionary<string, string>>();

		private static Dictionary<string, string> lastLobbyData = new Dictionary<string, string>();

		private static Callback<LobbyEnter_t> _c2;

		private static Callback<LobbyCreated_t> _c3;

		private static Callback<LobbyChatUpdate_t> _c4;

		private static Callback<LobbyDataUpdate_t> _c5;

		private const int MAX_MESSAGES = 500;

		private static IntPtr[] outMessages = new IntPtr[500];

		private static Dictionary<uint, Dictionary<string, List<MessageHandler>>> rpcs = new Dictionary<uint, Dictionary<string, List<MessageHandler>>>();

		public static CSteamID[] Players { get; private set; } = (CSteamID[])(object)new CSteamID[0];


		public static int PlayerCount => SteamMatchmaking.GetNumLobbyMembers(Lobby);

		public static int MaxPlayers => SteamMatchmaking.GetLobbyMemberLimit(Lobby);

		public static CSteamID LobbyHost => SteamMatchmaking.GetLobbyOwner(Lobby);

		public static bool IsHost => SteamMatchmaking.GetLobbyOwner(Lobby) == SteamUser.GetSteamID();

		public static CSteamID Lobby { get; private set; }

		public static bool InLobby { get; private set; }

		public static event Action LobbyCreated;

		public static event Action LobbyEntered;

		public static event Action LobbyLeft;

		public static event Action<EResult> LobbyCreationFailed;

		public static event Action<CSteamID> PlayerEntered;

		public static event Action<CSteamID> PlayerLeft;

		public static event Action<CSteamID, List<string>> PlayerDataUpdated;

		public static event Action<List<string>> LobbyDataUpdated;

		public static void Initialize()
		{
			_c2 = Callback<LobbyEnter_t>.Create((DispatchDelegate<LobbyEnter_t>)OnLobbyEnter);
			_c3 = Callback<LobbyCreated_t>.Create((DispatchDelegate<LobbyCreated_t>)OnLobbyCreated);
			_c4 = Callback<LobbyChatUpdate_t>.Create((DispatchDelegate<LobbyChatUpdate_t>)OnLobbyChatUpdate);
			_c5 = Callback<LobbyDataUpdate_t>.Create((DispatchDelegate<LobbyDataUpdate_t>)OnLobbyDataUpdate);
		}

		private static void OnLobbyEnter(LobbyEnter_t param)
		{
			//IL_0005: 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_0020: Unknown result type (might be due to invalid IL or missing references)
			RugLogger.Log($"Entering lobby {param.m_ulSteamIDLobby}");
			Lobby = new CSteamID(param.m_ulSteamIDLobby);
			InLobby = true;
			RefreshPlayerList();
			MyceliumNetwork.LobbyEntered?.Invoke();
		}

		internal static void OnLobbyLeft()
		{
			lastLobbyData.Clear();
			lastPlayerData.Clear();
			InLobby = false;
			MyceliumNetwork.LobbyLeft?.Invoke();
		}

		private static void OnLobbyCreated(LobbyCreated_t param)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: 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_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Invalid comparison between Unknown and I4
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			RugLogger.Log($"Created lobby {param.m_eResult}");
			if ((int)param.m_eResult == 1)
			{
				Lobby = new CSteamID(param.m_ulSteamIDLobby);
				InLobby = true;
				RefreshPlayerList();
				MyceliumNetwork.LobbyCreated?.Invoke();
			}
			else
			{
				MyceliumNetwork.LobbyCreationFailed?.Invoke(param.m_eResult);
			}
		}

		private static void OnLobbyChatUpdate(LobbyChatUpdate_t param)
		{
			//IL_0002: 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_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)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected I4, but got Unknown
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Invalid comparison between Unknown and I4
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Invalid comparison between Unknown and I4
			CSteamID obj = default(CSteamID);
			((CSteamID)(ref obj))..ctor(param.m_ulSteamIDUserChanged);
			RefreshPlayerList();
			EChatMemberStateChange val = (EChatMemberStateChange)param.m_rgfChatMemberStateChange;
			switch (val - 1)
			{
			default:
				if ((int)val != 8 && (int)val != 16)
				{
					return;
				}
				break;
			case 0:
				MyceliumNetwork.PlayerEntered?.Invoke(obj);
				return;
			case 1:
			case 3:
				break;
			case 2:
				return;
			}
			MyceliumNetwork.PlayerLeft?.Invoke(obj);
		}

		private static void RefreshPlayerList()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: 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)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: 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)
			Players = (CSteamID[])(object)new CSteamID[SteamMatchmaking.GetNumLobbyMembers(Lobby)];
			for (int i = 0; i < Players.Length; i++)
			{
				CSteamID lobbyMemberByIndex = SteamMatchmaking.GetLobbyMemberByIndex(Lobby, i);
				Players[i] = lobbyMemberByIndex;
			}
		}

		public static void RPCTargetMasked(uint modId, string methodName, CSteamID target, ReliableType reliable, int mask, params object[] parameters)
		{
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			Message message = new Message(modId, methodName, mask);
			MessageHandler messageHandler = GetMessageHandlers(modId, methodName)[0];
			int num = messageHandler.Parameters.Length;
			if (messageHandler.TakesInfo)
			{
				num--;
			}
			if (num != parameters.Length)
			{
				throw new Exception($"RPC call {modId}: {methodName} has an invalid number of parameters (it has {parameters.Length}, but it should have {num})");
			}
			for (int i = 0; i < num; i++)
			{
				if (messageHandler.Parameters[i].ParameterType != parameters[i].GetType())
				{
					throw new Exception($"RPC call {modId}: {methodName} has a mismatched parameter type ({parameters[i].GetType()} should be {messageHandler.Parameters[i].ParameterType}) for {messageHandler.Parameters[i].Name}");
				}
				message.WriteObject(messageHandler.Parameters[i].ParameterType, parameters[i]);
			}
			SendBytes(message.ToArray(), target, reliable);
		}

		public static void RPCTarget(uint modId, string methodName, CSteamID target, ReliableType reliable, params object[] parameters)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			RPCTargetMasked(modId, methodName, target, reliable, 0, parameters);
		}

		public static void RPCMasked(uint modId, string methodName, ReliableType reliable, int mask, params object[] parameters)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			for (int i = 0; i < Players.Length; i++)
			{
				RPCTargetMasked(modId, methodName, Players[i], reliable, mask, parameters);
			}
		}

		public static void RPC(uint modId, string methodName, ReliableType reliable, params object[] parameters)
		{
			RPCMasked(modId, methodName, reliable, 0, parameters);
		}

		public static void RegisterLobbyDataKey(string key)
		{
			if (lobbyDataKeys.Contains(key))
			{
				RugLogger.LogError("Lobby data key " + key + " is already defined");
			}
			else
			{
				lobbyDataKeys.Add(key);
			}
		}

		public static void RegisterPlayerDataKey(string key)
		{
			if (playerDataKeys.Contains(key))
			{
				RugLogger.LogError("Player data key " + key + " is already defined");
			}
			else
			{
				playerDataKeys.Add(key);
			}
		}

		private static void OnLobbyDataUpdate(LobbyDataUpdate_t param)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: 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)
			//IL_00ba: 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)
			//IL_00d8: 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_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			if (!InLobby || param.m_ulSteamIDLobby != Lobby.m_SteamID)
			{
				return;
			}
			if (param.m_ulSteamIDLobby == param.m_ulSteamIDMember)
			{
				List<string> list = new List<string>();
				for (int i = 0; i < lobbyDataKeys.Count; i++)
				{
					string text = lobbyDataKeys[i];
					string lobbyData = SteamMatchmaking.GetLobbyData(Lobby, text);
					if (lastLobbyData.ContainsKey(text))
					{
						if (!lastLobbyData[text].Equals(lobbyData))
						{
							list.Add(text);
						}
					}
					else
					{
						list.Add(text);
					}
					lastLobbyData[text] = lobbyData;
				}
				if (list.Count > 0)
				{
					MyceliumNetwork.LobbyDataUpdated?.Invoke(list);
				}
				return;
			}
			CSteamID val = default(CSteamID);
			((CSteamID)(ref val))..ctor(param.m_ulSteamIDMember);
			if (!lastPlayerData.ContainsKey(val))
			{
				lastPlayerData[val] = new Dictionary<string, string>();
			}
			List<string> list2 = new List<string>();
			for (int j = 0; j < playerDataKeys.Count; j++)
			{
				string text2 = playerDataKeys[j];
				string lobbyMemberData = SteamMatchmaking.GetLobbyMemberData(Lobby, val, text2);
				if (lastPlayerData[val].ContainsKey(text2))
				{
					if (!lastPlayerData[val][text2].Equals(lobbyMemberData))
					{
						list2.Add(text2);
					}
				}
				else
				{
					list2.Add(text2);
				}
				lastPlayerData[val][text2] = lobbyMemberData;
			}
			if (list2.Count > 0)
			{
				MyceliumNetwork.PlayerDataUpdated?.Invoke(val, list2);
			}
		}

		public static void SetLobbyData(string key, object value)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			if (!InLobby)
			{
				RugLogger.LogError("Cannot set lobby data when not in lobby.");
				return;
			}
			if (!lobbyDataKeys.Contains(key))
			{
				RugLogger.LogWarning("Accessing lobby data for unregistered key '" + key + "'. This might not exist.");
			}
			if (!SteamMatchmaking.SetLobbyData(Lobby, key, (string)Convert.ChangeType(value, typeof(string), CultureInfo.InvariantCulture)))
			{
				RugLogger.LogError("Error setting lobby data.");
			}
		}

		public static bool HasLobbyData(string key)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			if (!InLobby)
			{
				RugLogger.LogError("Cannot get lobby data when not in lobby.");
				return false;
			}
			if (!lobbyDataKeys.Contains(key))
			{
				RugLogger.LogWarning("Accessing lobby data for unregistered key '" + key + "'. This might not exist.");
			}
			string lobbyData = SteamMatchmaking.GetLobbyData(Lobby, key.ToString());
			return !string.IsNullOrEmpty(lobbyData);
		}

		public static T GetLobbyData<T>(string key)
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			if (!InLobby)
			{
				RugLogger.LogError("Cannot get lobby data when not in lobby.");
				return default(T);
			}
			if (!lobbyDataKeys.Contains(key))
			{
				RugLogger.LogWarning("Accessing lobby data for unregistered key '" + key + "'. This might not exist.");
			}
			string lobbyData = SteamMatchmaking.GetLobbyData(Lobby, key.ToString());
			try
			{
				return (T)Convert.ChangeType(lobbyData, typeof(T), CultureInfo.InvariantCulture);
			}
			catch (Exception ex)
			{
				RugLogger.LogError("Could not parse lobby data [" + key + ", " + lobbyData + "] as " + typeof(T).Name + ": " + ex.Message);
			}
			return default(T);
		}

		public static void SetPlayerData(string key, object value)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			if (!InLobby)
			{
				RugLogger.LogError("Cannot set player data when not in lobby.");
				return;
			}
			if (!playerDataKeys.Contains(key))
			{
				RugLogger.LogWarning("Accessing player data for unregistered key '" + key + "'. This might not exist.");
			}
			SteamMatchmaking.SetLobbyMemberData(Lobby, key.ToString(), (string)Convert.ChangeType(value, typeof(string), CultureInfo.InvariantCulture));
		}

		public static bool HasPlayerData(CSteamID player, string key)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			if (!InLobby)
			{
				RugLogger.LogError("Cannot get player data when not in lobby.");
				return false;
			}
			if (!playerDataKeys.Contains(key))
			{
				RugLogger.LogWarning("Accessing player data for unregistered key '" + key + "'. This might not exist.");
			}
			string lobbyMemberData = SteamMatchmaking.GetLobbyMemberData(Lobby, player, key.ToString());
			return !string.IsNullOrEmpty(lobbyMemberData);
		}

		public static T GetPlayerData<T>(CSteamID player, string key)
		{
			//IL_003d: 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)
			if (!InLobby)
			{
				RugLogger.LogError("Cannot get player data when not in lobby.");
				return default(T);
			}
			if (!playerDataKeys.Contains(key))
			{
				RugLogger.LogWarning("Accessing player data for unregistered key '" + key + "'. This might not exist.");
			}
			string lobbyMemberData = SteamMatchmaking.GetLobbyMemberData(Lobby, player, key.ToString());
			if (!string.IsNullOrEmpty(lobbyMemberData))
			{
				try
				{
					return (T)Convert.ChangeType(lobbyMemberData, typeof(T), CultureInfo.InvariantCulture);
				}
				catch (Exception ex)
				{
					RugLogger.LogError("Could not parse [" + key + ", " + lobbyMemberData + "] as " + typeof(T).Name + ": " + ex.Message);
				}
			}
			return default(T);
		}

		private static void SendBytes(byte[] data, CSteamID target, ReliableType reliable)
		{
			//IL_002c: 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_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Invalid comparison between Unknown and I4
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			if (data.Length > Message.MaxSize)
			{
				RugLogger.LogError($"Size of message ({data.Length} bytes) is greater than the max allowed size ({Message.MaxSize}).");
				return;
			}
			if (target == SteamUser.GetSteamID())
			{
				Message message = new Message(data);
				HandleMessage(message, target);
				return;
			}
			SteamNetworkingIdentity val = default(SteamNetworkingIdentity);
			((SteamNetworkingIdentity)(ref val)).SetSteamID(target);
			GCHandle gCHandle = GCHandle.Alloc(data, GCHandleType.Pinned);
			IntPtr intPtr = gCHandle.AddrOfPinnedObject();
			int num = 0;
			switch (reliable)
			{
			case ReliableType.Unreliable:
				num = 0;
				break;
			case ReliableType.Reliable:
				num = 8;
				break;
			case ReliableType.UnreliableNoDelay:
				num = 5;
				break;
			}
			EResult val2 = SteamNetworkingMessages.SendMessageToUser(ref val, intPtr, (uint)data.Length, num | 0x20, 120);
			if ((int)val2 != 1)
			{
				RugLogger.LogError($"Error sending message to user {target}: {val2}");
			}
			gCHandle.Free();
		}

		private static List<MessageHandler> GetMessageHandlers(uint modID, string methodName)
		{
			if (rpcs.TryGetValue(modID, out var value))
			{
				if (value.TryGetValue(methodName, out var value2))
				{
					return value2;
				}
				throw new Exception($"The RPC ({modID}: {methodName}) was not found");
			}
			throw new Exception(string.Format("The mod id {0} was not found (loaded mods: {1})", modID, string.Join(",", rpcs.Keys.ToArray())));
		}

		private static void HandleMessage(Message message, CSteamID sender)
		{
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				List<MessageHandler> messageHandlers = GetMessageHandlers(message.ModID, message.MethodName);
				bool flag = false;
				foreach (MessageHandler item in messageHandlers)
				{
					if (item.Mask == message.Mask)
					{
						object[] array = new object[item.Parameters.Length];
						int num = (item.TakesInfo ? (array.Length - 1) : array.Length);
						for (int i = 0; i < num; i++)
						{
							array[i] = message.ReadObject(item.Parameters[i].ParameterType);
						}
						if (item.TakesInfo)
						{
							array[item.Parameters.Length - 1] = new RPCInfo(sender);
						}
						item.Method.Invoke(item.Target, array);
						flag = true;
					}
				}
				if (!flag)
				{
					RugLogger.LogWarning($"Dropped RPC because no registered RPCs were found matching {message.ModID}: {message.MethodName}");
				}
			}
			catch (Exception ex2)
			{
				string text;
				try
				{
					text = message.GetDestination();
				}
				catch (Exception ex)
				{
					text = ex.Message;
				}
				RugLogger.LogError(string.Format("Error executing RPC from {0} ({1}):\n{2}\nFull exception:\n{3} {4}", (sender == SteamUser.GetSteamID()) ? "local loopback" : ((object)(CSteamID)(ref sender)).ToString(), text, ex2.InnerException, ex2, ex2.StackTrace));
			}
		}

		public static void ReceiveMessages()
		{
			//IL_00f4: 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)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: 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_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			int num = SteamNetworkingMessages.ReceiveMessagesOnChannel(120, outMessages, 500);
			for (int i = 0; i < num; i++)
			{
				IntPtr intPtr = outMessages[i];
				int num2 = Marshal.SizeOf(intPtr);
				if (num2 > Message.MaxSize)
				{
					RugLogger.LogError($"Ignored message because its size was above the max ({num2}/{Message.MaxSize})");
					SteamNetworkingMessage_t.Release(outMessages[i]);
					continue;
				}
				SteamNetworkingMessage_t val = Marshal.PtrToStructure<SteamNetworkingMessage_t>(intPtr);
				CSteamID steamID = ((SteamNetworkingIdentity)(ref val.m_identityPeer)).GetSteamID();
				if (!Players.Contains(steamID))
				{
					SteamNetworkingMessage_t.Release(outMessages[i]);
					continue;
				}
				byte[] array = new byte[val.m_cbSize];
				Marshal.Copy(val.m_pData, array, 0, val.m_cbSize);
				Message message = new Message(array);
				try
				{
					HandleMessage(message, steamID);
				}
				catch (Exception ex2)
				{
					string text;
					try
					{
						text = message.GetDestination();
					}
					catch (Exception ex)
					{
						text = ex.Message;
					}
					RugLogger.LogError($"Error executing RPC from {steamID} ({text}): {ex2.Message} {ex2.StackTrace}");
				}
				SteamNetworkingMessage_t.Release(outMessages[i]);
			}
		}

		public static void RegisterNetworkObject(object obj, uint modId, int mask = 0)
		{
			Type type = obj.GetType();
			int num = 0;
			MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			foreach (MethodInfo methodInfo in methods)
			{
				CustomRPCAttribute[] source = methodInfo.GetCustomAttributes(inherit: false).OfType<CustomRPCAttribute>().ToArray();
				if (source.Any())
				{
					ParameterInfo[] parameters = methodInfo.GetParameters();
					if (!rpcs.ContainsKey(modId))
					{
						rpcs[modId] = new Dictionary<string, List<MessageHandler>>();
					}
					if (!rpcs[modId].ContainsKey(methodInfo.Name))
					{
						rpcs[modId][methodInfo.Name] = new List<MessageHandler>();
					}
					rpcs[modId][methodInfo.Name].Add(new MessageHandler
					{
						Target = obj,
						Method = methodInfo,
						Parameters = parameters,
						TakesInfo = (parameters.Length != 0 && parameters[^1].ParameterType == typeof(RPCInfo)),
						Mask = mask
					});
					num++;
				}
			}
			RugLogger.Log($"Registered {num} CustomRPCs for {modId}: {obj}.");
		}

		public static void DeregisterNetworkObject(object obj, uint modId, int mask = 0)
		{
			Type type = obj.GetType();
			int num = 0;
			MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			foreach (MethodInfo methodInfo in methods)
			{
				CustomRPCAttribute[] source = methodInfo.GetCustomAttributes(inherit: false).OfType<CustomRPCAttribute>().ToArray();
				if (!source.Any())
				{
					continue;
				}
				if (!rpcs.ContainsKey(modId))
				{
					RugLogger.Log($"Attempted to deregister RPCs for mod id {modId}, but no RPCs from that mod are loaded.");
					return;
				}
				if (!rpcs[modId].ContainsKey(methodInfo.Name))
				{
					RugLogger.Log($"Attempted to deregister RPC {methodInfo.Name} for mod id {modId}, but no RPCs by that name are loaded.");
					return;
				}
				MessageHandler[] array = rpcs[modId][methodInfo.Name].ToArray();
				foreach (MessageHandler messageHandler in array)
				{
					if (messageHandler.Mask == mask)
					{
						rpcs[modId][methodInfo.Name].Remove(messageHandler);
					}
				}
				num++;
			}
			RugLogger.Log($"Deregistered {num} CustomRPCs for {modId}: {obj}.");
		}
	}
	public struct RPCInfo
	{
		public CSteamID SenderSteamID;

		public RPCInfo(CSteamID senderSteamId)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			SenderSteamID = senderSteamId;
		}
	}
	internal class PersistentGameObject : MonoBehaviour
	{
		private void Update()
		{
			MyceliumNetwork.ReceiveMessages();
		}
	}
	[BepInPlugin("RugbugRedfern.MyceliumNetworking", "Mycelium Networking", "1.0.14")]
	public class PluginLoader : BaseUnityPlugin
	{
		private static bool initialized;

		private void Awake()
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Expected O, but got Unknown
			if (!initialized)
			{
				initialized = true;
				RugLogger.Initialize("RugbugRedfern.MyceliumNetworking");
				Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), (string)null);
				RugLogger.Log("MyceliumNetworking Starting 1.0.14");
				MyceliumNetwork.Initialize();
				GameObject val = new GameObject("MyceliumNetworking Persistent");
				val.AddComponent<PersistentGameObject>();
				((Object)val).hideFlags = (HideFlags)61;
				Object.DontDestroyOnLoad((Object)(object)val);
			}
		}
	}
	public static class RugLogger
	{
		public static ManualLogSource logSource;

		public static void Initialize(string modGUID)
		{
			logSource = Logger.CreateLogSource(modGUID);
		}

		public static void Log(object message)
		{
			logSource.LogInfo(message);
		}

		public static void LogError(object message)
		{
			logSource.LogError(message);
		}

		public static void LogWarning(object message)
		{
			logSource.LogWarning(message);
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "RugbugRedfern.MyceliumNetworking";

		public const string PLUGIN_NAME = "Mycelium Networking";

		public const string PLUGIN_VERSION = "1.0.14";
	}
}
namespace MyceliumNetworking.Patches
{
	[HarmonyPatch(typeof(SteamLobbyHandler))]
	internal class SteamLobbyHandlerPatches
	{
		[HarmonyPatch("LeaveLobby")]
		[HarmonyPostfix]
		private static void LeaveLobbyPatch()
		{
			RugLogger.Log("Patching SteamLobbyHandler.LeaveLobby");
			MyceliumNetwork.OnLobbyLeft();
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}