Decompiled source of VoidManager v1.0.7

VoidManager.dll

Decompiled 4 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Cryptography;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using CG;
using CG.Client.UserData;
using CG.Game;
using CG.Game.Player;
using CG.GameLoopStateMachine;
using CG.GameLoopStateMachine.GameStates;
using CG.Input;
using CG.Profile;
using Client.Utils;
using ExitGames.Client.Photon;
using Gameplay.Chat;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using Photon.Realtime;
using ResourceAssets;
using ToolClasses;
using UI.Chat;
using UI.Matchmaking;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using UnityEngine.UIElements;
using VivoxUnity;
using VoidManager.Callbacks;
using VoidManager.Chat.Router;
using VoidManager.Content;
using VoidManager.CustomGUI;
using VoidManager.MPModChecks;
using VoidManager.ModMessages;
using VoidManager.Utilities;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("VoidManager")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyDescription("Handles Inputs and Commands")]
[assembly: AssemblyFileVersion("1.0.7.0")]
[assembly: AssemblyInformationalVersion("1.0.7")]
[assembly: AssemblyProduct("VoidManager")]
[assembly: AssemblyTitle("VoidManager")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.7.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 VoidManager
{
	[BepInPlugin("VoidManager", "VoidManager", "1.0.7")]
	[BepInProcess("Void Crew.exe")]
	public class BepinPlugin : BaseUnityPlugin
	{
		internal class Bindings
		{
			internal static ConfigEntry<TextAnchor> ModInfoTextAnchor;

			internal static ConfigEntry<bool> DebugMode;

			internal static ConfigEntry<float> MenuHeight;

			internal static ConfigEntry<float> MenuWidth;

			internal static ConfigEntry<float> MenuListWidth;

			internal static ConfigEntry<float> PlayerListWidth;

			internal static ConfigEntry<bool> MenuUnlockCursor;

			internal static ConfigEntry<KeyboardShortcut> MenuOpenKeybind;

			internal static KeyboardShortcut OpenMenu = new KeyboardShortcut((KeyCode)286, Array.Empty<KeyCode>());

			internal static ConfigEntry<bool> TrustMPTypeUnspecified;

			internal static ConfigEntry<string> UnspecifiedModListOverride;

			internal static Dictionary<string, MultiplayerType> ModOverrideDictionary;

			public static void SetDefault()
			{
				ModInfoTextAnchor.Value = (TextAnchor)0;
			}

			internal static void LoadModListOverride()
			{
				ModOverrideDictionary = new Dictionary<string, MultiplayerType>();
				if (UnspecifiedModListOverride.Value == string.Empty)
				{
					return;
				}
				string[] array = UnspecifiedModListOverride.Value.Split(new char[1] { ',' });
				string[] array2 = array;
				foreach (string text in array2)
				{
					if (text.EndsWith(":all", StringComparison.CurrentCultureIgnoreCase))
					{
						ModOverrideDictionary.Add(text.Substring(0, text.Length - 4), MultiplayerType.All);
					}
					else if (text.EndsWith(":client", StringComparison.CurrentCultureIgnoreCase))
					{
						ModOverrideDictionary.Add(text.Substring(0, text.Length - 7), MultiplayerType.Client);
					}
					else if (text.EndsWith(":h", StringComparison.CurrentCultureIgnoreCase))
					{
						ModOverrideDictionary.Add(text.Substring(0, text.Length - 2), MultiplayerType.Hidden);
					}
					else
					{
						Log.LogError((object)("Unspecified Mod Override - '" + text + "' is not a valid input."));
					}
				}
			}
		}

		internal static BepinPlugin instance;

		internal static readonly Harmony Harmony = new Harmony("VoidManager");

		internal static ManualLogSource Log;

		private void Awake()
		{
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			Harmony.PatchAll();
			Craftables.Instance = new Craftables();
			Unlocks.Instance = new Unlocks();
			Log.LogInfo((object)"VoidManager Initialized.");
			Bindings.DebugMode = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "DebugMode", false, "");
			Bindings.UnspecifiedModListOverride = ((BaseUnityPlugin)this).Config.Bind<string>("General", "Unspecified Mod Overrides", string.Empty, "Insert mods (not configured for VoidManager) for which you would like to override the MPType. Format: 'ModNameOrGUID:ClientOrAll', delineated by ','. Ex: VoidManager:all,Better Scoop:Client \n ModName/GUID can be gathered from log files and F5 menu.");
			Bindings.ModInfoTextAnchor = ((BaseUnityPlugin)this).Config.Bind<TextAnchor>("Menu", "ModInfoTextAnchor", (TextAnchor)0, "");
			Bindings.MenuHeight = ((BaseUnityPlugin)this).Config.Bind<float>("Menu", "Height", 0.5f, "");
			Bindings.MenuWidth = ((BaseUnityPlugin)this).Config.Bind<float>("Menu", "Width", 0.5f, "");
			Bindings.MenuListWidth = ((BaseUnityPlugin)this).Config.Bind<float>("Menu", "List Width", 0.3f, "");
			Bindings.PlayerListWidth = ((BaseUnityPlugin)this).Config.Bind<float>("Menu", "Player List Width", 0.3f, "");
			Bindings.MenuUnlockCursor = ((BaseUnityPlugin)this).Config.Bind<bool>("Menu", "Unlock Cursor", true, "");
			Bindings.MenuOpenKeybind = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Menu", "Open Keybind", Bindings.OpenMenu, "");
			Bindings.TrustMPTypeUnspecified = ((BaseUnityPlugin)this).Config.Bind<bool>("Multiplayer", "TrustMPTypeUnspecified", false, "");
		}
	}
	internal class DefaultVoidPlugin : VoidPlugin
	{
		internal MultiplayerType m_MPType;

		public override string Author => string.Empty;

		public override string Description => "Info auto-filled";

		public override MultiplayerType MPType => m_MPType;

		internal DefaultVoidPlugin(MultiplayerType inputMPType)
		{
			m_MPType = inputMPType;
		}
	}
	public class Events
	{
		public class PlayerEventArgs : EventArgs
		{
			public Player player;
		}

		[HarmonyPatch(typeof(GameSessionManager), "HostGameSession")]
		private class HostStartSessionpatch
		{
			private static void Postfix()
			{
				Instance.OnHostStartSession();
			}
		}

		public static Events Instance { get; internal set; }

		public event EventHandler<PlayerEventArgs> PlayerEnteredRoom;

		public event EventHandler<PlayerEventArgs> PlayerLeftRoom;

		public event EventHandler JoinedRoom;

		public event EventHandler LeftRoom;

		public event EventHandler<PlayerEventArgs> MasterClientSwitched;

		public event EventHandler<PlayerEventArgs> HostVerifiedClient;

		public event EventHandler<PlayerEventArgs> ClientModlistRecieved;

		public event EventHandler HostStartSession;

		internal void OnPlayerEnteredRoom(Player joiningPlayer)
		{
			this.PlayerEnteredRoom?.Invoke(this, new PlayerEventArgs
			{
				player = joiningPlayer
			});
		}

		internal void OnPlayerLeftRoom(Player leavingPlayer)
		{
			this.PlayerLeftRoom?.Invoke(this, new PlayerEventArgs
			{
				player = leavingPlayer
			});
		}

		internal void OnJoinedRoom()
		{
			this.JoinedRoom?.Invoke(this, EventArgs.Empty);
		}

		internal void CallOnLeftRoom()
		{
			this.LeftRoom?.Invoke(this, EventArgs.Empty);
		}

		internal void CallOnMasterClientSwitched(Player newMasterClient)
		{
			this.MasterClientSwitched?.Invoke(this, new PlayerEventArgs
			{
				player = newMasterClient
			});
		}

		internal void CallHostOnClientVerified(Player verifiedPlayer)
		{
			this.HostVerifiedClient?.Invoke(this, new PlayerEventArgs
			{
				player = verifiedPlayer
			});
		}

		internal void OnClientModlistRecieved(Player DataSender)
		{
			this.ClientModlistRecieved?.Invoke(this, new PlayerEventArgs
			{
				player = DataSender
			});
		}

		internal void OnHostStartSession()
		{
			this.HostStartSession?.Invoke(this, EventArgs.Empty);
		}
	}
	[HarmonyPatch(typeof(PlayerProfileLoader), "Awake")]
	internal class PluginDetectPatch
	{
		[HarmonyPostfix]
		public static void PostAwakeInit()
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			BepinPlugin.Log.LogInfo((object)"- - - Void Manager Initialization - - -");
			Events.Instance = new Events();
			((Object)new GameObject("ModManager", new Type[1] { typeof(GUIMain) })).hideFlags = (HideFlags)61;
			PluginHandler.DiscoverPlugins();
			MPModCheckManager.Instance = new MPModCheckManager();
			BepinPlugin.Log.LogInfo((object)"- - - - - - - - - - - - - - - - - - - -");
		}
	}
	[HarmonyPatch(typeof(GSMainMenu), "OnEnter")]
	internal class InitRoomCallbacksPatch
	{
		private static bool RoomCallbacksInitialized;

		[HarmonyPostfix]
		private static void InitRoomCallbacks()
		{
			if (!RoomCallbacksInitialized)
			{
				RoomCallbacksInitialized = true;
				MPModCheckManager.RoomCallbacksClass = new InRoomCallbacks();
			}
		}
	}
	internal static class PluginHandler
	{
		public static Dictionary<string, PluginInfo> ActiveBepinPlugins => Chainloader.PluginInfos;

		public static Dictionary<string, VoidPlugin> ActiveVoidPlugins { get; private set; }

		public static Dictionary<string, VoidPlugin> GeneratedVoidPlugins { get; private set; }

		internal static void DiscoverPlugins()
		{
			BepinPlugin.Bindings.LoadModListOverride();
			Dictionary<string, MultiplayerType> modOverrideDictionary = BepinPlugin.Bindings.ModOverrideDictionary;
			ActiveVoidPlugins = new Dictionary<string, VoidPlugin>();
			GeneratedVoidPlugins = new Dictionary<string, VoidPlugin>();
			foreach (PluginInfo value2 in Chainloader.PluginInfos.Values)
			{
				Assembly assembly = ((object)value2.Instance).GetType().Assembly;
				string gUID = value2.Metadata.GUID;
				string name = value2.Metadata.Name;
				if (gUID == "VoidManager")
				{
					CommandHandler.DiscoverCommands(assembly, name);
					CommandHandler.DiscoverPublicCommands(assembly, name);
					ModMessageHandler.DiscoverModMessages(assembly, value2);
					continue;
				}
				IEnumerable<Type> source = from t in assembly.GetTypes()
					where typeof(VoidPlugin).IsAssignableFrom(t) && !t.IsInterface && !t.IsAbstract
					select t;
				if (source.Any())
				{
					VoidPlugin voidPlugin = (VoidPlugin)Activator.CreateInstance(source.First());
					voidPlugin.VersionInfo = FileVersionInfo.GetVersionInfo(value2.Location);
					voidPlugin.ModHash = GetFileHash(value2.Location);
					voidPlugin.BepinPlugin = value2;
					CommandHandler.DiscoverCommands(assembly, name);
					CommandHandler.DiscoverPublicCommands(assembly, name);
					ModMessageHandler.DiscoverModMessages(assembly, value2);
					GUIMain.Instance.DiscoverGUIMenus(assembly, voidPlugin);
					ActiveVoidPlugins.Add(value2.Metadata.GUID, voidPlugin);
				}
				else
				{
					VoidPlugin voidPlugin;
					if (modOverrideDictionary.TryGetValue(gUID, out var value) || modOverrideDictionary.TryGetValue(name, out value))
					{
						voidPlugin = new DefaultVoidPlugin(value);
						BepinPlugin.Log.LogInfo((object)$"Discovered MPType override for {name}. Setting MPType to {value}");
					}
					else
					{
						voidPlugin = new DefaultVoidPlugin(MultiplayerType.Unspecified);
					}
					voidPlugin.VersionInfo = FileVersionInfo.GetVersionInfo(value2.Location);
					voidPlugin.ModHash = GetFileHash(value2.Location);
					voidPlugin.BepinPlugin = value2;
					GUIMain.Instance.DiscoverNonVManMod(voidPlugin);
					GeneratedVoidPlugins.Add(gUID, voidPlugin);
				}
			}
			BepinPlugin.Log.LogInfo((object)$"Loaded {CommandHandler.chatCommandCount} local command(s) and {CommandHandler.publicCommandCount} public command(s)");
			BepinPlugin.Log.LogInfo((object)$"Loaded {ModMessageHandler.modMessageHandlers.Count()} mod message(s)");
			BepinPlugin.Log.LogInfo((object)$"Discovered {ActiveVoidPlugins.Count} VoidManager plugin(s) from {ActiveBepinPlugins.Count - 1} mod(s)");
		}

		public static byte[] GetFileHash(string fileLocation)
		{
			using SHA256 sHA = SHA256.Create();
			return sHA.ComputeHash(File.ReadAllBytes(fileLocation));
		}
	}
	public abstract class VoidPlugin
	{
		internal FileVersionInfo VersionInfo;

		internal byte[] ModHash;

		internal PluginInfo BepinPlugin;

		public PluginInfo MyBepinPlugin => BepinPlugin;

		public virtual string Author => VersionInfo?.CompanyName;

		public virtual string Description => VersionInfo?.FileDescription;

		public virtual MultiplayerType MPType => MultiplayerType.Unspecified;
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "VoidManager";

		public const string PLUGIN_NAME = "VoidManager";

		public const string PLUGIN_VERSION = "1.0.7";
	}
}
namespace VoidManager.Utilities
{
	public class Game
	{
		public static ClientGame Instance => ClientGame.Current;

