Decompiled source of PulsarModLoader v1.0.0

BepInEx/patchers/PulsarModLoader.Adaptor/PulsarModLoader.Adaptor.dll

Decompiled 2 days ago
using System;
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.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Mono.Cecil;
using Mono.Cecil.Cil;
using PulsarModLoader.Injections;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("Pulsar Mod Loader Installer")]
[assembly: AssemblyDescription("https://github.com/TomRichter/pulsar-mod-loader")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Tom Richter")]
[assembly: AssemblyProduct("Pulsar Mod Loader")]
[assembly: AssemblyCopyright("Copyright © Tom Richter 2018")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("f15e6efa-3584-4503-98e0-17d3e87900f5")]
[assembly: AssemblyFileVersion("0.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.0.0")]
[module: UnverifiableCode]
namespace PulsarModLoader.Adaptor;

public class Patcher
{
	internal static readonly ManualLogSource Log = Logger.CreateLogSource("PML-Adaptor");

	public static IEnumerable<string> TargetDLLs { get; } = new string[1] { "Assembly-CSharp.dll" };


	public static void Initialize()
	{
		NoTranspilerNormalization();
		InjectAssemblies("PulsarModLoader");
	}

	public static void InjectAssemblies(string AssemblyName)
	{
		if (!AppDomain.CurrentDomain.GetAssemblies().Any((Assembly a) => a.GetName().Name == AssemblyName))
		{
			int startIndex = Assembly.GetExecutingAssembly().Location.LastIndexOf('\\');
			int length = ("\\" + Assembly.GetExecutingAssembly().GetName().Name + ".dll").Length;
			string text = Assembly.GetExecutingAssembly().Location.Remove(startIndex, length) + "\\" + AssemblyName + ".dll";
			if (File.Exists(text))
			{
				Assembly.LoadFrom(text);
				Log.LogInfo((object)("Loaded '" + AssemblyName + "' successfully."));
			}
			else
			{
				Log.LogWarning((object)("Failed to load '" + AssemblyName + "' - not found at expected location!"));
			}
		}
		else
		{
			Log.LogInfo((object)("Failed to load '" + AssemblyName + "' - assembly already loaded!"));
		}
	}

	internal static void NoTranspilerNormalization()
	{
		Assembly assembly = Assembly.GetAssembly(typeof(Harmony));
		Type type = assembly.GetType("HarmonyLib.Internal.Patching.ILManipulator");
		if (type == null)
		{
			return;
		}
		FieldInfo field = type.GetField("ShortToLongMap", BindingFlags.Static | BindingFlags.NonPublic);
		if (field != null)
		{
			if (field.GetValue(null) is Dictionary<OpCode, OpCode> dictionary)
			{
				dictionary.Clear();
				Log.LogInfo((object)"Transpiler ShortToLongMap cleared (Used for Transpiler Normalization).");
			}
			else
			{
				Log.LogWarning((object)"The ShortToLongMap is null. Transpiler short patches will be converted as standard with HarmonyX.");
			}
		}
		else
		{
			Log.LogWarning((object)"Field ShortToLongMap not found. Transpiler short patches will be converted as standard with HarmonyX.");
		}
	}

	public static void Patch(AssemblyDefinition assembly)
	{
		FieldInfo field = typeof(ModManager).GetField("ModsDir", BindingFlags.Static | BindingFlags.Public);
		if (field != null)
		{
			if (field.GetValue(null) is IList<string> list)
			{
				list.Add(Paths.PluginPath);
			}
			Log.LogInfo((object)("Added " + Paths.PluginPath + " to the mod directories."));
		}
		else
		{
			Log.LogWarning((object)"PulsarModLoader is outdated and cannot locate other directories!");
		}
		if (IsModified(assembly))
		{
			Log.LogInfo((object)"The assembly is already modified.");
			return;
		}
		PatchMethod(assembly, "PLGlobal", "Start", typeof(LoggingInjections), "LoggingCleanup");
		PatchMethod(assembly, "PLGlobal", "Awake", typeof(HarmonyInjector), "InitializeHarmony");
	}

	internal static bool IsModified(AssemblyDefinition targetAssembly)
	{
		//IL_0060: Unknown result type (might be due to invalid IL or missing references)
		//IL_0065: Unknown result type (might be due to invalid IL or missing references)
		string text = "PLGlobal";
		string targetMethodName = "Awake";
		MethodDefinition val = ((IEnumerable<MethodDefinition>)targetAssembly.MainModule.GetType(text).Methods).First((MethodDefinition m) => ((MemberReference)m).Name == targetMethodName);
		if (val == null)
		{
			throw new ArgumentNullException("Couldn't find method in target assembly!");
		}
		if (val.Body.Instructions[0].OpCode == OpCodes.Call)
		{
			return true;
		}
		return false;
	}

	internal static void PatchMethod(AssemblyDefinition targetAssembly, string targetClassName, string targetMethodName, Type sourceClassType, string sourceMethodName)
	{
		//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
		Log.LogDebug((object)("Attempting " + sourceClassType.ToString() + " injection"));
		MethodDefinition val = ((IEnumerable<MethodDefinition>)targetAssembly.MainModule.GetType(targetClassName).Methods).First((MethodDefinition m) => ((MemberReference)m).Name == targetMethodName);
		MethodReference val2 = targetAssembly.MainModule.ImportReference((MethodBase)sourceClassType.GetMethod(sourceMethodName));
		if (val == null)
		{
			Log.LogError((object)("Failed " + sourceClassType.ToString() + " injection - Couldn't find method in target assembly!"));
			return;
		}
		if (val2 == null)
		{
			Log.LogError((object)("Failed " + sourceClassType.ToString() + " injection - Couldn't find method in source assembly!"));
			return;
		}
		Log.LogDebug((object)"Found relevant methods.  Injecting hook...");
		ILProcessor iLProcessor = val.Body.GetILProcessor();
		Instruction val3 = val.Body.Instructions[0];
		Instruction val4 = iLProcessor.Create(OpCodes.Call, val2);
		iLProcessor.InsertBefore(val3, val4);
		Log.LogInfo((object)("Injected " + sourceClassType.ToString() + " successfully."));
	}
}

BepInEx/patchers/PulsarModLoader.Adaptor/PulsarModLoader.dll

Decompiled 2 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Cryptography;
using System.Security.Permissions;
using System.Text;
using System.Threading;
using CodeStage.AntiCheat.ObscuredTypes;
using ExitGames.Client.Photon;
using HarmonyLib;
using Photon;
using PulsarModLoader.Chat.Commands;
using PulsarModLoader.Chat.Commands.CommandRouter;
using PulsarModLoader.Chat.Extensions;
using PulsarModLoader.Content.Components.AutoTurret;
using PulsarModLoader.Content.Components.CPU;
using PulsarModLoader.Content.Components.CaptainsChair;
using PulsarModLoader.Content.Components.Extractor;
using PulsarModLoader.Content.Components.FBRecipeModule;
using PulsarModLoader.Content.Components.Hull;
using PulsarModLoader.Content.Components.HullPlating;
using PulsarModLoader.Content.Components.InertiaThruster;
using PulsarModLoader.Content.Components.ManeuverThruster;
using PulsarModLoader.Content.Components.MegaTurret;
using PulsarModLoader.Content.Components.Missile;
using PulsarModLoader.Content.Components.MissionShipComponent;
using PulsarModLoader.Content.Components.NuclearDevice;
using PulsarModLoader.Content.Components.PolytechModule;
using PulsarModLoader.Content.Components.Reactor;
using PulsarModLoader.Content.Components.Shield;
using PulsarModLoader.Content.Components.Thruster;
using PulsarModLoader.Content.Components.Turret;
using PulsarModLoader.Content.Components.Virus;
using PulsarModLoader.Content.Components.WarpDrive;
using PulsarModLoader.Content.Components.WarpDriveProgram;
using PulsarModLoader.Content.Items;
using PulsarModLoader.CustomGUI;
using PulsarModLoader.Keybinds;
using PulsarModLoader.MPModChecks;
using PulsarModLoader.Patches;
using PulsarModLoader.SaveData;
using PulsarModLoader.Utilities;
using Steamworks;
using UnityEngine;
using UnityEngine.UI;
using Valve.Newtonsoft.Json;
using Valve.Newtonsoft.Json.Linq;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("PulsarModLoader.dll")]
[assembly: AssemblyDescription("https://github.com/PULSAR-Modders/pulsar-mod-loader")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Contributors")]
[assembly: AssemblyProduct("Pulsar Mod Loader")]
[assembly: AssemblyCopyright("Copyright © Contributors 2020")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("cf6ce9ba-9603-439d-9173-96c052c94417")]
[assembly: AssemblyFileVersion("0.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.0.0")]
[module: UnverifiableCode]
namespace PulsarModLoader
{
	public class Events
	{
		public delegate void EnterNewGameDelegate();

		[HarmonyPatch(typeof(PLGlobal), "EnterNewGame")]
		private class EnterNewGamePatch
		{
			private static void Postfix()
			{
				Instance.EnterNewGameEvent?.Invoke();
			}
		}

		public delegate void OnLeaveGameDelegate();

		[HarmonyPatch(typeof(PLNetworkManager), "OnLeaveGame")]
		private class OnLeaveGamePatch
		{
			private static void Prefix()
			{
				Instance.OnLeaveGameEvent?.Invoke();
			}
		}

		public delegate void GameOverDelegate(bool backToMainMenu);

		[HarmonyPatch(typeof(PLNetworkManager), "GameOver")]
		private class GameOverPatch
		{
			private static void Prefix(bool backToMainMenu)
			{
				Instance.GameOverEvent?.Invoke(backToMainMenu);
			}
		}

		public delegate void SpawnNewPlayerDelegate(PhotonPlayer newPhotonPlayer, string inPlayerName);

		[HarmonyPatch(typeof(PLServer), "SpawnNewPlayer")]
		private class SpawnNewPlayerPatch
		{
			private static void Postfix(PhotonPlayer newPhotonPlayer, string inPlayerName)
			{
				PhotonProperties.UpdatePlayerList();
				Instance.SpawnNewPlayerEvent?.Invoke(newPhotonPlayer, inPlayerName);
			}
		}

		public delegate void RemovePlayerDelegate(PLPlayer player);

		[HarmonyPatch(typeof(PLServer), "RemovePlayer")]
		private class RemovePlayerPatch
		{
			private static void Prefix(PLPlayer inPlayer)
			{
				PhotonProperties.UpdatePlayerList();
				Instance.RemovePlayerEvent?.Invoke(inPlayer);
			}
		}

		public delegate void ServerStartDelegate(PLServer instance);

		[HarmonyPatch(typeof(PLServer), "Start")]
		private class ServerStartPatch
		{
			private static void Postfix(PLServer __instance)
			{
				ChatHelper.publicCached = false;
				HandlePublicCommands.RequestPublicCommands();
				Instance.ServerStartEvent?.Invoke(__instance);
			}
		}

		public delegate void ClientModlistRecievedDelegate(PhotonPlayer DataSender);

		public delegate void ServerOnClientVerifiedDelegate(PhotonPlayer JoiningPhotonPlayer);

		[HarmonyPatch(typeof(PLServer), "ServerOnClientVerified")]
		private class ServerOnClientVerifiedPatch
		{
			private static void Postfix(PhotonPlayer client)
			{
				Instance.ServerOnClientVerifiedEvent?.Invoke(client);
			}
		}

		public static Events Instance;

		public ServerOnClientVerifiedDelegate ServerOnClientVerifiedEvent;

		public event EnterNewGameDelegate EnterNewGameEvent;

		public event OnLeaveGameDelegate OnLeaveGameEvent;

		public event GameOverDelegate GameOverEvent;

		public event SpawnNewPlayerDelegate SpawnNewPlayerEvent;

		public event RemovePlayerDelegate RemovePlayerEvent;

		public event ServerStartDelegate ServerStartEvent;

		public event ClientModlistRecievedDelegate ClientModlistRecievedEvent;

		internal Events()
		{
			Instance = this;
		}

		internal void CallClientModlistRecievedEvent(PhotonPlayer DataSender)
		{
			this.ClientModlistRecievedEvent?.Invoke(DataSender);
		}
	}
	public class ModManager
	{
		public delegate void ModLoaded(string name, PulsarMod mod);

		public delegate void ModUnloaded(PulsarMod mod);

		public delegate void AllModsLoaded();

		public static bool IsOldVersion;

		public FileVersionInfo PMLVersionInfo = FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location);

		private readonly Dictionary<string, PulsarMod> activeMods;

		private readonly HashSet<string> modDirectories;

		internal List<ModUpdateCheck.UpdateModInfo> UpdatesAviable = new List<ModUpdateCheck.UpdateModInfo>(2);

		private static ModManager _instance = null;

		public static List<string> ModsDir = new List<string> { Path.Combine(Directory.GetCurrentDirectory(), "Mods") };

		public static ModManager Instance
		{
			get
			{
				if (_instance == null)
				{
					_instance = new ModManager();
				}
				return _instance;
			}
		}

		public event ModLoaded OnModSuccessfullyLoaded;

		public event ModUnloaded OnModUnloaded;

		public event AllModsLoaded OnAllModsLoaded;

		public ModManager()
		{
			Logger.Info("Starting " + PMLVersionInfo.ProductName + " v" + PMLVersionInfo.FileVersion);
			activeMods = new Dictionary<string, PulsarMod>();
			modDirectories = new HashSet<string>();
			AppDomain.CurrentDomain.AssemblyResolve += ResolveModsDirectory;
			RuntimeHelpers.RunClassConstructor(typeof(PhotonNetwork).TypeHandle);
			IsOldVersion = false;
		}

		public PulsarMod GetMod(string name)
		{
			if (activeMods.TryGetValue(name, out var value))
			{
				return value;
			}
			return null;
		}

		public PulsarMod GetModByHarmonyID(string HarmonyID)
		{
			foreach (PulsarMod value in activeMods.Values)
			{
				if (value.HarmonyIdentifier() == HarmonyID)
				{
					return value;
				}
			}
			return null;
		}

		public bool IsModLoaded(string name)
		{
			return activeMods.ContainsKey(name);
		}

		public bool IsModLoadedByHarmonyID(string HarmonyID)
		{
			foreach (PulsarMod value in activeMods.Values)
			{
				if (value.HarmonyIdentifier() == HarmonyID)
				{
					return true;
				}
			}
			return false;
		}

		public IEnumerable<PulsarMod> GetAllMods()
		{
			return activeMods.Values;
		}

		public void LoadMods()
		{
			MPModCheckManager.Instance.HoldMPModListRefresh();
			Logger.Info($"Modded Directories Count {ModsDir.Count()}");
			foreach (string item in ModsDir)
			{
				Logger.Info("Attempting to load mods from " + item);
				if (!Directory.Exists(item))
				{
					Directory.CreateDirectory(item);
				}
				modDirectories.Add(item);
				if ((bool)PMLConfig.ZipModLoad)
				{
					string[] files = Directory.GetFiles(item, "*.zip", SearchOption.AllDirectories);
					foreach (string text in files)
					{
						string fullPath = Path.GetFullPath(item);
						string text2 = fullPath;
						char directorySeparatorChar = Path.DirectorySeparatorChar;
						if (!text2.EndsWith(directorySeparatorChar.ToString(), StringComparison.Ordinal))
						{
							string text3 = fullPath;
							directorySeparatorChar = Path.DirectorySeparatorChar;
							fullPath = text3 + directorySeparatorChar;
						}
						using (ZipArchive zipArchive = ZipFile.OpenRead(text))
						{
							foreach (ZipArchiveEntry entry in zipArchive.Entries)
							{
								if (entry.FullName.EndsWith(".dll", StringComparison.OrdinalIgnoreCase))
								{
									if (entry.Length > PMLConfig.MaxLoadSizeBytes.Value)
									{
										Logger.Info("Error: Extraction of " + entry.Name + " failed, Too Large!)");
										break;
									}
									string fullPath2 = Path.GetFullPath(Path.Combine(item, entry.Name));
									if (File.Exists(fullPath2))
									{
										File.Delete(fullPath2);
									}
									entry.ExtractToFile(fullPath2);
								}
							}
						}
						if ((bool)PMLConfig.ZipModMode)
						{
							File.Delete(text);
						}
					}
				}
				string[] files2 = Directory.GetFiles(item, "*.dll", SearchOption.AllDirectories);
				foreach (string text4 in files2)
				{
					if (Path.GetFileName(text4) != "0Harmony.dll")
					{
						LoadMod(text4);
					}
				}
			}
			Logger.Info($"Finished loading {activeMods.Count} mods!");
			_ = ItemModManager.Instance;
			_ = AutoTurretModManager.Instance;
			_ = CaptainsChairModManager.Instance;
			_ = CPUModManager.Instance;
			_ = ExtractorModManager.Instance;
			_ = FBRecipeModuleModManager.Instance;
			_ = HullModManager.Instance;
			_ = HullPlatingModManager.Instance;
			_ = InertiaThrusterModManager.Instance;
			_ = ManeuverThrusterModManager.Instance;
			_ = MegaTurretModManager.Instance;
			_ = MissileModManager.Instance;
			_ = MissionShipComponentModManager.Instance;
			_ = NuclearDeviceModManager.Instance;
			_ = PolytechModuleModManager.Instance;
			_ = ReactorModManager.Instance;
			_ = ShieldModManager.Instance;
			_ = ThrusterModManager.Instance;
			_ = TurretModManager.Instance;
			_ = VirusModManager.Instance;
			_ = WarpDriveModManager.Instance;
			_ = WarpDriveProgramModManager.Instance;
			this.OnAllModsLoaded?.Invoke();
		}

		private Assembly ResolveModsDirectory(object sender, ResolveEventArgs args)
		{
			foreach (string modDirectory in modDirectories)
			{
				string text = Path.Combine(modDirectory, new AssemblyName(args.Name).Name + ".dll");
				if (File.Exists(text))
				{
					return Assembly.LoadFrom(text);
				}
			}
			return null;
		}

		public PulsarMod LoadMod(string assemblyPath)
		{
			if (!File.Exists(assemblyPath))
			{
				throw new IOException("Couldn't find file: " + assemblyPath);
			}
			try
			{
				byte[] array = File.ReadAllBytes(assemblyPath);
				Assembly assembly = Assembly.Load(array);
				Type type = assembly.GetTypes().FirstOrDefault((Type t) => t.IsSubclassOf(typeof(PulsarMod)));
				if (type != null)
				{
					PulsarMod pulsarMod = Activator.CreateInstance(type) as PulsarMod;
					pulsarMod.VersionInfo = FileVersionInfo.GetVersionInfo(assemblyPath);
					pulsarMod.ModHash = GetHash(array);
					activeMods.Add(pulsarMod.Name, pulsarMod);
					this.OnModSuccessfullyLoaded?.Invoke(pulsarMod.Name, pulsarMod);
					Logger.Info("Loaded Mod: " + pulsarMod.Name + ", Version: " + pulsarMod.Version + ", Author: " + pulsarMod.Author + ", License: " + pulsarMod.License + ", SourceURL: " + ((pulsarMod.SourceURL.Length != 0) ? pulsarMod.SourceURL : "N/A"));
					if (ModUpdateCheck.IsUpdateAviable(pulsarMod))
					{
						Logger.Info("↑ ↑ ↑ !This mod is outdated! ↑ ↑ ↑");
					}
					return pulsarMod;
				}
				Logger.Info("Skipping " + Path.GetFileName(assemblyPath) + "; couldn't find mod entry point.");
				return null;
			}
			catch (Exception arg)
			{
				Logger.Info($"Failed to load mod: {Path.GetFileName(assemblyPath)}\n{arg}");
				return null;
			}
		}

		public static byte[] GetHash(byte[] DataForHashing)
		{
			using SHA256 sHA = SHA256.Create();
			return sHA.ComputeHash(DataForHashing);
		}

		internal void UnloadMod(PulsarMod mod, ref Harmony harmony)
		{
			activeMods.Remove(mod.Name);
			harmony.UnpatchAll(mod.HarmonyIdentifier());
			this.OnModUnloaded?.Invoke(mod);
			Logger.Info("Unloaded mod: " + mod.Name + " Version " + mod.Version + " Author: " + mod.Author);
			GC.Collect();
		}
	}
	public abstract class ModMessage
	{
		public string GetIdentifier()
		{
			return GetType().Namespace + "." + GetType().Name;
		}

		public static void SendRPC(string harmonyIdentifier, string handlerIdentifier, PhotonPlayer player, object[] arguments)
		{
			((MonoBehaviour)ModMessageHelper.Instance).photonView.RPC("ReceiveMessage", player, new object[2]
			{
				harmonyIdentifier + "#" + handlerIdentifier,
				arguments
			});
		}

		public static void SendRPC(string harmonyIdentifier, string handlerIdentifier, PhotonTargets targets, object[] arguments)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			((MonoBehaviour)ModMessageHelper.Instance).photonView.RPC("ReceiveMessage", targets, new object[2]
			{
				harmonyIdentifier + "#" + handlerIdentifier,
				arguments
			});
		}

		public abstract void HandleRPC(object[] arguments, PhotonMessageInfo sender);
	}
	[HarmonyPatch(typeof(PLServer), "Awake")]
	internal static class MMHInstantiate
	{
		private static void Prefix(PLServer __instance)
		{
			((Component)__instance).gameObject.AddComponent(typeof(ModMessageHelper));
		}
	}
	public class ModMessageHelper : MonoBehaviour
	{
		public static ModMessageHelper Instance;

		[Obsolete]
		public Dictionary<PhotonPlayer, string> PlayersWithMods = new Dictionary<PhotonPlayer, string>();

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

		[Obsolete]
		public string GetPlayerMods(PhotonPlayer inPlayer)
		{
			return "NoPlayer";
		}

		private ModMessageHelper()
		{
			modMessageHandlers = new Dictionary<string, ModMessage>();
			IEnumerable<PulsarMod> allMods = ModManager.Instance.GetAllMods();
			foreach (PulsarMod item in allMods)
			{
				Assembly assembly = item.GetType().Assembly;
				Type typeFromHandle = typeof(ModMessage);
				Type[] types = assembly.GetTypes();
				foreach (Type type in types)
				{
					if (typeFromHandle.IsAssignableFrom(type) && !type.IsAbstract && !type.IsInterface)
					{
						ModMessage modMessage = (ModMessage)Activator.CreateInstance(type);
						modMessageHandlers.Add(item.HarmonyIdentifier() + "#" + modMessage.GetIdentifier(), modMessage);
					}
				}
			}
			ModMessage modMessage2 = new HandlePublicCommands();
			modMessageHandlers.Add("#" + modMessage2.GetIdentifier(), modMessage2);
			Instance = this;
		}

		[Obsolete]
		public string GetModName(string modName)
		{
			PulsarMod mod = ModManager.Instance.GetMod(modName);
			return $"{mod.Name} {mod.Version} MPF{mod.MPRequirements}";
		}

		[PunRPC]
		public void ReceiveMessage(string modID, object[] arguments, PhotonMessageInfo pmi)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			if (modMessageHandlers.TryGetValue(modID, out var value))
			{
				value.HandleRPC(arguments, pmi);
			}
			else
			{
				Logger.Info("ModMessage for " + modID + " doesn't exist");
			}
		}

		[PunRPC]
		public void RecieveErrorMessage(string message, PhotonMessageInfo pmi)
		{
			//IL_0001: 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_0026: Expected O, but got Unknown
			if (pmi.sender.IsMasterClient)
			{
				PLNetworkManager.Instance.MainMenu.AddActiveMenu((PLMenu)new PLErrorMessageMenu(message));
			}
		}

		[PunRPC]
		public void ServerRecieveModList(byte[] recievedData, PhotonMessageInfo pmi)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			MPUserDataBlock mPUserDataBlock = MPModCheckManager.DeserializeHashfullMPUserData(recievedData);
			Logger.Info("recieved modlist from user with the following info:\nPMLVersion: " + mPUserDataBlock.PMLVersion + "\nModlist:" + MPModCheckManager.GetModListAsString(mPUserDataBlock.ModData));
			MPModCheckManager.Instance.AddNetworkedPeerMods(pmi.sender, mPUserDataBlock);
		}

		[PunRPC]
		public void ClientRecieveModList(byte[] recievedData, PhotonMessageInfo pmi)
		{
			//IL_0001: 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_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: 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_0049: Unknown result type (might be due to invalid IL or missing references)
			if (!pmi.sender.IsMasterClient && !MPModCheckManager.Instance.SentModLists.Contains(pmi.sender))
			{
				MPModCheckManager.Instance.SendModlistToClient(pmi.sender);
				MPModCheckManager.Instance.SentModLists.Add(pmi.sender);
			}
			MPUserDataBlock mPUserDataBlock = MPModCheckManager.DeserializeHashlessMPUserData(recievedData);
			Logger.Info("recieved modlist from user with the following info:\nPMLVersion: " + mPUserDataBlock.PMLVersion + "\nModlist:" + MPModCheckManager.GetModListAsString(mPUserDataBlock.ModData));
			MPModCheckManager.Instance.AddNetworkedPeerMods(pmi.sender, mPUserDataBlock);
			Events.Instance.CallClientModlistRecievedEvent(pmi.sender);
		}

		[PunRPC]
		public void ClientRequestModList(PhotonMessageInfo pmi)
		{
			Logger.Info("ModMessageHelper recieved modlist request. This is a deprecated RPC and is only called by older modloader versions");
		}
	}
	[Obsolete]
	public enum MPFunction
	{
		None,
		HostOnly,
		HostRequired,
		All
	}
	public static class PMLConfig
	{
		public static SaveValue<TextAnchor> ModInfoTextAnchor = new SaveValue<TextAnchor>("ModInfoTextAnchor", (TextAnchor)0);

		public static SaveValue<bool> AutoPullReadme = new SaveValue<bool>("AutoPullReadme", @default: false);

		public static SaveValue<bool> DebugMode = new SaveValue<bool>("DebugMode", @default: false);

		public static SaveValue<bool> ZipModLoad = new SaveValue<bool>("ZipModLoad", @default: true);

		public static SaveValue<bool> ZipModMode = new SaveValue<bool>("ZipModMode", @default: false);

		public static uint DefaultMaxLoadSizeBytes = 10485760u;

		public static SaveValue<uint> MaxLoadSizeBytes = new SaveValue<uint>("MaxLoadSizeBytes", DefaultMaxLoadSizeBytes);

		public static SaveValue<DateTime> LastPMLUpdateCheck = new SaveValue<DateTime>("LastPMLUpdateCheck", DateTime.Today.AddDays(-2.0));

		public static void SetDefault()
		{
			ModInfoTextAnchor.Value = (TextAnchor)0;
		}
	}
	public abstract class PulsarMod
	{
		internal FileVersionInfo VersionInfo;

		internal byte[] ModHash;

		protected Harmony harmony;

		protected bool enabled = true;

		public virtual string License => "Proprietary";

		public virtual string ReadmeURL => string.Empty;

		public virtual string SourceURL => string.Empty;

		public virtual string Version => VersionInfo?.FileVersion;

		public virtual string Author => VersionInfo?.CompanyName;

		public virtual string ShortDescription => VersionInfo?.FileDescription;

		public virtual string LongDescription => string.Empty;

		public virtual string Name => VersionInfo?.ProductName;

		[Obsolete]
		public virtual int MPFunctionality => 0;

		public virtual int MPRequirements
		{
			get
			{
				if (MPFunctionality >= 2)
				{
					return MPFunctionality;
				}
				return 0;
			}
		}

		public virtual string VersionLink => string.Empty;

		public PulsarMod()
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Expected O, but got Unknown
			Assembly assembly = GetType().Assembly;
			harmony = new Harmony(HarmonyIdentifier());
			harmony.PatchAll(assembly);
		}

		public virtual void Unload()
		{
			ModManager.Instance.UnloadMod(this, ref harmony);
		}

		public abstract string HarmonyIdentifier();

		public virtual bool CanBeDisabled()
		{
			return false;
		}

		public virtual bool IsEnabled()
		{
			return enabled;
		}

		public virtual void Disable()
		{
			enabled = false;
		}

		public virtual void Enable()
		{
			enabled = true;
		}
	}
	[HarmonyPatch]
	internal class SaveValueManager
	{
		private static JsonSerializerSettings serializerSettings;

		private static Dictionary<Assembly, string> ModToConfigFile;

		private static Dictionary<Assembly, JObject> ModToCacheValues;

		private static List<object> AllSaveValues;

		[HarmonyPostfix]
		[HarmonyPatch(typeof(PLGlobal), "OnApplicationQuit")]
		private static void ForceSaveAllConfigsOnApplicationQuit()
		{
			Logger.Info("OnApplicationQuit");
			foreach (object allSaveValue in AllSaveValues)
			{
				Type type = allSaveValue.GetType();
				string text = (string)AccessTools.Field(type, "id").GetValue(allSaveValue);
				Assembly key = (Assembly)AccessTools.Field(type, "mod").GetValue(allSaveValue);
				object value = AccessTools.Field(type, "_value").GetValue(allSaveValue);
				ModToCacheValues[key][text] = JToken.FromObject(value);
			}
			foreach (KeyValuePair<Assembly, JObject> modToCacheValue in ModToCacheValues)
			{
				Assembly key2 = modToCacheValue.Key;
				string configFile = GetConfigFile(key2);
				File.WriteAllText(configFile, JsonConvert.SerializeObject((object)ModToCacheValues[key2], serializerSettings));
			}
		}

		public static string GetConfigFolder()
		{
			string text = Path.Combine(Directory.GetCurrentDirectory(), "ModConfigs");
			if (!Directory.Exists(text))
			{
				Directory.CreateDirectory(text);
			}
			return text;
		}

		static SaveValueManager()
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Expected O, but got Unknown
			ModToConfigFile = new Dictionary<Assembly, string>();
			ModToCacheValues = new Dictionary<Assembly, JObject>();
			AllSaveValues = new List<object>();
			serializerSettings = new JsonSerializerSettings();
			serializerSettings.Formatting = (Formatting)1;
		}

		internal static T GetValueFor<T>(SaveValue<T> saveValue, T @default)
		{
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Expected O, but got Unknown
			AllSaveValues.Add(saveValue);
			string configFile = GetConfigFile(saveValue.mod);
			if (ModToCacheValues.TryGetValue(saveValue.mod, out var value))
			{
				JToken val = default(JToken);
				if (value.TryGetValue(saveValue.id, ref val))
				{
					return val.ToObject<T>();
				}
			}
			else
			{
				ModToCacheValues.Add(saveValue.mod, new JObject());
			}
			ModToCacheValues[saveValue.mod].Add(saveValue.id, JToken.FromObject((object)@default));
			File.WriteAllText(configFile, JsonConvert.SerializeObject((object)ModToCacheValues[saveValue.mod], serializerSettings));
			return @default;
		}

		private static string GetConfigFile(Assembly mod)
		{
			if (ModToConfigFile.ContainsKey(mod))
			{
				return ModToConfigFile[mod];
			}
			string text = Path.Combine(GetConfigFolder(), mod.GetName().Name + ".json");
			ModToConfigFile.Add(mod, text);
			if (!ModToCacheValues.ContainsKey(mod) && File.Exists(text))
			{
				ModToCacheValues.Add(mod, JObject.Parse(File.ReadAllText(text)));
			}
			return text;
		}
	}
	public class SaveValue<T> : IEquatable<T>
	{
		internal string id;

		internal Assembly mod;

		internal T _value;

		public T Value
		{
			get
			{
				return _value;
			}
			set
			{
				_value = value;
			}
		}

		public SaveValue(string id, T @default)
		{
			this.id = id;
			mod = Assembly.GetCallingAssembly();
			_value = SaveValueManager.GetValueFor(this, @default);
		}

		public static implicit operator T(SaveValue<T> v)
		{
			return v._value;
		}

		public override bool Equals(object obj)
		{
			return _value.Equals(obj);
		}

		public bool Equals(T other)
		{
			return _value.Equals(other);
		}

		public override string ToString()
		{
			return _value.ToString();
		}

		public override int GetHashCode()
		{
			return _value.GetHashCode();
		}
	}
}
namespace PulsarModLoader.Utilities
{
	public static class Clipboard
	{
		public static void Copy(string text)
		{
			GUIUtility.systemCopyBuffer = text;
		}

