using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyFileVersion("1.0.10.0")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyVersion("1.0.10.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [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 TheFehu { [BepInPlugin("com.forteca.thefehu", "FehuLanding", "1.0.10")] [BepInProcess("valheim.exe")] public sealed class Plugin : BaseUnityPlugin { public const string PluginGuid = "com.forteca.thefehu"; public const string PluginName = "FehuLanding"; public const string PluginVersion = "1.0.10"; internal static ManualLogSource Log; private FehuMenu _menu; internal static Plugin Instance { get; private set; } private void Awake() { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Expected O, but got Unknown ((BaseUnityPlugin)this).Logger.LogInfo((object)"[FehuLanding] DLL LOADED VERSION 1.0.10"); try { ((BaseUnityPlugin)this).Logger.LogInfo((object)"[TheFehu] Startup begin"); Instance = this; Log = ((BaseUnityPlugin)this).Logger; GameObject val = new GameObject("FehuLanding Main Menu"); Object.DontDestroyOnLoad((Object)(object)val); _menu = val.AddComponent(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"[TheFehu] Startup complete"); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("[TheFehu] Startup failed: " + ex)); } } } public sealed class FehuMenu : MonoBehaviour { private const float ReferenceWidth = 1920f; private const float ReferenceHeight = 1080f; private ConfigEntry _enabled; private ConfigEntry _showOnMainMenu; private ConfigEntry _hideChangelog; private ConfigEntry _hideMerchStore; private ConfigEntry _hideVersionText; private ConfigEntry _hideModdedWarningText; private ConfigEntry _hideShowLogButton; private ConfigEntry _newsEnabled; private ConfigEntry _sagaEnabled; private ConfigEntry _realmsEnabled; private ConfigEntry _otherRealmsEnabled; private ConfigEntry _socialEnabled; private ConfigEntry _rightX; private ConfigEntry _rightY; private ConfigEntry _rightWidth; private ConfigEntry _rightHeight; private ConfigEntry _otherX; private ConfigEntry _otherY; private ConfigEntry _otherWidth; private ConfigEntry _otherHeight; private ConfigEntry _newsX; private ConfigEntry _newsY; private ConfigEntry _newsWidth; private ConfigEntry _newsHeight; private ConfigEntry _sagaX; private ConfigEntry _sagaY; private ConfigEntry _sagaWidth; private ConfigEntry _sagaHeight; private ConfigEntry _socialX; private ConfigEntry _socialY; private ConfigEntry _socialWidth; private ConfigEntry _socialHeight; private ConfigEntry _newsTitle; private ConfigEntry _sagaTitle; private ConfigEntry _realmsTitle; private ConfigEntry _otherRealmsTitle; private ConfigEntry _uiScale; private ConfigEntry _socialIconSize; private ConfigEntry _socialIconSpacing; private FehuContent _content; private string _contentPath; private bool _hiddenForSession; private bool _topLeftVisible = true; private bool _bottomLeftVisible = true; private bool _topRightVisible = true; private bool _bottomRightVisible = true; private bool _socialVisible = true; private Vector2 _newsScroll; private Vector2 _sagaScroll; private GUIStyle _titleStyle; private GUIStyle _bodyStyle; private GUIStyle _serverStyle; private GUIStyle _buttonStyle; private Texture2D _parchment; private Texture2D _ink; private Texture2D _gold; private Texture2D _fade; private readonly HashSet _hiddenLog = new HashSet(); private readonly HashSet _socialIconLog = new HashSet(); private readonly Dictionary _socialIcons = new Dictionary(); private bool _socialIconsLoaded; private void Awake() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown //IL_045d: Unknown result type (might be due to invalid IL or missing references) //IL_0467: Expected O, but got Unknown ConfigFile config = ((BaseUnityPlugin)Plugin.Instance).Config; config.Remove(new ConfigDefinition("Fehu Social", "Title")); config.Save(); _enabled = config.Bind("General", "EnableTheFehu", true, "Enable the TheFehu main-menu boards."); _showOnMainMenu = config.Bind("General", "ShowOnMainMenu", true, "Show the boards whenever the main menu opens."); _hideChangelog = config.Bind("Vanilla Menu", "HideChangelog", false, (ConfigDescription)null); _hideMerchStore = config.Bind("Vanilla Menu", "HideMerchStore", false, (ConfigDescription)null); _hideVersionText = config.Bind("Vanilla Menu", "HideVersionText", false, (ConfigDescription)null); _hideModdedWarningText = config.Bind("Vanilla Menu", "HideModdedWarningText", true, (ConfigDescription)null); if (!_hideModdedWarningText.Value) { _hideModdedWarningText.Value = true; config.Save(); } _hideShowLogButton = config.Bind("Vanilla Menu", "HideShowLogButton", false, (ConfigDescription)null); _newsEnabled = config.Bind("News Board", "Enabled", true, (ConfigDescription)null); _newsX = config.Bind("News Board", "X", 20, (ConfigDescription)null); _newsY = config.Bind("News Board", "Y", 70, (ConfigDescription)null); _newsWidth = config.Bind("News Board", "Width", 460, (ConfigDescription)null); _newsHeight = config.Bind("News Board", "Height", 475, (ConfigDescription)null); _newsTitle = config.Bind("News Board", "Title", "Announcements", (ConfigDescription)null); _sagaEnabled = config.Bind("Skald Saga Board", "Enabled", true, (ConfigDescription)null); _sagaX = config.Bind("Skald Saga Board", "X", 20, (ConfigDescription)null); _sagaY = config.Bind("Skald Saga Board", "Y", 550, (ConfigDescription)null); _sagaWidth = config.Bind("Skald Saga Board", "Width", 460, (ConfigDescription)null); _sagaHeight = config.Bind("Skald Saga Board", "Height", 500, (ConfigDescription)null); _sagaTitle = config.Bind("Skald Saga Board", "Title", "Saga Chronicles", (ConfigDescription)null); _realmsEnabled = config.Bind("Realms Board", "Enabled", true, (ConfigDescription)null); _rightX = config.Bind("Realms Board", "X", -20, (ConfigDescription)null); _rightY = config.Bind("Realms Board", "Y", 70, (ConfigDescription)null); _rightWidth = config.Bind("Realms Board", "Width", 460, (ConfigDescription)null); _rightHeight = config.Bind("Realms Board", "Height", 475, (ConfigDescription)null); _realmsTitle = config.Bind("Realms Board", "Title", "Fehu Realms", (ConfigDescription)null); _otherRealmsEnabled = config.Bind("Other Realms Board", "Enabled", true, (ConfigDescription)null); _otherX = config.Bind("Other Realms Board", "X", -20, (ConfigDescription)null); _otherY = config.Bind("Other Realms Board", "Y", 550, (ConfigDescription)null); _otherWidth = config.Bind("Other Realms Board", "Width", 460, (ConfigDescription)null); _otherHeight = config.Bind("Other Realms Board", "Height", 500, (ConfigDescription)null); _otherRealmsTitle = config.Bind("Other Realms Board", "Title", "Other Realms", (ConfigDescription)null); _socialEnabled = config.Bind("SocialPanel", "Enabled", true, (ConfigDescription)null); _socialX = config.Bind("SocialPanel", "X", -20, (ConfigDescription)null); _socialY = config.Bind("SocialPanel", "Y", 10, (ConfigDescription)null); _socialWidth = config.Bind("SocialPanel", "Width", 620, (ConfigDescription)null); _socialHeight = config.Bind("SocialPanel", "Height", 80, (ConfigDescription)null); _socialIconSize = config.Bind("SocialPanel", "SocialIconSize", 42, (ConfigDescription)null); _socialIconSpacing = config.Bind("SocialPanel", "SocialIconSpacing", 8, (ConfigDescription)null); Plugin.Log.LogInfo((object)"[TheFehu] SocialPanel config applied X/Y/W/H/IconSize/IconSpacing"); _uiScale = config.Bind("General", "UIScale", 1f, new ConfigDescription("Additional UI scale.", (AcceptableValueBase)(object)new AcceptableValueRange(0.5f, 2f), Array.Empty())); _contentPath = Path.Combine(Path.GetDirectoryName(typeof(Plugin).Assembly.Location), "FehuLanding.json"); LoadContent(); SceneManager.sceneLoaded += OnSceneLoaded; } private void OnDestroy() { SceneManager.sceneLoaded -= OnSceneLoaded; } private void OnSceneLoaded(Scene scene, LoadSceneMode mode) { if (IsMainMenu()) { _hiddenForSession = false; _topLeftVisible = (_bottomLeftVisible = (_topRightVisible = (_bottomRightVisible = (_socialVisible = true)))); ((MonoBehaviour)this).StartCoroutine(HideVanillaMenuAfterLoad()); } } private IEnumerator MerchDiscoveryAfterLoad() { yield return (object)new WaitForSeconds(1f); LogMerchCandidates(); } private IEnumerator HideVanillaMenuAfterLoad() { HideVanillaMenu(); yield return (object)new WaitForSeconds(0.5f); HideVanillaMenu(); yield return (object)new WaitForSeconds(0.5f); HideVanillaMenu(); yield return (object)new WaitForSeconds(2f); HideVanillaMenu(); yield return (object)new WaitForSeconds(2f); HideVanillaMenu(); } private void Update() { if (Input.GetKeyDown((KeyCode)288) && IsMainMenu()) { _hiddenForSession = !_hiddenForSession; _topLeftVisible = (_bottomLeftVisible = (_topRightVisible = (_bottomRightVisible = (_socialVisible = !_hiddenForSession)))); Plugin.Log.LogInfo((object)"[TheFehu] F7 toggle all panels"); } } private void OnGUI() { //IL_0083: 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_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_01a4: Unknown result type (might be due to invalid IL or missing references) //IL_024f: Unknown result type (might be due to invalid IL or missing references) //IL_03d1: Unknown result type (might be due to invalid IL or missing references) //IL_02eb: Unknown result type (might be due to invalid IL or missing references) //IL_03c6: Unknown result type (might be due to invalid IL or missing references) if (_enabled.Value && _showOnMainMenu.Value && !_hiddenForSession && IsMainMenu()) { if (_content == null) { LoadContent(); } if (_titleStyle == null) { BuildTheme(); HideVanillaMenu(); } float num = Mathf.Min((float)Screen.width / 1920f, (float)Screen.height / 1080f) * _uiScale.Value; num = Mathf.Max(0.35f, num); Matrix4x4 matrix = GUI.matrix; int depth = GUI.depth; GUI.matrix = Matrix4x4.Scale(new Vector3(num, num, 1f)); GUI.depth = -1000; float num2 = (float)Screen.width / num; if (_newsEnabled.Value && _topLeftVisible) { DrawStoryBoard("TopLeft", new Rect((float)_newsX.Value, (float)_newsY.Value, (float)_newsWidth.Value, (float)_newsHeight.Value), string.IsNullOrEmpty(_newsTitle.Value) ? _content.newsTitle : _newsTitle.Value, _content.newsText, ref _newsScroll, ref _topLeftVisible); } if (_sagaEnabled.Value && _bottomLeftVisible) { DrawStoryBoard("BottomLeft", new Rect((float)_sagaX.Value, (float)_sagaY.Value, (float)_sagaWidth.Value, (float)_sagaHeight.Value), string.IsNullOrEmpty(_sagaTitle.Value) ? _content.sagaTitle : _sagaTitle.Value, _content.sagaText, ref _sagaScroll, ref _bottomLeftVisible); } if (_realmsEnabled.Value && _topRightVisible) { DrawRealmsBoard("TopRight", new Rect(num2 - (float)_rightWidth.Value + (float)_rightX.Value, (float)_rightY.Value, (float)_rightWidth.Value, (float)_rightHeight.Value), string.IsNullOrEmpty(_realmsTitle.Value) ? _content.realmsTitle : _realmsTitle.Value, ServersFrom(0, 5), ref _topRightVisible); } if (_otherRealmsEnabled.Value && _bottomRightVisible) { DrawRealmsBoard("BottomRight", new Rect(num2 - (float)_otherWidth.Value + (float)_otherX.Value, (float)_otherY.Value, (float)_otherWidth.Value, (float)_otherHeight.Value), _otherRealmsTitle.Value, ServersFrom(5, int.MaxValue), ref _bottomRightVisible); } SocialPanelSettings socialPanelSettings = new SocialPanelSettings { Enabled = _socialEnabled.Value, X = _socialX.Value, Y = _socialY.Value, Width = _socialWidth.Value, Height = _socialHeight.Value, IconSize = _socialIconSize.Value, IconSpacing = _socialIconSpacing.Value }; if (socialPanelSettings.Enabled && _socialVisible) { DrawSocial(new Rect(num2 - (float)socialPanelSettings.Width + (float)socialPanelSettings.X, (float)socialPanelSettings.Y, (float)socialPanelSettings.Width, (float)socialPanelSettings.Height), socialPanelSettings); } GUI.matrix = matrix; GUI.depth = depth; } } private unsafe void DrawSocial(Rect panel, SocialPanelSettings settings) { //IL_0006: 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_012a: Unknown result type (might be due to invalid IL or missing references) //IL_014a: 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_01a1: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Unknown result type (might be due to invalid IL or missing references) //IL_01db: Unknown result type (might be due to invalid IL or missing references) LoadSocialIconsOnce(); GUI.DrawTexture(panel, (Texture)(object)_parchment, (ScaleMode)0); if (GUI.Button(new Rect(((Rect)(ref panel)).xMax - 28f, ((Rect)(ref panel)).y + 4f, 20f, 20f), "x", _buttonStyle)) { _socialVisible = false; Plugin.Log.LogInfo((object)"[TheFehu] Close panel clicked: Social"); } List list = DefaultSocialLinks(); Rect val = default(Rect); for (int i = 0; i < list.Count && i < 9; i++) { SocialLink socialLink = list[i]; float num = Mathf.Max(2f, (float)settings.IconSpacing); float num2 = Mathf.Clamp(settings.IconSize, 32, 48); num2 = Mathf.Min(num2, (((Rect)(ref panel)).width - num * 8f - 24f) / 9f); float num3 = num2 * 9f + num * 8f; ((Rect)(ref val))..ctor(((Rect)(ref panel)).x + (((Rect)(ref panel)).width - num3) * 0.5f + (float)i * (num2 + num), ((Rect)(ref panel)).y + (((Rect)(ref panel)).height - num2) * 0.5f, num2, num2); _socialIcons.TryGetValue(socialLink.Icon, out var value); GUI.Box(val, (GUIContent)((!((Object)(object)value == (Object)null)) ? ((object)GUIContent.none) : ((object)new GUIContent(socialLink.Title.Substring(0, 1)))), _buttonStyle); if ((Object)(object)value != (Object)null) { GUI.DrawTexture(val, (Texture)(object)value, (ScaleMode)2, true); string key = "visible:" + socialLink.Icon; string[] obj = new string[6] { "[TheFehu] Social icon rendered: ", socialLink.Icon, "\n[TheFehu] Social icon position: ", null, null, null }; Rect val2 = val; obj[3] = ((object)(*(Rect*)(&val2))/*cast due to .constrained prefix*/).ToString(); obj[4] = "\n[TheFehu] Social icon visible: "; obj[5] = socialLink.Icon; LogSocialIcon(key, string.Concat(obj)); } if (!string.IsNullOrEmpty(socialLink.Url) && GUI.Button(val, GUIContent.none, GUIStyle.none)) { Application.OpenURL(socialLink.Url); } } } private void LoadSocialIconsOnce() { if (_socialIconsLoaded) { return; } _socialIconsLoaded = true; string[] obj = new string[9] { "discord.png", "facebook.png", "instagram.png", "pinterest.png", "soundcloud.png", "steam.png", "tiktok.png", "twitch.png", "youtube.png" }; string path = Path.Combine(Path.GetDirectoryName(typeof(Plugin).Assembly.Location), "Assets", "social"); int num = 0; string[] array = obj; foreach (string text in array) { string text2 = Path.Combine(path, text); LogSocialIcon("exists:" + text, "[TheFehu] Social icon file exists: " + text + " " + File.Exists(text2).ToString().ToLowerInvariant()); try { Texture2D val = LoadIcon(text2); if ((Object)(object)val != (Object)null) { _socialIcons[text] = val; num++; LogSocialIcon("loaded:" + text2, "[TheFehu] Social icon loaded: " + text); } else { LogSocialIcon("failed:" + text, "[TheFehu] Social icon failed: " + text); } } catch (Exception ex) { LogSocialIcon("failed:" + text, "[TheFehu] Social icon failed: " + text + " " + ex); } } Plugin.Log.LogInfo((object)("[TheFehu] Social icon count discovered: " + num)); } private void LogSocialIcon(string key, string message) { if (_socialIconLog.Add(key)) { Plugin.Log.LogInfo((object)message); } } private static Texture2D LoadIcon(string path) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown //IL_0020: Expected O, but got Unknown if (!File.Exists(path)) { return null; } try { Texture2D val = new Texture2D(2, 2); ImageConversion.LoadImage(val, File.ReadAllBytes(path)); return val; } catch { return null; } } private static string SocialUrl(string name) { return name switch { "discord.png" => "https://discord.gg/", "facebook.png" => "https://facebook.com/", "instagram.png" => "https://instagram.com/", "pinterest.png" => "https://pinterest.com/", "soundcloud.png" => "https://soundcloud.com/", "steam.png" => "https://store.steampowered.com/", "tiktok.png" => "https://tiktok.com/", "twitch.png" => "https://twitch.tv/", "youtube.png" => "https://youtube.com/", _ => string.Empty, }; } private void DrawStoryBoard(string id, Rect panel, string title, string text, ref Vector2 scroll, ref bool visible) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0039: 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) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) GUI.DrawTexture(panel, (Texture)(object)_parchment, (ScaleMode)0); GUI.Label(new Rect(((Rect)(ref panel)).x + 35f, ((Rect)(ref panel)).y + 23f, ((Rect)(ref panel)).width - 70f, 38f), "ᚱ " + title + " ᚱ", _titleStyle); GUI.DrawTexture(new Rect(((Rect)(ref panel)).x + 42f, ((Rect)(ref panel)).y + 68f, ((Rect)(ref panel)).width - 84f, 2f), (Texture)(object)_gold); if (GUI.Button(new Rect(((Rect)(ref panel)).xMax - 47f, ((Rect)(ref panel)).y + 22f, 25f, 25f), "×", _buttonStyle)) { visible = false; Plugin.Log.LogInfo((object)("[TheFehu] Close panel clicked: " + id)); } DrawNews(panel, text, ref scroll); } private void DrawRealmsBoard(string id, Rect panel, string title, List servers, ref bool visible) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0039: 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) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) GUI.DrawTexture(panel, (Texture)(object)_parchment, (ScaleMode)0); GUI.Label(new Rect(((Rect)(ref panel)).x + 35f, ((Rect)(ref panel)).y + 23f, ((Rect)(ref panel)).width - 70f, 38f), "ᚱ " + title + " ᚱ", _titleStyle); GUI.DrawTexture(new Rect(((Rect)(ref panel)).x + 42f, ((Rect)(ref panel)).y + 68f, ((Rect)(ref panel)).width - 84f, 2f), (Texture)(object)_gold); if (GUI.Button(new Rect(((Rect)(ref panel)).xMax - 47f, ((Rect)(ref panel)).y + 22f, 25f, 25f), "×", _buttonStyle)) { visible = false; Plugin.Log.LogInfo((object)("[TheFehu] Close panel clicked: " + id)); } DrawServers(panel, servers); } private void DrawNews(Rect panel, string text, ref Vector2 scroll) { //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Invalid comparison between Unknown and I4 //IL_009d: 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_0155: Unknown result type (might be due to invalid IL or missing references) //IL_018e: 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) Rect val = default(Rect); ((Rect)(ref val))..ctor(((Rect)(ref panel)).x + 42f, ((Rect)(ref panel)).y + 88f, ((Rect)(ref panel)).width - 84f, ((Rect)(ref panel)).height - 122f); string[] lines = (string.IsNullOrWhiteSpace(text) ? "# No tale has been written yet." : text).Split(new char[1] { '\n' }); float num = NewsHeight(lines, ((Rect)(ref val)).width - 8f); if (((Rect)(ref val)).Contains(Event.current.mousePosition) && (int)Event.current.type == 6) { scroll.y = Mathf.Clamp(scroll.y + Event.current.delta.y * 26f, 0f, Mathf.Max(0f, num - ((Rect)(ref val)).height)); Event.current.Use(); } GUI.BeginGroup(val); DrawNewsLines(lines, 0f - scroll.y, ((Rect)(ref val)).width - 8f); GUI.EndGroup(); for (int i = 0; i < 6; i++) { float num2 = 0.6f - (float)i * 0.09f; GUI.color = new Color(0.86f, 0.65f, 0.31f, num2); GUI.DrawTexture(new Rect(((Rect)(ref val)).x, ((Rect)(ref val)).y + (float)i * 4f, ((Rect)(ref val)).width, 5f), (Texture)(object)_fade); GUI.DrawTexture(new Rect(((Rect)(ref val)).x, ((Rect)(ref val)).yMax - 5f - (float)i * 4f, ((Rect)(ref val)).width, 5f), (Texture)(object)_fade); } GUI.color = Color.white; } private float NewsHeight(string[] lines, float width) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Expected O, but got Unknown float num = 10f; foreach (string text in lines) { num += ((text.Trim() == "---") ? 20f : (text.StartsWith("# ") ? 34f : (Mathf.Max(22f, _bodyStyle.CalcHeight(new GUIContent(text), width)) + 7f))); } return num; } private void DrawNewsLines(string[] lines, float y, float width) { //IL_0047: 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_00bd: Expected O, but got Unknown //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < lines.Length; i++) { string text = lines[i].TrimEnd(new char[1] { '\r' }); if (text.Trim() == "---") { GUI.DrawTexture(new Rect(8f, y + 9f, width - 16f, 1f), (Texture)(object)_gold); y += 20f; } else if (text.StartsWith("# ")) { GUI.Label(new Rect(8f, y, width - 16f, 28f), text.Substring(2), _serverStyle); y += 34f; } else { float num = Mathf.Max(22f, _bodyStyle.CalcHeight(new GUIContent(text), width)); GUI.Label(new Rect(8f, y, width - 16f, num), text, _bodyStyle); y += num + 7f; } } } private List ServersFrom(int start, int count) { List list = new List(); List list2 = _content.servers ?? new List(); for (int i = start; i < list2.Count; i++) { if (list.Count >= count) { break; } list.Add(list2[i]); } return list; } private void DrawServers(Rect panel, List servers) { //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: 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_0128: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) float num = ((Rect)(ref panel)).y + 78f; float num2 = ((Rect)(ref panel)).width - 56f; foreach (FehuServer server in servers) { if (num + 62f > ((Rect)(ref panel)).yMax - 62f) { break; } GUI.Label(new Rect(((Rect)(ref panel)).x + 36f, num, num2, 24f), "⚔ " + (server.name ?? "Unnamed server"), _serverStyle); GUI.Label(new Rect(((Rect)(ref panel)).x + 40f, num + 26f, 250f, 20f), (server.players ?? "—") + " Warriors Online", _bodyStyle); if (GUI.Button(new Rect(((Rect)(ref panel)).xMax - 175f, num + 19f, 65f, 29f), "Join", _buttonStyle)) { OpenJoin(server); } if (GUI.Button(new Rect(((Rect)(ref panel)).xMax - 104f, num + 19f, 75f, 29f), "Copy IP", _buttonStyle)) { CopyAddress(server); } GUI.DrawTexture(new Rect(((Rect)(ref panel)).x + 36f, num + 47f, num2 - 14f, 1f), (Texture)(object)_gold); num += 52f; } LogSocialIcon("realm-links-removed", "[TheFehu] Removed old realm social buttons"); } private void DrawLinkButton(Rect rect, string label, string url) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) if (GUI.Button(rect, label, _buttonStyle) && Uri.IsWellFormedUriString(url, UriKind.Absolute)) { Application.OpenURL(url); } } private static List DefaultSocialLinks() { string[] obj = new string[9] { "discord", "facebook", "instagram", "pinterest", "soundcloud", "steam", "tiktok", "twitch", "youtube" }; List list = new List(); string[] array = obj; foreach (string text in array) { list.Add(new SocialLink { Title = text, Icon = text + ".png", Url = "" }); } return list; } private static void OpenJoin(FehuServer server) { if (server != null && !string.IsNullOrWhiteSpace(server.address) && server.port >= 1) { Application.OpenURL("steam://connect/" + server.address.Trim() + ":" + server.port); } } private static void CopyAddress(FehuServer server) { if (server != null && !string.IsNullOrWhiteSpace(server.address) && server.port >= 1) { GUIUtility.systemCopyBuffer = server.address.Trim() + ":" + server.port; } } private bool IsMainMenu() { //IL_0000: 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) Scene activeScene = SceneManager.GetActiveScene(); string name = ((Scene)(ref activeScene)).name; if (!string.Equals(name, "start", StringComparison.OrdinalIgnoreCase)) { return string.Equals(name, "main", StringComparison.OrdinalIgnoreCase); } return true; } private void HideVanillaMenu() { //IL_004a: 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) if (!IsMainMenu() || !_hideModdedWarningText.Value) { return; } Transform[] array = Resources.FindObjectsOfTypeAll(); foreach (Transform val in array) { if ((Object)(object)val == (Object)null || (Object)(object)((Component)val).gameObject == (Object)null) { continue; } Scene scene = ((Component)val).gameObject.scene; if (!((Scene)(ref scene)).IsValid() || IsOurObject(val)) { continue; } Component[] components = ((Component)val).GetComponents(); foreach (Component val2 in components) { if ((Object)(object)val2 == (Object)null) { continue; } PropertyInfo property = ((object)val2).GetType().GetProperty("text"); if (!(property == null) && !(property.PropertyType != typeof(string)) && property.CanRead) { string text = property.GetValue(val2, null) as string; if (!string.IsNullOrEmpty(text) && IsModdedWarningText(text)) { HideText(val2, "Modded Warning Text"); break; } } } } } private bool IsOurObject(Transform transform) { if (!((Object)(object)transform == (Object)null) && !((Object)(object)transform == (Object)(object)((Component)this).transform) && !((Object)(object)transform.root == (Object)(object)((Component)this).transform) && ((Object)transform.root).name.IndexOf("TheFehu", StringComparison.OrdinalIgnoreCase) < 0) { return ((Object)transform.root).name.IndexOf("FehuLanding", StringComparison.OrdinalIgnoreCase) >= 0; } return true; } private static bool IsModdedWarningText(string text) { if (string.IsNullOrEmpty(text)) { return false; } string text2 = Regex.Replace(text, "\\s+", " ").Trim(); if (text2.IndexOf("You are playing a modded version of Valheim", StringComparison.OrdinalIgnoreCase) < 0 && text2.IndexOf("this may change the original game experience", StringComparison.OrdinalIgnoreCase) < 0) { return text2.IndexOf("uninstall all mods before reporting it", StringComparison.OrdinalIgnoreCase) >= 0; } return true; } private void HideModdedWarning(Transform label) { Transform val = label; Transform val2 = label; for (int i = 0; i < 3; i++) { if (!((Object)(object)val.parent != (Object)null)) { break; } val = val.parent; val2 = val; if (CountTextComponents(val) >= 1 && CountUiImages(val) == 0) { HideObject(((Component)val).gameObject, "Modded Warning Text"); return; } } HideObject(((Component)val2).gameObject, "Modded Warning Text"); } private static int CountTextComponents(Transform root) { int num = 0; Component[] componentsInChildren = ((Component)root).GetComponentsInChildren(true); foreach (Component val in componentsInChildren) { if (!((Object)(object)val == (Object)null)) { PropertyInfo property = ((object)val).GetType().GetProperty("text"); if (property != null && property.PropertyType == typeof(string) && property.CanRead) { num++; } } } return num; } private static bool IsMerchObjectName(string name) { if (string.IsNullOrEmpty(name)) { return false; } if (name.IndexOf("Merch", StringComparison.OrdinalIgnoreCase) < 0 && name.IndexOf("StoreButton", StringComparison.OrdinalIgnoreCase) < 0 && name.IndexOf("TShirt", StringComparison.OrdinalIgnoreCase) < 0 && name.IndexOf("T-Shirt", StringComparison.OrdinalIgnoreCase) < 0 && name.IndexOf("Shirt", StringComparison.OrdinalIgnoreCase) < 0 && name.IndexOf("Mug", StringComparison.OrdinalIgnoreCase) < 0) { return name.IndexOf("Cup", StringComparison.OrdinalIgnoreCase) >= 0; } return true; } private static bool IsShowLogObjectName(string name) { if (string.IsNullOrEmpty(name)) { return false; } if (name.IndexOf("ShowLog", StringComparison.OrdinalIgnoreCase) < 0 && name.IndexOf("Player.log", StringComparison.OrdinalIgnoreCase) < 0) { return name.IndexOf("PlayerLog", StringComparison.OrdinalIgnoreCase) >= 0; } return true; } private static GameObject BestButtonRoot(Transform transform) { Transform val = transform; Transform val2 = transform; for (int i = 0; i < 3; i++) { if (!((Object)(object)val != (Object)null)) { break; } val2 = val; Component[] components = ((Component)val).GetComponents(); foreach (Component val3 in components) { if ((Object)(object)val3 != (Object)null && ((object)val3).GetType().Name.IndexOf("Button", StringComparison.OrdinalIgnoreCase) >= 0) { return ((Component)val).gameObject; } } val = val.parent; } if (!((Object)(object)val2 != (Object)null)) { return null; } return ((Component)val2).gameObject; } private void LogMerchCandidates() { //IL_0026: 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) Plugin.Log.LogInfo((object)"[TheFehu] Searching Merch Store UI..."); Transform[] array = Resources.FindObjectsOfTypeAll(); foreach (Transform val in array) { Scene scene = ((Component)val).gameObject.scene; if (!((Scene)(ref scene)).IsValid() || !((Component)val).gameObject.activeInHierarchy) { continue; } Component[] components = ((Component)val).GetComponents(); string text = string.Empty; List list = new List(); bool flag = false; Component[] array2 = components; foreach (Component val2 in array2) { if (!((Object)(object)val2 == (Object)null)) { Type type = ((object)val2).GetType(); list.Add(type.Name); if (type.Name.IndexOf("Button", StringComparison.OrdinalIgnoreCase) >= 0 || type.Name.IndexOf("Clickable", StringComparison.OrdinalIgnoreCase) >= 0) { flag = true; } PropertyInfo property = type.GetProperty("text"); if (property != null && property.PropertyType == typeof(string) && property.CanRead) { text = (property.GetValue(val2, null) as string) ?? text; } } } string text2 = (((Object)val).name + " " + text).ToUpperInvariant(); bool num = text2.Contains("MERCH") || text2.Contains("STORE") || text2.Contains("SHOP") || text2.Contains("TSHIRT") || text2.Contains("SHIRT") || text2.Contains("MUG") || text2.Contains("DONATE") || text2.Contains("SUPPORT"); bool flag2 = list.Exists((string t) => t.IndexOf("Image", StringComparison.OrdinalIgnoreCase) >= 0); if (num || (flag && flag2)) { string text3 = (((Object)(object)val.root != (Object)null) ? ((Object)val.root).name : ((Object)val).name); string text4 = (((Object)(object)val.parent != (Object)null) ? ((Object)val.parent).name : ""); Plugin.Log.LogInfo((object)("[TheFehu] Merch Candidate Found\nPath: " + ObjectPath(val) + "\nRoot: " + text3 + "\nParent: " + text4 + "\nName: " + ((Object)val).name + "\nComponents: " + string.Join(", ", list) + "\nText: " + text)); } } } private void HideObject(GameObject target, string label) { if (!((Object)(object)target == (Object)null) && !((Object)(object)target == (Object)(object)((Component)this).gameObject)) { string path = ObjectPath(target.transform); target.SetActive(false); LogHidden(label, path); } } private void HideText(Component component, string label) { string path = ObjectPath(component.transform); component.gameObject.SetActive(false); LogHidden(label, path); } private void HideMerchAdvertisement(Transform label) { Transform val = label; Transform val2 = label; for (int i = 0; i < 5; i++) { if (!((Object)(object)val.parent != (Object)null)) { break; } val = val.parent; val2 = val; if (CountUiImages(val) >= 2 || IsMerchObjectName(((Object)val).name)) { HideObject(((Component)val).gameObject, "Merch Store"); return; } } HideObject(((Component)val2).gameObject, "Merch Store"); } private static int CountUiImages(Transform root) { int num = 0; Component[] componentsInChildren = ((Component)root).GetComponentsInChildren(true); foreach (Component val in componentsInChildren) { if (!((Object)(object)val == (Object)null)) { string name = ((object)val).GetType().Name; if (name == "Image" || name == "RawImage") { num++; } } } return num; } private void HideChangelog(Transform label) { Transform val = (((Object)(object)label.parent != (Object)null) ? label.parent : label); HideObject(((Component)val).gameObject, "Changelog"); } private void LogHidden(string label, string path) { if (_hiddenLog.Add(label + path)) { Plugin.Log.LogInfo((object)("[TheFehu] Hidden " + label + ": " + path)); } } private static string ObjectPath(Transform value) { string text = ((Object)value).name; while ((Object)(object)value.parent != (Object)null) { value = value.parent; text = ((Object)value).name + "/" + text; } return text; } private void LoadContent() { FehuContent fehuContent = FehuContent.CreateDefault(); try { if (!File.Exists(_contentPath)) { File.WriteAllText(_contentPath, "{\n \"rightTitle\": \"FEHU REALMS\",\n \"leftTitle\": \"FEHU NEWS\",\n \"leftText\": \"# Latest News\\n---\\nShared Clans are now live.\\n\\nClan portals now use exact permissions.\\n\\nGames framework expanded.\\n---\\n# Upcoming\\n---\\nSkald Saga Integration\\nKingdom Buildings\\nNPC Guards\",\n \"servers\": [\n { \"name\": \"Fehu 10th World\", \"address\": \"play.forteca.net\", \"port\": 2456, \"status\": \"Online\", \"players\": \"32/64\" },\n { \"name\": \"Dominion\", \"address\": \"dominion.forteca.net\", \"port\": 2456, \"status\": \"Online\", \"players\": \"7/64\" }\n ],\n \"links\": { \"discord\": \"https://discord.gg/YOURCODE\", \"website\": \"https://forteca.net\", \"support\": \"https://forteca.net/support\" }\n}"); } _content = FehuJson.Parse(File.ReadAllText(_contentPath)) ?? fehuContent; } catch (Exception ex) { Plugin.Log.LogWarning((object)("Could not load FehuLanding.json; using defaults. " + ex.Message)); _content = fehuContent; } } private void BuildTheme() { //IL_0020: 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_0054: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_007a: 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) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Expected O, but got Unknown //IL_00b8: 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_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Expected O, but got Unknown //IL_00fe: 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_010b: 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_0127: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Expected O, but got Unknown //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_0155: 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_017b: Unknown result type (might be due to invalid IL or missing references) //IL_0185: Unknown result type (might be due to invalid IL or missing references) //IL_0196: Unknown result type (might be due to invalid IL or missing references) //IL_019c: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: Unknown result type (might be due to invalid IL or missing references) //IL_01b7: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: Expected O, but got Unknown _parchment = LoadParchment(); _ink = Solid(new Color(0.1f, 0.055f, 0.025f, 0.85f)); _gold = Solid(new Color(0.48f, 0.19f, 0.035f, 0.75f)); _fade = Solid(Color.white); GUIStyle val = new GUIStyle(GUI.skin.label) { alignment = (TextAnchor)4, fontSize = 27, fontStyle = (FontStyle)1 }; val.normal.textColor = new Color(0.55f, 0.18f, 0.025f); _titleStyle = val; GUIStyle val2 = new GUIStyle(GUI.skin.label) { wordWrap = true, fontSize = 16, richText = true }; val2.normal.textColor = new Color(0.16f, 0.075f, 0.03f); _bodyStyle = val2; GUIStyle val3 = new GUIStyle(_bodyStyle) { fontSize = 19, fontStyle = (FontStyle)1 }; val3.normal.textColor = new Color(0.4f, 0.13f, 0.02f); _serverStyle = val3; GUIStyle val4 = new GUIStyle(GUI.skin.button) { fontSize = 14, fontStyle = (FontStyle)1 }; val4.normal.background = _ink; val4.normal.textColor = new Color(1f, 0.76f, 0.35f); val4.hover.background = _gold; val4.hover.textColor = Color.white; val4.active.background = _gold; val4.active.textColor = Color.white; _buttonStyle = val4; } private static Texture2D LoadParchment() { //IL_0060: 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_0071: Expected O, but got Unknown //IL_0073: Expected O, but got Unknown string name = Array.Find(typeof(Plugin).Assembly.GetManifestResourceNames(), (string n) => n.EndsWith("Assets.Parchment.png", StringComparison.OrdinalIgnoreCase)); using Stream stream = typeof(Plugin).Assembly.GetManifestResourceStream(name); using MemoryStream memoryStream = new MemoryStream(); stream.CopyTo(memoryStream); Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false); ImageConversion.LoadImage(val, memoryStream.ToArray()); return val; } private static Texture2D Solid(Color color) { //IL_0004: 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_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Expected O, but got Unknown Texture2D val = new Texture2D(1, 1, (TextureFormat)4, false); val.SetPixel(0, 0, color); val.Apply(); return val; } private static Texture2D WoodTexture(Color light, Color dark, float alpha) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0094: 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_00a6: Unknown result type (might be due to invalid IL or missing references) Texture2D val = new Texture2D(128, 128, (TextureFormat)4, false); for (int i = 0; i < 128; i++) { for (int j = 0; j < 128; j++) { float num = Mathf.PerlinNoise((float)j * 0.045f, (float)i * 0.18f) * 0.45f + Mathf.PerlinNoise((float)j * 0.012f, (float)i * 0.48f) * 0.55f; float num2 = Mathf.Sin((float)i * 0.44f + Mathf.PerlinNoise((float)j * 0.05f, (float)i * 0.04f) * 2f) * 0.08f; Color val2 = Color.Lerp(dark, light, Mathf.Clamp01(num + num2)); val2.a = alpha; val.SetPixel(j, i, val2); } } ((Texture)val).wrapMode = (TextureWrapMode)0; val.Apply(); return val; } } [Serializable] public sealed class FehuContent { public string newsTitle; public string newsText; public string sagaTitle; public string sagaText; public string realmsTitle; public SocialPanelSettings socialPanel; public List socialLinks; public List servers; public FehuLinks links; public static FehuContent CreateDefault() { return new FehuContent { newsTitle = "FEHU NEWS", sagaTitle = "SKALD SAGA", realmsTitle = "FEHU REALMS", newsText = "# Latest News\n---\nShared Clans are now live.\n\nClan portals now use exact permissions.\n\nGames framework expanded.\n---\n# Upcoming\n---\nSkald Saga Integration\nKingdom Buildings\nNPC Guards", sagaText = "The saga has not begun yet.", servers = new List { new FehuServer("Fehu 10th World", "play.forteca.net", 2456, "Online", "32/64"), new FehuServer("Dominion", "dominion.forteca.net", 2456, "Online", "12/64"), new FehuServer("Conquest", "conquest.forteca.net", 2456, "Online", "7/64") }, links = new FehuLinks { discord = "https://discord.gg/YOURCODE", website = "https://forteca.net", support = "https://forteca.net/support" } }; } } [Serializable] public sealed class FehuServer { public string name; public string address; public string status; public string players; public int port; public FehuServer() { } public FehuServer(string name, string address, int port, string status, string players) { this.name = name; this.address = address; this.port = port; this.status = status; this.players = players; } } [Serializable] public sealed class FehuLinks { public string discord; public string website; public string support; } public sealed class SocialPanelSettings { public bool Enabled; public int X; public int Y; public int Width; public int Height; public int IconSize; public int IconSpacing; } public sealed class SocialLink { public string Title; public string Icon; public string Url; } internal static class FehuJson { internal const string DefaultText = "{\n \"rightTitle\": \"FEHU REALMS\",\n \"leftTitle\": \"FEHU NEWS\",\n \"leftText\": \"# Latest News\\n---\\nShared Clans are now live.\\n\\nClan portals now use exact permissions.\\n\\nGames framework expanded.\\n---\\n# Upcoming\\n---\\nSkald Saga Integration\\nKingdom Buildings\\nNPC Guards\",\n \"servers\": [\n { \"name\": \"Fehu 10th World\", \"address\": \"play.forteca.net\", \"port\": 2456, \"status\": \"Online\", \"players\": \"32/64\" },\n { \"name\": \"Dominion\", \"address\": \"dominion.forteca.net\", \"port\": 2456, \"status\": \"Online\", \"players\": \"7/64\" }\n ],\n \"links\": { \"discord\": \"https://discord.gg/YOURCODE\", \"website\": \"https://forteca.net\", \"support\": \"https://forteca.net/support\" }\n}"; internal static FehuContent Parse(string json) { if (string.IsNullOrWhiteSpace(json)) { return null; } FehuContent fehuContent = FehuContent.CreateDefault(); FehuContent fehuContent2 = new FehuContent { newsTitle = ReadString(json, "newsTitle", ReadString(json, "leftTitle", fehuContent.newsTitle)), newsText = ReadString(json, "newsText", ReadString(json, "leftText", fehuContent.newsText)), sagaTitle = ReadString(json, "sagaTitle", fehuContent.sagaTitle), sagaText = ReadString(json, "sagaText", fehuContent.sagaText), realmsTitle = ReadString(json, "realmsTitle", ReadString(json, "rightTitle", fehuContent.realmsTitle)), servers = new List(), links = new FehuLinks() }; fehuContent2.socialPanel = new SocialPanelSettings { Enabled = true, X = -20, Y = 35, Width = 620, Height = 80, IconSize = 42, IconSpacing = 8 }; string json2 = ReadSection(json, "SocialPanel", '{', '}'); fehuContent2.socialPanel.Enabled = ReadBool(json2, "Enabled", fehuContent2.socialPanel.Enabled); fehuContent2.socialPanel.X = ReadInt(json2, "X", fehuContent2.socialPanel.X); fehuContent2.socialPanel.Y = ReadInt(json2, "Y", fehuContent2.socialPanel.Y); fehuContent2.socialPanel.Width = ReadInt(json2, "Width", fehuContent2.socialPanel.Width); fehuContent2.socialPanel.Height = ReadInt(json2, "Height", fehuContent2.socialPanel.Height); fehuContent2.socialPanel.IconSize = ReadInt(json2, "IconSize", fehuContent2.socialPanel.IconSize); fehuContent2.socialPanel.IconSpacing = ReadInt(json2, "IconSpacing", fehuContent2.socialPanel.IconSpacing); fehuContent2.socialLinks = new List(); foreach (Match item in Regex.Matches(ReadSection(json, "SocialLinks", '[', ']') ?? "", "\\{(?[^{}]*)\\}")) { string value = item.Groups["item"].Value; fehuContent2.socialLinks.Add(new SocialLink { Title = ReadString(value, "Title", "?"), Icon = ReadString(value, "Icon", ""), Url = ReadString(value, "Url", "") }); } foreach (Match item2 in Regex.Matches(ReadSection(json, "servers", '[', ']') ?? string.Empty, "\\{(?[^{}]*)\\}")) { string value2 = item2.Groups["server"].Value; fehuContent2.servers.Add(new FehuServer(ReadString(value2, "name", "Unnamed server"), ReadString(value2, "address", string.Empty), ReadInt(value2, "port", 2456), ReadString(value2, "status", "Unknown"), ReadString(value2, "players", "—"))); } if (fehuContent2.servers.Count == 0) { fehuContent2.servers = fehuContent.servers; } string json3 = ReadSection(json, "links", '{', '}'); fehuContent2.links.discord = ReadString(json3, "discord", fehuContent.links.discord); fehuContent2.links.website = ReadString(json3, "website", fehuContent.links.website); fehuContent2.links.support = ReadString(json3, "support", fehuContent.links.support); return fehuContent2; } private static string ReadString(string json, string key, string fallback) { if (json == null) { return fallback; } Match match = Regex.Match(json, "\\\"" + Regex.Escape(key) + "\\\"\\s*:\\s*\\\"(?(?:\\\\.|[^\\\"])*)\\\""); if (!match.Success) { return fallback; } return Regex.Unescape(match.Groups["value"].Value); } private static int ReadInt(string json, string key, int fallback) { Match match = Regex.Match(json ?? string.Empty, "\\\"" + Regex.Escape(key) + "\\\"\\s*:\\s*(?-?\\d+)"); if (!match.Success || !int.TryParse(match.Groups["value"].Value, out var result)) { return fallback; } return result; } private static bool ReadBool(string json, string key, bool fallback) { Match match = Regex.Match(json ?? "", "\\\"" + Regex.Escape(key) + "\\\"\\s*:\\s*(?true|false)", RegexOptions.IgnoreCase); if (!match.Success || !bool.TryParse(match.Groups["value"].Value, out var result)) { return fallback; } return result; } private static string ReadSection(string json, string key, char open, char close) { int num = json.IndexOf("\"" + key + "\"", StringComparison.Ordinal); if (num < 0) { return null; } int num2 = json.IndexOf(open, num); if (num2 < 0) { return null; } int num3 = 0; for (int i = num2; i < json.Length; i++) { if (json[i] == open) { num3++; } if (json[i] == close && --num3 == 0) { return json.Substring(num2 + 1, i - num2 - 1); } } return null; } } }