		public static bool InGame
		{
			get
			{
				if (!((Object)(object)Instance == (Object)null))
				{
					return true;
				}
				return false;
			}
		}

		public static List<Player> Players
		{
			get
			{
				if (!InGame)
				{
					return new List<Player>();
				}
				return ClientGame.Current.Players;
			}
		}

		public static Player LocalPlayer => GetPlayerFromID(PhotonNetwork.LocalPlayer.ActorNumber);

		public static int GetIDFromPlayer(Player player)
		{
			if ((Object)(object)player == (Object)null || (Object)(object)((MonoBehaviourPun)player).photonView == (Object)null || ((MonoBehaviourPun)player).photonView.Owner == null)
			{
				return -1;
			}
			return ((MonoBehaviourPun)player).photonView.Owner.ActorNumber;
		}

		public static Player GetPlayerFromID(int id)
		{
			if (!InGame)
			{
				return null;
			}
			return ClientGame.Current.GetPlayerCharacterByActorNumber(id);
		}

		public static Player GetPlayerByName(string playerName)
		{
			if (!InGame)
			{
				return null;
			}
			foreach (Player player in Players)
			{
				if (string.Equals(((AbstractCloneStarObject)player).DisplayName, playerName, StringComparison.CurrentCultureIgnoreCase))
				{
					return player;
				}
			}
			return null;
		}
	}
	public static class HarmonyHelpers
	{
		public enum CheckMode
		{
			ALWAYS,
			NONNULL,
			NEVER
		}

		public enum PatchMode
		{
			BEFORE,
			AFTER,
			REPLACE
		}

		public static IEnumerable<CodeInstruction> PatchBySequence(IEnumerable<CodeInstruction> instructions, IEnumerable<CodeInstruction> targetSequence, IEnumerable<CodeInstruction> patchSequence, PatchMode patchMode = PatchMode.AFTER, CheckMode checkMode = CheckMode.ALWAYS, bool showDebugOutput = false)
		{
			List<CodeInstruction> list = instructions.ToList();
			CodeInstruction val = targetSequence.ElementAt(0);
			int num = targetSequence.Count();
			for (int i = 0; i < list.Count; i++)
			{
				if (i + num <= list.Count)
				{
					bool flag = true;
					for (int j = 0; j < num && flag; j++)
					{
						flag = list[i + j].opcode.Equals(targetSequence.ElementAt(j).opcode);
						if (checkMode != CheckMode.NEVER)
						{
							flag = flag && (((list[i + j].operand == null || checkMode == CheckMode.NONNULL) && targetSequence.ElementAt(j).operand == null) || list[i + j].operand.Equals(targetSequence.ElementAt(j).operand));
						}
						if (showDebugOutput && flag)
						{
							BepinPlugin.Log.LogInfo((object)$"[Helper] Found {targetSequence.ElementAt(j).opcode} at {i + j}");
						}
					}
					if (!flag)
					{
						continue;
					}
					switch (patchMode)
					{
					case PatchMode.BEFORE:
					case PatchMode.AFTER:
					{
						int index = ((patchMode == PatchMode.AFTER) ? (i + num) : i);
						list.InsertRange(index, patchSequence.Select((CodeInstruction c) => c.FullClone()));
						break;
					}
					case PatchMode.REPLACE:
						list.RemoveRange(i, num);
						list.InsertRange(i, patchSequence.Select((CodeInstruction c) => c.FullClone()));
						break;
					default:
						throw new ArgumentException($"[Helper] Argument PatchMode patchMode == {patchMode}; invalid value!");
					}
					break;
				}
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("[Helper] Failed to patch by sequence: couldn't find target sequence.  This might be okay in certain cases.");
				stringBuilder.AppendLine("[Helper] Stack Trace:");
				string[] array = new StackTrace().ToString().Split(new string[3] { "\r\n", "\r", "\n" }, StringSplitOptions.None);
				for (int k = 0; k < 2; k++)
				{
					stringBuilder.AppendLine(array[k]);
				}
				BepinPlugin.Log.LogInfo((object)stringBuilder.ToString());
				break;
			}
			return list.AsEnumerable();
		}

		public static int FindSequence(IEnumerable<CodeInstruction> instructions, IEnumerable<CodeInstruction> targetSequence, CheckMode checkMode = CheckMode.ALWAYS, bool showDebugOutput = false)
		{
			List<CodeInstruction> list = instructions.ToList();
			CodeInstruction val = targetSequence.ElementAt(0);
			int num = targetSequence.Count();
			for (int i = 0; i < list.Count; i++)
			{
				if (i + num <= list.Count)
				{
					bool flag = true;
					for (int j = 0; j < num && flag; j++)
					{
						flag = list[i + j].opcode.Equals(targetSequence.ElementAt(j).opcode);
						if (checkMode != CheckMode.NEVER)
						{
							flag = flag && (((list[i + j].operand == null || checkMode == CheckMode.NONNULL) && targetSequence.ElementAt(j).operand == null) || list[i + j].operand.Equals(targetSequence.ElementAt(j).operand));
						}
						if (showDebugOutput && flag)
						{
							BepinPlugin.Log.LogInfo((object)$"Found {targetSequence.ElementAt(j).opcode} at {i + j}");
						}
					}
					if (flag)
					{
						return i + num;
					}
					continue;
				}
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("Couldn't find target sequence.  This might be okay in certain cases.");
				stringBuilder.AppendLine("Stack Trace:");
				string[] array = new StackTrace().ToString().Split(new string[3] { "\r\n", "\r", "\n" }, StringSplitOptions.None);
				for (int k = 0; k < 2; k++)
				{
					stringBuilder.AppendLine(array[k]);
				}
				BepinPlugin.Log.LogInfo((object)stringBuilder.ToString());
				break;
			}
			return -1;
		}

		public static void LogSequence(string label, IEnumerable sequence)
		{
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.AppendLine(label);
			foreach (object item in sequence)
			{
				stringBuilder.AppendLine("\t" + item.ToString());
			}
			BepinPlugin.Log.LogInfo((object)stringBuilder.ToString());
		}

		public static CodeInstruction FullClone(this CodeInstruction instruction)
		{
			CodeInstruction val = instruction.Clone();
			val.labels = instruction.labels.ConvertAll((Label l) => l);
			val.blocks = instruction.blocks.ConvertAll((ExceptionBlock b) => b.Clone());
			return val;
		}

		public static ExceptionBlock Clone(this ExceptionBlock block)
		{
			//IL_0001: 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)
			//IL_0012: Expected O, but got Unknown
			return new ExceptionBlock(block.blockType, block.catchType);
		}
	}
	public class Messaging
	{
		public static void Notification(string message)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			Assembly callingAssembly = Assembly.GetCallingAssembly();
			TextChat.Instance.AddLog(new Log(callingAssembly.FullName.Split(new char[1] { ',' })[0] ?? "", message));
		}

		public static void Echo(string message, bool local = true)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			if (local)
			{
				TextChat.Instance.AddLog(new Log("", message));
			}
			else
			{
				VivoxVoiceManager.Instance.SendTextMessage("[Mod Manager]: " + message, (ChannelId)(object)VivoxVoiceManager.Instance.TextChannel, (string)null, (string)null);
			}
		}

		public static void KickMessage(string title, string body, Player player)
		{
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Expected O, but got Unknown
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			if (PhotonNetwork.IsMasterClient)
			{
				BepinPlugin.Log.LogInfo((object)("Sending kick message to " + player.NickName + ": " + title + "::" + body));
				object[] obj = new object[2] { title, body };
				RaiseEventOptions val = new RaiseEventOptions();
				val.TargetActors = new int[1] { player.ActorNumber };
				PhotonNetwork.RaiseEvent((byte)97, (object)obj, val, SendOptions.SendUnreliable);
			}
			else
			{
				BepinPlugin.Log.LogWarning((object)"Cannot send kick message while not master client.");
			}
		}
	}
}
namespace VoidManager.MPModChecks
{
	internal class KickMessagePatches
	{
		[HarmonyPatch(typeof(GSPhotonDisconnected), "OnSceneLoaded")]
		private class KickedPatch
		{
			[HarmonyPostfix]
			private static void patch(Scene scene)
			{
				if (((Scene)(ref scene)).buildIndex == CloneStarConstants.MainMenuSceneIndex && KickTitle != null && KickMessage != null)
				{
					BepinPlugin.Log.LogInfo((object)("Pushing Kick Message via info screen. Title:" + KickTitle + " message:\n"));
					MenuScreenController.Instance.ShowMessagePopup(KickTitle, KickMessage);
					KickTitle = null;
					KickMessage = null;
				}
			}
		}

		internal static string KickTitle;

