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 ZenLogin v1.3.0
plugins/ZenLogin.dll
Decompiled a month agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using Jotunn.Utils; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; using UnityEngine.Networking; using UnityEngine.UI; using Zen; using Zen.Lib; using Zen.Lib.Config; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("ZenLogin")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("ZenLogin")] [assembly: AssemblyCopyright("Copyright \ufffd 2026")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("e3243d22-4307-4008-ba36-9f326008cde5")] [assembly: AssemblyFileVersion("1.3.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.3.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace ZenLogin { internal static class Configs { public static readonly ConfigEntry<bool> Enabled; public static readonly ConfigEntry<string> ServerAddress; public static readonly ConfigEntry<string> ServerPassword; public static readonly ConfigEntry<bool> ShowMenuLogout; public static readonly ConfigEntry<string> LogoUrl; public static readonly ConfigEntry<bool> ShowChangeLog; public static readonly ConfigEntry<bool> ShowModdedText; static Configs() { Enabled = Config.Define<bool>(false, "General", "Enabled", true, "When enabled, automatically connect to the dedicated server after character selection.\r\nNOTE: You can temporarily disable this by holding the Alt key before clicking \"Connect\""); ServerAddress = Config.Define<string>(false, "General", "Server Address", string.Empty, "Host or IP address and port of the dedicated server. (Example: 127.0.0.1:2457)"); ServerPassword = Config.Define<string>(false, "General", "Server Password", string.Empty, "If left blank and the server requires a password it will prompt the user for the password."); ShowMenuLogout = Config.Define<bool>(true, "General", "Show Logout Menu", true, "Show the menu option \"Logout\" on the pause menu. (Vanilla: true)\r\nIf disabled it will force players to quit the game instead of logout.\r\nThis can be helpful when server admins need to force players to reboot the client."); LogoUrl = Config.Define<string>(false, "Title Screen", "Logo Url", string.Empty, "Set the path to a custom main menu title screen logo.\r\nIt can be a URL or a file path.\r\nIf it is a file path, it must be relative to: BepInEx/config/ \r\nYou can create a subfolder if you wish.\r\nMust be a .png file. Default dimensions: 1000x384\r\nExample: \r\n- YourLogo.png\r\n- your_folder/YourLogo.png\r\n- https://example.com/your_logo.png"); LogoUrl.SettingChanged += delegate { Logo.LoadFrom(LogoUrl.Value); }; ShowChangeLog = Config.Define<bool>(false, "Title Screen", "Show Changelog", true, "Show the Changelog Patch Notes on the title screen. (Vanilla: true)"); ShowChangeLog.SettingChanged += delegate { TitleScreen.ApplyConfig(); }; ShowModdedText = Config.Define<bool>(false, "Title Screen", "Show Modded Text", true, "Show the Modded Text Info on the title screen. (Vanilla: true)"); ShowModdedText.SettingChanged += delegate { TitleScreen.ApplyConfig(); }; } } [HarmonyPatch] internal static class Login { private static bool _disableAddToRecentServersList; private static bool IsAltKeyPressed { get { if (!ZInput.GetKey((KeyCode)308, true)) { return ZInput.GetKey((KeyCode)307, true); } return true; } } private static bool IsValid { get { if (Configs.Enabled.Value && !IsAltKeyPressed) { return !Utility.IsNullOrWhiteSpace(Configs.ServerAddress.Value); } return false; } } private static void InitConnection() { //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) bool flag = !Utility.IsNullOrWhiteSpace(Configs.ServerPassword.Value); Logging<Plugin>.Info((object)$"Connecting to server {Configs.ServerAddress.Value}, with password? {flag}", 0); FejdStartup.ServerPassword = (flag ? Configs.ServerPassword.Value : null); FejdStartup.instance.m_queuedJoinServer = new ServerJoinData(new ServerJoinDataDedicated(Configs.ServerAddress.Value)); _disableAddToRecentServersList = true; } [HarmonyPrefix] [HarmonyPatch(typeof(FejdStartup), "OnCharacterStart")] private static void FejdStartup_OnCharacterStart(FejdStartup __instance) { if (IsValid) { InitConnection(); } else { Logging<Plugin>.Info((object)"Auto connect disabled", 0); } } [HarmonyPostfix] [HarmonyPatch(typeof(FejdStartup), "Update")] private static void FejdStartup_Update(FejdStartup __instance) { string text = (IsValid ? "$menu_connect" : "$menu_start"); ((Component)((Component)__instance.m_csStartButton).transform.Find("Text")).GetComponent<TMP_Text>().text = StringExt.Localize(text); } [HarmonyPrefix] [HarmonyPatch(typeof(ServerListGui), "AddToRecentServersList")] private static void ServerListGui_AddToRecentServersList(ref bool __runOriginal) { __runOriginal = !_disableAddToRecentServersList; _disableAddToRecentServersList = false; } } [HarmonyPatch] internal static class Logo { [CompilerGenerated] private sealed class <Download>d__5 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public string url; private UnityWebRequest <req>5__2; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <Download>d__5(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || num == 1) { try { } finally { <>m__Finally1(); } } <req>5__2 = null; <>1__state = -2; } private bool MoveNext() { //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Invalid comparison between Unknown and I4 //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) bool result; try { switch (<>1__state) { default: result = false; break; case 0: <>1__state = -1; Logging<Plugin>.Info((object)("Downloading logo from url: " + url), 0); <req>5__2 = UnityWebRequestTexture.GetTexture(url); <>1__state = -3; <req>5__2.timeout = 20; <req>5__2.redirectLimit = 5; <>2__current = <req>5__2.SendWebRequest(); <>1__state = 1; result = true; break; case 1: <>1__state = -3; if ((int)<req>5__2.result != 1) { Logging<Plugin>.Warning((object)("Failed to load logo from url '" + url + "': " + <req>5__2.error), 0); ResetLogo(); result = false; } else { Texture2D content = DownloadHandlerTexture.GetContent(<req>5__2); if (!Object.op_Implicit((Object)(object)content)) { Logging<Plugin>.Warning((object)("Invalid texture data from '" + url + "'"), 0); ResetLogo(); result = false; } else { _logo = Sprite.Create(content, new Rect(0f, 0f, (float)((Texture)content).width, (float)((Texture)content).height), Vector2.one * 0.5f); Rect rect = _logo.rect; Logging<Plugin>.Info((object)$"Download complete. Logo dimensions: {((Rect)(ref rect)).size}", 0); SetLogo(); result = false; } } <>m__Finally1(); break; } } catch { //try-fault ((IDisposable)this).Dispose(); throw; } return result; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; if (<req>5__2 != null) { ((IDisposable)<req>5__2).Dispose(); } } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private static Sprite? _logo; private static Sprite? _valheimLogo; public static void LoadFrom(string urlOrFile) { urlOrFile = urlOrFile.Trim(); if (Utility.IsNullOrWhiteSpace(urlOrFile)) { ResetLogo(); } else if (urlOrFile.StartsWith("http")) { LoadFromWeb(urlOrFile); } else { LoadFromFile(urlOrFile); } } private static void LoadFromFile(string filePath) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) Logging<Plugin>.Info((object)("Load logo from file: " + filePath), 0); _logo = AssetUtils.LoadSpriteFromFile("../config/" + filePath, Vector2.one * 0.5f); if (!Object.op_Implicit((Object)(object)_logo)) { ResetLogo(); } else { SetLogo(); } } private static void LoadFromWeb(string url) { ((MonoBehaviour)ZenMod<Plugin>.Instance).StartCoroutine(Download(url)); } [IteratorStateMachine(typeof(<Download>d__5))] private static IEnumerator Download(string url) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <Download>d__5(0) { url = url }; } public static void SetLogo() { if (Object.op_Implicit((Object)(object)_logo) && Object.op_Implicit((Object)(object)FejdStartup.instance)) { Logging<Plugin>.Info((object)"Set logo", 0); Image component = ((Component)FejdStartup.instance.m_mainMenu.transform.Find("Logo/LOGO")).GetComponent<Image>(); if (!Object.op_Implicit((Object)(object)_valheimLogo)) { _valheimLogo = component.sprite; } component.sprite = _logo; } } private static void ResetLogo() { Logging<Plugin>.Info((object)"Reset main menu logo", 0); _logo = _valheimLogo; SetLogo(); } } [HarmonyPatch] internal static class MenuPatch { [HarmonyPrefix] [HarmonyPatch(typeof(Menu), "Show")] private static void Menu_Show(Menu __instance) { Transform val = ((Transform)__instance.menuEntriesParent).Find("Logout"); if (Object.op_Implicit((Object)(object)val)) { ((Component)val).gameObject.SetActive(Configs.ShowMenuLogout.Value); } } } [BepInPlugin("ZenDragon.ZenLogin", "ZenLogin", "1.3.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [SynchronizationMode(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] internal class Plugin : ZenMod<Plugin> { public const string PluginName = "ZenLogin"; public const string PluginVersion = "1.3.0"; public const string PluginGUID = "ZenDragon.ZenLogin"; protected override void Setup() { } private void Start() { Logo.LoadFrom(Configs.LogoUrl.Value); } protected override void TitleScene(bool isFirstBoot) { Logo.SetLogo(); } protected override void WorldStart() { } protected override void Shutdown() { } } [HarmonyPatch] internal static class TitleScreen { [HarmonyPostfix] [HarmonyPatch(typeof(FejdStartup), "SetupGui")] private static void FejdStartup_SetupGui() { ApplyConfig(); } public static void ApplyConfig() { if (Object.op_Implicit((Object)(object)FejdStartup.instance)) { ShowChangeLog(Configs.ShowChangeLog.Value); ShowModdedText(Configs.ShowModdedText.Value); } } private static void ShowChangeLog(bool isVisible) { ((Component)((Component)FejdStartup.instance.m_patchLogScroll).transform.parent).gameObject.SetActive(isVisible); } private static void ShowModdedText(bool isVisible) { FejdStartup.instance.m_moddedText.SetActive(isVisible); } } }