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 AutoConnector v1.0.0
plugins/AutoConnector.dll
Decompiled 4 days agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security.Permissions; using AutoConnector.Common; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using GUIFramework; using HarmonyLib; using Jotunn.Managers; using Jotunn.Utils; using TMPro; using UnityEngine; using YamlDotNet.Core; using YamlDotNet.Serialization; using YamlDotNet.Serialization.NamingConventions; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("AutoConnector")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("AutoConnector")] [assembly: AssemblyCopyright("Copyright © 2021")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("e3243d22-4307-4008-ba36-9f326008cde5")] [assembly: AssemblyFileVersion("1.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] namespace AutoConnector { [BepInPlugin("MidnightsFX.Autoconnect", "AutoConnector", "1.0.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] internal class AutoConnector : BaseUnityPlugin { public const string PluginGUID = "MidnightsFX.Autoconnect"; public const string PluginName = "AutoConnector"; public const string PluginVersion = "1.0.0"; internal static ManualLogSource Log; internal ValConfig cfg; public void Awake() { //IL_002e: Unknown result type (might be due to invalid IL or missing references) Log = ((BaseUnityPlugin)this).Logger; cfg = new ValConfig(((BaseUnityPlugin)this).Config); if (!GUIManager.IsHeadless()) { ServerStore.Init(); new Harmony("MidnightsFX.Autoconnect").PatchAll(Assembly.GetExecutingAssembly()); } } } internal class Logger { public static LogLevel Level = (LogLevel)16; public static void EnableDebugLogging(object sender, EventArgs e) { CheckEnableDebugLogging(); } public static void CheckEnableDebugLogging() { //IL_0016: 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) if (ValConfig.EnableDebugMode.Value) { Level = (LogLevel)32; } else { Level = (LogLevel)16; } } public static void SetDebugLogging(bool state) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) if (state) { Level = (LogLevel)32; } else { Level = (LogLevel)16; } } public static void LogDebug(string message) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Invalid comparison between Unknown and I4 if ((int)Level >= 32) { AutoConnector.Log.LogInfo((object)("[DEBUG]" + message)); } } public static void LogInfo(string message) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Invalid comparison between Unknown and I4 if ((int)Level >= 16) { AutoConnector.Log.LogInfo((object)message); } } public static void LogWarning(string message) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Invalid comparison between Unknown and I4 if ((int)Level >= 4) { AutoConnector.Log.LogWarning((object)message); } } public static void LogError(string message) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Invalid comparison between Unknown and I4 if ((int)Level >= 2) { AutoConnector.Log.LogError((object)message); } } } internal class ValConfig { public static ConfigFile cfg; public static ConfigEntry<bool> EnableDebugMode; public static readonly string cfgFolder = "AutoConnector"; public ValConfig(ConfigFile cf) { cfg = cf; cfg.SaveOnConfigSet = true; CreateConfigValues(cf); Logger.SetDebugLogging(EnableDebugMode.Value); } private void CreateConfigValues(ConfigFile Config) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown EnableDebugMode = Config.Bind<bool>("Client config", "EnableDebugMode", false, new ConfigDescription("Enables Debug logging.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { IsAdvanced = true } })); EnableDebugMode.SettingChanged += Logger.EnableDebugLogging; Logger.CheckEnableDebugLogging(); } } } namespace AutoConnector.Patches { internal static class Favorites { [HarmonyPatch(typeof(ServerListGui), "Initialize")] internal static class AddSavedServers { [HarmonyPostfix] private static void Postfix(ServerListGui __instance) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_008f: 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) LocalServerList favoriteServersList = __instance.m_favoriteServersList; if (favoriteServersList == null) { return; } int num = 0; foreach (SavedServer server in ServerStore.Servers) { if (!((ServerJoinData)(ref server.JoinData)).IsValid) { continue; } if (server.HasOwnName) { NameServer(server.JoinData, server.Name); foreach (ServerJoinData aliasJoinDatum in server.AliasJoinData) { NameServer(aliasJoinDatum, server.Name); } } if (!AlreadyListed(favoriteServersList, server)) { favoriteServersList.Add(server.JoinData); num++; } } if (num > 0) { Logger.LogInfo($"Added {num} saved server(s) to favorites."); } } private static void NameServer(ServerJoinData server, string name) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) MultiBackendMatchmaking.SetServerName(server, new ServerNameAtTimePoint(name, DateTime.MaxValue)); } private static bool AlreadyListed(LocalServerList favorites, SavedServer saved) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) if (favorites.Contains(saved.JoinData)) { return true; } foreach (ServerJoinData aliasJoinDatum in saved.AliasJoinData) { if (favorites.Contains(aliasJoinDatum)) { return true; } } return false; } } } internal static class PasswordFlow { private sealed class Rejection { internal readonly ServerJoinData Server; internal readonly string Name; internal readonly bool WasSaved; internal Rejection(ServerJoinData server, string name, bool wasSaved) { //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) Server = server; Name = name; WasSaved = wasSaved; } } [HarmonyPatch(typeof(FejdStartup), "JoinServer")] internal static class CaptureJoinTarget { [HarmonyPrefix] private static void Prefix(FejdStartup __instance) { //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_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: 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) //IL_0036: Unknown result type (might be due to invalid IL or missing references) joinTarget = __instance.m_joinServer; joinName = NameOf(joinTarget); sentPassword = null; if (retryTarget != joinTarget) { retryTarget = ServerJoinData.None; retryPassword = null; } } } [HarmonyPatch(typeof(ZNet), "RPC_ClientHandshake")] internal static class SupplyPassword { [HarmonyPrefix] private static void Prefix(bool needPassword, out PasswordLoan __state) { __state = null; if (needPassword && ((ServerJoinData)(ref joinTarget)).IsValid) { string text = TakeRetryPassword() ?? SavedPassword(); if (text != null) { __state = new PasswordLoan(FejdStartup.ServerPassword); FejdStartup.ServerPassword = text; } } } [HarmonyPostfix] private static void Postfix(PasswordLoan __state) { if (__state != null) { FejdStartup.ServerPassword = __state.Displaced; } } } internal sealed class PasswordLoan { internal readonly string Displaced; internal PasswordLoan(string displaced) { Displaced = displaced; } } [HarmonyPatch(typeof(ZNet), "SendPeerInfo")] internal static class RecordSentPassword { [HarmonyPrefix] private static void Prefix(ZNet __instance, string password) { if (!__instance.IsServer() && !string.IsNullOrEmpty(password)) { sentPassword = password; } } } [HarmonyPatch(typeof(ZNet), "RPC_PeerInfo")] internal static class SaveAcceptedPassword { [HarmonyPostfix] private static void Postfix(ZNet __instance) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Invalid comparison between Unknown and I4 //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) if (!__instance.IsServer() && sentPassword != null && (int)ZNet.GetConnectionStatus() == 2) { if (((ServerJoinData)(ref joinTarget)).IsValid) { ServerStore.Remember(joinTarget, joinName, sentPassword); rejected.Remove(joinTarget); } sentPassword = null; } } } [HarmonyPatch(typeof(ZNet), "RPC_Error")] internal static class NoteRejectedPassword { [HarmonyPostfix] private static void Postfix(int error) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_004e: 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) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) if (error == 6 && sentPassword != null && ((ServerJoinData)(ref joinTarget)).IsValid) { if (!rejected.TryGetValue(joinTarget, out var value)) { value = new HashSet<string>(); rejected[joinTarget] = value; } value.Add(sentPassword); SavedServer savedServer = ServerStore.Find(joinTarget); bool flag = savedServer != null && savedServer.ServerPass == sentPassword; pendingPrompt = new Rejection(joinTarget, joinName, flag); Logger.LogInfo(JoinAddress.Label(joinTarget, joinName) + " rejected the " + (flag ? "saved " : "") + "password."); sentPassword = null; } } } [HarmonyPatch(typeof(FejdStartup), "ShowConnectError")] internal static class PromptAfterRejection { [HarmonyPostfix] private static void Postfix(FejdStartup __instance) { if (PasswordFlow.pendingPrompt != null) { Rejection pendingPrompt = PasswordFlow.pendingPrompt; PasswordFlow.pendingPrompt = null; ((MonoBehaviour)__instance).StartCoroutine(PromptForPassword(__instance, pendingPrompt)); } } } [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static PopupButtonCallback <>9__16_0; public static ValidateTextEntry <>9__16_1; internal void <PromptForPassword>b__16_0() { ClosePrompt(); } internal bool <PromptForPassword>b__16_1(string entry) { return !string.IsNullOrEmpty(entry); } } private static ServerJoinData joinTarget = ServerJoinData.None; private static string joinName; private static string sentPassword; private static ServerJoinData retryTarget = ServerJoinData.None; private static string retryPassword; private static Rejection pendingPrompt; private static readonly Dictionary<ServerJoinData, HashSet<string>> rejected = new Dictionary<ServerJoinData, HashSet<string>>(); private static ContentType? unmaskedContentType; private static IEnumerator PromptForPassword(FejdStartup startup, Rejection rejection) { yield return null; if ((Object)(object)startup == (Object)null || !UnifiedPopup.IsAvailable()) { yield break; } startup.m_connectionFailedPanel.SetActive(false); string text = JoinAddress.Label(rejection.Server, rejection.Name); string text2 = (rejection.WasSaved ? ("The saved password for " + text + " is incorrect.\nEnter the current password to reconnect.") : ("The password for " + text + " is incorrect.\nEnter it again to reconnect.")); object obj = <>c.<>9__16_0; if (obj == null) { PopupButtonCallback val = delegate { ClosePrompt(); }; <>c.<>9__16_0 = val; obj = (object)val; } object obj2 = <>c.<>9__16_1; if (obj2 == null) { ValidateTextEntry val2 = (string entry) => !string.IsNullOrEmpty(entry); <>c.<>9__16_1 = val2; obj2 = (object)val2; } UnifiedPopup.Push((PopupBase)new TextEntryPopup("Incorrect password", text2, "Password", (PopupButtonCallback)obj, (ValidateTextEntry)obj2, (RetrieveTextEntryResult)delegate(string entry) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) if (!string.IsNullOrEmpty(entry)) { ClosePrompt(); Reconnect(startup, rejection.Server, entry); } }, false)); SetPromptMasked(masked: true); UnifiedPopup.SetFocus(); } private static void ClosePrompt() { SetPromptMasked(masked: false); UnifiedPopup.Pop(); } private static void SetPromptMasked(bool masked) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)UnifiedPopup.instance == (Object)null) { return; } GuiInputField textEntryField = UnifiedPopup.instance.textEntryField; if (!((Object)(object)textEntryField == (Object)null)) { if (masked) { unmaskedContentType = ((TMP_InputField)textEntryField).contentType; ((TMP_InputField)textEntryField).contentType = (ContentType)7; } else if (unmaskedContentType.HasValue) { ((TMP_InputField)textEntryField).contentType = unmaskedContentType.Value; unmaskedContentType = null; } ((TMP_InputField)textEntryField).ForceLabelUpdate(); } } private static void Reconnect(FejdStartup startup, ServerJoinData server, string password) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: 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) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) retryTarget = server; retryPassword = password; if (!((Object)(object)startup == (Object)null)) { List<PlayerProfile> profiles = startup.m_profiles; int profileIndex = startup.m_profileIndex; if (profiles != null && profileIndex >= 0 && profileIndex < profiles.Count) { PlayerProfile val = profiles[profileIndex]; startup.SelectCharacter(val.GetFilename(), val.m_fileSource); startup.SetServerToJoin(server); startup.JoinServer(); } else { startup.ProceedJoinRequest(server); } } } private static string TakeRetryPassword() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) if (!((ServerJoinData)(ref retryTarget)).IsValid || retryTarget != joinTarget) { return null; } string result = retryPassword; retryTarget = ServerJoinData.None; retryPassword = null; return result; } private static string SavedPassword() { //IL_0009: 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) if (FejdStartup.ServerPassword != null) { return null; } SavedServer savedServer = ServerStore.Find(joinTarget); if (savedServer == null || string.IsNullOrEmpty(savedServer.ServerPass)) { return null; } if (rejected.TryGetValue(joinTarget, out var value) && value.Contains(savedServer.ServerPass)) { Logger.LogInfo("Not sending the saved password for " + savedServer.Name + "; it was rejected earlier this session."); return null; } Logger.LogDebug("Sending the saved password for " + savedServer.Name + "."); return savedServer.ServerPass; } private static string NameOf(ServerJoinData server) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) if (!((ServerJoinData)(ref server)).IsValid) { return null; } SavedServer savedServer = ServerStore.Find(server); if (savedServer != null && savedServer.HasOwnName) { return savedServer.Name; } string result = default(string); if (!MultiBackendMatchmaking.TryGetServerName(server, ref result)) { return null; } return result; } } } namespace AutoConnector.Common { internal static class JoinAddress { private const string SteamPrefix = "steam:"; private const string PlayFabPrefix = "playfab:"; internal static bool TryParse(string address, out ServerJoinData server) { //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_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: 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_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) server = ServerJoinData.None; if (string.IsNullOrWhiteSpace(address)) { return false; } address = address.Trim(); if (address.StartsWith("steam:", StringComparison.OrdinalIgnoreCase)) { if (!ulong.TryParse(address.Substring("steam:".Length).Trim(), out var result)) { return false; } server = new ServerJoinData(new ServerJoinDataSteamUser(result)); return ((ServerJoinData)(ref server)).IsValid; } if (address.StartsWith("playfab:", StringComparison.OrdinalIgnoreCase)) { string text = address.Substring("playfab:".Length).Trim(); if (text.Length == 0) { return false; } server = new ServerJoinData(new ServerJoinDataPlayFabUser(text)); return true; } ServerJoinDataDedicated val = default(ServerJoinDataDedicated); ((ServerJoinDataDedicated)(ref val))..ctor(address); if (string.IsNullOrEmpty(((ServerJoinDataDedicated)(ref val)).m_host)) { return false; } server = new ServerJoinData(val); return true; } internal static string Label(ServerJoinData server, string name) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) if (!string.IsNullOrEmpty(name)) { return name; } return Format(server); } internal static string Format(ServerJoinData server) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //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_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected I4, but got Unknown //IL_003a: 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_005e: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) ServerJoinDataType type = server.m_type; switch (type - 1) { case 2: return ((object)((ServerJoinData)(ref server)).Dedicated/*cast due to .constrained prefix*/).ToString(); case 0: { ulong steamID = ((ServerJoinData)(ref server)).SteamUser.m_joinUserID.m_SteamID; return "steam:" + steamID; } case 1: return "playfab:" + ((ServerJoinData)(ref server)).PlayFabUser.m_remotePlayerId; default: return null; } } } public class SavedServer { public string ServerAddress; public List<string> ServerAliases; public string ServerPass; [YamlIgnore] internal string Name; [YamlIgnore] internal ServerJoinData JoinData; [YamlIgnore] internal List<ServerJoinData> AliasJoinData = new List<ServerJoinData>(); internal bool HasOwnName { get { if (!string.IsNullOrEmpty(Name)) { return Name != ServerAddress; } return false; } } internal bool Matches(ServerJoinData server) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) if (((ServerJoinData)(ref JoinData)).IsValid && JoinData == server) { return true; } foreach (ServerJoinData aliasJoinDatum in AliasJoinData) { if (aliasJoinDatum == server) { return true; } } return false; } } internal static class ServerStore { private const string Header = "# AutoConnector saved servers\n#\n# Every server in this list is added to the Favorites tab of the Join Game screen, and its password is\n# entered for you when you join it. Join a server that is not listed here and type its password, and it\n# is added automatically. If a saved password stops working you are asked for the new one, and this file\n# is updated once it is accepted.\n#\n# Each server is filed under its name, which is also the name shown in the server list:\n#\n# Home server:\n# ServerAddress: 192.168.1.20:2456\n# ServerAliases:\n# - valheim.example.com:2456\n# ServerPass: hunter2\n#\n# ServerAddress The address added to favorites, e.g. 192.168.1.20:2456 or valheim.example.com:2456.\n# The port is 2456 when left off. Games hosted by a player rather than a dedicated\n# server are saved as steam:<id> or playfab:<id>.\n# ServerAliases Other addresses for the same server. Optional. The game treats a server added by name\n# and the same server joined by IP as two different servers; list the other one here and\n# the password is sent to both. Only ServerAddress is added to favorites.\n# ServerPass The server's password.\n#\n# If a name or password contains a # or : or starts with a symbol, wrap it in single quotes, and write\n# any single quote inside it twice: 'it''s#secret'\n#\n# Removing a server from favorites in game does not remove it from this file, so it comes back the next\n# time the server list opens. Delete its entry here instead.\n#\n# Passwords are stored as plain text. Anyone who can read this file can read them.\n#\n# AutoConnector rewrites this file when it saves a password, so comments other than this header are lost.\n\n"; private static readonly ISerializer serializer = ((BuilderSkeleton<SerializerBuilder>)new SerializerBuilder()).WithNamingConvention(PascalCaseNamingConvention.Instance).ConfigureDefaultValuesHandling((DefaultValuesHandling)1).WithQuotingNecessaryStrings(false) .DisableAliases() .Build(); private static readonly IDeserializer deserializer = new DeserializerBuilder().WithCaseInsensitivePropertyMatching().IgnoreUnmatchedProperties().Build(); private static string filePath; private static Dictionary<string, SavedServer> current = new Dictionary<string, SavedServer>(); private static DateTime loadedWriteTimeUtc; private static bool fileIsBroken; internal static IEnumerable<SavedServer> Servers { get { Refresh(); return current.Values; } } internal static void Init() { filePath = Path.Combine(Paths.ConfigPath, ValConfig.cfgFolder, "servers.yaml"); if (!File.Exists(filePath)) { Write(); } Refresh(); } internal static SavedServer Find(ServerJoinData server) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) if (!((ServerJoinData)(ref server)).IsValid) { return null; } foreach (SavedServer server2 in Servers) { if (server2.Matches(server)) { return server2; } } return null; } internal static void Remember(ServerJoinData server, string name, string password) { //IL_0012: 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_0093: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: 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) if (!((ServerJoinData)(ref server)).IsValid || string.IsNullOrEmpty(password)) { return; } SavedServer savedServer = Find(server); if (fileIsBroken) { Logger.LogWarning("The password for " + JoinAddress.Label(server, name) + " was not saved, because " + filePath + " could not be read. Fix the file and join again to save it."); return; } if (savedServer != null) { if (savedServer.ServerPass == password) { return; } savedServer.ServerPass = password; Logger.LogInfo("Updated the saved password for " + savedServer.Name + "."); } else { string text = JoinAddress.Format(server); if (text == null) { return; } savedServer = new SavedServer { ServerAddress = text, ServerPass = password, JoinData = server }; savedServer.Name = UnusedName(string.IsNullOrEmpty(name) ? text : name, text); current.Add(savedServer.Name, savedServer); Logger.LogInfo("Saved " + savedServer.Name + " and its password to " + filePath + "."); } Write(); } private static string UnusedName(string name, string address) { if (!current.ContainsKey(name)) { return name; } string text = name + " (" + address + ")"; string text2 = text; int num = 2; while (current.ContainsKey(text2)) { text2 = $"{text} {num}"; num++; } return text2; } private static void Refresh() { //IL_00b2: Expected O, but got Unknown //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) if (!File.Exists(filePath)) { if (loadedWriteTimeUtc != default(DateTime) || fileIsBroken) { current = new Dictionary<string, SavedServer>(); loadedWriteTimeUtc = default(DateTime); fileIsBroken = false; } return; } DateTime lastWriteTimeUtc = File.GetLastWriteTimeUtc(filePath); if (lastWriteTimeUtc == loadedWriteTimeUtc) { return; } string text; try { text = File.ReadAllText(filePath); } catch (Exception ex) { fileIsBroken = true; Logger.LogWarning(filePath + " could not be opened: " + ex.Message); return; } loadedWriteTimeUtc = lastWriteTimeUtc; Dictionary<string, SavedServer> dictionary; try { dictionary = deserializer.Deserialize<Dictionary<string, SavedServer>>(text) ?? new Dictionary<string, SavedServer>(); } catch (YamlException ex2) { YamlException ex3 = ex2; fileIsBroken = true; string arg = ((((Exception)(object)ex3).InnerException != null) ? ((Exception)(object)ex3).InnerException.Message : ((Exception)(object)ex3).Message); string arg2 = filePath; Mark start = ex3.Start; Logger.LogError($"{arg2} could not be read (line {((Mark)(ref start)).Line}: {arg}). The servers that last loaded from it are still used, but nothing new will be saved to it until it is fixed."); return; } foreach (string item in new List<string>(dictionary.Keys)) { if (dictionary[item] == null) { dictionary[item] = new SavedServer(); } } foreach (KeyValuePair<string, SavedServer> item2 in dictionary) { ParseAddresses(item2.Key, item2.Value); } current = dictionary; fileIsBroken = false; Logger.LogDebug($"Loaded {current.Count} saved servers from {filePath}."); } private static void ParseAddresses(string name, SavedServer saved) { //IL_00d1: Unknown result type (might be due to invalid IL or missing references) saved.Name = name; if (string.IsNullOrWhiteSpace(saved.ServerAddress)) { Logger.LogWarning("Skipping '" + name + "' in " + filePath + ": it has no ServerAddress."); } else if (!JoinAddress.TryParse(saved.ServerAddress, out saved.JoinData)) { Logger.LogWarning("Skipping '" + name + "' in " + filePath + ": '" + saved.ServerAddress + "' is not an address AutoConnector can read."); } if (saved.ServerAliases == null) { return; } foreach (string serverAlias in saved.ServerAliases) { if (JoinAddress.TryParse(serverAlias, out var server)) { saved.AliasJoinData.Add(server); continue; } Logger.LogWarning("Ignoring the alias '" + serverAlias + "' of '" + name + "' in " + filePath + ": it is not an address AutoConnector can read."); } } private static void Write() { try { Directory.CreateDirectory(Path.GetDirectoryName(filePath)); File.WriteAllText(filePath, "# AutoConnector saved servers\n#\n# Every server in this list is added to the Favorites tab of the Join Game screen, and its password is\n# entered for you when you join it. Join a server that is not listed here and type its password, and it\n# is added automatically. If a saved password stops working you are asked for the new one, and this file\n# is updated once it is accepted.\n#\n# Each server is filed under its name, which is also the name shown in the server list:\n#\n# Home server:\n# ServerAddress: 192.168.1.20:2456\n# ServerAliases:\n# - valheim.example.com:2456\n# ServerPass: hunter2\n#\n# ServerAddress The address added to favorites, e.g. 192.168.1.20:2456 or valheim.example.com:2456.\n# The port is 2456 when left off. Games hosted by a player rather than a dedicated\n# server are saved as steam:<id> or playfab:<id>.\n# ServerAliases Other addresses for the same server. Optional. The game treats a server added by name\n# and the same server joined by IP as two different servers; list the other one here and\n# the password is sent to both. Only ServerAddress is added to favorites.\n# ServerPass The server's password.\n#\n# If a name or password contains a # or : or starts with a symbol, wrap it in single quotes, and write\n# any single quote inside it twice: 'it''s#secret'\n#\n# Removing a server from favorites in game does not remove it from this file, so it comes back the next\n# time the server list opens. Delete its entry here instead.\n#\n# Passwords are stored as plain text. Anyone who can read this file can read them.\n#\n# AutoConnector rewrites this file when it saves a password, so comments other than this header are lost.\n\n" + serializer.Serialize((object)current)); loadedWriteTimeUtc = File.GetLastWriteTimeUtc(filePath); } catch (Exception ex) { Logger.LogError("Could not write " + filePath + ": " + ex.Message); } } } }