		internal static string KickMessage;
	}
	[HarmonyPatch(typeof(MatchmakingHandler), "ConvertRoom")]
	internal class ModdedRoomTagPatch
	{
		[HarmonyPostfix]
		private static void ModdedRoomPatch(RoomInfo pRoom, MatchmakingRoom __result)
		{
			if (((Dictionary<object, object>)(object)pRoom.CustomProperties).ContainsKey((object)"Mods"))
			{
				__result.RoomName = "<color=yellow>[M]</color> " + __result.RoomName;
			}
		}
	}
	[HarmonyPatch(typeof(MatchmakingList), "BindItem")]
	internal class ModdedRoomTagPatch2
	{
		[HarmonyPostfix]
		private static void RoomNameRichTextPatch(VisualElement item, MatchmakingRoom room)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			((TextElement)UQueryExtensions.Q(item, "RoomName", (string)null)).enableRichText = true;
		}
	}
	public class MPModCheckManager
	{
		internal static InRoomCallbacks RoomCallbacksClass;

		private MPModDataBlock[] MyModList;

		private MPModDataBlock[] MyMPUnspecifiedModList;

		private MPModDataBlock[] MyMPModList;

		private byte[] RoomProperties;

		internal Dictionary<Player, MPUserDataBlock> NetworkedPeersModLists = new Dictionary<Player, MPUserDataBlock>();

		public string LastModCheckFailReason;

		public MultiplayerType HighestLevelOfMPMods { get; private set; }

		public static MPModCheckManager Instance { get; internal set; }

		internal MPModCheckManager()
		{
			UpdateMyModList();
			BuildRoomProperties();
		}

		public byte[] GetRoomProperties()
		{
			return RoomProperties;
		}

		public void BuildRoomProperties()
		{
			RoomProperties = SerializeHashlessMPUserData();
		}

		public void UpdateLobbyProperties()
		{
			//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)
			//IL_004b: Expected O, but got Unknown
			//IL_0052: Expected O, but got Unknown
			if (PhotonNetwork.IsMasterClient)
			{
				Room currentRoom = PhotonNetwork.CurrentRoom;
				if (currentRoom == null)
				{
					BepinPlugin.Log.LogWarning((object)"Attempted to update lobby properties while room was null");
				}
				else if (((Dictionary<object, object>)(object)((RoomInfo)currentRoom).CustomProperties).ContainsKey((object)"Mods"))
				{
					Hashtable val = new Hashtable();
					((Dictionary<object, object>)val).Add((object)"Mods", (object)RoomProperties);
					currentRoom.SetCustomProperties(val, (Hashtable)null, (WebFlags)null);
				}
			}
		}

		private void UpdateHighestLevelOfMPMods(MultiplayerType MT)
		{
			if (HighestLevelOfMPMods == MultiplayerType.Hidden && MT != 0)
			{
				HighestLevelOfMPMods = MT;
				BepinPlugin.Log.LogInfo((object)("Incrementing HighestLevelOfMPMods to " + MT));
			}
			else if (HighestLevelOfMPMods == MultiplayerType.Client && (int)MT > 3)
			{
				HighestLevelOfMPMods = MT;
				BepinPlugin.Log.LogInfo((object)("Incrementing HighestLevelOfMPMods to " + MT));
			}
			else if (HighestLevelOfMPMods == MultiplayerType.Unspecified && (int)MT > 6)
			{
				HighestLevelOfMPMods = MultiplayerType.All;
				BepinPlugin.Log.LogInfo((object)"Incrementing HighestLevelOfMPMods to MPType.All");
			}
		}

		private void UpdateMyModList()
		{
			BepinPlugin.Log.LogInfo((object)"Building MyModList");
			Stopwatch stopwatch = new Stopwatch();
			stopwatch.Start();
			KeyValuePair<string, PluginInfo>[] array = Chainloader.PluginInfos.ToArray();
			MPModDataBlock[] array2 = new MPModDataBlock[array.Length];
			for (int i = 0; i < array.Length; i++)
			{
				PluginInfo value = array[i].Value;
				string gUID = value.Metadata.GUID;
				if (!(gUID == "VoidManager") && (PluginHandler.ActiveVoidPlugins.TryGetValue(gUID, out var value2) || PluginHandler.GeneratedVoidPlugins.TryGetValue(gUID, out value2)) && value2.MPType != 0)
				{
					array2[i] = new MPModDataBlock(gUID, value.Metadata.Name, value.Metadata.Version.ToString(), value2.MPType, string.Empty, value2.ModHash);
					UpdateHighestLevelOfMPMods(value2.MPType);
				}
			}
			array2 = (MyModList = array2.Where((MPModDataBlock mod) => mod != null).ToArray());
			MyMPModList = array2.Where((MPModDataBlock Mod) => Mod.MPType == MultiplayerType.All).ToArray();
			MyMPUnspecifiedModList = array2.Where((MPModDataBlock Mod) => Mod.MPType == MultiplayerType.Unspecified).ToArray();
			stopwatch.Stop();
			BepinPlugin.Log.LogInfo((object)("Finished Building MyModList, time elapsted: " + stopwatch.ElapsedMilliseconds + " ms"));
			BepinPlugin.Log.LogInfo((object)("MyModList:\n" + GetModListAsString(MyModList) + "\n"));
		}

		public byte[] SerializeHashlessMPUserData()
		{
			MemoryStream memoryStream = new MemoryStream();
			using (BinaryWriter binaryWriter = new BinaryWriter(memoryStream))
			{
				binaryWriter.Write("1.0.7");
				binaryWriter.Write(MyModList.Length);
				for (int i = 0; i < MyModList.Length; i++)
				{
					MPModDataBlock mPModDataBlock = MyModList[i];
					binaryWriter.Write(mPModDataBlock.ModName);
					binaryWriter.Write(mPModDataBlock.ModGUID);
					binaryWriter.Write(mPModDataBlock.Version);
					binaryWriter.Write((byte)mPModDataBlock.MPType);
					binaryWriter.Write(mPModDataBlock.DownloadID);
				}
			}
			return memoryStream.ToArray();
		}

		public static MPUserDataBlock DeserializeHashlessMPUserData(byte[] byteData)
		{
			MemoryStream memoryStream = new MemoryStream(byteData);
			memoryStream.Position = 0L;
			try
			{
				using BinaryReader binaryReader = new BinaryReader(memoryStream);
				string voidManagerVersion = binaryReader.ReadString();
				int num = binaryReader.ReadInt32();
				MPModDataBlock[] array = new MPModDataBlock[num];
				for (int i = 0; i < num; i++)
				{
					string modName = binaryReader.ReadString();
					string gUID = binaryReader.ReadString();
					string version = binaryReader.ReadString();
					MultiplayerType mPType = (MultiplayerType)binaryReader.ReadByte();
					string downloadID = binaryReader.ReadString();
					array[i] = new MPModDataBlock(gUID, modName, version, mPType, downloadID);
				}
				memoryStream.Dispose();
				return new MPUserDataBlock(voidManagerVersion, array);
			}
			catch (Exception ex)
			{
				BepinPlugin.Log.LogInfo((object)("Failed to read mod list from Hashless MPUserData, returning null.\n" + ex.Message));
				memoryStream.Dispose();
				return null;
			}
		}

		public byte[] SerializeHashfullMPUserData()
		{
			MemoryStream memoryStream = new MemoryStream();
			using (BinaryWriter binaryWriter = new BinaryWriter(memoryStream))
			{
				binaryWriter.Write("1.0.7");
				binaryWriter.Write(MyModList.Length);
				for (int i = 0; i < MyModList.Length; i++)
				{
					MPModDataBlock mPModDataBlock = MyModList[i];
					binaryWriter.Write(mPModDataBlock.ModName);
					binaryWriter.Write(mPModDataBlock.ModGUID);
					binaryWriter.Write(mPModDataBlock.Version);
					binaryWriter.Write((byte)mPModDataBlock.MPType);
					binaryWriter.Write(mPModDataBlock.DownloadID);
					binaryWriter.Write(mPModDataBlock.Hash);
				}
			}
			return memoryStream.ToArray();
		}

		public static MPUserDataBlock DeserializeHashfullMPUserData(byte[] byteData)
		{
			MemoryStream memoryStream = new MemoryStream(byteData);
			memoryStream.Position = 0L;
			try
			{
				using BinaryReader binaryReader = new BinaryReader(memoryStream);
				string voidManagerVersion = binaryReader.ReadString();
				int num = binaryReader.ReadInt32();
				MPModDataBlock[] array = new MPModDataBlock[num];
				for (int i = 0; i < num; i++)
				{
					string modName = binaryReader.ReadString();
					string gUID = binaryReader.ReadString();
					string version = binaryReader.ReadString();
					MultiplayerType mPType = (MultiplayerType)binaryReader.ReadByte();
					string downloadID = binaryReader.ReadString();
					byte[] hash = binaryReader.ReadBytes(32);
					array[i] = new MPModDataBlock(gUID, modName, version, mPType, downloadID, hash);
				}
				memoryStream.Dispose();
				return new MPUserDataBlock(voidManagerVersion, array);
			}
			catch (Exception ex)
			{
				BepinPlugin.Log.LogInfo((object)("Failed to read mod list from Hashfull MPUserData, returning null.\n" + ex.Message));
				memoryStream.Dispose();
				return null;
			}
		}

		public static string GetModListAsString(MPModDataBlock[] ModDatas)
		{
			string text = string.Empty;
			foreach (MPModDataBlock mPModDataBlock in ModDatas)
			{
				text = text + "\n - " + mPModDataBlock.ModName + " " + mPModDataBlock.Version;
			}
			return text;
		}

		internal MPUserDataBlock GetHostModList()
		{
			if (((Dictionary<object, object>)(object)((RoomInfo)PhotonNetwork.CurrentRoom).CustomProperties).ContainsKey((object)"Mods"))
			{
				try
				{
					return DeserializeHashlessMPUserData((byte[])((RoomInfo)PhotonNetwork.CurrentRoom).CustomProperties[(object)"Mods"]);
				}
				catch
				{
					BepinPlugin.Log.LogError((object)"Failed to Deserialize host mod list.");
				}
			}
			return null;
		}

		public MPUserDataBlock GetNetworkedPeerMods(Player Player)
		{
			if (NetworkedPeersModLists.TryGetValue(Player, out var value))
			{
				return value;
			}
			return null;
		}

		public bool NetworkedPeerHasMod(Player Player, string ModGUID)
		{
			MPUserDataBlock networkedPeerMods = GetNetworkedPeerMods(Player);
			if (networkedPeerMods != null)
			{
				MPModDataBlock[] modData = networkedPeerMods.ModData;
				foreach (MPModDataBlock mPModDataBlock in modData)
				{
					if (mPModDataBlock.ModGUID == ModGUID)
					{
						return true;
					}
				}
			}
			return false;
		}

		public List<Player> NetworkedPeersWithMod(string ModGUID)
		{
			List<Player> list = new List<Player>();
			foreach (KeyValuePair<Player, MPUserDataBlock> networkedPeersModList in NetworkedPeersModLists)
			{
				MPModDataBlock[] modData = networkedPeersModList.Value.ModData;
				foreach (MPModDataBlock mPModDataBlock in modData)
				{
					if (mPModDataBlock.ModGUID == ModGUID)
					{
						list.Add(networkedPeersModList.Key);
					}
				}
			}
			return list;
		}

		public void AddNetworkedPeerMods(Player Player, MPUserDataBlock modList)
		{
			BepinPlugin.Log.LogMessage((object)("recieved modlist from user '" + Player.NickName + "' with the following info:\nVoidManager Version: " + modList.VMVersion + "\nModList:\n" + GetModListAsString(modList.ModData) + "\n"));
			if (NetworkedPeersModLists.ContainsKey(Player))
			{
				NetworkedPeersModLists[Player] = modList;
				return;
			}
			NetworkedPeersModLists.Add(Player, modList);
			Events.Instance.OnClientModlistRecieved(Player);
		}

		public void RemoveNetworkedPeerMods(Player Player)
		{
			NetworkedPeersModLists.Remove(Player);
		}

		internal void ClearAllNetworkedPeerMods()
		{
			NetworkedPeersModLists.Clear();
		}

		public bool GetNetworkedPeerModlistExists(Player Player)
		{
			return NetworkedPeersModLists.ContainsKey(Player);
		}

		private static MPUserDataBlock GetHostModList(RoomInfo room)
		{
			if (((Dictionary<object, object>)(object)room.CustomProperties).ContainsKey((object)"modList"))
			{
				try
				{
					return DeserializeHashlessMPUserData((byte[])room.CustomProperties[(object)"modList"]);
				}
				catch
				{
					BepinPlugin.Log.LogError((object)"Failed to Deserialize host mod list. Could be an older version of VoidManager");
				}
			}
			return new MPUserDataBlock();
		}

		internal void SendModlistToClient(Player Player)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Expected O, but got Unknown
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			if (!Player.IsLocal)
			{
				object[] obj = new object[2]
				{
					false,
					SerializeHashlessMPUserData()
				};
				RaiseEventOptions val = new RaiseEventOptions();
				val.TargetActors = new int[1] { Player.ActorNumber };
				PhotonNetwork.RaiseEvent((byte)99, (object)obj, val, SendOptions.SendReliable);
			}
		}

		internal void SendModlistToHost()
		{
			//IL_0022: 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_0029: 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_0038: Expected O, but got Unknown
			if (!PhotonNetwork.IsMasterClient)
			{
				PhotonNetwork.RaiseEvent((byte)99, (object)new object[2]
				{
					true,
					SerializeHashfullMPUserData()
				}, new RaiseEventOptions
				{
					Receivers = (ReceiverGroup)2
				}, SendOptions.SendReliable);
			}
		}

		internal void SendModListToOthers()
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			BepinPlugin.Log.LogMessage((object)"sending others");
			PhotonNetwork.RaiseEvent((byte)99, (object)new object[2]
			{
				false,
				SerializeHashlessMPUserData()
			}, (RaiseEventOptions)null, SendOptions.SendReliable);
		}

		internal void PlayerJoined(Player JoiningPlayer)
		{
			if (PhotonNetwork.IsMasterClient)
			{
				((MonoBehaviour)PunSingleton<PhotonService>.Instance).StartCoroutine(PlayerJoinedChecks(JoiningPlayer));
			}
			else
			{
				Instance.SendModlistToClient(JoiningPlayer);
			}
		}

		public static IEnumerator PlayerJoinedChecks(Player JoiningPlayer)
		{
			for (int i = 0; i < 50; i++)
			{
				yield return (object)new WaitForSeconds(0.2f);
				if (Instance.GetNetworkedPeerModlistExists(JoiningPlayer))
				{
					Instance.ModChecksHostOnClientJoin(JoiningPlayer);
					yield break;
				}
			}
			if (Instance.HighestLevelOfMPMods == MultiplayerType.All)
			{
				BepinPlugin.Log.LogMessage((object)("Kicked player " + JoiningPlayer.NickName + " for not having mods."));
				Messaging.Echo("Kicked player " + JoiningPlayer.NickName + " for not having mods.", local: false);
				PhotonNetwork.CloseConnection(JoiningPlayer);
			}
			Events.Instance.CallHostOnClientVerified(JoiningPlayer);
		}

		internal bool ModChecksClientside(Hashtable RoomProperties, bool inRoom = true)
		{
			LastModCheckFailReason = string.Empty;
			BepinPlugin.Log.LogMessage((object)string.Format("Starting Clientside mod checks for room: {0}", RoomProperties[(object)"R_Na"]));
			if (!((Dictionary<object, object>)(object)RoomProperties).ContainsKey((object)"Mods"))
			{
				if (HighestLevelOfMPMods == MultiplayerType.All)
				{
					LastModCheckFailReason = "Host has no mods, but client has MPType.All mods." + GetModListAsString(MyMPModList);
					KickMessagePatches.KickTitle = "Disconnected: Incompatable mod list";
					KickMessagePatches.KickMessage = LastModCheckFailReason;
					BepinPlugin.Log.LogMessage((object)("Mod check failed.\n" + LastModCheckFailReason));
					return false;
				}
				if ((int)HighestLevelOfMPMods >= 6)
				{
					LastModCheckFailReason = "Host has no mods, but client has MPType.Unspecified mods." + GetModListAsString(MyMPUnspecifiedModList);
					KickMessagePatches.KickTitle = "Disconnected: Incompatable mod list";
					KickMessagePatches.KickMessage = LastModCheckFailReason;
					BepinPlugin.Log.LogMessage((object)("Mod check failed.\n" + LastModCheckFailReason));
					return false;
				}
				BepinPlugin.Log.LogMessage((object)"Clientside mod check passed.");
				return true;
			}
			MPUserDataBlock mPUserDataBlock = DeserializeHashlessMPUserData((byte[])RoomProperties[(object)"Mods"]);
			MPModDataBlock[] array = mPUserDataBlock.ModData.Where((MPModDataBlock Mod) => Mod.MPType == MultiplayerType.All).ToArray();
			BepinPlugin.Log.LogMessage((object)("Void Manager versions - Host: " + mPUserDataBlock.VMVersion + " Client: 1.0.7"));
			List<string> list = new List<string>();
			List<string> list2 = new List<string>();
			List<string> list3 = new List<string>();
			for (int i = 0; i < MyMPModList.Length; i++)
			{
				MPModDataBlock mPModDataBlock = MyMPModList[i];
				bool flag = false;
				for (int j = 0; j < array.Length; j++)
				{
					if (mPModDataBlock.ModGUID == array[j].ModGUID)
					{
						MPModDataBlock mPModDataBlock2 = array[j];
						flag = true;
						if (mPModDataBlock.Version != mPModDataBlock2.Version)
						{
							list.Add("Client:" + mPModDataBlock.ModName + "-" + mPModDataBlock.Version + ", Host:" + mPModDataBlock2.Version);
							BepinPlugin.Log.LogMessage((object)("Mismatched mod version - " + list.Last() + ". " + ((mPModDataBlock2.DownloadID != string.Empty) ? ("Download Link: " + mPModDataBlock2.DownloadID) : "")));
						}
						break;
					}
				}
				if (!flag)
				{
					list3.Add(mPModDataBlock.ModName);
					BepinPlugin.Log.LogMessage((object)("Host is missing the required mod '" + mPModDataBlock.ModName + "'"));
				}
			}
			foreach (MPModDataBlock mPModDataBlock2 in array)
			{
				bool flag2 = false;
				for (int j = 0; j < MyMPModList.Length; j++)
				{
					if (mPModDataBlock2.ModGUID == MyMPModList[j].ModGUID)
					{
						flag2 = true;
						break;
					}
				}
				if (!flag2)
				{
					list2.Add(mPModDataBlock2.ModName);
					BepinPlugin.Log.LogMessage((object)("Client is missing the required mod '" + mPModDataBlock2.ModName + "'"));
				}
			}
			string text = string.Empty;
			if (list.Count > 0)
			{
				text += "The following mods have mismatched versions:\n";
				foreach (string item in list)
				{
					text = text + item + "\n";
				}
			}
			if (list2.Count > 0)
			{
				text += "The following mods are required to join the session:\n";
				foreach (string item2 in list2)
				{
					text = text + item2 + "\n";
				}
			}
			if (list3.Count > 0)
			{
				text += "The following mods must be uninstalled to join the session:";
				foreach (string item3 in list3)
				{
					text = text + "\n" + item3;
				}
			}
			if (text != string.Empty)
			{
				if (inRoom)
				{
					KickMessagePatches.KickTitle = "Disconnected: Incompatable mod list";
					KickMessagePatches.KickMessage = text;
				}
				else
				{
					LastModCheckFailReason = text;
				}
				BepinPlugin.Log.LogMessage((object)("Couldn't join session.\n" + text));
				return false;
			}
			BepinPlugin.Log.LogMessage((object)"Clientside mod check passed.");
			return true;
		}

		internal void ModChecksHostOnClientJoin(Player joiningPlayer)
		{
			MPUserDataBlock networkedPeerMods = GetNetworkedPeerMods(joiningPlayer);
			MPModDataBlock[] array = networkedPeerMods.ModData.Where((MPModDataBlock Mod) => Mod.MPType == MultiplayerType.All).ToArray();
			if (!BepinPlugin.Bindings.TrustMPTypeUnspecified.Value)
			{
				MPModDataBlock[] second = networkedPeerMods.ModData.Where((MPModDataBlock Mod) => Mod.MPType == MultiplayerType.Unspecified).ToArray();
				array = array.Concat(second).ToArray();
				MPModDataBlock[] array2 = MyModList.Concat(MyMPUnspecifiedModList).ToArray();
			}
			else
			{
				MPModDataBlock[] array2 = MyModList;
			}
			List<string> list = new List<string>();
			List<string> list2 = new List<string>();
			List<string> list3 = new List<string>();
			for (int i = 0; i < MyMPModList.Length; i++)
			{
				MPModDataBlock mPModDataBlock = MyMPModList[i];
				bool flag = false;
				for (int j = 0; j < array.Length; j++)
				{
					if (mPModDataBlock.ModGUID == array[j].ModGUID)
					{
						MPModDataBlock mPModDataBlock2 = array[j];
						flag = true;
						if (mPModDataBlock.Version != mPModDataBlock2.Version)
						{
							list.Add("Client:" + mPModDataBlock.ModName + "-" + mPModDataBlock.Version + ", Host:" + mPModDataBlock2.Version);
							BepinPlugin.Log.LogMessage((object)("Mismatched mod version - " + list.Last() + ". " + ((mPModDataBlock.DownloadID != string.Empty) ? ("Download Link: " + mPModDataBlock.DownloadID) : "")));
						}
						else if (Encoding.ASCII.GetString(mPModDataBlock.Hash) != Encoding.ASCII.GetString(mPModDataBlock2.Hash))
						{
							list.Add("Client:" + mPModDataBlock.ModName + "-" + mPModDataBlock.Version + ", Host: " + mPModDataBlock2.Version);
							BepinPlugin.Log.LogMessage((object)("Mismatched mod hash - " + list.Last() + " - LocalHash: " + Encoding.ASCII.GetString(mPModDataBlock.Hash) + " IncomingHash: " + Encoding.ASCII.GetString(mPModDataBlock2.Hash) + ". " + ((mPModDataBlock.DownloadID != string.Empty) ? ("Download Link: " + mPModDataBlock.DownloadID) : "")));
						}
						break;
					}
				}
				if (!flag)
				{
					list2.Add(mPModDataBlock.ModName);
					BepinPlugin.Log.LogMessage((object)("Client is missing the required mod '" + mPModDataBlock.ModName + "'"));
				}
			}
			foreach (MPModDataBlock mPModDataBlock2 in array)
			{
				bool flag2 = false;
				for (int j = 0; j < MyMPModList.Length; j++)
				{
					if (mPModDataBlock2.ModGUID == MyMPModList[j].ModGUID)
					{
						flag2 = true;
						break;
					}
				}
				if (!flag2)
				{
					list3.Add(mPModDataBlock2.ModName);
					BepinPlugin.Log.LogMessage((object)("Client must uninstall the " + mPModDataBlock2.MPType.ToString() + " Mod '" + mPModDataBlock2.ModName + "'"));
				}
			}
			string text = string.Empty;
			if (list.Count > 0)
			{
				text += "The following mods have mismatched versions:\n";
				foreach (string item in list)
				{
					text = text + item + "\n";
				}
			}
			if (list2.Count > 0)
			{
				text += "The following mods are required to join the session:\n";
				foreach (string item2 in list2)
				{
					text = text + item2 + "\n";
				}
			}
			if (list3.Count > 0)
			{
				text += "The following mods must be uninstalled to join the session:";
				foreach (string item3 in list3)
				{
					text = text + "\n" + item3;
				}
			}
			if (text != string.Empty)
			{
				Messaging.Echo("Kicking player " + joiningPlayer.NickName + " from session for incompatable mods.", local: false);
				Messaging.KickMessage("Kicked: Incompatable mod list", text, joiningPlayer);
				PhotonNetwork.CloseConnection(joiningPlayer);
				BepinPlugin.Log.LogMessage((object)("Kicked player " + joiningPlayer.NickName + " from session for incompatable mods.\n" + text));
			}
			else
			{
				BepinPlugin.Log.LogMessage((object)("Hostside mod check passed for player " + joiningPlayer.NickName));
				Events.Instance.CallHostOnClientVerified(joiningPlayer);
			}
		}
	}
	public class MPModDataBlock
	{
		public string ModGUID { get; }

		public string ModName { get; }

		public string Version { get; }

		public MultiplayerType MPType { get; }

		public byte[] Hash { get; }

		public string DownloadID { get; }

		public MPModDataBlock(string GUID, string ModName, string Version, MultiplayerType MPType, string DownloadID, byte[] Hash)
		{
			ModGUID = GUID;
			this.ModName = ModName;
			this.Version = Version;
			this.MPType = MPType;
			this.Hash = Hash;
			this.DownloadID = DownloadID;
		}

		public MPModDataBlock(string GUID, string ModName, string Version, MultiplayerType MPType, string DownloadID)
		{
			ModGUID = GUID;
			this.ModName = ModName;
			this.Version = Version;
			this.MPType = MPType;
			Hash = new byte[32];
			this.DownloadID = DownloadID;
		}
	}
	public class MPUserDataBlock
	{
		public string VMVersion { get; }

		public MPModDataBlock[] ModData { get; }

		public MPUserDataBlock(string VoidManagerVersion, MPModDataBlock[] ModData)
		{
			VMVersion = VoidManagerVersion;
			this.ModData = ModData;
		}

		public MPUserDataBlock()
		{
			VMVersion = string.Empty;
			ModData = null;
		}
	}
	public enum MultiplayerType : byte
	{
		Hidden = 0,
		Client = 3,
		Unspecified = 6,
		All = 10
	}
	[HarmonyPatch(typeof(MatchmakingTerminal), "JoinRequested")]
	internal class OnJoinCheckModsPatch
	{
		private static bool Prefix(FailPopup ___failPopup, MatchmakingList ___matchList)
		{
			LobbyCallbacks instance = LobbyCallbacks.Instance;
			if (instance == null || (Object)(object)instance.ActiveTerminal == (Object)null || instance.RoomList == null)
			{
				if ((Object)(object)instance.ActiveTerminal == (Object)null)
				{
					BepinPlugin.Log.LogInfo((object)"Terminal");
				}
				if (instance.RoomList == null)
				{
					BepinPlugin.Log.LogInfo((object)"Roomlist");
				}
				BepinPlugin.Log.LogInfo((object)"Attempted to join room, VoidManager LobbyCallbacks instance, Active Terminal, or RoomList not found");
				___failPopup.Show("VoidManager could not find the room. Please wait a moment then try again. Could also be bugged.");
				return false;
			}
			foreach (RoomInfo room in instance.RoomList)
			{
				if (room.Name == ___matchList.GetSelectedRoom().RoomId)
				{
					if (!MPModCheckManager.Instance.ModChecksClientside(room.CustomProperties, inRoom: false))
					{
						___failPopup.Show("VoidManager blocked connection, Modlists incompatable.\n" + MPModCheckManager.Instance.LastModCheckFailReason);
						return false;
					}
					return true;
				}
			}
			BepinPlugin.Log.LogInfo((object)"Attempted to join room, VoidManager could not find the room.");
			___failPopup.Show("VoidManager could not find the room. Please wait a moment then try again. Could also be bugged.");
			return false;
		}
	}
	[HarmonyPatch(typeof(PhotonService), "PhotonCreateRoom")]
	internal class RoomInfoPatch
	{
		private static RoomOptions PatchMethod(RoomOptions RoomOptions)
		{
			((Dictionary<object, object>)(object)RoomOptions.CustomRoomProperties).Add((object)"Mods", (object)MPModCheckManager.Instance.GetRoomProperties());
			int num = RoomOptions.CustomRoomPropertiesForLobby.Length;
			string[] array = new string[num + 1];
			int i;
			for (i = 0; i < num; i++)
			{
				array[i] = RoomOptions.CustomRoomPropertiesForLobby[i];
			}
			array[i] = "Mods";
			RoomOptions.CustomRoomPropertiesForLobby = array;
			return RoomOptions;
		}

		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> RoomPropertiesPatch(IEnumerable<CodeInstruction> instructions)
		{
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Expected O, but got Unknown
			List<CodeInstruction> list = instructions.ToList();
			int count = list.Count;
			for (int num = count - 1; num >= 0; num--)
			{
				if (list[num].opcode == OpCodes.Call)
				{
					if ((MethodInfo)list[num].operand == AccessTools.Method(typeof(PhotonNetwork), "CreateRoom", (Type[])null, (Type[])null))
					{
						list.Insert(num - 3, new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(RoomInfoPatch), "PatchMethod", (Type[])null, (Type[])null)));
					}
					else
					{
						BepinPlugin.Log.LogError((object)("Failed to patch PhotonService.PhotonCreateRoom. Targeted method appears to have changed. Index: " + num));
					}
					break;
				}
			}
			return list.AsEnumerable();
		}
	}
}
namespace VoidManager.ModMessages
{
	public abstract class ModMessage
	{
		public string GetIdentifier()
		{
			return GetType().Namespace + "." + GetType().Name;
		}