		public static string Paste()
		{
			return GUIUtility.systemCopyBuffer;
		}
	}
	[HarmonyPatch(typeof(PLNetworkManager), "Start")]
	internal class ExceptionWarningPatch
	{
		private static void Prefix()
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected O, but got Unknown
			Application.logMessageReceived += new LogCallback(OnUnityLog);
		}

		private static void OnUnityLog(string line, string stackTrace, LogType type)
		{
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			if (((object)(LogType)(ref type)).Equals((object)(LogType)4))
			{
				string text = $"{DateTime.UtcNow.GetHashCode():X}".Substring(0, 7).ToUpper();
				string message = "<color='#" + ColorUtility.ToHtmlStringRGB(Color.red) + "'>Exception!</color> " + text;
				if ((bool)PMLConfig.DebugMode && (Object)(object)PLNetworkManager.Instance != (Object)null && (Object)(object)PLNetworkManager.Instance.LocalPlayer != (Object)null)
				{
					Messaging.Notification(message);
				}
				Logger.Info("Exception ID: " + text);
			}
		}
	}
	public static class HelperMethods
	{
		public static PLPlayer GetPlayer(string argument)
		{
			PLPlayer val = GetPlayerFromPlayerID(argument);
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
			if (argument.Length == 1)
			{
				val = GetPlayerFromClassName(argument);
			}
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
			return GetPlayerFromPlayerName(argument);
		}

		public static PLPlayer GetPlayerFromPlayerID(string ID)
		{
			if (int.TryParse(ID, out var result))
			{
				return PLServer.Instance.GetPlayerFromPlayerID(result);
			}
			return null;
		}

		public static PLPlayer GetPlayerFromPlayerID(int ID)
		{
			return PLServer.Instance.GetPlayerFromPlayerID(ID);
		}

		public static PLPlayer GetPlayerFromPlayerName(string playerName)
		{
			foreach (PLPlayer allPlayer in PLServer.Instance.AllPlayers)
			{
				if ((Object)(object)allPlayer != (Object)null && allPlayer.GetPlayerName(false).ToLower().StartsWith(playerName.ToLower()))
				{
					return allPlayer;
				}
			}
			return null;
		}

		public static PLPlayer GetPlayerFromClassName(string ClassName)
		{
			return (PLPlayer)(ClassName.ToLower().Substring(0, 1) switch
			{
				"c" => PLServer.Instance.GetCachedFriendlyPlayerOfClass(0), 
				"p" => PLServer.Instance.GetCachedFriendlyPlayerOfClass(1), 
				"s" => PLServer.Instance.GetCachedFriendlyPlayerOfClass(2), 
				"w" => PLServer.Instance.GetCachedFriendlyPlayerOfClass(3), 
				"e" => PLServer.Instance.GetCachedFriendlyPlayerOfClass(4), 
				_ => null, 
			});
		}

		public static int GetClassIDFromClassName(string ClassName, out bool Successfull)
		{
			if (ClassName == string.Empty)
			{
				Successfull = false;
				return -1;
			}
			Successfull = true;
			switch (ClassName.Substring(0, 1).ToLower())
			{
			case "c":
				return 0;
			case "p":
				return 1;
			case "s":
				return 2;
			case "w":
				return 3;
			case "e":
				return 4;
			default:
				Successfull = false;
				return -1;
			}
		}

		public static PLShipInfoBase GetShipFromLetterTag(string arg)
		{
			char c = arg.ToUpper()[0];
			foreach (PLShipInfoBase value in PLEncounterManager.Instance.AllShips.Values)
			{
				if ((Object)(object)value != (Object)null && value is PLShipInfo && value.TagID != -1 && PLGlobal.getTagChar(value.TagID) == c)
				{
					return value;
				}
			}
			return null;
		}
	}
	public static class Logger
	{
		private static readonly string LogPath;

		private static StreamWriter Stream;

		static Logger()
		{
			LogPath = Path.Combine(Directory.GetCurrentDirectory(), "PMLLog.txt");
			try
			{
				Stream = new StreamWriter(LogPath);
			}
			catch (IOException)
			{
				Stream = null;
			}
		}

		public static void Info(string message)
		{
			if (message == null)
			{
				Messaging.AntiNullReferenceException("message: null");
				return;
			}
			string text3;
			if ((bool)PMLConfig.DebugMode)
			{
				MethodBase method = new StackTrace().GetFrame(1).GetMethod();
				string text = method.DeclaringType.ToString();
				string text2 = "." + method.Name;
				if (text2.Contains("..ctor"))
				{
					text2 = text2.Replace("..ctor", string.Empty);
					text = "new " + text;
				}
				text3 = "[PML-" + text + text2 + "(" + string.Join(", ", from p in method.GetParameters()
					select p.Name) + ")] " + message;
			}
			else
			{
				text3 = "[PML] " + message;
			}
			Console.WriteLine(text3);
			if (Stream != null)
			{
				Stream.WriteLine(DateTime.Now.ToString("HH:mm:ss") + " " + text3);
				Stream.Flush();
			}
		}
	}
	public static class Messaging
	{
		private static string[] ignore = new string[5] { "ShipLog", "Centerprint", "Notification", "Echo", "ChatMessage" };

		public static void ChatMessage(PLPlayer recipient, string message, int sendingPlayerId = -1)
		{
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)recipient == (Object)null || message == null)
			{
				AntiNullReferenceException(string.Format("{0}, {1}, sendingPlayerId: {2}", ((Object)(object)recipient == (Object)null) ? "recipent: null" : "recipent: PLPlayer", (message == null) ? "message: null" : ("message: \"" + message + "\""), sendingPlayerId));
				return;
			}
			if (sendingPlayerId == -1)
			{
				sendingPlayerId = ObscuredInt.op_Implicit(PLNetworkManager.Instance.LocalPlayerID);
			}
			ChatMessage(recipient.GetPhotonPlayer(), message, sendingPlayerId);
		}

		public static void ChatMessage(PhotonPlayer recipient, string message, int sendingPlayerId = -1)
		{
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			if (recipient == null || message == null)
			{
				AntiNullReferenceException(string.Format("{0}, {1}, sendingPlayerId: {2}", (recipient == null) ? "recipent: null" : "recipent: PLPlayer", (message == null) ? "message: null" : ("message: \"" + message + "\""), sendingPlayerId));
				return;
			}
			if (sendingPlayerId == -1)
			{
				sendingPlayerId = ObscuredInt.op_Implicit(PLNetworkManager.Instance.LocalPlayerID);
			}
			((MonoBehaviour)PLServer.Instance).photonView.RPC("TeamMessage", recipient, new object[2] { message, sendingPlayerId });
		}

		public static void ChatMessage(PhotonTargets targets, string message, int sendingPlayerId = -1)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			if (message == null)
			{
				AntiNullReferenceException(string.Format("targets: {0}, {1}, sendingPlayerId: {2}", targets, (message == null) ? "message: null" : ("message: \"" + message + "\""), sendingPlayerId));
				return;
			}
			if (sendingPlayerId == -1)
			{
				sendingPlayerId = ObscuredInt.op_Implicit(PLNetworkManager.Instance.LocalPlayerID);
			}
			((MonoBehaviour)PLServer.Instance).photonView.RPC("TeamMessage", targets, new object[2] { message, sendingPlayerId });
		}

		public static void Echo(PLPlayer recipient, string message)
		{
			if ((Object)(object)recipient == (Object)null || message == null)
			{
				AntiNullReferenceException((((Object)(object)recipient == (Object)null) ? "recipent: null" : "recipent: PLPlayer") + ", " + ((message == null) ? "message: null" : ("message: \"" + message + "\"")));
			}
			else
			{
				Echo(recipient.GetPhotonPlayer(), message);
			}
		}

		public static void Echo(PhotonPlayer recipient, string message)
		{
			if (recipient == null || message == null)
			{
				AntiNullReferenceException(((recipient == null) ? "recipent: null" : "recipent: PhotonPlayer") + ", " + ((message == null) ? "message: null" : ("message: \"" + message + "\"")));
				return;
			}
			((MonoBehaviour)PLServer.Instance).photonView.RPC("ConsoleMessage", recipient, new object[1] { message });
		}

		public static void Echo(PhotonTargets targets, string message)
		{
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			if (message == null)
			{
				AntiNullReferenceException(string.Format("targets: {0}, {1}", targets, (message == null) ? "message: null" : ("message: \"" + message + "\"")));
				return;
			}
			((MonoBehaviour)PLServer.Instance).photonView.RPC("ConsoleMessage", targets, new object[1] { message });
		}

		public static void Notification(string message, PLPlayer recipient = null, int subjectPlayerId = 0, int durationMs = 6000, bool addToShipLog = false)
		{
			if ((Object)(object)recipient == (Object)null && (Object)(object)PLNetworkManager.Instance != (Object)null)
			{
				recipient = PLNetworkManager.Instance.LocalPlayer;
			}
			Notification(message, recipient.GetPhotonPlayer(), subjectPlayerId, durationMs, addToShipLog);
		}

		public static void Notification(string message, PhotonPlayer recipient, int subjectPlayerId = 0, int durationMs = 6000, bool addToShipLog = false)
		{
			if ((Object)(object)PLServer.Instance == (Object)null)
			{
				Logger.Info("Notification attempted and PLServer was null. Message: " + message);
			}
			else if (recipient == null || message == null)
			{
				AntiNullReferenceException(string.Format("{0}, {1}, subjectPlayerId: {2}, durationMs: {3}, addToShipLog: {4}", (message == null) ? "message: null" : ("message: \"" + message + "\""), (recipient == null) ? "recipent: null" : "recipent: PLPlayer", subjectPlayerId, durationMs, addToShipLog));
			}
			else
			{
				((MonoBehaviour)PLServer.Instance).photonView.RPC("AddNotification", recipient, new object[4]
				{
					message,
					subjectPlayerId,
					PLServer.Instance.GetEstimatedServerMs() + durationMs,
					addToShipLog
				});
			}
		}

		public static void Notification(string message, PhotonTargets targets, int subjectPlayerId = 0, int durationMs = 6000, bool addToShipLog = false)
		{
			//IL_0099: 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)
			if ((Object)(object)PLServer.Instance == (Object)null)
			{
				Logger.Info("Notification attempted and PLServer was null. Message: " + message);
			}
			else if (message == null)
			{
				AntiNullReferenceException(string.Format("{0}, targets: {1}, subjectPlayerId: {2}, durationMs: {3}, addToShipLog: {4}", (message == null) ? "message: null" : ("message: \"" + message + "\""), targets, subjectPlayerId, durationMs, addToShipLog));
			}
			else
			{
				((MonoBehaviour)PLServer.Instance).photonView.RPC("AddNotification", targets, new object[4]
				{
					message,
					subjectPlayerId,
					PLServer.Instance.GetEstimatedServerMs() + durationMs,
					addToShipLog
				});
			}
		}

		public static void Centerprint(string message, PLPlayer recipient, string tag = "msg", Color color = default(Color), EWarningType type = 0)
		{
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)recipient == (Object)null || message == null || tag == null)
			{
				AntiNullReferenceException((((Object)(object)recipient == (Object)null) ? "recipent: null" : "recipent: PLPlayer") + ", " + ((message == null) ? "message: null" : ("message: \"" + message + "\"")) + ", ..., " + ((tag == null) ? "tag: null" : ("tag: \"" + tag + "\"")));
			}
			else
			{
				Centerprint(message, recipient.GetPhotonPlayer(), tag, color, type);
			}
		}

		public static void Centerprint(string message, PhotonPlayer recipient, string tag = "msg", Color color = default(Color), EWarningType type = 0)
		{
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Expected I4, but got Unknown
			if (recipient == null || message == null || tag == null)
			{
				AntiNullReferenceException(((recipient == null) ? "recipent: null" : "recipent: PhotonPlayer") + ", " + ((message == null) ? "message: null" : ("message: \"" + message + "\"")) + ", ..., " + ((tag == null) ? "tag: null" : ("tag: \"" + tag + "\"")));
			}
			else
			{
				((MonoBehaviour)PLServer.Instance).photonView.RPC("AddCrewWarning", recipient, new object[4]
				{
					message,
					color,
					(int)type,
					tag
				});
			}
		}

		public static void Centerprint(string message, PhotonTargets targets, string tag = "msg", Color color = default(Color), EWarningType type = 0)
		{
			//IL_006b: 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_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Expected I4, but got Unknown
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			if (message == null || tag == null)
			{
				AntiNullReferenceException(string.Format("targets: {0}, {1}, {2}", targets, (message == null) ? "message: null" : ("message: \"" + message + "\""), (tag == null) ? "tag: null" : ("tag: \"" + tag + "\"")));
				return;
			}
			((MonoBehaviour)PLServer.Instance).photonView.RPC("AddCrewWarning", targets, new object[4]
			{
				message,
				color,
				(int)type,
				tag
			});
		}

		public static void ShipLog(string message, string tag = "msg", Color color = default(Color), bool addOnlyLocally = false, PLShipInfoBase source = null, PLShipInfoBase destination = null, int turretID = -1, int damage = 0)
		{
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			if (PhotonNetwork.isMasterClient)
			{
				if (message == null || tag == null)
				{
					AntiNullReferenceException(((message == null) ? "message: null" : ("message: \"" + message + "\"")) + ", " + ((tag == null) ? "tag: null" : ("tag: \"" + tag + "\"")) + ", ..., " + (((Object)(object)source == (Object)null) ? "null source" : $"source: \"{source}\"") + ", " + (((Object)(object)destination == (Object)null) ? "null destination" : $"destination: \"{destination}\""));
				}
				else
				{
					PLServer.Instance.AddToShipLog(tag, message, color, addOnlyLocally, source, destination, turretID, damage);
				}
			}
		}

		internal static void AntiNullReferenceException(string args)
		{
			StackTrace stackTrace = new StackTrace();
			MethodBase method = stackTrace.GetFrame(1).GetMethod();
			MethodBase methodBase = stackTrace.GetFrames().Skip(1).FirstOrDefault((StackFrame f) => !ignore.Any((string i) => i == f.GetMethod().Name))?.GetMethod();
			string[] obj = new string[11]
			{
				"NullReferenceException! Target -> ",
				method.Name,
				"(",
				args,
				"); Caller -> ",
				methodBase?.ReflectedType?.FullName,
				".",
				methodBase?.Name,
				"(",
				null,
				null
			};
			object obj2;
			if ((object)methodBase == null)
			{
				obj2 = null;
			}
			else
			{
				ParameterInfo[] parameters = methodBase.GetParameters();
				if (parameters == null)
				{
					obj2 = null;
				}
				else
				{
					object[] array = parameters;
					obj2 = Extensions.ToStringFull(array);
				}
			}
			obj[9] = (string)obj2;
			obj[10] = ");";
			Logger.Info(string.Concat(obj));
			if ((bool)PMLConfig.DebugMode)
			{
				Notification("NullReferenceException! Check the logs!");
			}
		}
	}
	internal static class ModUpdateCheck
	{
		internal struct VersionFile
		{
			public string Version;

			public string DownloadLink;
		}

		internal class UpdateModInfo
		{
			public PulsarMod Mod;

			public VersionFile Data;

			public bool IsUpdated = false;
		}

		internal static bool IsUpdateAviable(PulsarMod mod)
		{
			return false;
		}

		private static bool CompareVersions(string current, string fromServer)
		{
			int[] array = current.Split(new char[1] { '.' }, StringSplitOptions.RemoveEmptyEntries).Select(int.Parse).ToArray();
			int[] array2 = fromServer.Split(new char[1] { '.' }, StringSplitOptions.RemoveEmptyEntries).Select(int.Parse).ToArray();
			for (int i = 0; i < array.Length; i++)
			{
				if (array[i] > array2[i])
				{
					return false;
				}
				if (array[i] < array2[i])
				{
					return true;
				}
			}
			if (array2.Length > array.Length)
			{
				return true;
			}
			return false;
		}

		internal static void UpdateMod(UpdateModInfo info)
		{
			string fileName = info.Mod.VersionInfo.FileName;
			using (WebClient webClient = new WebClient())
			{
				webClient.Headers.Add("user-agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.71 Safari/537.36");
				byte[] bytes = webClient.DownloadData(info.Data.DownloadLink);
				File.WriteAllBytes(fileName, bytes);
			}
			info.IsUpdated = true;
		}
	}
}
namespace PulsarModLoader.Utilities.Uploaders
{
	internal interface IUploader
	{
		string UploadFile(string filePath);
	}
	internal class TransferShUploader : IUploader
	{
		private readonly Uri uploadUri = new Uri("https://transfer.sh/");

