Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of CompatibilityChecker v1.1.6
Ryokune.CompatibilityChecker.dll
Decompiled 2 years agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Net.Http; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Logging; using CompatibilityChecker.MonoBehaviours; using CompatibilityChecker.Netcode; using CompatibilityChecker.Patches; using CompatibilityChecker.Utils; using HarmonyLib; using Newtonsoft.Json; using Steamworks; using Steamworks.Data; using TMPro; using UnityEngine; using UnityEngine.Events; using UnityEngine.SceneManagement; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = "")] [assembly: AssemblyCompany("Ryokune")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyDescription("Lethal Company Library that lets you know which mods a modded server has.")] [assembly: AssemblyFileVersion("1.1.6.0")] [assembly: AssemblyInformationalVersion("1.1.6")] [assembly: AssemblyProduct("CompatibilityChecker")] [assembly: AssemblyTitle("Ryokune.CompatibilityChecker")] [assembly: AssemblyVersion("1.1.6.0")] namespace CompatibilityChecker { [BepInPlugin("Ryokune.CompatibilityChecker", "CompatibilityChecker", "1.1.6")] [BepInProcess("Lethal Company.exe")] public class ModNotifyBase : BaseUnityPlugin { public static ModNotifyBase instance; public static ManualLogSource Logger; private readonly Harmony harmony = new Harmony("Ryokune.CompatibilityChecker"); public static Dictionary<string, PluginInfo> ModList = new Dictionary<string, PluginInfo>(); public static string ModListString; public static string[] ModListArray; public static bool loadedMods; public static string seperator = "/@/"; public static string Text; public static TMP_InputField searchInputField; private static IEnumerator JoinLobby(SteamId lobbyId, SteamLobbyManager lobbyManager) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) bool found = false; Logger.LogWarning((object)"Getting Lobby"); Task<Lobby?> joinTask = SteamMatchmaking.JoinLobbyAsync(lobbyId); yield return (object)new WaitUntil((Func<bool>)(() => joinTask.IsCompleted)); if (joinTask.Result.HasValue) { Logger.LogWarning((object)"Getting Lobby Value"); Lobby lobby = joinTask.Result.Value; if (!Utility.IsNullOrWhiteSpace(((Lobby)(ref lobby)).GetData("vers"))) { LobbySlot.JoinLobbyAfterVerifying(lobby, ((Lobby)(ref lobby)).Id); found = true; Logger.LogWarning((object)"Success!"); } lobby = default(Lobby); } else { Logger.LogWarning((object)"Failed to join lobby."); } if (!found) { lobbyManager.LoadServerList(); } else if ((Object)(object)searchInputField != (Object)null) { searchInputField.text = ""; Text = ""; } } private static void OnEndEdit(string newValue) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) Text = newValue; SteamLobbyManager val = Object.FindObjectOfType<SteamLobbyManager>(); if (ulong.TryParse(newValue, out var result)) { SteamId val2 = default(SteamId); val2.Value = result; CoroutineHandler.Instance.NewCoroutine(JoinLobby(SteamId.op_Implicit(result), val)); } else { val.LoadServerList(); } } private static IEnumerator displayCopied(TextMeshProUGUI textMesh) { string oldtext = ((TMP_Text)textMesh).text; if (GameNetworkManager.Instance.currentLobby.HasValue) { ((TMP_Text)textMesh).text = "(Copied to clipboard!)"; Lobby value = GameNetworkManager.Instance.currentLobby.Value; SteamId id2 = ((Lobby)(ref value)).Id; string id = (GUIUtility.systemCopyBuffer = ((object)(SteamId)(ref id2)).ToString()); Logger.LogWarning((object)("Lobby code copied to clipboard: " + id)); } else { ((TMP_Text)textMesh).text = "Can't get Lobby code!"; } yield return (object)new WaitForSeconds(1.2f); ((TMP_Text)textMesh).text = oldtext; } private static void sceneLoad(Scene sceneName, LoadSceneMode load) { //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_019f: Unknown result type (might be due to invalid IL or missing references) //IL_01a9: Expected O, but got Unknown //IL_01b9: Unknown result type (might be due to invalid IL or missing references) //IL_01c3: Expected O, but got Unknown //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Expected O, but got Unknown //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Expected O, but got Unknown //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Expected O, but got Unknown if (((Scene)(ref sceneName)).name == "MainMenu") { GameObject val = GameObject.Find("/Canvas/MenuContainer/LobbyList/JoinCode"); if ((Object)(object)val != (Object)null) { try { GameObject val2 = Object.Instantiate<GameObject>(val.gameObject, val.transform.parent); val2.SetActive(true); searchInputField = val2.GetComponent<TMP_InputField>(); ((Selectable)searchInputField).interactable = true; ((TMP_Text)((Component)searchInputField.placeholder).gameObject.GetComponent<TextMeshProUGUI>()).text = "Search or Enter a room code..."; searchInputField.onEndEdit = new SubmitEvent(); searchInputField.onEndTextSelection = new TextSelectionEvent(); searchInputField.onSubmit = new SubmitEvent(); ((UnityEvent<string>)(object)searchInputField.onSubmit).AddListener((UnityAction<string>)OnEndEdit); } catch (Exception ex) { Logger.LogError((object)ex); } } } else { if (!(((Scene)(ref sceneName)).name == "SampleSceneRelay")) { return; } GameObject val3 = GameObject.Find("/Systems/UI/Canvas/QuickMenu/MainButtons/Resume"); if ((Object)(object)val3 != (Object)null) { GameObject val4 = Object.Instantiate<GameObject>(val3.gameObject, val3.transform.parent); RectTransform component = val4.GetComponent<RectTransform>(); component.anchoredPosition += new Vector2(0f, 182f); TextMeshProUGUI LobbyCodeTextMesh = val4.GetComponentInChildren<TextMeshProUGUI>(); ((TMP_Text)LobbyCodeTextMesh).text = "> Lobby Code"; Button component2 = val4.GetComponent<Button>(); component2.onClick = new ButtonClickedEvent(); ((UnityEvent)component2.onClick).AddListener((UnityAction)delegate { CoroutineHandler.Instance.NewCoroutine(displayCopied(LobbyCodeTextMesh)); }); } } } private void Awake() { SceneManager.sceneLoaded += sceneLoad; if ((Object)(object)instance == (Object)null) { instance = this; Logger = ((BaseUnityPlugin)this).Logger; } CoroutineHandler.Instance.NewCoroutine(ThunderstoreAPI.Initialize()); Logger.LogInfo((object)"Plugin Ryokune.CompatibilityChecker is loaded!"); Logger.LogInfo((object)"Modded servers with CompatibilityChecker will now notify you what mods are needed."); harmony.PatchAll(typeof(ModNotifyBase)); harmony.PatchAll(typeof(PlayerJoinNetcode)); harmony.PatchAll(typeof(SteamLobbyManagerPatch)); } public static IEnumerator InitializeModsCoroutine() { yield return (object)new WaitUntil((Func<bool>)(() => ThunderstoreAPI.Packages != null)); ModList = Chainloader.PluginInfos; StringBuilder messageBuilder = new StringBuilder(); MenuManager menuManager = Object.FindObjectOfType<MenuManager>(); PlayerJoinNetcode.old = ((((Component)((TMP_Text)menuManager.menuNotificationButtonText).transform.parent).GetComponent<RectTransform>().sizeDelta != Vector2.zero) ? ((Component)((TMP_Text)menuManager.menuNotificationButtonText).transform.parent).GetComponent<RectTransform>().sizeDelta : PlayerJoinNetcode.old); int i = 0; int count = ModList.Count(); menuManager.menuNotification.SetActive(true); foreach (PluginInfo info in ModList.Values) { i++; ((TMP_Text)menuManager.menuNotificationText).text = $"Loading mods {i}/{count}"; ((TMP_Text)menuManager.menuNotificationButtonText).text = null; ((Component)((TMP_Text)menuManager.menuNotificationButtonText).transform.parent).GetComponent<RectTransform>().sizeDelta = Vector2.zero; string noSpace = Regex.Replace(info.Metadata.Name, "[\\s\\-_]", ""); Package package = ThunderstoreAPI.GetPackage(noSpace, info); if (package != null) { Logger.LogInfo((object)$"[{info.Metadata.GUID}] Found package: {info.Metadata.Name}[{info.Metadata.Version}]\n\t\tDATA:\n\t\t--NAME: {package.FullName}\n\t\t--LINK: {package.PackageUrl}"); if (VersionUtil.ConvertToNumber(package.Versions[0].VersionNumber) > VersionUtil.ConvertToNumber(info.Metadata.Version.ToString())) { messageBuilder.AppendLine($"\n\t\t--Mod {info.Metadata.Name} [{info.Metadata.GUID}] v{info.Metadata.Version} does not equal the latest release!"); messageBuilder.AppendLine("\t\t--Latest version: v" + package.Versions[0].VersionNumber); messageBuilder.AppendLine("\t\t--Link: " + package.PackageUrl); messageBuilder.AppendLine("\t\t--Full mod name: " + package.FullName); messageBuilder.AppendLine("\t\t--(If this is wrong, please ignore this.)"); } } if (package?.Categories.Contains("Server-side") ?? false) { if (package.Name == "CompatibilityChecker" && package.Versions[0].VersionNumber != "1.1.6") { string warning = "Current CompatibilityChecker v1.1.6 does not equal latest release v" + package.Versions[0].VersionNumber + "!\nPlease update to the latest version of CompatibilityChecker!!!"; Logger.LogWarning((object)warning); Object.FindObjectOfType<MenuManager>().DisplayMenuNotification(warning, (string)null); } ModListString += $"{info.Metadata.Name}[{info.Metadata.Version}]{seperator}"; } else if (package == null) { Logger.LogWarning((object)$"Couldn't find package: {info.Metadata.Name}[{info.Metadata.Version}]\n\t\t[{info.Metadata.GUID}]"); ModListString += $"{info.Metadata.GUID}[{info.Metadata.Version}]{seperator}"; } yield return null; } if (messageBuilder.Length != 0) { Logger.LogWarning((object)messageBuilder.ToString()); } ModListString = ModListString.Remove(ModListString.Length - 3, 3); ModListArray = ModListString.Split(seperator); Logger.LogWarning((object)$"Server-sided Mod List Count: {ModListArray.Count()}"); menuManager.menuNotification.SetActive(false); loadedMods = true; } } public static class PluginInfo { public const string PLUGIN_GUID = "Ryokune.CompatibilityChecker"; public const string PLUGIN_NAME = "CompatibilityChecker"; public const string PLUGIN_VERSION = "1.1.6"; } } namespace CompatibilityChecker.Utils { [Serializable] public class Package { [JsonProperty("name")] public string Name; [JsonProperty("full_name")] public string FullName; [JsonProperty("owner")] public string Owner; [JsonProperty("package_url")] public string PackageUrl; [JsonProperty("categories")] public string[] Categories; [JsonProperty("versions")] public Version[] Versions; public long TotalDownloads; [JsonProperty("is_deprecated")] public bool IsDeprecated; } [Serializable] public class Version { [JsonProperty("name")] public string Name; [JsonProperty("full_name")] public string FullName; [JsonProperty("version_number")] public string VersionNumber; [JsonProperty("download_url")] public Uri DownloadUrl; [JsonProperty("downloads")] public long Downloads; [JsonProperty("website_url")] public Uri WebsiteUrl; } public static class ThunderstoreAPI { private const string ApiBaseUrl = "https://thunderstore.io/c/lethal-company/api/v1/package/"; private static List<Package> packages; public static List<Package> Packages => packages; public static async Task InitializeThunderstorePackagesAsync(Action onComplete) { try { using HttpClient httpClient = new HttpClient(); packages = JsonConvert.DeserializeObject<List<Package>>(await httpClient.GetStringAsync("https://thunderstore.io/c/lethal-company/api/v1/package/")); ModNotifyBase.Logger.LogInfo((object)$"ThunderstoreAPI Initialized! Got packages: {packages.Count()}"); foreach (Package pack in packages) { Version[] versions = pack.Versions; foreach (Version ver in versions) { pack.TotalDownloads += ver.Downloads; } } } catch (Exception ex2) { Exception ex = ex2; ModNotifyBase.Logger.LogError((object)("Failed to initialize Thunderstore packages. Error: " + ex.Message)); } onComplete?.Invoke(); } public static bool IsSimilar(string s1, string s2) { string pattern = string.Join(".*?", s2.ToCharArray()); Match match = Regex.Match(s1, pattern); if (match.Success) { return match.Success; } int[,] array = new int[s1.Length + 1, s2.Length + 1]; for (int i = 0; i <= s1.Length; i++) { for (int j = 0; j <= s2.Length; j++) { if (i == 0) { array[i, j] = j; } else if (j == 0) { array[i, j] = i; } else { array[i, j] = Math.Min(Math.Min(array[i - 1, j] + 1, array[i, j - 1] + 1), array[i - 1, j - 1] + ((s1[i - 1] != s2[j - 1]) ? 1 : 0)); } } } int num = Math.Max(s1.Length, s2.Length); int num2 = array[s1.Length, s2.Length]; double num3 = 1.0 - (double)num2 / (double)num; return num3 > 0.54; } private static bool IsMatchingName(Package package, string searchString) { string[] array = Regex.Split(package.Name, "(?<=[a-z])(?=[A-Z])|[\\s_\\-]"); string[] searchStringSplit = Regex.Split(searchString, "(?<=[a-z])(?=[A-Z])|[\\s_\\-]"); int num = ((array.Length > searchStringSplit.Length) ? (searchStringSplit.Length / 2) : (array.Length / 2)); int num2 = array.Count((string token) => searchStringSplit.Contains<string>(token, StringComparer.OrdinalIgnoreCase)); return num2 >= num; } private static bool IsMatchingName(Package package, string searchString, string owner) { string[] source = Regex.Split(Regex.Replace(package.Name, "[\\s_]+(\\w)", (Match m) => m.Groups[1].Value.ToUpper()).Replace(" ", ""), "(?<=[a-z])(?=[A-Z])"); string[] searchStringNameTokens = Regex.Split(searchString, "(?<=[a-z])(?=[A-Z])"); int num = 2; int num2 = source.Count((string token) => searchStringNameTokens.Contains<string>(token, StringComparer.OrdinalIgnoreCase)); return num2 >= num && owner.Contains(package.Owner, StringComparison.OrdinalIgnoreCase); } public static List<Package> GetPackages(string searchString) { return Packages?.Where((Package package) => IsMatchingName(package, searchString)).ToList(); } public static List<Package> GetPackages(string searchString, string owner) { return Packages?.Where((Package package) => IsMatchingName(package, searchString, owner)).ToList(); } public static Package GetPackage(string searchString) { Package package = null; foreach (Package package2 in Packages) { if (package2.IsDeprecated) { continue; } string text = Regex.Replace(package2.Name, "[\\s\\-_]", ""); if (text.Equals(searchString, StringComparison.OrdinalIgnoreCase) || searchString.Contains(text, StringComparison.OrdinalIgnoreCase) || text.Contains(searchString, StringComparison.OrdinalIgnoreCase)) { if (package == null) { package = package2; } if (package2.TotalDownloads >= package?.TotalDownloads) { package = package2; } } } return package; } public static Package GetPackage(string searchString, PluginInfo info) { Package result = null; bool flag = false; foreach (Package package in Packages) { if (package.IsDeprecated) { continue; } if (info.Metadata.GUID.Split(".").Contains(package.Owner)) { flag = true; } string text = Regex.Replace(package.Name, "[\\s\\-_]", ""); if (text.Equals(searchString, StringComparison.OrdinalIgnoreCase) || text.Equals(info.Metadata.Name, StringComparison.OrdinalIgnoreCase) || text.Equals(info.Metadata.GUID, StringComparison.OrdinalIgnoreCase)) { if (flag) { return package; } result = package; } if (searchString.Contains(text, StringComparison.OrdinalIgnoreCase) || text.Contains(searchString, StringComparison.OrdinalIgnoreCase) || text.Contains(info.Metadata.Name, StringComparison.OrdinalIgnoreCase) || text.Contains(info.Metadata.GUID, StringComparison.OrdinalIgnoreCase)) { result = package; } if (IsSimilar(package.Name, searchString)) { result = package; } } return result; } public static IEnumerator Initialize(Action onComplete = null) { yield return InitializeThunderstorePackagesAsync(onComplete); } } internal static class VersionUtil { public static int ConvertToNumber(string version) { string s = version.Replace(".", ""); if (int.TryParse(s, out var result)) { return result; } ModNotifyBase.Logger.LogError((object)("Error parsing version: " + version)); return 0; } } } namespace CompatibilityChecker.Patches { internal class SteamLobbyManagerPatch { [HarmonyPatch(typeof(SteamLobbyManager), "LoadServerList")] [HarmonyPostfix] [HarmonyAfter(new string[] { "me.swipez.melonloader.morecompany" })] public static void loadserverListPatch(ref SteamLobbyManager __instance, ref Lobby[] ___currentLobbyList) { CoroutineHandler.Instance.NewCoroutine(BetterCompatibility(__instance)); } public static IEnumerator BetterCompatibility(SteamLobbyManager lobbyManager) { yield return (object)new WaitUntil((Func<bool>)(() => ((Transform)((Component)lobbyManager.levelListContainer).GetComponent<RectTransform>()).childCount - 1 != 0 && ((Transform)((Component)lobbyManager.levelListContainer).GetComponent<RectTransform>()).childCount - 1 == Object.FindObjectsOfType(typeof(LobbySlot)).Length && !GameNetworkManager.Instance.waitingForLobbyDataRefresh)); int i = 0; float lobbySlotPositionOffset = 0f; try { LobbySlot[] array = (LobbySlot[])(object)Object.FindObjectsOfType(typeof(LobbySlot)); foreach (LobbySlot slot in array) { i++; Transform obj = ((Component)slot).transform.Find("JoinButton"); GameObject JoinButton = ((obj != null) ? ((Component)obj).gameObject : null); if ((Object)(object)JoinButton != (Object)null) { GameObject CopyCodeButton = Object.Instantiate<GameObject>(JoinButton, JoinButton.transform.parent); CopyCodeButton.SetActive(true); RectTransform rectTransform = CopyCodeButton.GetComponent<RectTransform>(); if ((Object)(object)rectTransform != (Object)null) { rectTransform.anchoredPosition -= new Vector2(78f, 0f); ((TMP_Text)CopyCodeButton.GetComponentInChildren<TextMeshProUGUI>()).text = "Code"; Button ButtonComponent = CopyCodeButton.GetComponent<Button>(); if ((Object)(object)ButtonComponent != (Object)null) { ButtonComponent.onClick = new ButtonClickedEvent(); ((UnityEvent)ButtonComponent.onClick).AddListener((UnityAction)delegate { string text2 = (GUIUtility.systemCopyBuffer = ((object)(SteamId)(ref slot.lobbyId)).ToString()); ModNotifyBase.Logger.LogInfo((object)("Lobby code copied to clipboard: " + text2)); }); } } } Lobby lobby = slot.thisLobby; if (!Utility.IsNullOrWhiteSpace(((Lobby)(ref lobby)).GetData("mods")) && !((TMP_Text)slot.LobbyName).text.Contains("[Checker]")) { ((TMP_Text)slot.LobbyName).text = ((TMP_Text)slot.LobbyName).text + " [Checker]"; } if (!Utility.IsNullOrWhiteSpace(ModNotifyBase.Text) && !((TMP_Text)slot.LobbyName).text.Contains(ModNotifyBase.Text, StringComparison.OrdinalIgnoreCase)) { i--; Object.DestroyImmediate((Object)(object)((Component)slot).gameObject); } else { ((Component)slot).gameObject.GetComponent<RectTransform>().anchoredPosition = new Vector2(0f, lobbySlotPositionOffset); lobbySlotPositionOffset -= 42f; lobby = default(Lobby); } } RectTransform rect = ((Component)lobbyManager.levelListContainer).GetComponent<RectTransform>(); float newWidth = rect.sizeDelta.x; float newHeight = Mathf.Max(0f, (float)i * 42f); rect.SetSizeWithCurrentAnchors((Axis)0, newWidth); rect.SetSizeWithCurrentAnchors((Axis)1, newHeight); } catch (Exception err) { ModNotifyBase.Logger.LogError((object)err); } } [HarmonyPatch(typeof(SteamLobbyManager), "loadLobbyListAndFilter")] [HarmonyAfter(new string[] { "me.swipez.melonloader.morecompany" })] [HarmonyPrefix] public static bool loadLobbyPrefixPatch(ref SteamLobbyManager __instance, ref Lobby[] ___currentLobbyList, ref float ___lobbySlotPositionOffset, ref IEnumerator __result) { __result = modifiedLoadLobbyIEnumerator(__instance, ___currentLobbyList, ___lobbySlotPositionOffset); return false; } public static IEnumerator modifiedLoadLobbyIEnumerator(SteamLobbyManager __instance, Lobby[] ___currentLobbyList, float ___lobbySlotPositionOffset) { string[] offensiveWords = new string[21] { "nigger", "faggot", "n1g", "nigers", "cunt", "pussies", "pussy", "minors", "chink", "buttrape", "molest", "rape", "coon", "negro", "beastiality", "cocks", "cumshot", "ejaculate", "pedophile", "furfag", "necrophilia" }; for (int i = 0; i < ___currentLobbyList.Length; i++) { Lobby currentLobby = ___currentLobbyList[i]; Friend[] blockedUsers = SteamFriends.GetBlocked().ToArray(); if (blockedUsers != null) { Friend[] array = blockedUsers; for (int j = 0; j < array.Length; j++) { Friend blockedUser = array[j]; if (((Lobby)(ref currentLobby)).IsOwnedBy(blockedUser.Id)) { } } } string lobbyName = ((Lobby)(ref currentLobby)).GetData("name"); bool lobbyModded = !Utility.IsNullOrWhiteSpace(((Lobby)(ref currentLobby)).GetData("mods")); if (!Utility.IsNullOrWhiteSpace(lobbyName)) { string lobbyNameLowercase = lobbyName.ToLower(); if (__instance.censorOffensiveLobbyNames) { string[] array2 = offensiveWords; foreach (string word in array2) { if (lobbyNameLowercase.Contains(word)) { } } } GameObject gameObject = Object.Instantiate<GameObject>(__instance.LobbySlotPrefab, __instance.levelListContainer); gameObject.GetComponent<RectTransform>().anchoredPosition = new Vector2(0f, ___lobbySlotPositionOffset); ___lobbySlotPositionOffset -= 42f; LobbySlot componentInChildren = gameObject.GetComponentInChildren<LobbySlot>(); ((TMP_Text)componentInChildren.LobbyName).text = lobbyName + " " + (lobbyModded ? "[Checker]" : ""); ((TMP_Text)componentInChildren.playerCount).text = $"{((Lobby)(ref currentLobby)).MemberCount} / 4"; componentInChildren.lobbyId = ((Lobby)(ref currentLobby)).Id; componentInChildren.thisLobby = currentLobby; } currentLobby = default(Lobby); } yield break; } } } namespace CompatibilityChecker.Netcode { [HarmonyPatch] internal class PlayerJoinNetcode { private static string[] serverModList = null; public static Vector2 old = Vector2.zero; public static IEnumerator SetLobbyData(Lobby lobby) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) if (GameNetworkManager.Instance.currentLobby.HasValue) { ((Lobby)(ref lobby)).SetData("mods", ModNotifyBase.ModListString); ModNotifyBase.Logger.LogInfo((object)("Set " + ((Lobby)(ref lobby)).GetData("name") + " mods to: " + ModNotifyBase.ModListString)); } yield break; } [HarmonyPatch(typeof(GameNetworkManager), "SteamMatchmaking_OnLobbyCreated")] [HarmonyPrefix] public static bool OnLobbyCreated(ref GameNetworkManager __instance, Result result, ref Lobby lobby) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Invalid comparison between Unknown and I4 //IL_0010: Unknown result type (might be due to invalid IL or missing references) if ((int)result == 1) { CoroutineHandler.Instance.NewCoroutine(SetLobbyData(lobby)); } return true; } [HarmonyPatch(typeof(GameNetworkManager), "StartHost")] [HarmonyPrefix] public static bool StartHost(ref GameNetworkManager __instance) { if (!ModNotifyBase.loadedMods) { CoroutineHandler.Instance.NewCoroutine(Connect()); CoroutineHandler.Instance.NewCoroutine(ModNotifyBase.InitializeModsCoroutine()); return false; } return true; } public static IEnumerator Connect() { yield return (object)new WaitUntil((Func<bool>)(() => ModNotifyBase.loadedMods)); GameNetworkManager.Instance.StartHost(); } [HarmonyPatch(typeof(GameNetworkManager), "LobbyDataIsJoinable")] [HarmonyPrefix] public static bool IsJoinable(ref Lobby lobby) { string data = ((Lobby)(ref lobby)).GetData("mods"); if (!Utility.IsNullOrWhiteSpace(data)) { serverModList = data.Split(ModNotifyBase.seperator); ModNotifyBase.Logger.LogWarning((object)(((Lobby)(ref lobby)).GetData("name") + " returned:")); try { string[] array = serverModList; foreach (string input in array) { string text = Regex.Replace(input, "\\[([\\d.]+)\\]", ""); string text2 = (Regex.Match(input, "\\[([\\d.]+)\\]").Groups[1].Value ?? "") ?? "No version number found"; string text3 = ""; if (Chainloader.PluginInfos.ContainsKey(text)) { PluginInfo obj = Chainloader.PluginInfos[text]; object obj2; if (obj == null) { obj2 = null; } else { BepInPlugin metadata = obj.Metadata; obj2 = ((metadata == null) ? null : metadata.Version?.ToString()); } text3 = (string)obj2; } string text4 = text; string text5 = ((!Utility.IsNullOrWhiteSpace(text3) && !Utility.IsNullOrWhiteSpace(text2) && !VersionUtil.ConvertToNumber(text2).Equals(VersionUtil.ConvertToNumber(text3))) ? (" (May be incompatible with your version v" + text3 + ")") : ""); Package package = ThunderstoreAPI.GetPackage(text); if (package != null) { text4 = Regex.Replace(input, "\\[([\\d.]+)\\]", "") + " v" + text2 + text5; } ModNotifyBase.Logger.LogWarning((object)text4); } } catch (Exception ex) { ModNotifyBase.Logger.LogError((object)ex); } } return true; } [HarmonyPatch(typeof(GameNetworkManager), "ConnectionApproval")] [HarmonyPostfix] public static void JoinLobbyPostfix() { if (ModNotifyBase.ModList.Count == 0) { CoroutineHandler.Instance.NewCoroutine(ModNotifyBase.InitializeModsCoroutine()); } } [HarmonyPatch(typeof(MenuManager), "SetLoadingScreen")] [HarmonyPostfix] public static void SetLoadingScreenPatch(ref MenuManager __instance, ref RoomEnter result, ref bool isLoading, ref string overrideMessage) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_008b: 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) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_01ab: Unknown result type (might be due to invalid IL or missing references) //IL_01b0: Unknown result type (might be due to invalid IL or missing references) if (old == Vector2.zero) { old = ((Component)((TMP_Text)__instance.menuNotificationButtonText).transform.parent).GetComponent<RectTransform>().sizeDelta; } if ((int)result != 5 || !Utility.IsNullOrWhiteSpace(overrideMessage)) { ((Component)((TMP_Text)__instance.menuNotificationButtonText).transform.parent).GetComponent<RectTransform>().sizeDelta = old; return; } ((Component)((TMP_Text)__instance.menuNotificationButtonText).transform.parent).GetComponent<RectTransform>().sizeDelta = old; Package package = ThunderstoreAPI.GetPackage("CompatibilityChecker"); bool flag = VersionUtil.ConvertToNumber(package.Versions[0].VersionNumber) > VersionUtil.ConvertToNumber("1.1.6"); string text = (flag ? ("New CompatibilityChecker update is available! v" + package.Versions[0].VersionNumber + " != 1.1.6") : "[ Close ]"); if (flag & !isLoading) { ((Component)((TMP_Text)__instance.menuNotificationButtonText).transform.parent).GetComponent<RectTransform>().sizeDelta = new Vector2(256.375f, 58.244f); } if (ModNotifyBase.ModList.Count == 0) { CoroutineHandler.Instance.NewCoroutine(ModNotifyBase.InitializeModsCoroutine()); } if (Utility.IsNullOrWhiteSpace(overrideMessage) && Utility.IsNullOrWhiteSpace(GameNetworkManager.Instance.disconnectionReasonMessage) && !isLoading) { if (serverModList == null) { __instance.DisplayMenuNotification("Failed to join Modded Crew!\n Missing mods:\nCan't display: Host does not have CompatibilityChecker!", text); } else { GameNetworkManager instance = GameNetworkManager.Instance; object obj; if (instance == null) { obj = null; } else { Lobby value = instance.currentLobby.Value; obj = ((Lobby)(ref value)).GetData("name"); } string text2 = (string)obj; string[] array = serverModList.Except(ModNotifyBase.ModListArray).ToArray(); string[] array2 = ModNotifyBase.ModListArray.Except(serverModList).ToArray(); string text3 = ((array == null || array.Length == 0) ? "None..?" : string.Join("\n", array)); string text4 = ((array2 == null || array2.Length == 0) ? "None." : string.Join("\n\t\t", array2)); __instance.DisplayMenuNotification("Modded crew\n(Check logs/console for links)!\n Missing mods:\n" + text3, text); ModNotifyBase.Logger.LogError((object)("\nMissing server-sided mods from lobby \"" + text2 + "\":")); string[] array3 = array; foreach (string text5 in array3) { string text6 = text5; Package package2 = ThunderstoreAPI.GetPackage(text5); if (package2 != null) { string text7 = (Regex.Match(text5, "\\[([\\d.]+)\\]").Success ? ("v" + Regex.Match(text5, "\\[([\\d.]+)\\]").Value) : "No version number found"); text6 = string.Format("\n\t--Name: {0}\n\t--Link: {1}\n\t--Version: {2}\n\t--Downloads: {3}\n\t--Categories: [{4}]", text5, package2.PackageUrl, text7, package2.Versions[0].Downloads, string.Join(", ", package2.Categories)); } ModNotifyBase.Logger.LogError((object)text6); } ModNotifyBase.Logger.LogWarning((object)("Mods \"" + text2 + "\" may not be compatible with:\n\t\t" + text4)); serverModList = null; } } if (flag) { ModNotifyBase.Logger.LogWarning((object)("NEW VERSION OF COMPATIBILITY CHECKER IS AVAILABE. PLEASE UPDATE TO " + package.Versions[0].VersionNumber)); } } [HarmonyPatch(typeof(MenuManager), "connectionTimeOut")] [HarmonyPostfix] public static void timeoutPatch() { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) if (GameNetworkManager.Instance.currentLobby.HasValue && serverModList == null) { Lobby value = GameNetworkManager.Instance.currentLobby.Value; serverModList = ((Lobby)(ref value)).GetData("mods")?.Split(ModNotifyBase.seperator); } } [HarmonyPatch(typeof(GameNetworkManager), "Singleton_OnClientConnectedCallback")] [HarmonyPostfix] public static void ConnectCallbackPatch() { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) Lobby? currentLobby = GameNetworkManager.Instance.currentLobby; if ((Object)(object)StartOfRound.Instance != (Object)null && currentLobby.HasValue) { Lobby value = currentLobby.Value; if (Utility.IsNullOrWhiteSpace(((Lobby)(ref value)).GetData("mods"))) { ModNotifyBase.Logger.LogInfo((object)"Setting lobbys mods"); CoroutineHandler.Instance.NewCoroutine(SetLobbyData(currentLobby.Value)); } } } } } namespace CompatibilityChecker.MonoBehaviours { internal class CoroutineHandler : MonoBehaviour { private static CoroutineHandler instance; private List<Type> runningCoroutines = new List<Type>(); public static CoroutineHandler Instance { get { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown if ((Object)(object)instance == (Object)null) { GameObject val = new GameObject("CoroutineHandler"); instance = val.AddComponent<CoroutineHandler>(); Object.DontDestroyOnLoad((Object)(object)val); } return instance; } } public void NewCoroutine(IEnumerator coroutine) { if (!IsCoroutineRunning(coroutine.GetType())) { runningCoroutines.Add(coroutine.GetType()); ((MonoBehaviour)this).StartCoroutine(ExecuteCoroutine(coroutine)); } else { ModNotifyBase.Logger.LogWarning((object)("Coroutine " + coroutine.GetType().FullName + " is already running")); } } private bool IsCoroutineRunning(Type coroutine) { return runningCoroutines.Any((Type runningCoroutine) => runningCoroutine == coroutine); } private IEnumerator ExecuteCoroutine(IEnumerator coroutine) { yield return ((MonoBehaviour)this).StartCoroutine(coroutine); runningCoroutines.Remove(coroutine.GetType()); } } public class SearchBox : MonoBehaviour { private TMP_InputField searchInputField; private GameObject canvas; public string Text = ""; public void Awake() { ModNotifyBase.Logger.LogInfo((object)"SearchBox: I have awoken"); } public void Start() { ModNotifyBase.Logger.LogInfo((object)"SearchBox: Start method called"); LoadCanvas(); } private void LoadCanvas() { canvas = GameObject.Find("/Canvas/MenuContainer/LobbyList"); if ((Object)(object)canvas == (Object)null) { ModNotifyBase.Logger.LogError((object)"SearchBox: Canvas not found. Make sure the hierarchy and names are correct."); return; } ModNotifyBase.Logger.LogInfo((object)"SearchBox: Canvas found. Creating search box."); CreateSearchBox(); } private void CreateSearchBox() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0071: 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_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) ModNotifyBase.Logger.LogInfo((object)"SearchBox: Creating search box"); searchInputField = CreateInputField("Search..", Vector2.zero); ((UnityEvent<string>)(object)searchInputField.onEndEdit).AddListener((UnityAction<string>)OnEndEdit); RectTransform component = ((Component)searchInputField).GetComponent<RectTransform>(); component.sizeDelta = new Vector2(200f, 30f); component.anchoredPosition = new Vector2(0f, 0f); component.anchoredPosition = new Vector2(canvas.GetComponent<RectTransform>().sizeDelta.x / 2f, canvas.GetComponent<RectTransform>().sizeDelta.y / 2f); ((Component)searchInputField).transform.SetParent(canvas.transform, false); ((Component)searchInputField).gameObject.SetActive(false); ((Component)searchInputField).gameObject.SetActive(true); } private TMP_InputField CreateInputField(string placeholder, Vector2 position) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Expected O, but got Unknown //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Expected O, but got Unknown //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) TextMeshProUGUI component = GameObject.Find("/Canvas/MenuContainer/LobbyList/ListPanel/ListHeader").GetComponent<TextMeshProUGUI>(); GameObject val = new GameObject("SearchInputField"); RectTransform val2 = val.AddComponent<RectTransform>(); val2.anchoredPosition = position; TMP_InputField val3 = val.AddComponent<TMP_InputField>(); ((Selectable)val3).interactable = true; GameObject val4 = new GameObject("Placeholder"); val4.transform.SetParent(val.transform, false); TextMeshProUGUI val5 = val4.AddComponent<TextMeshProUGUI>(); ((TMP_Text)val5).text = placeholder; ((TMP_Text)val5).font = ((TMP_Text)component).font; ((Graphic)val5).color = ((Graphic)component).color; val3.placeholder = (Graphic)(object)val5; GameObject val6 = new GameObject("Text"); val6.transform.SetParent(val.transform, false); TextMeshProUGUI val7 = val6.AddComponent<TextMeshProUGUI>(); ((TMP_Text)val7).font = ((TMP_Text)component).font; ((Graphic)val7).color = ((Graphic)component).color; val3.textComponent = (TMP_Text)(object)val7; RectTransform component2 = ((Component)val3).GetComponent<RectTransform>(); component2.sizeDelta = new Vector2(200f, 30f); component2.anchoredPosition = new Vector2(0f, 0f); return val3; } private void OnEndEdit(string newValue) { Text = newValue; ModNotifyBase.Logger.LogInfo((object)("SearchBox: Search Value Changed - " + newValue)); SteamLobbyManager val = Object.FindObjectOfType<SteamLobbyManager>(); val.LoadServerList(); } } }