		public static string GetIdentifier(Type ModMessageType)
		{
			return ModMessageType.Namespace + "." + ModMessageType.Name;
		}

		public static void Send(string pluginGUID, string handlerIdentifier, Player player, object[] arguments, bool reliable = false)
		{
			Send(pluginGUID, handlerIdentifier, (Player[])(object)new Player[1] { player }, arguments, reliable);
		}

		public static void Send(string pluginGUID, string handlerIdentifier, Player[] players, object[] arguments, bool reliable = false)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			object[] first = new object[2] { pluginGUID, handlerIdentifier };
			first = first.Concat(arguments).ToArray();
			RaiseEventOptions val = new RaiseEventOptions();
			val.TargetActors = players.Select((Player player) => player.ActorNumber).ToArray();
			PhotonNetwork.RaiseEvent((byte)98, (object)first, val, reliable ? SendOptions.SendReliable : SendOptions.SendUnreliable);
		}

		public static void Send(string pluginGUID, string handlerIdentifier, ReceiverGroup recieverGroup, object[] arguments, bool reliable = false)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			//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)
			//IL_0038: 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)
			object[] first = new object[2] { pluginGUID, handlerIdentifier };
			first = first.Concat(arguments).ToArray();
			RaiseEventOptions val = new RaiseEventOptions();
			val.Receivers = recieverGroup;
			PhotonNetwork.RaiseEvent((byte)98, (object)first, val, reliable ? SendOptions.SendReliable : SendOptions.SendUnreliable);
		}

		public abstract void Handle(object[] arguments, Player sender);
	}
	public class ModMessageHandler
	{
		public static Dictionary<string, ModMessage> modMessageHandlers = new Dictionary<string, ModMessage>();

		public static void DiscoverModMessages(Assembly assembly, PluginInfo bepinPlugin)
		{
			Type[] types = assembly.GetTypes();
			IEnumerable<Type> enumerable = types.Where((Type t) => typeof(ModMessage).IsAssignableFrom(t) && !t.IsInterface && !t.IsAbstract);
			int num = 0;
			foreach (Type item in enumerable)
			{
				ModMessage modMessage = (ModMessage)Activator.CreateInstance(item);
				modMessageHandlers.Add(bepinPlugin.Metadata.GUID + "#" + modMessage.GetIdentifier(), modMessage);
				num++;
			}
			if (num != 0)
			{
				BepinPlugin.Log.LogInfo((object)$"[{bepinPlugin.Metadata.Name}] Detected {num} mod messages");
			}
		}
	}
}
namespace VoidManager.CustomGUI
{
	internal class GUIMain : MonoBehaviour, IShowCursorSource, IInputActionMapRequest
	{
		private GameObject Background;