		public string UploadFile(string filePath)
		{
			using WebClient webClient = new WebClient();
			return Encoding.UTF8.GetString(webClient.UploadFile(uploadUri, "PUT", filePath)).TrimEnd(new char[1]);
		}
	}
}
namespace PulsarModLoader.SaveData
{
	[HarmonyPatch(typeof(PLUILoadMenu), "Update")]
	internal class DisplayModdedSavePatch
	{
		public static List<string> MFileNames = new List<string>();

		private static string AppendModdedLine(string originalText, PLUILoadMenu instance)
		{
			string text = PLNetworkManager.Instance.FileNameToRelative(ObscuredString.op_Implicit(((SaveGameDataBasic)instance.DataToLoad).FileName));
			if (text.StartsWith("Saves/"))
			{
				text = text.Remove(0, 6);
			}
			if (instance.DataToLoad != null && MFileNames.Contains(text))
			{
				originalText = originalText + "\n<color=yellow>Modded</color>" + SaveDataManager.ReadMods;
			}
			return originalText;
		}

		private static string CheckAddPMLSaveFileTag(string inFileName)
		{
			if (MFileNames.Contains(inFileName))
			{
				return "<color=yellow>M</color> " + inFileName;
			}
			return inFileName;
		}

		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Expected O, but got Unknown
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Expected O, but got Unknown
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Expected O, but got Unknown
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Expected O, but got Unknown
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Expected O, but got Unknown
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Expected O, but got Unknown
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Expected O, but got Unknown
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Expected O, but got Unknown
			List<CodeInstruction> list = new List<CodeInstruction>();
			list.Add(new CodeInstruction(OpCodes.Ldarg_0, (object)null));
			list.Add(new CodeInstruction(OpCodes.Ldfld, (object)AccessTools.Field(typeof(PLUILoadMenu), "GameInfoLabel")));
			list.Add(new CodeInstruction(OpCodes.Ldloc_S, (object)null));
			List<CodeInstruction> targetSequence = list;
			list = new List<CodeInstruction>();
			list.Add(new CodeInstruction(OpCodes.Ldarg_0, (object)null));
			list.Add(new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(DisplayModdedSavePatch), "AppendModdedLine", (Type[])null, (Type[])null)));
			List<CodeInstruction> patchSequence = list;
			IEnumerable<CodeInstruction> instructions2 = HarmonyHelpers.PatchBySequence(instructions, targetSequence, patchSequence, HarmonyHelpers.PatchMode.AFTER, HarmonyHelpers.CheckMode.NONNULL);
			targetSequence = new List<CodeInstruction>
			{
				new CodeInstruction(OpCodes.Ldloc_S, (object)null),
				new CodeInstruction(OpCodes.Ldfld, (object)null),
				new CodeInstruction(OpCodes.Ldloc_S, (object)null)
			};
			list = new List<CodeInstruction>();
			list.Add(new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(DisplayModdedSavePatch), "CheckAddPMLSaveFileTag", (Type[])null, (Type[])null)));
			patchSequence = list;
			return HarmonyHelpers.PatchBySequence(instructions2, targetSequence, patchSequence, HarmonyHelpers.PatchMode.AFTER, HarmonyHelpers.CheckMode.NONNULL);
		}
	}
	[HarmonyPatch(typeof(PLSaveGameIO), "AddSaveGameDataBasicFromDir")]
	internal class ListModdedSavesPatch
	{
		private static void Postfix()
		{
			List<string> list = new List<string>();
			foreach (SaveGameDataBasic item in PLSaveGameIO.Instance.SaveGamesBasic)
			{
				string text = ObscuredString.op_Implicit(item.FileName);
				if (SaveDataManager.IsFileModded(text))
				{
					text = PLNetworkManager.Instance.FileNameToRelative(text);
					if (text.StartsWith("Saves/"))
					{
						text = text.Remove(0, 6);
					}
					list.Add(text);
				}
			}
			DisplayModdedSavePatch.MFileNames = list;
		}
	}
	public abstract class PMLSaveData
	{
		public PulsarMod MyMod;

		public virtual uint VersionID => 0u;

		public abstract string Identifier();

		public abstract byte[] SaveData();

		public abstract void LoadData(byte[] Data, uint VersionID);
	}
	internal class SaveDataManager
	{
		public static SaveDataManager Instance;

		public static string ReadMods = "";

		public static string SaveDir = Directory.GetCurrentDirectory() + "/Saves";

		public static string LocalSaveDir = SaveDir + "/Local";

		private List<PMLSaveData> SaveConfigs = new List<PMLSaveData>();

		public int SaveCount = 0;

		public SaveDataManager()
		{
			ModManager.Instance.OnModSuccessfullyLoaded += OnModLoaded;
			ModManager.Instance.OnModUnloaded += OnModRemoved;
			Instance = this;
		}

		private void OnModLoaded(string modName, PulsarMod mod)
		{
			mod.GetType().Assembly.GetTypes().AsParallel().ForAll(delegate(Type type)
			{
				if (typeof(PMLSaveData).IsAssignableFrom(type) && !type.IsAbstract)
				{
					PMLSaveData pMLSaveData = (PMLSaveData)Activator.CreateInstance(type);
					pMLSaveData.MyMod = mod;
					SaveConfigs.Add(pMLSaveData);
					SaveCount = SaveConfigs.Count;
				}
			});
		}

		private void OnModRemoved(PulsarMod mod)
		{
			List<PMLSaveData> saveConfigsToRemove = new List<PMLSaveData>();
			SaveConfigs.AsParallel().ForAll(delegate(PMLSaveData arg)
			{
				if (arg.GetType().Assembly == mod.GetType().Assembly)
				{
					saveConfigsToRemove.Add(arg);
				}
			});
			for (byte b = 0; b < saveConfigsToRemove.Count; b++)
			{
				SaveConfigs.Remove(saveConfigsToRemove[b]);
				SaveCount = SaveConfigs.Count;
			}
		}

		public void SaveDatas(BinaryWriter writer)
		{
			if (SaveCount == 0)
			{
				writer.Close();
				return;
			}
			writer.Write(0u);
			int num = 0;
			writer.Write(SaveCount);
			foreach (PMLSaveData saveConfig in SaveConfigs)
			{
				try
				{
					Logger.Info($"Writing: {saveConfig.MyMod.HarmonyIdentifier()}::{saveConfig.Identifier()} pos: {writer.BaseStream.Position}");
					byte[] array = saveConfig.SaveData();
					writer.Write(saveConfig.MyMod.HarmonyIdentifier());
					writer.Write(saveConfig.Identifier());
					writer.Write(saveConfig.VersionID);
					writer.Write(array.Length);
					num += array.Length;
					if (array.Length != 0)
					{
						writer.Write(array);
					}
				}
				catch (Exception ex)
				{
					writer.Write("PMLSaveDataManager.DataCorruptionWarning");
					writer.Write("DataCorruptionWarning");
					writer.Write(0u);
					writer.Write(0);
					Logger.Info("Failed to save a mod data.\n" + ex.Message + "\n");
				}
			}
			writer.Write(ulong.MaxValue);
			writer.Close();
			Logger.Info($"PMLSaveManager has finished saving file. Bytes: {num}");
		}

		public void LoadDatas(BinaryReader reader, bool ldarg3)
		{
			//IL_0290: Unknown result type (might be due to invalid IL or missing references)
			//IL_029a: Expected O, but got Unknown
			//IL_02d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02dc: Expected O, but got Unknown
			if (reader.BaseStream.Length <= reader.BaseStream.Position + 1 || !ldarg3)
			{
				reader.Close();
				return;
			}
			uint num = reader.ReadUInt32();
			int num2 = reader.ReadInt32();
			string text = "";
			string text2 = "";
			string text3 = "";
			int num3 = 0;
			for (int i = 0; i < num2; i++)
			{
				string text4 = reader.ReadString();
				string text5 = reader.ReadString();
				uint num4 = reader.ReadUInt32();
				int num5 = reader.ReadInt32();
				Logger.Info($"Reading SaveData: {text4}::{text5} SaveDataVersion: {num4} bytecount: {num5} Pos: {reader.BaseStream.Position}");
				text3 = text3 + "\n" + text4;
				num3 += num5;
				bool flag = false;
				foreach (PMLSaveData saveConfig in SaveConfigs)
				{
					if (!(saveConfig.MyMod.HarmonyIdentifier() == text4) || !(saveConfig.Identifier() == text5))
					{
						continue;
					}
					if (num4 != saveConfig.VersionID)
					{
						Logger.Info($"Mismatched SaveData VersionID. Read: {num4} SaveData: {saveConfig.VersionID}");
						text2 = text2 + "\n" + text4;
					}
					if (num5 > 0)
					{
						try
						{
							saveConfig.LoadData(reader.ReadBytes(num5), num4);
						}
						catch (Exception ex)
						{
							Logger.Info("Failed to load " + text4 + "::" + text5 + "\n" + ex.Message);
						}
					}
					flag = true;
				}
				if (!flag)
				{
					reader.BaseStream.Position += num5;
					text = text + "\n" + text4;
				}
			}
			reader.Close();
			Logger.Info($"PMLSaveManager has finished reading file. Bytes: {num3}");
			ReadMods = text3;
			if (text.Length > 0)
			{
				PLNetworkManager.Instance.MainMenu.AddActiveMenu((PLMenu)new PLErrorMessageMenu("Warning: Found save data for following missing mods: " + text));
				Logger.Info("Warning: Found save data for following missing mods: " + text);
			}
			if (!string.IsNullOrEmpty(text2))
			{
				PLNetworkManager.Instance.MainMenu.AddActiveMenu((PLMenu)new PLErrorMessageMenu("Warning: The following mods used in this save have been updated: " + text2));
				Logger.Info("Warning: The following mods used in this save have been updated: " + text2);
			}
		}

		public static bool IsFileModded(string inFileName)
		{
			bool result = false;
			if (File.Exists(inFileName))
			{
				FileStream fileStream = File.OpenRead(inFileName);
				fileStream.Position = fileStream.Length - 8;
				using BinaryReader binaryReader = new BinaryReader(fileStream);
				if (binaryReader.ReadUInt64() == ulong.MaxValue)
				{
					result = true;
				}
			}
			return result;
		}
	}
	[HarmonyPatch(typeof(PLSaveGameIO), "SaveToFile")]
	internal class SavePatch
	{
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Expected O, but got Unknown
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Expected O, but got Unknown
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Expected O, but got Unknown
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Expected O, but got Unknown
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Expected O, but got Unknown
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Expected O, but got Unknown
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Expected O, but got Unknown
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Expected O, but got Unknown
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Expected O, but got Unknown
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Expected O, but got Unknown
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ba: Expected O, but got Unknown
			//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ea: Expected O, but got Unknown
			//IL_01f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fd: Expected O, but got Unknown
			//IL_021b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0225: Expected O, but got Unknown
			List<CodeInstruction> list = instructions.ToList();
			List<CodeInstruction> list2 = new List<CodeInstruction>();
			list2.Add(new CodeInstruction(OpCodes.Callvirt, (object)null));
			list2.Add(new CodeInstruction(OpCodes.Ldsfld, (object)AccessTools.Field(typeof(PLServer), "Instance")));
			list2.Add(new CodeInstruction(OpCodes.Ldfld, (object)AccessTools.Field(typeof(PLServer), "AllPDAs")));
			list2.Add(new CodeInstruction(OpCodes.Callvirt, (object)null));
			List<CodeInstruction> targetSequence = list2;
			int num = HarmonyHelpers.FindSequence(instructions, targetSequence, HarmonyHelpers.CheckMode.NONNULL) - 3;
			list2 = new List<CodeInstruction>();
			list2.Add(new CodeInstruction(OpCodes.Ldsfld, (object)AccessTools.Field(typeof(PLServer), "Instance")));
			list2.Add(new CodeInstruction(OpCodes.Callvirt, (object)AccessTools.Method(typeof(PLServer), "get_AllPSIs", (Type[])null, (Type[])null)));
			list2.Add(new CodeInstruction(OpCodes.Callvirt, (object)null));
			targetSequence = list2;
			int num2 = HarmonyHelpers.FindSequence(instructions, targetSequence, HarmonyHelpers.CheckMode.NONNULL) - 5;
			targetSequence = list.GetRange(num, num2 - num);
			list2 = new List<CodeInstruction>();
			list2.Add(new CodeInstruction(OpCodes.Ldarg_0, (object)null));
			list2.Add(new CodeInstruction(OpCodes.Ldloc_3, (object)null));
			list2.Add(new CodeInstruction(OpCodes.Callvirt, (object)AccessTools.Method(typeof(SavePatch), "Replacement", (Type[])null, (Type[])null)));
			List<CodeInstruction> patchSequence = list2;
			instructions = HarmonyHelpers.PatchBySequence(instructions, targetSequence, patchSequence, HarmonyHelpers.PatchMode.REPLACE);
			list2 = new List<CodeInstruction>();
			list2.Add(new CodeInstruction(OpCodes.Ldloc_3, (object)null));
			list2.Add(new CodeInstruction(OpCodes.Callvirt, (object)AccessTools.Method(typeof(BinaryWriter), "Close", (Type[])null, (Type[])null)));
			targetSequence = list2;
			list2 = new List<CodeInstruction>();
			list2.Add(new CodeInstruction(OpCodes.Ldsfld, (object)AccessTools.Field(typeof(SaveDataManager), "Instance")));
			list2.Add(new CodeInstruction(OpCodes.Ldloc_3, (object)null));
			list2.Add(new CodeInstruction(OpCodes.Callvirt, (object)AccessTools.Method(typeof(SaveDataManager), "SaveDatas", (Type[])null, (Type[])null)));
			patchSequence = list2;
			return HarmonyHelpers.PatchBySequence(instructions, targetSequence, patchSequence, HarmonyHelpers.PatchMode.BEFORE);
		}

		public static void Replacement(PLSaveGameIO __instance, BinaryWriter binaryWriter)
		{
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: 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)
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			foreach (PLPersistantDialogueActor allPDA in PLServer.Instance.AllPDAs)
			{
				if (allPDA == null)
				{
					continue;
				}
				PLPersistantDialogueActorNPC val = (PLPersistantDialogueActorNPC)(object)((allPDA is PLPersistantDialogueActorNPC) ? allPDA : null);
				PLPersistantDialogueActorShip val2 = (PLPersistantDialogueActorShip)(object)((allPDA is PLPersistantDialogueActorShip) ? allPDA : null);
				bool flag = false;
				if (val != null)
				{
					binaryWriter.Write(0);
					binaryWriter.Write(ObscuredBool.op_Implicit(((PLPersistantDialogueActor)val).Hostile));
					binaryWriter.Write(ObscuredString.op_Implicit(((PLPersistantDialogueActor)val).DialogueActorID));
					try
					{
						binaryWriter.Write(ObscuredString.op_Implicit(val.NPCName));
					}
					catch (ArgumentNullException)
					{
						Debug.DebugBreak();
					}
					flag = true;
				}
				else if (val2 != null)
				{
					binaryWriter.Write(1);
					binaryWriter.Write(ObscuredBool.op_Implicit(((PLPersistantDialogueActor)val2).Hostile));
					binaryWriter.Write(ObscuredString.op_Implicit(((PLPersistantDialogueActor)val2).DialogueActorID));
					binaryWriter.Write(ObscuredString.op_Implicit(val2.ShipName));
					binaryWriter.Write(ObscuredBool.op_Implicit(val2.SpecialActionCompleted));
					binaryWriter.Write(val2.LinesToShowPercent.Count);
					foreach (ObscuredInt item in val2.LinesToShowPercent)
					{
						binaryWriter.Write(ObscuredInt.op_Implicit(item));
					}
					flag = true;
				}
				else
				{
					binaryWriter.Write(2);
					flag = true;
				}
				if (!flag)
				{
					continue;
				}
				int count = allPDA.LinesAleradyDisplayed.Count;
				binaryWriter.Write(count);
				foreach (ObscuredInt item2 in allPDA.LinesAleradyDisplayed)
				{
					int value = ObscuredInt.op_Implicit(item2);
					binaryWriter.Write(value);
				}
			}
		}
	}
	[HarmonyPatch(typeof(PLSaveGameIO), "LoadFromFile")]
	internal class LoadPatch
	{
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Expected O, but got Unknown
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Expected O, but got Unknown
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Expected O, but got Unknown
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Expected O, but got Unknown
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Expected O, but got Unknown
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Expected O, but got Unknown
			List<CodeInstruction> list = new List<CodeInstruction>();
			list.Add(new CodeInstruction(OpCodes.Callvirt, (object)AccessTools.Method(typeof(BinaryReader), "Close", (Type[])null, (Type[])null)));
			List<CodeInstruction> targetSequence = list;
			list = new List<CodeInstruction>();
			list.Add(new CodeInstruction(OpCodes.Pop, (object)null));
			list.Add(new CodeInstruction(OpCodes.Ldsfld, (object)AccessTools.Field(typeof(SaveDataManager), "Instance")));
			list.Add(new CodeInstruction(OpCodes.Ldloc_1, (object)null));
			list.Add(new CodeInstruction(OpCodes.Ldarg_3, (object)null));
			list.Add(new CodeInstruction(OpCodes.Callvirt, (object)AccessTools.Method(typeof(SaveDataManager), "LoadDatas", (Type[])null, (Type[])null)));
			List<CodeInstruction> patchSequence = list;
			return HarmonyHelpers.PatchBySequence(instructions, targetSequence, patchSequence, HarmonyHelpers.PatchMode.REPLACE);
		}
	}
}
namespace PulsarModLoader.Patches
{
	[HarmonyPatch(typeof(NetworkingPeer), "ExecuteRpc")]
	internal class AllowPMLRPCPatch
	{
		private static bool PatchMethod(bool ShouldContinue, string MethodName)
		{
			switch (MethodName)
			{
			default:
				if (!(MethodName == "ClientRequestModList"))
				{
					return ShouldContinue;
				}
				goto case "ReceiveMessage";
			case "ReceiveMessage":
			case "ClientRecieveModList":
			case "ServerRecieveModList":
				return true;
			}
		}

		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Expected O, but got Unknown
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Expected O, but got Unknown
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Expected O, but got Unknown
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Expected O, but got Unknown
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Expected O, but got Unknown
			List<CodeInstruction> targetSequence = new List<CodeInstruction>
			{
				new CodeInstruction(OpCodes.Brfalse_S, (object)null),
				new CodeInstruction(OpCodes.Ldc_I4_1, (object)null),
				new CodeInstruction(OpCodes.Stloc_S, (object)null),
				new CodeInstruction(OpCodes.Ldloc_S, (object)null)
			};
			List<CodeInstruction> list = new List<CodeInstruction>();
			list.Add(new CodeInstruction(OpCodes.Ldloc_2, (object)null));
			list.Add(new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(AllowPMLRPCPatch), "PatchMethod", (Type[])null, (Type[])null)));
			List<CodeInstruction> patchSequence = list;
			return HarmonyHelpers.PatchBySequence(instructions, targetSequence, patchSequence, HarmonyHelpers.PatchMode.AFTER, HarmonyHelpers.CheckMode.NEVER);
		}
	}
	public static class AntiCheatBypass
	{
		[HarmonyPatch(typeof(PLGameStatic), "OnInjectionCheatDetected")]
		private class InjectionCheatDetectedPatch
		{
			private static bool Prefix()
			{
				return false;
			}
		}

		[HarmonyPatch(typeof(PLGameStatic), "OnInjectionCheatDetected_Private")]
		public class OnInjectionCheatDetected_PrivatePatch
		{
			public static bool Prefix()
			{
				return false;
			}
		}

		[HarmonyPatch(typeof(PLGameStatic), "OnSpeedHackCheatDetected")]
		private class OnSpeedHackCheatDetectedPatch
		{
			private static bool Prefix()
			{
				return false;
			}
		}

		[HarmonyPatch(typeof(PLGameStatic), "OnTimeCheatDetected")]
		private class OnTimeCheatDetectedPatch
		{
			private static bool Prefix()
			{
				return false;
			}
		}

		[HarmonyPatch(typeof(PLGameStatic), "OnObscuredCheatDetected")]
		private class OnObscuredCheatDetectedPatch
		{
			private static bool Prefix()
			{
				return false;
			}
		}
	}
	[HarmonyPatch(typeof(PLInGameUI), "Update")]
	internal class DebugReadout
	{
		private static void Postfix(PLInGameUI __instance)
		{
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			if ((bool)PMLConfig.DebugMode && (Object)(object)PLServer.Instance != (Object)null && (Object)(object)PLEncounterManager.Instance != (Object)null && (Object)(object)PLNetworkManager.Instance != (Object)null && GameVersion.Version != string.Empty)
			{
				Vector3 val;
				if ((Object)(object)PLNetworkManager.Instance.LocalPlayer != (Object)null)
				{
					PLPawn pawn = PLNetworkManager.Instance.LocalPlayer.GetPawn();
					val = (((Object)(object)pawn != (Object)null) ? ((Component)pawn).transform.position : Vector3.zero);
				}
				else
				{
					val = Vector3.zero;
				}
				PLPersistantEncounterInstance currentPersistantEncounterInstance = PLEncounterManager.Instance.GetCurrentPersistantEncounterInstance();
				int num = ((currentPersistantEncounterInstance != null) ? ((ObscuredInt)(ref currentPersistantEncounterInstance.LevelID)).GetDecrypted() : (-1));
				PLSectorInfo currentSector = PLServer.GetCurrentSector();
				object obj;
				if (currentSector == null)
				{
					obj = "--";
				}
				else
				{
					ESectorVisualIndication visualIndication = currentSector.VisualIndication;
					obj = ((object)(ESectorVisualIndication)(ref visualIndication)).ToString();
				}
				string text = (string)obj;
				int num2 = currentSector?.ID ?? (-1);
				PLGlobal.SafeLabelSetText(__instance.CurrentVersionLabel, $"{GameVersion.Version}\nPOS: {val}, Level ID: {num}, Sector: {num2}, Visual: {text}");
			}
		}
	}
	[HarmonyPriority(800)]
	[HarmonyPatch(typeof(PLCachedFormatString<int, string, string>), "ToString", new Type[]
	{
		typeof(int),
		typeof(string),
		typeof(string)
	})]
	internal class GameVersion
	{
		internal static string Version = string.Empty;

		public static readonly string PMLVersion = FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location).FileVersion;

		private static void Prefix(ref string Obj3)
		{
			if (Obj3.Contains("v"))
			{
				Obj3 = Obj3 + "    PML " + PMLVersion + (ModManager.IsOldVersion ? " (OLD)" : string.Empty);
			}
		}

		private static void Postfix(string __result)
		{
			Version = __result;
		}
	}
	[HarmonyPatch(typeof(PLLevelSync), "LateUpdate")]
	internal class FreeCursor
	{
		private static bool PatchMethod()
		{
			return GUIMain.Instance.ShouldUnlockCursor() || PLNetworkManager.Instance.CurrentGame.ShouldShowClassSelectionScreen();
		}

		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Expected O, but got Unknown
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Expected O, but got Unknown
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Expected O, but got Unknown
			List<CodeInstruction> targetSequence = new List<CodeInstruction>
			{
				new CodeInstruction(OpCodes.Ldsfld, (object)null),
				new CodeInstruction(OpCodes.Ldfld, (object)null),
				new CodeInstruction(OpCodes.Callvirt, (object)null)
			};
			List<CodeInstruction> list = new List<CodeInstruction>();
			list.Add(new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(FreeCursor), "PatchMethod", (Type[])null, (Type[])null)));
			List<CodeInstruction> patchSequence = list;
			return HarmonyHelpers.PatchBySequence(instructions, targetSequence, patchSequence, HarmonyHelpers.PatchMode.REPLACE, HarmonyHelpers.CheckMode.NONNULL);
		}
	}
	[HarmonyPatch(typeof(PLMouseLook), "Update")]
	internal class LockMouselook
	{
		private static bool PatchMethod()
		{
			if ((Object)(object)GUIMain.Instance == (Object)null)
			{
				return false;
			}
			return ((PLInputBase)PLInput.Instance).GetButton((EInputActionName)19) || GUIMain.Instance.ShouldUnlockCursor();
		}

		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Expected O, but got Unknown
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Expected O, but got Unknown
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Expected O, but got Unknown
			List<CodeInstruction> targetSequence = new List<CodeInstruction>
			{
				new CodeInstruction(OpCodes.Ldsfld, (object)null),
				new CodeInstruction(OpCodes.Ldc_I4_S, (object)null),
				new CodeInstruction(OpCodes.Callvirt, (object)null)
			};
			List<CodeInstruction> list = new List<CodeInstruction>();
			list.Add(new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(LockMouselook), "PatchMethod", (Type[])null, (Type[])null)));
			List<CodeInstruction> patchSequence = list;
			return HarmonyHelpers.PatchBySequence(instructions, targetSequence, patchSequence, HarmonyHelpers.PatchMode.REPLACE, HarmonyHelpers.CheckMode.NONNULL);
		}
	}
	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();
			if (showDebugOutput && GetCallingAssemblyName(out var assemblyname, out var className, out var methodName))
			{
				Logger.Info("[PatchBySequence] Called by assembly: " + assemblyname + ", class: " + className + ", method: " + methodName);
			}
			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)
						{
							Logger.Info($"Found {targetSequence.ElementAt(j).opcode} at {i + j}");
						}
					}
					if (!flag)
					{
						continue;
					}
					if (patchMode == PatchMode.BEFORE || patchMode == PatchMode.AFTER)
					{
						int index = ((patchMode == PatchMode.AFTER) ? (i + num) : i);
						list.InsertRange(index, patchSequence.Select((CodeInstruction c) => c.FullClone()));
						break;
					}
					if (patchMode == PatchMode.REPLACE)
					{
						list.RemoveRange(i, num);
						list.InsertRange(i, patchSequence.Select((CodeInstruction c) => c.FullClone()));
						break;
					}
					throw new ArgumentException($"Argument PatchMode patchMode == {patchMode}; invalid value!");
				}
				StringBuilder stringBuilder = new StringBuilder();
				if (!showDebugOutput && GetCallingAssemblyName(out var assemblyname2, out var className2, out var methodName2))
				{
					Logger.Info("[PatchBySequence] Called by assembly: " + assemblyname2 + ", class: " + className2 + ", method: " + methodName2);
				}
				stringBuilder.AppendLine("Failed to patch by sequence: 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]);
				}
				Logger.Info(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();
			if (showDebugOutput && GetCallingAssemblyName(out var assemblyname, out var className, out var methodName))
			{
				Logger.Info("[FindSequence] Called by assembly: " + assemblyname + ", class: " + className + ", method: " + methodName);
			}
			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)
						{
							Logger.Info($"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]);
				}
				Logger.Info(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());
			}
			Logger.Info(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_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Expected O, but got Unknown
			return new ExceptionBlock(block.blockType, block.catchType);
		}

		public static bool GetCallingAssemblyName(out string assemblyname, out string className, out string methodName)
		{
			assemblyname = "Unknown";
			className = "Unknown";
			methodName = "Unknown";
			StackTrace stackTrace = new StackTrace(2);
			int num = 5;
			StackFrame[] frames = stackTrace.GetFrames();
			foreach (StackFrame stackFrame in frames)
			{
				if (num <= 0)
				{
					break;
				}
				MethodBase method = stackFrame.GetMethod();
				if (method == null)
				{
					continue;
				}
				Type declaringType = method.DeclaringType;
				if (!(declaringType == null))
				{
					Assembly assembly = declaringType.Assembly;
					assemblyname = assembly.GetName().Name;
					if (!assemblyname.StartsWith("System") && !assemblyname.StartsWith("Harmony") && !assemblyname.StartsWith("BepInEx"))
					{
						className = declaringType.FullName;
						methodName = method.Name;
						return true;
					}
					num--;
				}
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(PLUIPlayMenu), "Update")]
	internal class ModdedLobbyTag
	{
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Expected O, but got Unknown
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Expected O, but got Unknown
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Expected O, but got Unknown
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Expected O, but got Unknown
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Expected O, but got Unknown
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Expected O, but got Unknown
			List<CodeInstruction> list = new List<CodeInstruction>();
			list.Add(new CodeInstruction(OpCodes.Ldfld, (object)null));
			list.Add(new CodeInstruction(OpCodes.Ldsfld, (object)null));
			list.Add(new CodeInstruction(OpCodes.Ldloc_S, (object)null));
			list.Add(new CodeInstruction(OpCodes.Callvirt, (object)null));
			list.Add(new CodeInstruction(OpCodes.Callvirt, (object)AccessTools.Method(typeof(PLReadableStringManager), "GetFormattedResultFromInputString", (Type[])null, (Type[])null)));
			list.Add(new CodeInstruction(OpCodes.Callvirt, (object)AccessTools.Method(typeof(Text), "set_text", (Type[])null, (Type[])null)));
			List<CodeInstruction> targetSequence = list;
			list = new List<CodeInstruction>();
			list.Add(new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(ModdedLobbyTag), "PatchMethod", (Type[])null, (Type[])null)));
			List<CodeInstruction> patchSequence = list;
			return HarmonyHelpers.PatchBySequence(instructions, targetSequence, patchSequence, HarmonyHelpers.PatchMode.REPLACE, HarmonyHelpers.CheckMode.NONNULL);
		}

		private static void PatchMethod(UIJoinGameElement jge)
		{
			if (jge != null)
			{
				string formattedResultFromInputString = PLReadableStringManager.Instance.GetFormattedResultFromInputString(jge.Room.Name);
				if (((Dictionary<object, object>)(object)jge.Room.CustomProperties).TryGetValue((object)"isModded", out object _))
				{
					jge.GameName.text = "<size=20><color=yellow>M</color></size> " + formattedResultFromInputString;
				}
				else
				{
					jge.GameName.text = formattedResultFromInputString;
				}
			}
		}
	}
	[HarmonyPatch(typeof(PhotonNetwork), "CreateRoom", new Type[]
	{
		typeof(string),
		typeof(RoomOptions),
		typeof(TypedLobby),
		typeof(string[])
	})]
	public static class PhotonProperties
	{
		private static void Prefix(RoomOptions roomOptions)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Expected O, but got Unknown
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Expected O, but got Unknown
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Expected O, but got Unknown
			//IL_0045: Expected O, but got Unknown
			Hashtable customRoomProperties = roomOptions.CustomRoomProperties;
			Hashtable val = new Hashtable();
			((Dictionary<object, object>)val).Add((object)"isModded", (object)true);
			((Dictionary<object, object>)val).Add((object)"playerList", (object)"");
			((Dictionary<object, object>)val).Add((object)"modList", (object)"");
			Extensions.Merge((IDictionary)customRoomProperties, (IDictionary)val);
			roomOptions.CustomRoomPropertiesForLobby = CollectionExtensions.AddRangeToArray<string>(roomOptions.CustomRoomPropertiesForLobby, new string[3] { "isModded", "playerList", "modList" });
			roomOptions.CustomRoomProperties[(object)"modList"] = MPModCheckManager.Instance.SerializeHashlessUserData();
		}

		public static void UpdatePlayerList()
		{
			if (PhotonNetwork.isMasterClient && PhotonNetwork.inRoom && (Object)(object)PLNetworkManager.Instance != (Object)null)
			{
				Room room = PhotonNetwork.room;
				Hashtable customProperties = ((RoomInfo)room).CustomProperties;
				customProperties[(object)"playerList"] = string.Join("\n", (from player in PLServer.Instance.AllPlayers.Where(delegate(PLPlayer player)
					{
						//IL_000f: 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)
						ObscuredInt? val = player?.TeamID;
						return (val.HasValue ? new int?(ObscuredInt.op_Implicit(val.GetValueOrDefault())) : null) == 0;
					})
					select player.GetPlayerName(false) + "\t" + player.GetClassName()).ToArray());
				room.SetCustomProperties(customProperties, (Hashtable)null, false);
			}
		}
	}
	[HarmonyPatch(typeof(PLPlayer), "SetClassID")]
	internal class ChangedClass
	{
		private static void Postfix()
		{
			PhotonProperties.UpdatePlayerList();
		}
	}
	[HarmonyPatch(typeof(PLGlobal), "Start")]
	internal class PLGlobalStart
	{
		private static bool modsLoaded;

		private static void Prefix()
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			if (!modsLoaded)
			{
				new Events();
				((Object)new GameObject("ModManager", new Type[1] { typeof(GUIMain) })).hideFlags = (HideFlags)61;
				new SaveDataManager();
				_ = KeybindManager.Instance;
				new MPModCheckManager();
				ModManager.Instance.LoadMods();
				modsLoaded = true;
			}
		}
	}
}
namespace PulsarModLoader.MPModChecks
{
	public class MPModCheckManager
	{
		[HarmonyPatch(typeof(PLUIPlayMenu), "ActuallyJoinRoom")]
		private class JoinRoomPatch
		{
			private static bool Prefix(RoomInfo room)
			{
				return Instance.ClientClickJoinRoom(room);
			}
		}

