Please disclose if your mod was created primarily 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 QuickConnect v1.7.0
plugins/QuickConnect.dll
Decompiled 6 months agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Net; using System.Net.Sockets; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Threading.Tasks; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("QuickConnect")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("QuickConnect")] [assembly: AssemblyCopyright("Copyright © 2021")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("1c6b0fc4-ad65-4bb6-a9db-7ca3b47eadf6")] [assembly: AssemblyFileVersion("1.5.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyVersion("1.5.0.0")] namespace QuickConnect; [HarmonyPatch(typeof(ZNet), "RPC_ClientHandshake")] internal class PatchPasswordPrompt { private static bool Prefix(ZNet __instance, ZRpc rpc, bool needPassword, string serverPasswordSalt) { string text = QuickConnectUI.CurrentPass(); if (text != null) { if (needPassword) { Mod.Log.LogInfo((object)"Authenticating with saved password..."); ((Component)__instance.m_connectingDialog).gameObject.SetActive(false); FieldInfo field = typeof(ZNet).GetField("m_serverPasswordSalt", BindingFlags.Static | BindingFlags.NonPublic); field.SetValue(null, serverPasswordSalt); MethodInfo method = typeof(ZNet).GetMethod("SendPeerInfo", BindingFlags.Instance | BindingFlags.NonPublic); method.Invoke(__instance, new object[2] { rpc, text }); QuickConnectUI.connecting = null; return false; } Mod.Log.LogInfo((object)"Server didn't want password?"); } return true; } } [HarmonyPatch(typeof(ZNet), "OnDestroy")] internal class PatchConnectFailed { private static void Postfix() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Invalid comparison between Unknown and I4 if ((int)ZNet.GetConnectionStatus() == 5) { QuickConnectUI.instance.JoinServerFailed(); } } } [HarmonyPatch(typeof(FejdStartup), "OnSelelectCharacterBack")] internal class PatchCharacterBack { private static void Postfix() { QuickConnectUI.instance.AbortConnect(); } } [HarmonyPatch(typeof(FejdStartup), "SetupGui")] internal class PatchUiInit { private static void Postfix() { ((Object)QuickConnectUI.instance).GetInstanceID(); } } [BepInPlugin("net.bdew.valheim.QuickConnect", "QuickConnect", "1.6.1")] internal class Mod : BaseUnityPlugin { public static ManualLogSource Log; public static ConfigEntry<float> windowPosX; public static ConfigEntry<float> windowPosY; public static ConfigEntry<int> buttonFontSize; public static ConfigEntry<int> labelFontSize; public static ConfigEntry<int> windowWidth; public static ConfigEntry<int> windowHeight; public static ConfigEntry<bool> customConnectionError; public static ConfigEntry<string> customDelimiter; private void Awake() { //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Expected O, but got Unknown Log = Logger.CreateLogSource("QuickConnect"); windowPosX = ((BaseUnityPlugin)this).Config.Bind<float>("UI", "WindowPosX", 20f, (ConfigDescription)null); windowPosY = ((BaseUnityPlugin)this).Config.Bind<float>("UI", "WindowPosY", 20f, (ConfigDescription)null); buttonFontSize = ((BaseUnityPlugin)this).Config.Bind<int>("UI", "ButtonFontSize", 0, (ConfigDescription)null); labelFontSize = ((BaseUnityPlugin)this).Config.Bind<int>("UI", "LabelFontSize", 0, (ConfigDescription)null); windowWidth = ((BaseUnityPlugin)this).Config.Bind<int>("UI", "WindowWidth", 250, (ConfigDescription)null); windowHeight = ((BaseUnityPlugin)this).Config.Bind<int>("UI", "WindowHeight", 50, (ConfigDescription)null); customConnectionError = ((BaseUnityPlugin)this).Config.Bind<bool>("UI", "CustomConnectionError", false, "Show custom connection failure message in addition to vanilla connection failure message."); customDelimiter = ((BaseUnityPlugin)this).Config.Bind<string>("UI", "CustomDelimiter", "", "Override server config delimiter. Defaults to a colon (':')."); ((BaseUnityPlugin)this).Config.SettingChanged += delegate { Servers.Init(); QuickConnectUI.instance.redraw = true; }; Harmony val = new Harmony("net.bdew.valheim.QuickConnect"); val.PatchAll(); } } internal class QuickConnectUI : MonoBehaviour { private enum windowState { ServerList, Connecting, NoServers } private static QuickConnectUI _instance; public Rect windowRect; public Rect lastRect; public Rect errorWinRect; private Rect dragRect = new Rect(0f, 0f, 10000f, 20f); private int buttonFontSize; private int labelFontSize; private GUIStyle buttonStyle; private GUIStyle labelStyle; public bool redraw = true; private windowState state = windowState.ServerList; private Task<IPHostEntry> resolveTask; public static Servers.Entry connecting; private static string errorMsg; public static QuickConnectUI instance { get { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown if ((Object)(object)_instance == (Object)null) { Servers.Init(); GameObject val = new GameObject("QuickConnect"); _instance = val.AddComponent<QuickConnectUI>(); } return _instance; } } private void Update() { if (resolveTask == null) { return; } if (resolveTask.IsFaulted) { Mod.Log.LogError((object)$"Error resolving IP: {resolveTask.Exception}"); if (resolveTask.Exception != null) { ShowError(resolveTask.Exception.InnerException.Message); } else { ShowError(resolveTask.Exception.Message); } resolveTask = null; connecting = null; } else if (resolveTask.IsCanceled) { resolveTask = null; connecting = null; } else { if (!resolveTask.IsCompleted) { return; } IPAddress[] addressList = resolveTask.Result.AddressList; foreach (IPAddress iPAddress in addressList) { if (iPAddress.AddressFamily == AddressFamily.InterNetwork) { Mod.Log.LogInfo((object)$"Resolved: {iPAddress}"); resolveTask = null; ZSteamMatchmaking.instance.QueueServerJoin($"{iPAddress}:{connecting.port}"); return; } } resolveTask = null; connecting = null; ShowError("Server DNS resolved to no valid addresses"); } } private void Draw() { //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) ((Rect)(ref windowRect)).x = Mod.windowPosX.Value; ((Rect)(ref windowRect)).y = Mod.windowPosY.Value; buttonFontSize = Mod.buttonFontSize.Value; labelFontSize = Mod.labelFontSize.Value; ((Rect)(ref windowRect)).width = Mod.windowWidth.Value; ((Rect)(ref windowRect)).height = Mod.windowHeight.Value; lastRect = windowRect; } private void Awake() { Draw(); } private void OnGUI() { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Expected O, but got Unknown //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Expected O, but got Unknown //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_0059: 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_0079: Expected O, but got Unknown //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) if (buttonStyle == null) { buttonStyle = new GUIStyle(GUI.skin.button); } if (labelStyle == null) { labelStyle = new GUIStyle(GUI.skin.label); } if (errorMsg != null) { errorWinRect = GUILayout.Window(1586464, errorWinRect, new WindowFunction(DrawErrorWindow), "Error", Array.Empty<GUILayoutOption>()); return; } windowRect = GUILayout.Window(1586463, windowRect, new WindowFunction(DrawConnectWindow), "Quick Connect", Array.Empty<GUILayoutOption>()); if (!((Rect)(ref lastRect)).Equals(windowRect)) { Mod.windowPosX.Value = ((Rect)(ref windowRect)).x; Mod.windowPosY.Value = ((Rect)(ref windowRect)).y; lastRect = windowRect; } else if (redraw) { Draw(); buttonStyle.fontSize = buttonFontSize; labelStyle.fontSize = labelFontSize; redraw = false; } } private void DrawConnectWindow(int windowID) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) GUI.DragWindow(dragRect); if (connecting != null) { CheckWindowState(windowState.Connecting); GUILayout.Label("Connecting to " + connecting.name, labelStyle, Array.Empty<GUILayoutOption>()); if (GUILayout.Button("Cancel", buttonStyle, Array.Empty<GUILayoutOption>())) { AbortConnect(); } return; } if (Servers.entries.Count > 0) { CheckWindowState(windowState.ServerList); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUILayout.Label("Choose A Server:", labelStyle, Array.Empty<GUILayoutOption>()); if (GUILayout.Button("Reload from Disk", buttonStyle, Array.Empty<GUILayoutOption>())) { Servers.Init(); DrawConnectWindow(windowID); } GUILayout.EndHorizontal(); { foreach (Servers.Entry entry in Servers.entries) { if (GUILayout.Button(entry.name, buttonStyle, Array.Empty<GUILayoutOption>())) { DoConnect(entry); } } return; } } CheckWindowState(windowState.NoServers); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUILayout.Label("No servers defined", labelStyle, Array.Empty<GUILayoutOption>()); if (GUILayout.Button("Reload from Disk", buttonStyle, Array.Empty<GUILayoutOption>())) { Servers.Init(); DrawConnectWindow(windowID); } GUILayout.EndHorizontal(); GUILayout.Label("Add/modify quick_connect_servers.cfg", labelStyle, Array.Empty<GUILayoutOption>()); } private void DrawErrorWindow(int windowID) { GUILayout.Label(errorMsg, labelStyle, Array.Empty<GUILayoutOption>()); if (GUILayout.Button("Close", buttonStyle, Array.Empty<GUILayoutOption>())) { errorMsg = null; } } private void DoConnect(Servers.Entry server) { connecting = server; try { IPAddress.Parse(server.ip); ZSteamMatchmaking.instance.QueueServerJoin($"{server.ip}:{server.port}"); } catch (FormatException) { Mod.Log.LogInfo((object)("Resolving: " + server.ip)); resolveTask = Dns.GetHostEntryAsync(server.ip); } } public static string CurrentPass() { if (connecting != null) { return connecting.pass; } return null; } public void JoinServerFailed() { if (Mod.customConnectionError.Value) { ShowError("Server connection failed"); } connecting = null; } public void ShowError(string msg) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) errorMsg = msg; errorWinRect = new Rect((float)(Screen.width / 2 - 125), (float)(Screen.height / 2), 250f, 30f); } public void AbortConnect() { connecting = null; resolveTask = null; } private void CheckWindowState(windowState state) { if (this.state != state) { this.state = state; Draw(); } } } internal class Servers { public class Entry { public string name; public string ip; public int port; public string pass; public override string ToString() { return $"Server(name={name},ip={ip},port={port})"; } } public static string ConfigPath; public static List<Entry> entries; public static void Init() { entries.Clear(); try { char c = (Mod.customDelimiter.Value.Equals(string.Empty) ? ':' : Mod.customDelimiter.Value[0]); if (!File.Exists(ConfigPath)) { return; } using StreamReader streamReader = new StreamReader(ConfigPath); string text; while ((text = streamReader.ReadLine()) != null) { text = text.Trim(); if (text.Length == 0 || text.StartsWith("#")) { continue; } string[] array = text.Split(new char[1] { c }); if (array.Length >= 3) { string name = array[0]; string ip = array[1]; int port = int.Parse(array[2]); string pass = null; if (array.Length >= 4) { pass = array[3]; } entries.Add(new Entry { name = name, ip = ip, port = port, pass = pass }); } else { Mod.Log.LogDebug((object)("Invalid config line: " + text)); } } Mod.Log.LogInfo((object)$"Loaded {entries.Count} server entries"); } catch (Exception arg) { Mod.Log.LogError((object)$"Error loading config {arg}"); QuickConnectUI.instance.ShowError("Error loading server config"); } } static Servers() { string? directoryName = Path.GetDirectoryName(Paths.BepInExConfigPath); char directorySeparatorChar = Path.DirectorySeparatorChar; ConfigPath = directoryName + directorySeparatorChar + "quick_connect_servers.cfg"; entries = new List<Entry>(); } }