		private GameObject MMCanvas;

		private Image Image;

		public bool GUIActive;

		private Rect Window;

		private byte Tab;

		private List<VoidPlugin> mods = new List<VoidPlugin>();

		private VoidPlugin selectedMod;

		private List<VoidPlugin> NonVManMods = new List<VoidPlugin>();

		private Rect ModListArea;

		private Vector2 ModListScroll = Vector2.zero;

		private Rect ModInfoArea;

		private Vector2 ModInfoScroll = Vector2.zero;

		private Rect PlayerListArea;

		private Vector2 PlayerListScroll = Vector2.zero;

		private Player selectedPlayer;

		private Rect PlayerModInfoArea;

		private Vector2 PlayerModInfoScroll = Vector2.zero;

		private Rect ModSettingsArea;

		private Vector2 ModSettingsScroll = Vector2.zero;

		private List<ModSettingsMenu> settings = new List<ModSettingsMenu>();

		private ushort selectedSettings = ushort.MaxValue;

		internal static GUISkin _cachedSkin;

		private static readonly Color32 _classicMenuBackground = new Color32((byte)32, (byte)32, (byte)32, byte.MaxValue);

		private static readonly Color32 _classicButtonBackground = new Color32((byte)40, (byte)40, (byte)40, byte.MaxValue);

		private static readonly Color32 _hoverButtonFromMenu = new Color32((byte)18, (byte)79, (byte)179, byte.MaxValue);

		private bool ShowingCursor;

		public static GUIMain Instance { get; internal set; }

		internal void updateWindowSize()
		{
			//IL_0073: 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_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			float value = BepinPlugin.Bindings.MenuHeight.Value;
			float value2 = BepinPlugin.Bindings.MenuWidth.Value;
			float value3 = BepinPlugin.Bindings.MenuListWidth.Value;
			float value4 = BepinPlugin.Bindings.PlayerListWidth.Value;
			Window = new Rect((float)Screen.width * 0.5f - (float)Screen.width * value2 / 2f, (float)Screen.height * 0.5f - (float)Screen.height * value / 2f, (float)Screen.width * value2, (float)Screen.height * value);
			ModListArea = new Rect(6f, 43f, ((Rect)(ref Window)).width * value3, (float)Screen.height * value - 45f);
			ModInfoArea = new Rect(((Rect)(ref ModListArea)).width + 15f, 43f, (float)Screen.width * value2 - (((Rect)(ref ModListArea)).width + 11f) - 10f, (float)Screen.height * value - 45f);
			PlayerListArea = new Rect(6f, 43f, ((Rect)(ref Window)).width * value4, (float)Screen.height * value - 45f);
			PlayerModInfoArea = new Rect(((Rect)(ref PlayerListArea)).width + 15f, 43f, (float)Screen.width * value2 - (((Rect)(ref PlayerListArea)).width + 11f) - 10f, (float)Screen.height * value - 45f);
			ModSettingsArea = new Rect(6f, 43f, (float)Screen.width * value2 - 12f, (float)Screen.height * value - 45f);
		}

		internal GUIMain()
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: 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_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: 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_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Expected O, but got Unknown
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Expected O, but got Unknown
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			Instance = this;
			MMCanvas = new GameObject("ModManagerCanvas", new Type[1] { typeof(Canvas) });
			Canvas component = MMCanvas.GetComponent<Canvas>();
			component.renderMode = (RenderMode)0;
			component.sortingOrder = 1000;
			((Component)component).transform.SetAsLastSibling();
			Object.DontDestroyOnLoad((Object)(object)MMCanvas);
			updateWindowSize();
			settings.Add(new VManSettings());
			Background = new GameObject("GUIMainBG", new Type[1] { typeof(GraphicRaycaster) });
			Image = Background.AddComponent<Image>();
			((Graphic)Image).color = Color.clear;
			Background.transform.SetParent(MMCanvas.transform);
			Background.SetActive(false);
		}

		private void Awake()
		{
			Application.SetStackTraceLogType((LogType)3, (StackTraceLogType)0);
			Application.SetStackTraceLogType((LogType)2, (StackTraceLogType)0);
		}

		private void Update()
		{
			if (((KeyboardShortcut)(ref BepinPlugin.Bindings.OpenMenu)).IsDown())
			{
				GUIActive = !GUIActive;
				if (GUIActive)
				{
					GUIOpen();
				}
				else
				{
					GUIClose();
				}
			}
		}

		private void GUIOpen()
		{
			if (selectedSettings != ushort.MaxValue)
			{
				settings[selectedSettings].OnOpen();
			}
			GUIToggleCursor(enable: true);
			Background.SetActive(true);
		}

		private void GUIClose()
		{
			if (selectedSettings != ushort.MaxValue)
			{
				settings[selectedSettings].OnClose();
			}
			GUIToggleCursor(enable: false);
			Background.SetActive(false);
		}

