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 BifrostConnect v1.0.4
BifrostConnect.dll
Decompiled 4 hours agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Logging; using BifrostConnect.Models; using BifrostConnect.UI; using HarmonyLib; using Jotunn.Managers; using Jotunn.Utils; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using TMPro; using UnityEngine; using UnityEngine.Events; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")] [assembly: AssemblyCompany("Jubaroo")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("Copyright © 2026 Jubaroo")] [assembly: AssemblyDescription("Main menu dedicated server browser with auto-fill passwords and scrollable directory for Valheim")] [assembly: AssemblyFileVersion("1.0.4.0")] [assembly: AssemblyInformationalVersion("1.0.4")] [assembly: AssemblyProduct("BifrostConnect")] [assembly: AssemblyTitle("BifrostConnect")] [assembly: AssemblyVersion("1.0.4.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [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] [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] [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 BifrostConnect { [BepInPlugin("com.jubaroo.bifrostconnect", "Bifrost Connect", "1.0.4")] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { public const string ModGUID = "com.jubaroo.bifrostconnect"; public const string ModName = "Bifrost Connect"; public const string ModVersion = "1.0.4"; private readonly Harmony _harmony = new Harmony("com.jubaroo.bifrostconnect"); internal static ManualLogSource Log = null; public static List<ServerEntry> ServerList = new List<ServerEntry>(); private static string _jsonConfigPath = null; private void Awake() { Log = ((BaseUnityPlugin)this).Logger; _jsonConfigPath = Path.Combine(Paths.ConfigPath, "BifrostConnect_Servers.json"); LoadServerConfig(); Log.LogInfo((object)"Initializing Bifrost Connect hooks..."); _harmony.PatchAll(); } private static string StripComments(string text) { string[] array = text.Split(new string[3] { "\r\n", "\r", "\n" }, StringSplitOptions.None); StringBuilder stringBuilder = new StringBuilder(); string[] array2 = array; foreach (string text2 in array2) { string text3 = text2.Trim(); if (!text3.StartsWith("//") && !text3.StartsWith("#")) { stringBuilder.AppendLine(text2); } } return stringBuilder.ToString(); } internal static void LoadServerConfig() { if (!File.Exists(_jsonConfigPath) || new FileInfo(_jsonConfigPath).Length == 0L) { Log.LogInfo((object)("Server config not found at '" + _jsonConfigPath + "'. Generating default template with examples.")); GenerateDefaultConfig(); } try { string text = File.ReadAllText(_jsonConfigPath); ServerList = new List<ServerEntry>(); try { ServerListWrapper serverListWrapper = JsonConvert.DeserializeObject<ServerListWrapper>(text); if (serverListWrapper != null && serverListWrapper.Servers != null && serverListWrapper.Servers.Count > 0) { ServerList = serverListWrapper.Servers; } else { List<ServerEntry> list = JsonConvert.DeserializeObject<List<ServerEntry>>(text); if (list != null && list.Count > 0) { ServerList = list; } } } catch (Exception ex) { Log.LogWarning((object)("Newtonsoft.Json direct parse attempt: " + ex.Message + ". Trying with stripped comments.")); try { ServerListWrapper serverListWrapper2 = JsonConvert.DeserializeObject<ServerListWrapper>(StripComments(text)); if (serverListWrapper2 != null && serverListWrapper2.Servers != null && serverListWrapper2.Servers.Count > 0) { ServerList = serverListWrapper2.Servers; } } catch (Exception ex2) { Log.LogWarning((object)("Stripped JSON parse attempt: " + ex2.Message + ". Proceeding to line-by-line fallback.")); } } if (ServerList.Count == 0) { string[] array = text.Split(new string[3] { "\r\n", "\r", "\n" }, StringSplitOptions.None); for (int i = 0; i < array.Length; i++) { string text2 = array[i].Trim(); if (string.IsNullOrEmpty(text2) || text2.StartsWith("{") || text2.StartsWith("}") || text2.StartsWith("[") || text2.StartsWith("]") || text2.StartsWith("//") || text2.StartsWith("#")) { continue; } string[] array2 = text2.Split(new char[1] { ':' }); if (array2.Length >= 3) { string name = array2[0].Trim(); string iP = array2[1].Trim(); if (int.TryParse(array2[2].Trim(), out var result)) { string password = ((array2.Length > 3) ? array2[3].Trim() : string.Empty); ServerList.Add(new ServerEntry { Name = name, IP = iP, Port = result, Password = password }); } } } } Log.LogInfo((object)$"Loaded {ServerList.Count} servers from config: {_jsonConfigPath}"); foreach (ServerEntry server in ServerList) { Log.LogInfo((object)$" - Server: '{server.Name}' ({server.IP}:{server.Port})"); } } catch (Exception ex3) { Log.LogError((object)("Failed to load server config: " + ex3.Message)); } } private static void GenerateDefaultConfig() { string contents = "// ====================================================================\r\n// BifrostConnect Server Configuration\r\n// ====================================================================\r\n// Add your Valheim dedicated servers to the 'Servers' list below.\r\n//\r\n// Fields:\r\n// - Name: The display name shown on the button in the main menu.\r\n// - IP: The server IPv4 address or domain (e.g. 192.168.1.50 or valheim.myserver.com).\r\n// - Port: The connection port (default Valheim server port is 2456).\r\n// - Password: The server password (leave as \"\" if password is not required).\r\n//\r\n// You can add as many servers as you like to this list!\r\n// ====================================================================\r\n{\r\n \"Servers\": [\r\n {\r\n \"Name\": \"My Survival Server\",\r\n \"IP\": \"127.0.0.1\",\r\n \"Port\": 2456,\r\n \"Password\": \"\"\r\n },\r\n {\r\n \"Name\": \"Community Dedicated Server\",\r\n \"IP\": \"192.168.1.100\",\r\n \"Port\": 2456,\r\n \"Password\": \"secretpassword\"\r\n },\r\n {\r\n \"Name\": \"Modded World\",\r\n \"IP\": \"valheim.example.com\",\r\n \"Port\": 2456,\r\n \"Password\": \"valheim123\"\r\n }\r\n ]\r\n}\r\n"; File.WriteAllText(_jsonConfigPath, contents); } } } namespace BifrostConnect.UI { public class MenuEscapeHandler : MonoBehaviour { public FejdStartup? Instance; private void Update() { if (Input.GetKeyDown((KeyCode)27) && (Object)(object)Instance != (Object)null) { MenuBuilder.HandleEscape(Instance); } } } public static class MenuBuilder { [CompilerGenerated] private static class <>O { public static UnityAction <0>__CloseConfirmation; } private static GameObject _customMenuPanel; private static GameObject _confirmPanel; public static void InjectMainMenuButton(FejdStartup instance) { //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_016f: Expected O, but got Unknown if ((Object)(object)instance.m_mainMenu == (Object)null || (Object)(object)Utils.FindChild(instance.m_mainMenu.transform, "Button_BifrostConnect", (IterativeSearchType)0) != (Object)null) { return; } Transform val = Utils.FindChild(instance.m_mainMenu.transform, "Settings", (IterativeSearchType)0); if ((Object)(object)val == (Object)null) { return; } GameObject val2 = Object.Instantiate<GameObject>(((Component)val).gameObject, val.parent); ((Object)val2).name = "Button_BifrostConnect"; val2.transform.SetSiblingIndex(val.GetSiblingIndex()); Localize[] componentsInChildren = val2.GetComponentsInChildren<Localize>(true); for (int i = 0; i < componentsInChildren.Length; i++) { Object.DestroyImmediate((Object)(object)componentsInChildren[i]); } TMP_Text[] componentsInChildren2 = val2.GetComponentsInChildren<TMP_Text>(true); for (int i = 0; i < componentsInChildren2.Length; i++) { componentsInChildren2[i].text = "BIFROST CONNECT"; } Text[] componentsInChildren3 = val2.GetComponentsInChildren<Text>(true); for (int i = 0; i < componentsInChildren3.Length; i++) { componentsInChildren3[i].text = "BIFROST CONNECT"; } Button component = val2.GetComponent<Button>(); if ((Object)(object)component != (Object)null) { for (int j = 0; j < ((UnityEventBase)component.onClick).GetPersistentEventCount(); j++) { ((UnityEventBase)component.onClick).SetPersistentListenerState(j, (UnityEventCallState)0); } ((UnityEventBase)component.onClick).RemoveAllListeners(); ((UnityEvent)component.onClick).AddListener((UnityAction)delegate { OpenMenu(instance); }); } UIInputHandler[] componentsInChildren4 = val2.GetComponentsInChildren<UIInputHandler>(true); foreach (UIInputHandler obj in componentsInChildren4) { obj.m_onLeftClick = null; obj.m_onLeftDown = null; obj.m_onLeftUp = null; } if (!((Object)(object)instance.m_menuList != (Object)null)) { return; } try { AccessTools.Field(typeof(FejdStartup), "m_menuButtons")?.SetValue(instance, instance.m_menuList.GetComponentsInChildren<Button>()); } catch (Exception ex) { Plugin.Log.LogWarning((object)("Could not update m_menuButtons via reflection: " + ex.Message)); } } public static void BuildCustomPanel(FejdStartup instance) { //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_010b: 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_0127: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Unknown result type (might be due to invalid IL or missing references) //IL_0184: Unknown result type (might be due to invalid IL or missing references) //IL_01a9: Unknown result type (might be due to invalid IL or missing references) //IL_01b3: Expected O, but got Unknown //IL_028f: Unknown result type (might be due to invalid IL or missing references) //IL_0295: Expected O, but got Unknown //IL_02bd: Unknown result type (might be due to invalid IL or missing references) //IL_02d2: Unknown result type (might be due to invalid IL or missing references) //IL_02e7: Unknown result type (might be due to invalid IL or missing references) //IL_02fc: Unknown result type (might be due to invalid IL or missing references) //IL_0311: Unknown result type (might be due to invalid IL or missing references) //IL_0336: Unknown result type (might be due to invalid IL or missing references) //IL_03ac: Unknown result type (might be due to invalid IL or missing references) //IL_03b3: Expected O, but got Unknown //IL_03db: Unknown result type (might be due to invalid IL or missing references) //IL_03f1: Unknown result type (might be due to invalid IL or missing references) //IL_0407: Unknown result type (might be due to invalid IL or missing references) //IL_0413: Unknown result type (might be due to invalid IL or missing references) //IL_041f: Unknown result type (might be due to invalid IL or missing references) //IL_0444: Unknown result type (might be due to invalid IL or missing references) //IL_044e: Expected O, but got Unknown //IL_04bf: Unknown result type (might be due to invalid IL or missing references) //IL_04c6: Expected O, but got Unknown //IL_04ef: Unknown result type (might be due to invalid IL or missing references) //IL_0504: Unknown result type (might be due to invalid IL or missing references) //IL_0519: Unknown result type (might be due to invalid IL or missing references) //IL_052e: Unknown result type (might be due to invalid IL or missing references) //IL_0542: Unknown result type (might be due to invalid IL or missing references) //IL_0575: Unknown result type (might be due to invalid IL or missing references) //IL_057c: Expected O, but got Unknown //IL_0598: Unknown result type (might be due to invalid IL or missing references) //IL_05a3: Unknown result type (might be due to invalid IL or missing references) //IL_05ad: Unknown result type (might be due to invalid IL or missing references) //IL_05dc: Unknown result type (might be due to invalid IL or missing references) //IL_05e1: Unknown result type (might be due to invalid IL or missing references) //IL_05f4: Unknown result type (might be due to invalid IL or missing references) //IL_05fe: Unknown result type (might be due to invalid IL or missing references) //IL_060a: Unknown result type (might be due to invalid IL or missing references) //IL_0616: Unknown result type (might be due to invalid IL or missing references) //IL_0200: Unknown result type (might be due to invalid IL or missing references) //IL_020f: Unknown result type (might be due to invalid IL or missing references) //IL_021e: Unknown result type (might be due to invalid IL or missing references) //IL_022f: Unknown result type (might be due to invalid IL or missing references) //IL_0235: Unknown result type (might be due to invalid IL or missing references) //IL_069c: Unknown result type (might be due to invalid IL or missing references) //IL_06ab: Unknown result type (might be due to invalid IL or missing references) //IL_06b0: Unknown result type (might be due to invalid IL or missing references) //IL_0726: Unknown result type (might be due to invalid IL or missing references) //IL_0730: Expected O, but got Unknown //IL_078b: Unknown result type (might be due to invalid IL or missing references) //IL_0790: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_customMenuPanel != (Object)null) { Object.Destroy((Object)(object)_customMenuPanel); } object obj; if (!((Object)(object)GUIManager.CustomGUIFront != (Object)null)) { GameObject mainMenu = instance.m_mainMenu; obj = ((mainMenu != null) ? mainMenu.transform.parent : null); } else { obj = GUIManager.CustomGUIFront.transform; } Transform val = (Transform)obj; if ((Object)(object)val == (Object)null) { Plugin.Log.LogWarning((object)"No suitable GUI root/parent found for BifrostConnect panel."); return; } _customMenuPanel = GUIManager.Instance.CreateWoodpanel(val, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0f, 0f), 600f, 700f); _customMenuPanel.AddComponent<MenuEscapeHandler>().Instance = instance; GUIManager.Instance.CreateText("Server Directory", _customMenuPanel.transform, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -35f), GUIManager.Instance.AveriaSerifBold, 24, GUIManager.Instance.ValheimOrange, true, Color.black, 400f, 40f, false); _customMenuPanel.SetActive(false); ((UnityEvent)GUIManager.Instance.CreateButton("Close", _customMenuPanel.transform, new Vector2(0.5f, 0f), new Vector2(0.5f, 0f), new Vector2(0f, 50f), 150f, 45f).GetComponent<Button>().onClick).AddListener((UnityAction)delegate { CloseMenu(instance); }); Plugin.Log.LogInfo((object)$"BifrostConnect: Building directory UI for {Plugin.ServerList.Count} servers."); if (Plugin.ServerList.Count == 0) { GUIManager.Instance.CreateText("No servers configured.\nAdd servers to BepInEx/config/BifrostConnect_Servers.json", _customMenuPanel.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0f, 0f), GUIManager.Instance.AveriaSerif, 18, Color.gray, false, Color.black, 500f, 100f, false); } else { GameObject val2 = new GameObject("Bifrost_ScrollView", new Type[4] { typeof(RectTransform), typeof(Image), typeof(RectMask2D), typeof(ScrollRect) }); val2.transform.SetParent(_customMenuPanel.transform, false); RectTransform component = val2.GetComponent<RectTransform>(); component.anchorMin = new Vector2(0.5f, 0.5f); component.anchorMax = new Vector2(0.5f, 0.5f); component.pivot = new Vector2(0.5f, 0.5f); component.anchoredPosition = new Vector2(0f, 15f); component.sizeDelta = new Vector2(500f, 500f); Image component2 = val2.GetComponent<Image>(); ((Graphic)component2).color = new Color(0f, 0f, 0f, 0.25f); ((Graphic)component2).raycastTarget = true; ScrollRect component3 = val2.GetComponent<ScrollRect>(); component3.horizontal = false; component3.vertical = true; component3.scrollSensitivity = 35f; component3.movementType = (MovementType)2; component3.viewport = component; GameObject val3 = new GameObject("Content", new Type[3] { typeof(RectTransform), typeof(VerticalLayoutGroup), typeof(ContentSizeFitter) }); val3.transform.SetParent(val2.transform, false); RectTransform component4 = val3.GetComponent<RectTransform>(); component4.anchorMin = new Vector2(0f, 1f); component4.anchorMax = new Vector2(1f, 1f); component4.pivot = new Vector2(0.5f, 1f); component4.anchoredPosition = Vector2.zero; component4.sizeDelta = Vector2.zero; VerticalLayoutGroup component5 = val3.GetComponent<VerticalLayoutGroup>(); ((HorizontalOrVerticalLayoutGroup)component5).spacing = 10f; ((LayoutGroup)component5).padding = new RectOffset(10, 10, 10, 10); ((LayoutGroup)component5).childAlignment = (TextAnchor)1; ((HorizontalOrVerticalLayoutGroup)component5).childControlWidth = true; ((HorizontalOrVerticalLayoutGroup)component5).childControlHeight = true; ((HorizontalOrVerticalLayoutGroup)component5).childForceExpandWidth = false; ((HorizontalOrVerticalLayoutGroup)component5).childForceExpandHeight = false; ContentSizeFitter component6 = val3.GetComponent<ContentSizeFitter>(); component6.horizontalFit = (FitMode)0; component6.verticalFit = (FitMode)2; component3.content = component4; GameObject val4 = new GameObject("Bifrost_Scrollbar", new Type[3] { typeof(RectTransform), typeof(Image), typeof(Scrollbar) }); val4.transform.SetParent(_customMenuPanel.transform, false); RectTransform component7 = val4.GetComponent<RectTransform>(); component7.anchorMin = new Vector2(0.5f, 0.5f); component7.anchorMax = new Vector2(0.5f, 0.5f); component7.pivot = new Vector2(0.5f, 0.5f); component7.anchoredPosition = new Vector2(240f, 15f); component7.sizeDelta = new Vector2(12f, 490f); Scrollbar component8 = val4.GetComponent<Scrollbar>(); component8.direction = (Direction)2; GameObject val5 = new GameObject("Sliding Area", new Type[1] { typeof(RectTransform) }); val5.transform.SetParent(val4.transform, false); RectTransform component9 = val5.GetComponent<RectTransform>(); component9.anchorMin = Vector2.zero; component9.anchorMax = Vector2.one; component9.sizeDelta = Vector2.zero; GameObject val6 = new GameObject("Handle", new Type[2] { typeof(RectTransform), typeof(Image) }); val6.transform.SetParent(val5.transform, false); RectTransform component10 = val6.GetComponent<RectTransform>(); component10.anchorMin = Vector2.zero; component10.anchorMax = Vector2.one; component10.sizeDelta = Vector2.zero; Image component11 = val6.GetComponent<Image>(); component8.handleRect = component10; ((Selectable)component8).targetGraphic = (Graphic)(object)component11; GUIManager.Instance.ApplyScrollbarStyle(component8); component3.verticalScrollbar = component8; component3.verticalScrollbarVisibility = (ScrollbarVisibility)1; foreach (ServerEntry server in Plugin.ServerList) { GameObject obj2 = GUIManager.Instance.CreateButton(server.Name, val3.transform, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), Vector2.zero, 440f, 50f); LayoutElement obj3 = obj2.AddComponent<LayoutElement>(); obj3.minWidth = 440f; obj3.preferredWidth = 440f; obj3.minHeight = 50f; obj3.preferredHeight = 50f; obj3.flexibleWidth = 0f; obj3.flexibleHeight = 0f; Button component12 = obj2.GetComponent<Button>(); ServerEntry currentServer = server; ((UnityEvent)component12.onClick).AddListener((UnityAction)delegate { OpenConfirmation(instance, currentServer); }); Plugin.Log.LogInfo((object)("BifrostConnect: Added button for server '" + server.Name + "'")); } LayoutRebuilder.ForceRebuildLayoutImmediate(component4); component3.verticalNormalizedPosition = 1f; ManualLogSource log = Plugin.Log; Rect rect = component4.rect; log.LogInfo((object)$"BifrostConnect: Layout rebuilt. Total content height: {((Rect)(ref rect)).height}"); } _customMenuPanel.SetActive(false); } public static void BuildConfirmationPanel(FejdStartup instance, ServerEntry server) { //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Unknown result type (might be due to invalid IL or missing references) //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_0197: Unknown result type (might be due to invalid IL or missing references) //IL_019d: Unknown result type (might be due to invalid IL or missing references) //IL_01f1: Unknown result type (might be due to invalid IL or missing references) //IL_0200: Unknown result type (might be due to invalid IL or missing references) //IL_020f: Unknown result type (might be due to invalid IL or missing references) //IL_022f: Unknown result type (might be due to invalid IL or missing references) //IL_0235: Unknown result type (might be due to invalid IL or missing references) //IL_028e: Unknown result type (might be due to invalid IL or missing references) //IL_029d: Unknown result type (might be due to invalid IL or missing references) //IL_02ac: Unknown result type (might be due to invalid IL or missing references) //IL_02cc: Unknown result type (might be due to invalid IL or missing references) //IL_02d2: Unknown result type (might be due to invalid IL or missing references) //IL_0306: Unknown result type (might be due to invalid IL or missing references) //IL_0315: Unknown result type (might be due to invalid IL or missing references) //IL_0324: Unknown result type (might be due to invalid IL or missing references) //IL_0349: Unknown result type (might be due to invalid IL or missing references) //IL_0353: Expected O, but got Unknown //IL_0371: Unknown result type (might be due to invalid IL or missing references) //IL_0380: Unknown result type (might be due to invalid IL or missing references) //IL_038f: Unknown result type (might be due to invalid IL or missing references) //IL_03bd: Unknown result type (might be due to invalid IL or missing references) //IL_03c2: Unknown result type (might be due to invalid IL or missing references) //IL_03c8: Expected O, but got Unknown if ((Object)(object)_confirmPanel != (Object)null) { Object.Destroy((Object)(object)_confirmPanel); } object obj; if (!((Object)(object)GUIManager.CustomGUIFront != (Object)null)) { GameObject mainMenu = instance.m_mainMenu; obj = ((mainMenu != null) ? mainMenu.transform.parent : null); } else { obj = GUIManager.CustomGUIFront.transform; } Transform val = (Transform)obj; if ((Object)(object)val == (Object)null) { Plugin.Log.LogWarning((object)"No suitable GUI root/parent found for confirmation panel."); return; } _confirmPanel = GUIManager.Instance.CreateWoodpanel(val, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0f, 0f), 500f, 340f); _confirmPanel.AddComponent<MenuEscapeHandler>().Instance = instance; GUIManager.Instance.CreateText("Join Server", _confirmPanel.transform, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -35f), GUIManager.Instance.AveriaSerifBold, 24, GUIManager.Instance.ValheimOrange, true, Color.black, 400f, 40f, false); GUIManager.Instance.CreateText(server.Name, _confirmPanel.transform, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -90f), GUIManager.Instance.AveriaSerifBold, 22, Color.white, true, Color.black, 460f, 35f, false); GUIManager.Instance.CreateText($"Address: {server.IP}:{server.Port}", _confirmPanel.transform, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -135f), GUIManager.Instance.AveriaSerif, 18, new Color(0.9f, 0.9f, 0.9f), true, Color.black, 440f, 30f, false); string text = (string.IsNullOrEmpty(server.Password) ? "None" : "Saved (Auto-Fill)"); GUIManager.Instance.CreateText("Password: " + text, _confirmPanel.transform, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -175f), GUIManager.Instance.AveriaSerif, 18, new Color(0.9f, 0.9f, 0.9f), true, Color.black, 440f, 30f, false); ((UnityEvent)GUIManager.Instance.CreateButton("Connect", _confirmPanel.transform, new Vector2(0.5f, 0f), new Vector2(0.5f, 0f), new Vector2(-100f, 45f), 160f, 45f).GetComponent<Button>().onClick).AddListener((UnityAction)delegate { ConnectToServer(instance, server); }); ButtonClickedEvent onClick = GUIManager.Instance.CreateButton("Back", _confirmPanel.transform, new Vector2(0.5f, 0f), new Vector2(0.5f, 0f), new Vector2(100f, 45f), 160f, 45f).GetComponent<Button>().onClick; object obj2 = <>O.<0>__CloseConfirmation; if (obj2 == null) { UnityAction val2 = CloseConfirmation; <>O.<0>__CloseConfirmation = val2; obj2 = (object)val2; } ((UnityEvent)onClick).AddListener((UnityAction)obj2); _confirmPanel.SetActive(false); } public static void OpenConfirmation(FejdStartup instance, ServerEntry server) { if ((Object)(object)_customMenuPanel != (Object)null) { _customMenuPanel.SetActive(false); } BuildConfirmationPanel(instance, server); if ((Object)(object)_confirmPanel != (Object)null) { _confirmPanel.SetActive(true); } } public static void CloseConfirmation() { if ((Object)(object)_confirmPanel != (Object)null) { _confirmPanel.SetActive(false); } if ((Object)(object)_customMenuPanel != (Object)null) { _customMenuPanel.SetActive(true); Canvas.ForceUpdateCanvases(); } } private static void ConnectToServer(FejdStartup instance, ServerEntry server) { //IL_014c: 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_011f: Unknown result type (might be due to invalid IL or missing references) Plugin.Log.LogInfo((object)$"Connecting to {server.Name} at {server.IP}:{server.Port}"); if ((Object)(object)_confirmPanel != (Object)null) { _confirmPanel.SetActive(false); } if ((Object)(object)_customMenuPanel != (Object)null) { _customMenuPanel.SetActive(false); } ServerJoinDataDedicated val = default(ServerJoinDataDedicated); ((ServerJoinDataDedicated)(ref val))..ctor(server.IP, (ushort)server.Port); ServerJoinData val2 = default(ServerJoinData); ((ServerJoinData)(ref val2))..ctor(val); string text = ((!string.IsNullOrEmpty(server.Password)) ? server.Password : string.Empty); try { AccessTools.PropertySetter(typeof(FejdStartup), "ServerPassword")?.Invoke(null, new object[1] { text }); } catch (Exception ex) { Plugin.Log.LogWarning((object)("Could not set FejdStartup.ServerPassword via reflection: " + ex.Message)); } try { AccessTools.Field(typeof(ZNet), "m_serverPassword")?.SetValue(null, text); } catch { } try { AccessTools.Field(typeof(FejdStartup), "m_queuedJoinServer")?.SetValue(instance, val2); } catch (Exception ex2) { Plugin.Log.LogWarning((object)("Could not set FejdStartup.m_queuedJoinServer via reflection: " + ex2.Message)); } instance.SetServerToJoin(val2); if ((Object)(object)instance.m_mainMenu != (Object)null) { instance.m_mainMenu.SetActive(false); } try { instance.OnStartGame(); } catch (Exception ex3) { Plugin.Log.LogWarning((object)("OnStartGame failed: " + ex3.Message + ". Falling back to reflection.")); try { AccessTools.Method(typeof(FejdStartup), "ShowCharacterSelection", (Type[])null, (Type[])null)?.Invoke(instance, null); if (SaveSystem.GetAllPlayerProfiles().Count == 0) { instance.OnCharacterNew(); } } catch (Exception arg) { Plugin.Log.LogError((object)$"Failed to show character selection: {arg}"); } } } public static void OpenMenu(FejdStartup instance) { Plugin.LoadServerConfig(); BuildCustomPanel(instance); if ((Object)(object)instance.m_mainMenu != (Object)null) { instance.m_mainMenu.SetActive(false); } if ((Object)(object)_customMenuPanel != (Object)null) { _customMenuPanel.SetActive(true); Canvas.ForceUpdateCanvases(); } } public static void CloseMenu(FejdStartup instance) { if ((Object)(object)_confirmPanel != (Object)null) { _confirmPanel.SetActive(false); } if ((Object)(object)_customMenuPanel != (Object)null) { _customMenuPanel.SetActive(false); } if ((Object)(object)instance.m_mainMenu != (Object)null) { instance.m_mainMenu.SetActive(true); } } public static void HandleEscape(FejdStartup instance) { if ((Object)(object)_confirmPanel != (Object)null && _confirmPanel.activeSelf) { CloseConfirmation(); } else if ((Object)(object)_customMenuPanel != (Object)null && _customMenuPanel.activeSelf) { CloseMenu(instance); } } } } namespace BifrostConnect.Patches { [HarmonyPatch(typeof(FejdStartup), "Start")] public static class MainMenuPatch { public static void Postfix(FejdStartup __instance) { try { Plugin.Log.LogInfo((object)"FejdStartup Start detected. Injecting Bifrost UI."); MenuBuilder.InjectMainMenuButton(__instance); MenuBuilder.BuildCustomPanel(__instance); } catch (Exception arg) { Plugin.Log.LogError((object)$"Exception during Bifrost UI injection: {arg}"); } } } } namespace BifrostConnect.Models { [Serializable] public class ServerEntry { public string Name = string.Empty; public string IP = string.Empty; public int Port = 2456; public string Password = string.Empty; } [Serializable] public class ServerListWrapper { public List<ServerEntry> Servers = new List<ServerEntry>(); } }