		[HarmonyPatch(typeof(PLServer), "AttemptGetVerified")]
		private class AttemptGetVerifiedRecievePatch
		{
			private static bool Prefix(PhotonMessageInfo pmi)
			{
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				return Instance.HostOnClientJoined(pmi.sender);
			}
		}

		[HarmonyPatch(typeof(PLServer), "Update")]
		private class AttemptGetVerifiedSendPatch
		{
			private static void PatchMethod()
			{
				Logger.Info("Sending 'RecieveConnectionMessage' RPC");
				((MonoBehaviour)ModMessageHelper.Instance).photonView.RPC("ServerRecieveModList", (PhotonTargets)2, new object[1] { Instance.SerializeHashfullUserData() });
				Instance.SentModLists.Add(PhotonNetwork.masterClient);
			}

			private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
			{
				//IL_0011: Unknown result type (might be due to invalid IL or missing references)
				//IL_001b: Expected O, but got Unknown
				//IL_003f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0049: Expected O, but got Unknown
				List<CodeInstruction> targetSequence = new List<CodeInstruction>
				{
					new CodeInstruction(OpCodes.Ldstr, (object)"Attempting to get verified")
				};
				List<CodeInstruction> list = new List<CodeInstruction>();
				list.Add(new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(AttemptGetVerifiedSendPatch), "PatchMethod", (Type[])null, (Type[])null)));
				List<CodeInstruction> patchSequence = list;
				return HarmonyHelpers.PatchBySequence(instructions, targetSequence, patchSequence);
			}
		}

		[HarmonyPatch(typeof(PLNetworkManager), "OnPhotonPlayerDisconnected")]
		private class RemovePlayerPatch
		{
			private static void Postfix(PhotonPlayer photonPlayer)
			{
				Instance.RemoveNetworkedPeerMods(photonPlayer);
				Instance.SentModLists.Remove(photonPlayer);
			}
		}

		[HarmonyPatch(typeof(PLNetworkManager), "OnPhotonPlayerConnected")]
		private class AddPlayerPatch
		{
			private static void Postfix(PhotonPlayer photonPlayer)
			{
				Instance.SendModlistToClient(photonPlayer);
			}
		}

		private bool HoldRefreshUntilAllModsLoaded = false;

		public static MPModCheckManager Instance;

		private MPModDataBlock[] MyModList = null;

		internal List<PhotonPlayer> SentModLists = new List<PhotonPlayer>();

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

		public MPRequirement HighestLevelOfMPMods { get; private set; } = MPRequirement.None;


		public MPModCheckManager()
		{
			Instance = this;
			ModManager.Instance.OnModUnloaded += RefreshData;
			ModManager.Instance.OnModSuccessfullyLoaded += RefreshData;
			ModManager.Instance.OnAllModsLoaded += RefreshData;
			Events.Instance.OnLeaveGameEvent += OnLeaveGame;
		}

		internal void OnLeaveGame()
		{
			SentModLists.Clear();
			NetworkedPeersModLists.Clear();
		}

		public void HoldMPModListRefresh()
		{
			HoldRefreshUntilAllModsLoaded = true;
		}

		public void RefreshData()
		{
			HoldRefreshUntilAllModsLoaded = true;
			UpdateMyModList();
			UpdateLobbyModList();
			foreach (PhotonPlayer sentModList in SentModLists)
			{
				Instance.SendModlistToClient(sentModList);
			}
		}

		private void RefreshData(string name, PulsarMod mod)
		{
			if (!HoldRefreshUntilAllModsLoaded)
			{
				RefreshData();
			}
		}

		private void RefreshData(PulsarMod mod = null)
		{
			RefreshData();
		}

		internal void UpdateLobbyModList()
		{
			if (PhotonNetwork.isMasterClient && PhotonNetwork.inRoom && (Object)(object)PLNetworkManager.Instance != (Object)null)
			{
				Room room = PhotonNetwork.room;
				Hashtable customProperties = ((RoomInfo)room).CustomProperties;
				customProperties[(object)"modList"] = SerializeHashlessUserData();
				room.SetCustomProperties(customProperties, (Hashtable)null, false);
			}
		}

		internal void SendModlistToClient(PhotonPlayer photonPlayer)
		{
			((MonoBehaviour)ModMessageHelper.Instance).photonView.RPC("ClientRecieveModList", photonPlayer, new object[1] { Instance.SerializeHashlessUserData() });
		}

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

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

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

		public void AddNetworkedPeerMods(PhotonPlayer PhotonPlayer, MPUserDataBlock modList)
		{
			if (NetworkedPeersModLists.ContainsKey(PhotonPlayer))
			{
				NetworkedPeersModLists[PhotonPlayer] = modList;
			}
			else
			{
				NetworkedPeersModLists.Add(PhotonPlayer, modList);
			}
		}

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

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

		private List<PulsarMod> GetMPModList()
		{
			HighestLevelOfMPMods = MPRequirement.None;
			List<PulsarMod> list = new List<PulsarMod>();
			foreach (PulsarMod allMod in ModManager.Instance.GetAllMods())
			{
				if (allMod.MPRequirements != 1)
				{
					if (allMod.MPRequirements != 4 && (allMod.MPRequirements == 2 || allMod.MPRequirements == 3) && allMod.MPRequirements > (int)HighestLevelOfMPMods)
					{
						HighestLevelOfMPMods = (MPRequirement)allMod.MPRequirements;
					}
					list.Add(allMod);
				}
			}
			return list;
		}

		private void UpdateMyModList()
		{
			Logger.Info("Building MyModList");
			Stopwatch stopwatch = new Stopwatch();
			stopwatch.Start();
			List<PulsarMod> mPModList = GetMPModList();
			MPModDataBlock[] array = new MPModDataBlock[mPModList.Count];
			for (int i = 0; i < mPModList.Count; i++)
			{
				PulsarMod pulsarMod = mPModList[i];
				array[i] = new MPModDataBlock(pulsarMod.HarmonyIdentifier(), pulsarMod.Name, pulsarMod.Version, (MPRequirement)pulsarMod.MPRequirements, pulsarMod.VersionLink, pulsarMod.ModHash);
			}
			MyModList = array;
			stopwatch.Stop();
			Logger.Info("Finished Building MyModList, time elapsted: " + stopwatch.ElapsedMilliseconds);
		}

		public byte[] SerializeHashlessUserData()
		{
			MemoryStream memoryStream = new MemoryStream();
			using (BinaryWriter binaryWriter = new BinaryWriter(memoryStream))
			{
				binaryWriter.Write(GameVersion.PMLVersion);
				binaryWriter.Write(MyModList.Length);
				for (int i = 0; i < MyModList.Length; i++)
				{
					MPModDataBlock mPModDataBlock = MyModList[i];
					binaryWriter.Write(mPModDataBlock.ModName);
					binaryWriter.Write(mPModDataBlock.HarmonyIdentifier);
					binaryWriter.Write(mPModDataBlock.Version);
					binaryWriter.Write((byte)mPModDataBlock.MPRequirement);
					binaryWriter.Write(mPModDataBlock.ModID);
				}
			}
			byte[] result = memoryStream.ToArray();
			memoryStream.Dispose();
			return result;
		}

		public byte[] SerializeHashfullUserData()
		{
			MemoryStream memoryStream = new MemoryStream();
			using (BinaryWriter binaryWriter = new BinaryWriter(memoryStream))
			{
				binaryWriter.Write(GameVersion.PMLVersion);
				binaryWriter.Write(MyModList.Length);
				for (int i = 0; i < MyModList.Length; i++)
				{
					MPModDataBlock mPModDataBlock = MyModList[i];
					binaryWriter.Write(mPModDataBlock.ModName);
					binaryWriter.Write(mPModDataBlock.HarmonyIdentifier);
					binaryWriter.Write(mPModDataBlock.Version);
					binaryWriter.Write((byte)mPModDataBlock.MPRequirement);
					binaryWriter.Write(mPModDataBlock.ModID);
					binaryWriter.Write(mPModDataBlock.Hash);
				}
			}
			byte[] result = memoryStream.ToArray();
			memoryStream.Dispose();
			return result;
		}

		public static MPUserDataBlock DeserializeHashlessMPUserData(byte[] byteData)
		{
			MemoryStream memoryStream = new MemoryStream(byteData);
			memoryStream.Position = 0L;
			try
			{
				using BinaryReader binaryReader = new BinaryReader(memoryStream);
				string pMLVersion = binaryReader.ReadString();
				int num = binaryReader.ReadInt32();
				MPModDataBlock[] array = new MPModDataBlock[num];
				for (int i = 0; i < num; i++)
				{
					string modName = binaryReader.ReadString();
					string harmonyIdentifier = binaryReader.ReadString();
					string version = binaryReader.ReadString();
					MPRequirement mPRequirement = (MPRequirement)binaryReader.ReadByte();
					string modID = binaryReader.ReadString();
					array[i] = new MPModDataBlock(harmonyIdentifier, modName, version, mPRequirement, modID);
				}
				memoryStream.Dispose();
				return new MPUserDataBlock(pMLVersion, array);
			}
			catch (Exception ex)
			{
				Logger.Info("Failed to read mod list from Hashless MPUserData, returning null.\n" + ex.Message);
				memoryStream.Dispose();
				return null;
			}
		}

		public static MPUserDataBlock DeserializeHashfullMPUserData(byte[] byteData)
		{
			MemoryStream memoryStream = new MemoryStream(byteData);
			memoryStream.Position = 0L;
			try
			{
				using BinaryReader binaryReader = new BinaryReader(memoryStream);
				string pMLVersion = binaryReader.ReadString();
				int num = binaryReader.ReadInt32();
				MPModDataBlock[] array = new MPModDataBlock[num];
				for (int i = 0; i < num; i++)
				{
					string modName = binaryReader.ReadString();
					string harmonyIdentifier = binaryReader.ReadString();
					string version = binaryReader.ReadString();
					MPRequirement mPRequirement = (MPRequirement)binaryReader.ReadByte();
					string modID = binaryReader.ReadString();
					byte[] hash = binaryReader.ReadBytes(32);
					array[i] = new MPModDataBlock(harmonyIdentifier, modName, version, mPRequirement, modID, hash);
				}
				memoryStream.Dispose();
				return new MPUserDataBlock(pMLVersion, array);
			}
			catch (Exception ex)
			{
				Logger.Info("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;
			}
			return text;
		}

		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
				{
					Logger.Info("Failed to Deserialize host mod list. Could be an older version of PML");
				}
			}
			return new MPUserDataBlock();
		}

		private static void KickClient(PhotonPlayer client)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			if (SteamManager.Initialized && client.SteamID != CSteamID.Nil)
			{
				SteamUser.EndAuthSession(client.SteamID);
			}
			PhotonNetwork.CloseConnection(client);
		}

		public bool ClientClickJoinRoom(RoomInfo room)
		{
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Expected O, but got Unknown
			//IL_0395: Unknown result type (might be due to invalid IL or missing references)
			//IL_039f: Expected O, but got Unknown
			MPUserDataBlock hostModList = GetHostModList(room);
			if (hostModList.PMLVersion == string.Empty)
			{
				if (HighestLevelOfMPMods == MPRequirement.Host || HighestLevelOfMPMods == MPRequirement.All)
				{
					PLNetworkManager.Instance.MainMenu.AddActiveMenu((PLMenu)new PLErrorMessageMenu("<color=red>FAILED TO JOIN CREW!</color>\nMods requiring host installation or higher have been installed locally"));
					Logger.Info("Mods requiring host installation or higher have been installed locally");
					return false;
				}
				return true;
			}
			MPModDataBlock[] modData = hostModList.ModData;
			string modListAsString = GetModListAsString(modData);
			string modListAsString2 = GetModListAsString(MyModList);
			Logger.Info("Joining room: " + room.Name + " ServerPMLVersion: " + hostModList.PMLVersion + "\n--Hostmodlist: " + modListAsString + "\n--Localmodlist: " + modListAsString2);
			string text = string.Empty;
			string text2 = string.Empty;
			string text3 = string.Empty;
			int num = MyModList.Length;
			int num2 = modData.Length;
			for (int i = 0; i < num; i++)
			{
				bool flag = false;
				int j;
				for (j = 0; j < num2; j++)
				{
					if (modData[j].HarmonyIdentifier == MyModList[i].HarmonyIdentifier)
					{
						flag = true;
						break;
					}
				}
				if (!flag)
				{
					if (MyModList[i].MPRequirement == MPRequirement.Host || MyModList[i].MPRequirement == MPRequirement.All)
					{
						text2 = text2 + "\n" + MyModList[i].ModName;
					}
				}
				else if (MyModList[i].MPRequirement != 0 && MyModList[i].Version != modData[j].Version)
				{
					text3 = text3 + "\nLocal: " + MyModList[i].ModName + " " + MyModList[i].Version + " Host: " + modData[j].ModName + " " + modData[j].Version;
				}
			}
			for (int k = 0; k < num2; k++)
			{
				bool flag2 = false;
				for (int l = 0; l < num; l++)
				{
					if (modData[k].HarmonyIdentifier == MyModList[l].HarmonyIdentifier)
					{
						flag2 = true;
						break;
					}
				}
				if (!flag2 && modData[k].MPRequirement == MPRequirement.All)
				{
					text = text + "\n" + modData[k].ModName;
				}
			}
			string text4 = string.Empty;
			if (text != string.Empty)
			{
				text4 = text4 + "\n<color=yellow>YOU ARE MISSING THE FOLLOWING REQUIRED MODS</color>" + text;
			}
			if (text2 != string.Empty)
			{
				text4 = text4 + "\n<color=yellow>YOU CANNOT JOIN WITH THE FOLLOWING MODS INSTALLED</color>" + text2;
			}
			if (text3 != string.Empty)
			{
				text4 = text4 + "\n<color=yellow>THE FOLLOWING MOD VERSIONS DO NOT MATCH</color>" + text3;
			}
			if (text4 != string.Empty)
			{
				PLNetworkManager.Instance.MainMenu.AddActiveMenu((PLMenu)new PLErrorMessageMenu("<color=red>Failed to join crew!</color>" + text4));
				Logger.Info("Local mod list is not equal to Server mod list");
				return false;
			}
			Logger.Info("Modcheck passed, proceding ondwards");
			return true;
		}

		public bool HostOnClientJoined(PhotonPlayer Player)
		{
			MPModDataBlock[] array = null;
			bool flag = false;
			if (NetworkedPeersModLists.ContainsKey(Player))
			{
				array = NetworkedPeersModLists[Player].ModData;
				flag = true;
			}
			Logger.Info("HostOnClientJoined checking for player mods, returned " + flag);
			if (flag)
			{
				string text = string.Empty;
				string text2 = string.Empty;
				string text3 = string.Empty;
				string text4 = string.Empty;
				Logger.Info("Starting Serverside Mod check");
				int num = MyModList.Length;
				int num2 = array.Length;
				for (int i = 0; i < num; i++)
				{
					bool flag2 = false;
					int j;
					for (j = 0; j < num2; j++)
					{
						if (MyModList[i].HarmonyIdentifier == array[j].HarmonyIdentifier)
						{
							flag2 = true;
							break;
						}
					}
					if (flag2)
					{
						if (MyModList[i].MPRequirement >= MPRequirement.Host)
						{
							if (MyModList[i].Version != array[j].Version)
							{
								text3 = text3 + "\nLocal: " + MyModList[i].ModName + " " + MyModList[i].Version + " Client: " + array[j].ModName + " " + array[j].Version;
							}
							else if (Encoding.ASCII.GetString(MyModList[i].Hash) != Encoding.ASCII.GetString(array[j].Hash))
							{
								text4 = text4 + "\n" + array[j].ModName;
								text = text + "\n" + array[j].ModName;
								Logger.Info("Client has bad hash for " + MyModList[i].ModName + ". Local: " + Encoding.ASCII.GetString(MyModList[i].Hash) + " Client: " + Encoding.ASCII.GetString(array[j].Hash));
							}
						}
					}
					else if (MyModList[i].MPRequirement == MPRequirement.All)
					{
						text = text + "\n" + MyModList[i].ModName;
					}
				}
				for (int k = 0; k < num2; k++)
				{
					bool flag3 = false;
					for (int l = 0; l < num; l++)
					{
						if (MyModList[l].HarmonyIdentifier == array[k].HarmonyIdentifier)
						{
							flag3 = true;
							break;
						}
					}
					if (!flag3 && (array[k].MPRequirement == MPRequirement.Host || array[k].MPRequirement == MPRequirement.All))
					{
						text2 = text2 + "\n" + array[k].ModName;
					}
				}
				string text5 = string.Empty;
				if (text != string.Empty)
				{
					text5 = text5 + "\n<color=yellow>You are missing the following required mods</color>" + text;
				}
				if (text2 != string.Empty)
				{
					text5 = text5 + "\n<color=yellow>You cannot join with the following mods installed</color>" + text2;
				}
				if (text3 != string.Empty)
				{
					text5 = text5 + "\n<color=yellow>The following mod versions do not match</color>" + text3;
				}
				if (text5 != string.Empty)
				{
					((MonoBehaviour)ModMessageHelper.Instance).photonView.RPC("RecieveErrorMessage", Player, new object[1] { "<color=red>Failed to join crew!</color>" + text5 });
					KickClient(Player);
					Logger.Info("Kicked client for failing mod check with the following message:" + text5);
					return false;
				}
				Logger.Info("Modcheck passed, proceding onwards");
			}
			else
			{
				if (HighestLevelOfMPMods >= MPRequirement.All)
				{
					Logger.Info("Didn't receive message or proper modlist. proceeding to kick PhotonPlayer");
					string text6 = "You have been disconnected for not having the mod loader installed";
					((MonoBehaviour)ModMessageHelper.Instance).photonView.RPC("RecieveErrorMessage", Player, new object[1] { text6 });
					KickClient(Player);
					return false;
				}
				Logger.Info("Didn't receive message or proper modlist, but the server doesn't have multiplayer explicit mods. Proceeding onwards");
			}
			return true;
		}
	}
	public class MPModDataBlock
	{
		public string HarmonyIdentifier { get; }

		public string ModName { get; }

		public string Version { get; }

		public MPRequirement MPRequirement { get; }

		public byte[] Hash { get; }

		public string ModID { get; }

		public MPModDataBlock(str