		private void OnGUI()
		{
			//IL_001d: 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_0038: Expected O, but got Unknown
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: 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)
			if (GUIActive)
			{
				GUI.skin = ChangeSkin();
				Window = GUI.Window(999910, Window, new WindowFunction(WindowFunction), "ModManager");
				((Transform)((Graphic)Image).rectTransform).position = new Vector3(((Rect)(ref Window)).center.x, ((Rect)(ref Window)).center.y * -1f + (float)Screen.height, 0f);
				((Graphic)Image).rectTransform.sizeDelta = ((Rect)(ref Window)).size;
			}
		}

		private void WindowFunction(int WindowID)
		{
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_033b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0346: Unknown result type (might be due to invalid IL or missing references)
			//IL_0352: Unknown result type (might be due to invalid IL or missing references)
			//IL_035c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0361: Unknown result type (might be due to invalid IL or missing references)
			//IL_0434: Unknown result type (might be due to invalid IL or missing references)
			//IL_0440: Unknown result type (might be due to invalid IL or missing references)
			//IL_044a: Unknown result type (might be due to invalid IL or missing references)
			//IL_044f: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_04b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_04bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			if (GUILayout.Button("Mod Info", Array.Empty<GUILayoutOption>()))
			{
				Tab = 0;
			}
			if (GUILayout.Button("Mod Settings", Array.Empty<GUILayoutOption>()))
			{
				Tab = 1;
			}
			if (GUILayout.Button("Player List", Array.Empty<GUILayoutOption>()))
			{
				Tab = 2;
			}
			GUILayout.EndHorizontal();
			switch (Tab)
			{
			case 0:
				GUILayout.BeginArea(ModListArea);
				ModListScroll = GUILayout.BeginScrollView(ModListScroll, Array.Empty<GUILayoutOption>());
				if (GUILayout.Button("VoidManager", Array.Empty<GUILayoutOption>()))
				{
					selectedMod = null;
				}
				foreach (VoidPlugin mod in mods)
				{
					DrawModButton(mod);
				}
				GUI.skin.label.alignment = (TextAnchor)4;
				GUILayout.Label("<color=yellow>Non-VoidManager Mods</color>", Array.Empty<GUILayoutOption>());
				foreach (VoidPlugin nonVManMod in NonVManMods)
				{
					DrawModButton(nonVManMod);
				}
				GUILayout.Label("Overall MPType: " + GetColoredMPTypeText(MPModCheckManager.Instance.HighestLevelOfMPMods), Array.Empty<GUILayoutOption>());
				GUILayout.EndScrollView();
				GUILayout.EndArea();
				GUI.skin.label.alignment = BepinPlugin.Bindings.ModInfoTextAnchor.Value;
				GUILayout.BeginArea(ModInfoArea);
				ModInfoScroll = GUILayout.BeginScrollView(ModInfoScroll, Array.Empty<GUILayoutOption>());
				if (selectedMod != null)
				{
					BepInPlugin metadata = selectedMod.BepinPlugin.Metadata;
					GUILayout.Label("Author: " + selectedMod.Author, Array.Empty<GUILayoutOption>());
					GUILayout.Label("Name: " + metadata.Name, Array.Empty<GUILayoutOption>());
					GUILayout.Label($"Version: {metadata.Version}", Array.Empty<GUILayoutOption>());
					if (selectedMod.Description != string.Empty)
					{
						GUILayout.Label("Description: " + selectedMod.Description, Array.Empty<GUILayoutOption>());
					}
					GUILayout.Label("MPRequirement: " + GetTextForMPType(selectedMod.MPType), Array.Empty<GUILayoutOption>());
				}
				else
				{
					GUI.skin.label.alignment = (TextAnchor)4;
					GUILayout.Label("VoidManager - BepInEx Plugin Manager for Void Crew.", Array.Empty<GUILayoutOption>());
					GUILayout.Label("Provides APIs to developers and multiplayer mod management.", Array.Empty<GUILayoutOption>());
					GUILayout.Label("Version: 1.0.7", Array.Empty<GUILayoutOption>());
					GUILayout.Label("\n\nDeveloped by Mest and Dragon", Array.Empty<GUILayoutOption>());
					GUILayout.Label("Based on the 'Pulsar Mod Loader' developed by Tom Ritcher", Array.Empty<GUILayoutOption>());
					GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
					GUILayout.FlexibleSpace();
					if (GUILayout.Button("Github", Array.Empty<GUILayoutOption>()))
					{
						Application.OpenURL("https://github.com/Void-Crew-Modding-Team/VoidManager");
					}
					if (GUILayout.Button("Discord", Array.Empty<GUILayoutOption>()))
					{
						Application.OpenURL("https://discord.gg/4QhRRBWsJz");
					}
					GUILayout.FlexibleSpace();
					GUILayout.EndHorizontal();
				}
				GUILayout.EndScrollView();
				GUILayout.EndArea();
				break;
			case 1:
				GUI.skin.label.alignment = BepinPlugin.Bindings.ModInfoTextAnchor.Value;
				GUILayout.BeginArea(ModSettingsArea);
				ModSettingsScroll = GUILayout.BeginScrollView(ModSettingsScroll, Array.Empty<GUILayoutOption>());
				if (selectedSettings == ushort.MaxValue)
				{
					for (ushort num = 0; num < settings.Count; num++)
					{
						if (GUILayout.Button(settings[num].Name(), Array.Empty<GUILayoutOption>()))
						{
							settings[num].OnOpen();
							selectedSettings = num;
							break;
						}
					}
				}
				else if (GUILayout.Button("Back", Array.Empty<GUILayoutOption>()))
				{
					settings[selectedSettings].OnClose();
					selectedSettings = ushort.MaxValue;
				}
				else
				{
					settings[selectedSettings].Draw();
				}
				GUILayout.EndScrollView();
				GUILayout.EndArea();
				break;
			case 2:
			{
				GUI.skin.label.alignment = (TextAnchor)3;
				GUILayout.BeginArea(PlayerListArea);
				PlayerListScroll = GUILayout.BeginScrollView(PlayerListScroll, Array.Empty<GUILayoutOption>());
				Player[] playerList = PhotonNetwork.PlayerList;
				foreach (Player val in playerList)
				{
					if (!val.IsLocal && GUILayout.Button(val.NickName, Array.Empty<GUILayoutOption>()))
					{
						selectedPlayer = val;
					}
				}
				GUILayout.EndScrollView();
				GUILayout.EndArea();
				GUILayout.BeginArea(PlayerModInfoArea);
				PlayerModInfoScroll = GUILayout.BeginScrollView(PlayerModInfoScroll, Array.Empty<GUILayoutOption>());
				if (selectedPlayer != null)
				{
					GUILayout.Label("Player: " + selectedPlayer.NickName + " " + (selectedPlayer.IsMasterClient ? "(Host)" : string.Empty), Array.Empty<GUILayoutOption>());
					DrawPlayerModList(selectedPlayer);
				}
				GUILayout.EndScrollView();
				GUILayout.EndArea();
				break;
			}
			}
			GUI.DragWindow();
		}

		private GUISkin ChangeSkin()
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0203: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0395: Unknown result type (might be due to invalid IL or missing references)
			//IL_039a: Unknown result type (might be due to invalid IL or missing references)
			//IL_039f: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_03bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_03cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_03de: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0400: Unknown result type (might be due to invalid IL or missing references)
			//IL_0405: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_0506: Unknown result type (might be due to invalid IL or missing references)
			//IL_0507: Unknown result type (might be due to invalid IL or missing references)
			//IL_0520: Unknown result type (might be due to invalid IL or missing references)
			//IL_0521: Unknown result type (might be due to invalid IL or missing references)
			if (_cachedSkin == null || _cachedSkin.window.active.background == null)
			{
				_cachedSkin = GUI.skin;
				Texture2D val = BuildTexFrom1Color(Color32.op_Implicit(_classicMenuBackground));
				_cachedSkin.window.active.background = val;
				_cachedSkin.window.onActive.background = val;
				_cachedSkin.window.focused.background = val;
				_cachedSkin.window.onFocused.background = val;
				_cachedSkin.window.hover.background = val;
				_cachedSkin.window.onHover.background = val;
				_cachedSkin.window.normal.background = val;
				_cachedSkin.window.onNormal.background = val;
				_cachedSkin.window.hover.textColor = Color.white;
				_cachedSkin.window.onHover.textColor = Color.white;
				Color32 val2 = default(Color32);
				((Color32)(ref val2))..ctor(byte.MaxValue, byte.MaxValue, (byte)0, byte.MaxValue);
				Texture2D val3 = BuildTexFrom1Color(Color32.op_Implicit(_classicButtonBackground));
				Texture2D val4 = BuildTexFrom1Color(Color32.op_Implicit(val2));
				_cachedSkin.button.active.background = val3;
				_cachedSkin.button.onActive.background = val3;
				_cachedSkin.button.focused.background = val3;
				_cachedSkin.button.onFocused.background = val3;
				_cachedSkin.button.hover.background = val4;
				_cachedSkin.button.onHover.background = val4;
				_cachedSkin.button.normal.background = val3;
				_cachedSkin.button.onNormal.background = val3;
				Texture2D background = BuildTexFrom1Color(Color32.op_Implicit(new Color32((byte)47, (byte)79, (byte)79, byte.MaxValue)));
				_cachedSkin.horizontalSlider.active.background = background;
				_cachedSkin.horizontalSlider.onActive.background = background;
				_cachedSkin.horizontalSlider.focused.background = background;
				_cachedSkin.horizontalSlider.onFocused.background = background;
				_cachedSkin.horizontalSlider.hover.background = background;
				_cachedSkin.horizontalSlider.onHover.background = background;
				_cachedSkin.horizontalSlider.normal.background = background;
				_cachedSkin.horizontalSlider.onNormal.background = background;
				Texture2D background2 = BuildTexFrom1Color(Color32.op_Implicit(new Color32((byte)47, (byte)79, (byte)79, byte.MaxValue)));
				_cachedSkin.horizontalSliderThumb.active.background = background2;
				_cachedSkin.horizontalSliderThumb.onActive.background = background2;
				_cachedSkin.horizontalSliderThumb.focused.background = background2;
				_cachedSkin.horizontalSliderThumb.onFocused.background = background2;
				_cachedSkin.horizontalSliderThumb.hover.background = background2;
				_cachedSkin.horizontalSliderThumb.onHover.background = background2;
				_cachedSkin.horizontalSliderThumb.normal.background = background2;
				_cachedSkin.horizontalSliderThumb.onNormal.background = background2;
				Texture2D val5 = BuildTexFromColorArray((Color[])(object)new Color[7]
				{
					Color32.op_Implicit(_classicButtonBackground),
					Color32.op_Implicit(_classicButtonBackground),
					Color32.op_Implicit(_classicMenuBackground),
					Color32.op_Implicit(_classicMenuBackground),
					Color32.op_Implicit(_classicMenuBackground),
					Color32.op_Implicit(_classicMenuBackground),
					Color32.op_Implicit(_classicMenuBackground)
				}, 1, 7);
				_cachedSkin.textField.active.background = val5;
				_cachedSkin.textField.onActive.background = val5;
				_cachedSkin.textField.focused.background = val5;
				_cachedSkin.textField.onFocused.background = val5;
				_cachedSkin.textField.hover.background = val5;
				_cachedSkin.textField.onHover.background = val5;
				_cachedSkin.textField.normal.background = val5;
				_cachedSkin.textField.onNormal.background = val5;
				_cachedSkin.textField.active.textColor = Color32.op_Implicit(val2);
				_cachedSkin.textField.onActive.textColor = Color32.op_Implicit(val2);
				_cachedSkin.textField.hover.textColor = Color32.op_Implicit(val2);
				_cachedSkin.textField.onHover.textColor = Color32.op_Implicit(val2);
				Object.DontDestroyOnLoad((Object)(object)val);
				Object.DontDestroyOnLoad((Object)(object)val3);
				Object.DontDestroyOnLoad((Object)(object)val4);
				Object.DontDestroyOnLoad((Object)(object)val5);
				Object.DontDestroyOnLoad((Object)(object)_cachedSkin);
			}
			return _cachedSkin;
		}

		private static string GetColorTextForMPType(MultiplayerType mptype)
		{
			return mptype switch
			{
				MultiplayerType.Unspecified => "#FFFF99", 
				MultiplayerType.All => "#FF3333", 
				_ => string.Empty, 
			};
		}

		private static string GetColoredMPTypeText(MultiplayerType mptype)
		{
			return mptype switch
			{
				MultiplayerType.Client => "<color=#00CC00>Client</color>", 
				MultiplayerType.Unspecified => "<color=#FFFF99>Unspecified</color>", 
				MultiplayerType.All => "<color=#FF3333>All</color>", 
				_ => mptype.ToString(), 
			};
		}

		private static string GetTextForMPType(MultiplayerType mptype)
		{
			return mptype switch
			{
				MultiplayerType.All => "<color=#FF3333>All</color> - All Clients will be required to install this mod.", 
				MultiplayerType.Client => "<color=#00CC00>Client</color> - This mod is client-side, but might have special behavior.", 
				MultiplayerType.Unspecified => "<color=#FFFF99>Unspecified</color> - This mod has not had it's multiplayer operations specified for VoidManager.\n- If the host has VoidManager and this mod, Connection will be allowed.\n- If the host has VoidManager but not this mod, they can optionally trust Unspecified Mods.\n- If the host does not have VoidManager, Connection will be disallowed.\n- If the local client is hosting, vanilla clients will be allowed to join the session.", 
				_ => mptype.ToString(), 
			};
		}

		private void DrawModButton(VoidPlugin voidPlugin)
		{
			if ((int)voidPlugin.MPType > 3)
			{
				if (GUILayout.Button("<color=" + GetColorTextForMPType(voidPlugin.MPType) + ">" + voidPlugin.BepinPlugin.Metadata.Name + "</color>", Array.Empty<GUILayoutOption>()))
				{
					selectedMod = voidPlugin;
				}
			}
			else if (GUILayout.Button(voidPlugin.BepinPlugin.Metadata.Name, Array.Empty<GUILayoutOption>()))
			{
				selectedMod = voidPlugin;
			}
		}

		private void DrawPlayerModList(Player player)
		{
			MPUserDataBlock networkedPeerMods = MPModCheckManager.Instance.GetNetworkedPeerMods(player);
			if (networkedPeerMods != null)
			{
				GUILayout.Label("User VoidManager version: " + networkedPeerMods.VMVersion, Array.Empty<GUILayoutOption>());
				GUILayout.Label("ModList:", Array.Empty<GUILayoutOption>());
				string text = string.Empty;
				bool flag = true;
				MPModDataBlock[] modData = networkedPeerMods.ModData;
				foreach (MPModDataBlock mPModDataBlock in modData)
				{
					if (flag)
					{
						flag = false;
					}
					else
					{
						text += "\n";
					}
					text = text + "- " + mPModDataBlock.ModName + " v" + mPModDataBlock.Version + ", MPType: " + GetColoredMPTypeText(mPModDataBlock.MPType);
				}
				GUILayout.Label(text, Array.Empty<GUILayoutOption>());
			}
			else
			{
				GUILayout.Label("No Mod data.", Array.Empty<GUILayoutOption>());
			}
		}

		private Texture2D BuildTexFrom1Color(Color color)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Expected O, but got Unknown
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val = new Texture2D(1, 1);
			val.SetPixel(0, 0, color);
			val.Apply();
			return val;
		}

		private Texture2D BuildTexFromColorArray(Color[] color, int width, int height)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Expected O, but got Unknown
			Texture2D val = new Texture2D(width, height);
			val.SetPixels(color);
			val.Apply();
			return val;
		}

		public void DiscoverGUIMenus(Assembly assembly, VoidPlugin voidPlugin)
		{
			mods.Add(voidPlugin);
			Type[] types = assembly.GetTypes();
			IEnumerable<Type> enumerable = types.Where((Type t) => typeof(ModSettingsMenu).IsAssignableFrom(t) && !t.IsInterface && !t.IsAbstract);
			bool flag = false;
			foreach (Type item2 in enumerable)
			{
				ModSettingsMenu item = (ModSettingsMenu)Activator.CreateInstance(item2);
				settings.Add(item);
				flag = true;
			}
			if (flag)
			{
				BepinPlugin.Log.LogInfo((object)("[" + voidPlugin.BepinPlugin.Metadata.Name + "] detected settings menu"));
			}
		}

		public void DiscoverNonVManMod(VoidPlugin voidPlugin)
		{
			NonVManMods.Add(voidPlugin);
		}

		private void GUIToggleCursor(bool enable)
		{
			if (BepinPlugin.Bindings.MenuUnlockCursor.Value || (!enable && ShowingCursor))
			{
				ShowingCursor = enable;
				CursorUtility.ShowCursor((IShowCursorSource)(object)this, enable);
				if (ShowingCursor)
				{
					InputActionMapRequests.AddOrChangeRequestAllMaps((IInputActionMapRequest)(object)this, false);
					InputActionMapRequests.AddOrChangeRequest((IInputActionMapRequest)(object)this, "GlobalBindings", true);
					InputActionMapRequests.AddOrChangeRequest((IInputActionMapRequest)(object)this, "Debug", true);
				}
				else
				{
					InputActionMapRequests.RemoveRequestAllMaps((IInputActionMapRequest)(object)this);
				}
			}
		}
	}
	public abstract class ModSettingsMenu
	{
		public abstract string Name();

		public abstract void Draw();

		public virtual void OnOpen()
		{
		}

		public virtual void OnClose()
		{
		}
	}
	internal class VManSettings : ModSettingsMenu
	{
		private string SizeX = string.Empty;

		private string SizeY = string.Empty;

		private string ModListSizeX = string.Empty;

		private string PlayerListSizeX = string.Empty;

		private string SizeErrString = string.Empty;

		public override string Name()
		{
			return "VoidManager";
		}

		public override void OnOpen()
		{
			SizeX = BepinPlugin.Bindings.MenuWidth.Value.ToString();
			SizeY = BepinPlugin.Bindings.MenuHeight.Value.ToString();
			ModListSizeX = BepinPlugin.Bindings.MenuListWidth.Value.ToString();
			PlayerListSizeX = BepinPlugin.Bindings.PlayerListWidth.Value.ToString();
		}

		public override void Draw()
		{
			//IL_0069: 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_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			if (GUILayout.Button("Debug Mode: " + (BepinPlugin.Bindings.DebugMode.Value ? "Enabled" : "Disabled"), Array.Empty<GUILayoutOption>()))
			{
				BepinPlugin.Bindings.DebugMode.Value = !BepinPlugin.Bindings.DebugMode.Value;
			}
			GUI.skin.label.alignment = (TextAnchor)0;
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			TextAnchor value = BepinPlugin.Bindings.ModInfoTextAnchor.Value;
			GUILayout.Label("ModInfoTextAnchor: " + ((object)(TextAnchor)(ref value)).ToString(), Array.Empty<GUILayoutOption>());
			if (GUILayout.Button("<", Array.Empty<GUILayoutOption>()))
			{
				BepinPlugin.Bindings.ModInfoTextAnchor.Value = Enum.GetValues(typeof(TextAnchor)).Cast<TextAnchor>().SkipWhile((TextAnchor e) => e != (TextAnchor)(BepinPlugin.Bindings.ModInfoTextAnchor.Value - 1))
					.First();
			}
			if (GUILayout.Button(">", Array.Empty<GUILayoutOption>()))
			{
				BepinPlugin.Bindings.ModInfoTextAnchor.Value = Enum.GetValues(typeof(TextAnchor)).Cast<TextAnchor>().SkipWhile((TextAnchor e) => e != BepinPlugin.Bindings.ModInfoTextAnchor.Value)
					.Skip(1)
					.First();
			}
			GUILayout.EndHorizontal();
			if (GUILayout.Button("Reset to default", Array.Empty<GUILayoutOption>()))
			{
				BepinPlugin.Bindings.SetDefault();
			}
			GUILayout.HorizontalSlider(0f, 100f, 100f, Array.Empty<GUILayoutOption>());
			GUI.skin.label.alignment = (TextAnchor)4;
			GUILayout.Label("ModManager Size", Array.Empty<GUILayoutOption>());
			GUI.skin.label.alignment = (TextAnchor)5;
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Label("Width:", Array.Empty<GUILayoutOption>());
			SizeX = GUILayout.TextField(SizeX, Array.Empty<GUILayoutOption>());
			GUILayout.EndHorizontal();
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Label("Height:", Array.Empty<GUILayoutOption>());
			SizeY = GUILayout.TextField(SizeY, Array.Empty<GUILayoutOption>());
			GUILayout.EndHorizontal();
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Label("Modlist Scrollbar Width:", Array.Empty<GUILayoutOption>());
			ModListSizeX = GUILayout.TextField(ModListSizeX, Array.Empty<GUILayoutOption>());
			GUILayout.EndHorizontal();
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Label("Playerlist Scrollbar Width:", Array.Empty<GUILayoutOption>());
			PlayerListSizeX = GUILayout.TextField(PlayerListSizeX, Array.Empty<GUILayoutOption>());
			GUILayout.EndHorizontal();
			GUI.skin.label.alignment = (TextAnchor)4;
			if (SizeErrString != string.Empty)
			{
				GUILayout.Label("<color=red>" + SizeErrString + "</color>", Array.Empty<GUILayoutOption>());
			}
			if (GUILayout.Button("Apply Size", Array.Empty<GUILayoutOption>()))
			{
				if (!float.TryParse(SizeX, out var result) || !float.TryParse(SizeY, out var result2) || !float.TryParse(ModListSizeX, out var result3) || !float.TryParse(PlayerListSizeX, out var result4))
				{
					SizeErrString = "Size values are not numbers";
				}
				else if ((double)result < 0.3)
				{
					SizeErrString = "Width value cannot be smaller than .3";
				}
				else if ((double)result2 < 0.3)
				{
					SizeErrString = "Hight value cannot be smaller than .3";
				}
				else if ((double)result3 < 0.1)
				{
					SizeErrString = "Modlist Scrollbar Width value canot be smaller than .1";
				}
				else if ((double)result4 < 0.1)
				{
					SizeErrString = "Modlist Scrollbar Width value canot be smaller than .1";
				}
				else
				{
					BepinPlugin.Bindings.MenuHeight.Value = result2;
					BepinPlugin.Bindings.MenuWidth.Value = result;
					BepinPlugin.Bindings.MenuListWidth.Value = result3;
					BepinPlugin.Bindings.PlayerListWidth.Value = result4;
					SizeErrString = string.Empty;
					GUIMain.Instance.updateWindowSize();
				}
			}
			GUILayout.HorizontalSlider(0f, 100f, 100f, Array.Empty<GUILayoutOption>());
			if (GUILayout.Button("Unlock Cursor While Open: " + (BepinPlugin.Bindings.MenuUnlockCursor.Value ? "Enabled" : "Disabled"), Array.Empty<GUILayoutOption>()))
			{
				BepinPlugin.Bindings.MenuUnlockCursor.Value = !BepinPlugin.Bindings.MenuUnlockCursor.Value;
			}
			GUILayout.HorizontalSlider(0f, 100f, 100f, Array.Empty<GUILayoutOption>());
			if (GUILayout.Button("Trust MPType.Unspecified mods: " + (BepinPlugin.Bindings.TrustMPTypeUnspecified.Value ? "Trusted" : "Not Trusted"), Array.Empty<GUILayoutOption>()))
			{
				BepinPlugin.Bindings.TrustMPTypeUnspecified.Value = !BepinPlugin.Bindings.TrustMPTypeUnspecified.Value;
			}
		}
	}
}
namespace VoidManager.Content
{
	public class Craftables
	{
		private Dictionary<GUIDUnion, Tuple<string, CraftingRules>> ModifiedRecipes = new Dictionary<GUIDUnion, Tuple<string, CraftingRules>>();

