using 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();
}
}
}