Thunderstore support for Pulsar: Lost Colony is still under development. For the time being, most mods are available through the legacy mod loader and support can be found in the Pulsar Crew Matchup Server
Decompiled source of PulsarModLoader v1.0.0
BepInEx/patchers/PulsarModLoader.Adaptor/PulsarModLoader.Adaptor.dll
Decompiled 2 days agousing 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
The result has been truncated due to the large size, download it to view full contents!
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