		public static Craftables Instance { get; internal set; }

		public void SetRecipe(GUIDUnion GUID, string CallerID, CraftingRules craftingRules)
		{
			//IL_0006: 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_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: 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_005c: 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)
			if (ModifiedRecipes.ContainsKey(GUID))
			{
				BepinPlugin.Log.LogError((object)$"Attempted to modify recipe for object at GUID: {GUID}, however it has already been modified.");
				return;
			}
			CraftableItemDef val = default(CraftableItemDef);
			if (!((ResourceAssetContainer<CraftingDataContainer, Object, CraftableItemDef>)(object)ResourceAssetContainer<CraftingDataContainer, Object, CraftableItemDef>.Instance).TryGetByGuid(GUID, ref val))
			{
				throw new ArgumentException("An asset with the provided GUID does not exist.");
			}
			ModifiedRecipes.Add(GUID, new Tuple<string, CraftingRules>(CallerID, val.crafting));
			val.crafting = craftingRules;
		}

		public void SetRecipe(string GUID, string CallerID, CraftingRules craftingRules)
		{
			//IL_0002: 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)
			SetRecipe(new GUIDUnion(GUID), CallerID, craftingRules);
		}

		public void SetRecipe(int[] GUID, string CallerID, CraftingRules craftingRules)
		{
			//IL_0002: 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)
			SetRecipe(new GUIDUnion(GUID), CallerID, craftingRules);
		}

		public void ResetRecipe(GUIDUnion GUID, string CallerID)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: 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)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			if (ModifiedRecipes.TryGetValue(GUID, out var value))
			{
				if (value.Item1 != CallerID)
				{
					throw new ArgumentException("CallerID must match Assignment CallerID. Maybe another mod changed the same recipe?", "CallerID");
				}
				((ResourceAssetContainer<CraftingDataContainer, Object, CraftableItemDef>)(object)ResourceAssetContainer<CraftingDataContainer, Object, CraftableItemDef>.Instance).GetAssetDefById(GUID).crafting = value.Item2;
				ModifiedRecipes.Remove(GUID);
			}
		}

		public void ResetRecipe(string GUID, string CallerID)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			ResetRecipe(new GUIDUnion(GUID), CallerID);
		}

		public void ResetRecipe(int[] GUID, string CallerID)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			ResetRecipe(new GUIDUnion(GUID), CallerID);
		}

		public CraftingRules GetRecipe(GUIDUnion GUID)
		{
			//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)
			return ((ResourceAssetContainer<CraftingDataContainer, Object, CraftableItemDef>)(object)ResourceAssetContainer<CraftingDataContainer, Object, CraftableItemDef>.Instance).GetAssetDefById(GUID).crafting;
		}

		public CraftingRules GetRecipe(string GUID)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			return GetRecipe(new GUIDUnion(GUID));
		}

		public CraftingRules GetRecipe(int[] GUID)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			return GetRecipe(new GUIDUnion(GUID));
		}
	}
	public class Unlocks
	{
		private static FieldInfo UnlockOptionsFI = AccessTools.Field(typeof(UnlockItemDef), "unlockOptions");

		private Dictionary<GUIDUnion, Tuple<string, UnlockOptions>> ModifiedUnlockOptions = new Dictionary<GUIDUnion, Tuple<string, UnlockOptions>>();

		public static Unlocks Instance { get; internal set; }

		public void SetUnlockOptions(GUIDUnion GUID, string CallerID, UnlockOptions unlockOptions)
		{
			//IL_0006: 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_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: 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_006b: Unknown result type (might be due to invalid IL or missing references)
			if (ModifiedUnlockOptions.ContainsKey(GUID))
			{
				BepinPlugin.Log.LogError((object)$"Attempted to modify recipe for object at GUID: {GUID}, however it has already been modified.");
				return;
			}
			UnlockItemDef obj = default(UnlockItemDef);
			if (!((ResourceAssetContainer<UnlockContainer, Object, UnlockItemDef>)(object)ResourceAssetContainer<UnlockContainer, Object, UnlockItemDef>.Instance).TryGetByGuid(GUID, ref obj))
			{
				throw new ArgumentException("An asset with the provided GUID does not exist.");
			}
			ModifiedUnlockOptions.Add(GUID, new Tuple<string, UnlockOptions>(CallerID, (UnlockOptions)UnlockOptionsFI.GetValue(obj)));
			UnlockOptionsFI.SetValue(obj, unlockOptions);
		}

		public void SetUnlockOptions(string GUID, string CallerID, UnlockOptions unlockOptions)
		{
			//IL_0002: 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)
			SetUnlockOptions(new GUIDUnion(GUID), CallerID, unlockOptions);
		}

		public void SetUnlockOptions(int[] GUID, string CallerID, UnlockOptions unlockOptions)
		{
			//IL_0002: 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)
			SetUnlockOptions(new GUIDUnion(GUID), CallerID, unlockOptions);
		}

		public void ResetUnlockOptions(GUIDUnion GUID, string CallerID)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: 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)
			if (ModifiedUnlockOptions.TryGetValue(GUID, out var value))
			{
				if (value.Item1 != CallerID)
				{
					throw new ArgumentException("CallerID must match Assignment CallerID. Maybe another mod changed the same UnlockOptions?", "CallerID");
				}
				UnlockOptionsFI.SetValue(((ResourceAssetContainer<UnlockContainer, Object, UnlockItemDef>)(object)ResourceAssetContainer<UnlockContainer, Object, UnlockItemDef>.Instance).GetAssetDefById(GUID), value.Item2);
				ModifiedUnlockOptions.Remove(GUID);
			}
		}

		public void ResetUnlockOptions(string GUID, string CallerID)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			ResetUnlockOptions(new GUIDUnion(GUID), CallerID);
		}

		public void ResetUnlockOptions(int[] GUID, string CallerID)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			ResetUnlockOptions(new GUIDUnion(GUID), CallerID);
		}

		public UnlockOptions GetUnlockOptions(GUIDUnion GUID)
		{
			//IL_000a: 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)
			return (UnlockOptions)UnlockOptionsFI.GetValue(((ResourceAssetContainer<UnlockContainer, Object, UnlockItemDef>)(object)ResourceAssetContainer<UnlockContainer, Object, UnlockItemDef>.Instance).GetAssetDefById(GUID));
		}

		public UnlockOptions GetUnlockOptions(string GUID)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			return GetUnlockOptions(new GUIDUnion(GUID));
		}

		public UnlockOptions GetUnlockOptions(int[] GUID)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			return GetUnlockOptions(new GUIDUnion(GUID));
		}
	}
}
namespace VoidManager.Chat
{
	internal class EchoCommand : ChatCommand
	{
		public override string[] CommandAliases()
		{
			return new string[2] { "echo", "e" };
		}

		public override string Description()
		{
			return "Repeats the input text back through the chat box.";
		}

		public override string[] UsageExamples()
		{
			return new string[1] { "/" + CommandAliases()[0] + " <text>" };
		}

		public override void Execute(string arguments)
		{
			Messaging.Echo("Echo: " + arguments);
		}
	}
	internal class HelpCommand : ChatCommand
	{
		public override string[] CommandAliases()
		{
			return new string[2] { "help", "?" };
		}

		public override string Description()
		{
			return "Displays help text for a command, or the list of commands if none specified.";
		}

		public override string[] UsageExamples()
		{
			return new List<string>(base.UsageExamples()).Concat(new string[2]
			{
				"/" + CommandAliases()[0] + " clear",
				"/" + CommandAliases()[0] + " 3"
			}).ToArray();
		}

		public override void Execute(string arguments)
		{
			int result = 1;
			if (!string.IsNullOrWhiteSpace(arguments) && !int.TryParse(arguments, out result))
			{
				if (arguments[0] == '/')
				{
					arguments = arguments.Substring(1);
				}
				ChatCommand command = CommandHandler.GetCommand(arguments.Split(new char[1] { ' ' })[0]);
				StringBuilder stringBuilder = new StringBuilder();
				if (command != null)
				{
					stringBuilder.AppendLine("<color=green>/" + command.CommandAliases()[0] + "</color> - " + command.Description());
					stringBuilder.AppendLine("Aliases: /" + string.Join(", /", command.CommandAliases()));
					stringBuilder.AppendLine("Usage: " + command.UsageExamples()[0]);
					for (int i = 1; i < command.UsageExamples().Length; i++)
					{
						stringBuilder.AppendLine("       " + command.UsageExamples()[i]);
					}
				}
				else
				{
					stringBuilder.AppendLine("Command /" + arguments + " not found");
				}
				Messaging.Echo(stringBuilder.ToString());
				return;
			}
			int num = 6;
			IOrderedEnumerable<ChatCommand> commands = CommandHandler.GetCommands();
			int num2 = Mathf.CeilToInt((float)commands.Count() / (float)num);
			result--;
			if (result < 0)
			{
				result = 0;
			}
			StringBuilder stringBuilder2 = new StringBuilder();
			stringBuilder2.AppendLine((num2 == 1 && result == 0) ? "<color=green>Command List:</color> :" : $"<color=green>Command List:</color> Page {result + 1} : {num2}");
			for (int j = 0; j < num; j++)
			{
				int index = j + result * num;
				if (j + result * num >= commands.Count())
				{
					break;
				}
				ChatCommand chatCommand = commands.ElementAt(index);
				stringBuilder2.AppendLine("/" + chatCommand.CommandAliases()[0] + " - " + chatCommand.Description());
			}
			stringBuilder2.AppendLine("Use <color=green>/help <command></color> for details about a specific command");
			Messaging.Echo(stringBuilder2.ToString());
		}
	}
	internal class ListPlayers : ChatCommand
	{
		public override string[] CommandAliases()
		{
			return new string[3] { "listplayers", "players", "list" };
		}

		public override string Description()
		{
			return "Returns a list of players with their ID's";
		}

		public override string[] UsageExamples()
		{
			return new string[1] { "/" + CommandAliases()[0] };
		}

		public override void Execute(string arguments)
		{
			if (!PhotonNetwork.InRoom)
			{
				return;
			}
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.AppendLine("[Player List]");
			Player[] playerList = PhotonNetwork.PlayerList;
			foreach (Player val in playerList)
			{
				if (val != null)
				{
					stringBuilder.AppendLine($"{val.ActorNumber} - {val.NickName}");
				}
			}
			Messaging.Notification(stringBuilder.ToString());
		}
	}
	internal class PublicHelpCommand : PublicCommand
	{
		public override string[] CommandAliases()
		{
			return new string[1] { "help" };
		}

		public override string Description()
		{
			return "Displays a list of available public commands";
		}

		public override string[] UsageExamples()
		{
			return new List<string>(base.UsageExamples()).Concat(new string[2]
			{
				"!" + CommandAliases()[0] + " help",
				"!" + CommandAliases()[0] + " 2"
			}).ToArray();
		}

		public override void Execute(string arguments, int senderId)
		{
			if (!PhotonNetwork.IsMasterClient)
			{
				return;
			}
			int result = 1;
			if (!string.IsNullOrWhiteSpace(arguments) && !int.TryParse(arguments, out result))
			{
				if (arguments[0] == '!')
				{
					arguments = arguments.Substring(1);
				}
				PublicCommand publicCommand = CommandHandler.GetPublicCommand(arguments.Split(new char[1] { ' ' })[0]);
				StringBuilder stringBuilder = new StringBuilder();
				if (publicCommand != null)
				{
					stringBuilder.AppendLine("<color=green>!" + publicCommand.CommandAliases()[0] + "</color> - " + publicCommand.Description());
					stringBuilder.AppendLine("Aliases: !" + string.Join(", !", publicCommand.CommandAliases()));
					stringBuilder.AppendLine("Usage: " + publicCommand.UsageExamples()[0]);
					for (int i = 1; i < publicCommand.UsageExamples().Length; i++)
					{
						stringBuilder.AppendLine("       " + publicCommand.UsageExamples()[i]);
					}
				}
				else
				{
					stringBuilder.AppendLine("Public Command !" + arguments + " not found");
				}
				Messaging.Echo(stringBuilder.ToString(), local: false);
				return;
			}
			int num = 6;
			IOrderedEnumerable<PublicCommand> publicCommands = CommandHandler.GetPublicCommands();
			int num2 = Mathf.CeilToInt((float)publicCommands.Count() / (float)num);
			result--;
			if (result < 0)
			{
				result = 0;
			}
			StringBuilder stringBuilder2 = new StringBuilder();
			stringBuilder2.AppendLine((num2 == 1 && result == 0) ? "<color=green>Public Command List:</color> :" : $"<color=green>Public Command List:</color> Page {result + 1} : {num2}");
			for (int j = 0; j < num; j++)
			{
				int index = j + result * num;
				if (j + result * num >= publicCommands.Count())
				{
					break;
				}
				PublicCommand publicCommand2 = publicCommands.ElementAt(index);
				stringBuilder2.AppendLine("!" + publicCommand2.CommandAliases()[0] + " - " + publicCommand2.Description());
			}
			stringBuilder2.AppendLine("Use <color=green>!help <command></color> for details about a specific public command");
			Messaging.Echo(stringBuilder2.ToString(), local: false);
		}
	}
}
namespace VoidManager.Chat.Router
{
	public abstract class ChatCommand
	{
		public abstract string[] CommandAliases();

		public abstract string Description();

		public virtual string[] UsageExamples()
		{
			return new string[1] { "/" + CommandAliases()[0] };
		}

		public abstract void Execute(string arguments);
	}
	public abstract class PublicCommand
	{
		public abstract string[] CommandAliases();

		public abstract string Description();

		public virtual string[] UsageExamples()
		{
			return new string[1] { "/" + CommandAliases()[0] };
		}

		public abstract void Execute(string arguments, int Sender);
	}
	[HarmonyPatch(typeof(TextChatVE), "GetMessage")]
	internal class ChatCommandDetectPatch
	{
		[HarmonyPostfix]
		public static void DiscoverChatCommand(ref string __result)
		{
			if (__result.StartsWith("/"))
			{
				__result = __result.Substring(1);
				string text = __result.Split(new char[1] { ' ' })[0];
				string arguments = __result.Substring(text.Length + ((__result.Split(new char[1] { ' ' }).Count() != 1) ? 1 : 0));
				CommandHandler.ExecuteCommandFromAlias(text, arguments);
				__result = "";
			}
		}
	}
	[HarmonyPatch(typeof(TextChat), "IncomingMessage")]
	internal class PublicCommandDetectPatch
	{
		[HarmonyPostfix]
		public static void DiscoverPublicCommand(Player p, string channelTextMessage)
		{
			if (channelTextMessage.StartsWith("!"))
			{
				channelTextMessage = channelTextMessage.Substring(1);
				string text = channelTextMessage.Split(new char[1] { ' ' })[0];
				Player playerByName = Game.GetPlayerByName(p.NickName);
				string text2 = channelTextMessage.Substring(text.Length + ((channelTextMessage.Split(new char[1] { ' ' }).Count() != 1) ? 1 : 0));
				BepinPlugin.Log.LogInfo((object)("'!" + text + " " + text2 + "' attempted by " + p.NickName));
				CommandHandler.ExecuteCommandFromAlias(text, text2, publicCommand: true, Game.GetIDFromPlayer(playerByName));
			}
		}
	}
	internal class CommandHandler
	{
		private static Dictionary<string, ChatCommand> chatCommands = new Dictionary<string, ChatCommand>();

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

		public static int chatCommandCount => chatCommands.Coun