using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Net; using System.Net.Sockets; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using Steamworks; using UnityEngine; using UnityEngine.Events; using UnityEngine.SceneManagement; using UnityEngine.UI; [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 { internal sealed class ActiveServerQuery { public readonly ServerQueryWorkItem Item; public readonly string CacheKey; public readonly int Generation; public readonly HServerQuery Handle; public readonly ISteamMatchmakingPingResponse Handler; public readonly DateTime StartedUtc; public bool Cancelled; public ActiveServerQuery(ServerQueryWorkItem item, string cacheKey, int generation, HServerQuery handle, ISteamMatchmakingPingResponse handler) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) Item = item; CacheKey = cacheKey; Generation = generation; Handle = handle; Handler = handler; StartedUtc = DateTime.UtcNow; } } [Serializable] public sealed class FehuContent { public string newsTitle; public string newsText; public string sagaTitle; public string sagaText; public string realmsTitle; public int ServerIconSize; public int ServerIconSpacing; public SocialPanelSettings socialPanel; public List socialLinks; public List servers; public FehuLinks links; public List miniPanels; public static FehuContent CreateDefault() { return new FehuContent { newsTitle = "Development Roadmap", sagaTitle = "Saga Chronicles", 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 = "Connecting...", servers = new List { new FehuServer("10th World", "play.forteca.net", 2456, string.Empty, string.Empty), new FehuServer("Adventure", "play.forteca.net", 2458, string.Empty, string.Empty), new FehuServer("Immersive", "play.forteca.net", 2460, string.Empty, string.Empty), new FehuServer("Conquest", "play.forteca.net", 2462, string.Empty, string.Empty), new FehuServer("Dominion", "play.forteca.net", 2464, string.Empty, string.Empty), new FehuServer("Builders Heaven", "play.forteca.net", 2468, string.Empty, string.Empty), new FehuServer("Balrond Realm", "play.forteca.net", 2474, string.Empty, string.Empty), new FehuServer("Aurora III", "play.forteca.net", 2470, string.Empty, string.Empty), new FehuServer("Black Ymir", "play.forteca.net", 2466, string.Empty, string.Empty), new FehuServer("Test Server", "play.forteca.net", 2472, string.Empty, string.Empty) }, links = new FehuLinks { discord = "https://discord.gg/YOURCODE", website = "https://forteca.net", support = "https://forteca.net/support" }, ServerIconSize = 28, ServerIconSpacing = 6 }; } } internal static class FehuJson { internal const string DefaultText = "{\n \"newsTitle\": \"Development Roadmap\",\n \"newsText\": \"# Latest News\\n---\\nShared Clans are now live.\",\n \"sagaTitle\": \"Saga Chronicles\",\n \"sagaText\": \"Connecting...\",\n \"realmsTitle\": \"FEHU REALMS\",\n \"servers\": [\n { \"name\": \"10th World\", \"address\": \"play.forteca.net\", \"port\": 2456, \"queryPort\": 2457, \"description\": \"The Eternal Realm\\nOne Save To Rule Them ALL\\nMarket \\u2022 Settlement\", \"icon\": \"10th.png\" },\n { \"name\": \"Adventure\", \"address\": \"play.forteca.net\", \"port\": 2458, \"queryPort\": 2459, \"description\": \"Events and expeditions\", \"icon\": \"event.png\" },\n { \"name\": \"Immersive\", \"address\": \"play.forteca.net\", \"port\": 2460, \"queryPort\": 2461, \"description\": \"Very Hard\", \"icon\": \"immersive.png\" },\n { \"name\": \"Conquest\", \"address\": \"play.forteca.net\", \"port\": 2462, \"queryPort\": 2463, \"description\": \"Kingdoms PvP Warfare\", \"icon\": \"conquest.png\" },\n { \"name\": \"Dominion\", \"address\": \"play.forteca.net\", \"port\": 2464, \"queryPort\": 2465, \"description\": \"Kingdoms PvP Warfare\", \"icon\": \"dominion.png\" },\n { \"name\": \"Builders Heaven\", \"address\": \"play.forteca.net\", \"port\": 2468, \"queryPort\": 2469, \"description\": \"Supporters Creative Mode\", \"icon\": \"buildersheaven.png\" },\n { \"name\": \"Balrond Realm\", \"address\": \"play.forteca.net\", \"port\": 2474, \"queryPort\": 2475, \"description\": \"All Balronds Mods\", \"icon\": \"balrond.png\" },\n { \"name\": \"Aurora III\", \"address\": \"play.forteca.net\", \"port\": 2470, \"queryPort\": 2471, \"description\": \"Adventure - Partner Realm\", \"icon\": \"event.png\" },\n { \"name\": \"Black Ymir\", \"address\": \"play.forteca.net\", \"port\": 2466, \"queryPort\": 2467, \"description\": \"Hard EU\", \"icon\": \"forteca-ymir.png\" },\n { \"name\": \"Test Server\", \"address\": \"play.forteca.net\", \"port\": 2472, \"queryPort\": 2473, \"description\": \"Testing and staging\", \"icon\": \"test-server.png\" }\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 = NormalizeSagaText(ReadString(json, "sagaText", fehuContent.sagaText)), realmsTitle = ReadString(json, "realmsTitle", ReadString(json, "rightTitle", fehuContent.realmsTitle)), servers = new List(), links = new FehuLinks(), miniPanels = new List(), ServerIconSize = ReadInt(json, "ServerIconSize", fehuContent.ServerIconSize), ServerIconSpacing = ReadInt(json, "ServerIconSpacing", fehuContent.ServerIconSpacing) }; 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, "MiniPanels", '[', ']') ?? "", "\\{(?[^{}]*)\\}")) { string value2 = item2.Groups["item"].Value; fehuContent2.miniPanels.Add(new MiniPanelSettings { Enabled = ReadBool(value2, "Enabled", fallback: false), X = ReadInt(value2, "X", 0), Y = ReadInt(value2, "Y", 0), Width = ReadInt(value2, "Width", fehuContent2.socialPanel.Width / 2), Height = ReadInt(value2, "Height", fehuContent2.socialPanel.Height), Icon = ReadString(value2, "Icon", ""), Icons = ReadString(value2, "Icons", ""), Url = ReadString(value2, "Url", ""), Text = ReadString(value2, "Text", "") }); } foreach (Match item3 in Regex.Matches(ReadSection(json, "servers", '[', ']') ?? string.Empty, "\\{(?[^{}]*)\\}")) { string value3 = item3.Groups["server"].Value; int num = ReadInt(value3, "port", 2456); fehuContent2.servers.Add(new FehuServer(ReadString(value3, "name", "Unnamed server"), NormalizeJsonServerAddress(ReadString(value3, "address", string.Empty)), num, string.Empty, string.Empty) { queryPort = ReadInt(value3, "queryPort", num + 1), password = ReadString(value3, "password", string.Empty), description = ReadString(value3, "description", string.Empty), icon = ReadString(value3, "icon", string.Empty), steamIdIcon = false }); } 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 NormalizeJsonServerAddress(string address) { object obj; if (!string.Equals((address ?? string.Empty).Trim(), "forteca.net", StringComparison.OrdinalIgnoreCase)) { obj = address; if (obj == null) { return string.Empty; } } else { obj = "play.forteca.net"; } return (string)obj; } private static string NormalizeSagaText(string value) { if (!string.Equals((value ?? string.Empty).Trim(), "The saga has not begun yet.", StringComparison.OrdinalIgnoreCase)) { return value; } return "Connecting..."; } 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; } } [Serializable] public sealed class FehuLinks { public string discord; public string website; public string support; } public sealed class FehuMenu : MonoBehaviour { private sealed class SagaFeedEntry { public DateTime TimestampUtc; public string RealmDisplayName; public string Category; public string Title; public string Text; public string Priority; } private sealed class ThemeDefinition { public string Name; public Texture2D Background; public Texture2D Frame; public Texture2D Header; public Texture2D Separator; public Texture2D Button; public Texture2D ButtonHover; public Texture2D ButtonActive; public Texture2D CloseButton; public Texture2D Panel; public Texture2D BottomPanel; public Texture2D Badge; } private sealed class ThemeInfo { public string Name; public string DisplayName; public Color PanelLight; public Color PanelDark; public Color FrameLight; public Color FrameDark; public Color Button; public Color ButtonHover; public Color ButtonActive; public Color Accent; public Color Title; public Color Body; public Color Server; } [CompilerGenerated] private static class _003C_003EO { public static UnityAction _003C1_003E__OpenSupportUrl; } [CompilerGenerated] private static class <>O { public static UnityAction <0>__OpenSupportUrl; } 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 _enablePanelDragging; private ConfigEntry _enableSteamIdIcons; private ConfigEntry _enableLiveStatus; 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 _statusRefreshIntervalSeconds; private ConfigEntry _queryTimeoutMilliseconds; private ConfigEntry _queryRetryCount; private ConfigEntry _retryDelayMilliseconds; private ConfigEntry _initialStaggerMilliseconds; private ConfigEntry _offlineConfirmationCycles; private ConfigEntry _onlineConfirmationCycles; private ConfigEntry _newsTitle; private ConfigEntry _sagaTitle; private ConfigEntry _realmsTitle; private ConfigEntry _otherRealmsTitle; private ConfigEntry _uiScale; private ConfigEntry _themeName; private string _loadedThemeName; private Texture2D _bottomPanel; private ConfigEntry _showPlayerCounts; private ConfigEntry _pauseWhenLandingHidden; private ConfigEntry _logOnlyStateChanges; private ConfigEntry _debugStatusQueries; private ConfigEntry _enableLayoutDiagnostics; private ConfigEntry _keepLastKnownStatusWhileChecking; private ConfigEntry _bottomLegendEnabled; private ConfigEntry _leftLegendEnabled; private ConfigEntry _rightLegendEnabled; private ConfigEntry _legendF1Enabled; private ConfigEntry _legendF3Enabled; private ConfigEntry _legendF4Enabled; private ConfigEntry _legendF6Enabled; private ConfigEntry _legendF7Enabled; private ConfigEntry _legendF8Enabled; private ConfigEntry _legendF9Enabled; private ConfigEntry _legendF10Enabled; private ConfigEntry _steamIdLegendEnabled; private ConfigEntry _joinLegendEnabled; private ConfigEntry _legendF1Label; private ConfigEntry _legendF3Label; private ConfigEntry _legendF4Label; private ConfigEntry _legendF6Label; private ConfigEntry _legendF7Label; private ConfigEntry _legendF8Label; private ConfigEntry _legendF9Label; private ConfigEntry _legendF10Label; private ConfigEntry _steamIdLegendLabel; private ConfigEntry _steamIdLegendText; private ConfigEntry _joinLegendTitle; private ConfigEntry _joinLegendText; private ConfigEntry _socialIconSize; private ConfigEntry _socialIconSpacing; private ConfigEntry _bottomLeftLegendX; private ConfigEntry _bottomLeftLegendY; private ConfigEntry _bottomRightLegendX; private ConfigEntry _bottomRightLegendY; private ConfigEntry[] _miniEnabled; private ConfigEntry[] _miniX; private ConfigEntry[] _miniY; private ConfigEntry[] _miniWidth; private ConfigEntry[] _miniHeight; private ConfigEntry[] _miniText; private ConfigEntry[] _miniIcons; private ConfigEntry[] _miniUrl; 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 _bottomLeftLegendVisible = true; private bool _bottomRightLegendVisible = true; private bool _socialVisible = true; private bool _themeSelectorVisible; private string _pendingThemeName; private readonly bool[] _miniVisible = new bool[3] { true, true, true }; private string _dragPanelId; private Vector2 _dragOffset; 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 Texture2D _joinIcon; private Texture2D _copyIpIcon; private Texture2D _onlineIcon; private Texture2D _offlineIcon; private Texture2D _checkIcon; private Texture2D _steamIdIcon; private readonly HashSet _hiddenLog = new HashSet(); private readonly HashSet _socialIconLog = new HashSet(); private readonly Dictionary _socialIcons = new Dictionary(); private readonly Dictionary _assetIcons = new Dictionary(StringComparer.OrdinalIgnoreCase); private readonly HashSet _missingStatusIcons = new HashSet(StringComparer.OrdinalIgnoreCase); private readonly HashSet _missingDrawTextureLog = new HashSet(StringComparer.OrdinalIgnoreCase); private readonly Dictionary> _serverSteamIdIconEntries = new Dictionary>(StringComparer.OrdinalIgnoreCase); private readonly Dictionary _serverStates = new Dictionary(); private readonly Dictionary _lastQueryFailureLog = new Dictionary(); private readonly Dictionary _lastLogUtc = new Dictionary(); private readonly Dictionary _realmDescriptionFontSizeCache = new Dictionary(StringComparer.Ordinal); private readonly Dictionary _serverDescriptionLinesCache = new Dictionary(StringComparer.Ordinal); private readonly Dictionary _miniIconListCache = new Dictionary(StringComparer.Ordinal); private readonly List _fehuRealmServers = new List(); private readonly List _otherRealmServers = new List(); private readonly List _chronicleEntries = new List(); private readonly float[] _shortcutEntryWidths = new float[8]; private readonly int[] _shortcutEntryIndexes = new int[8]; private readonly GUIContent _measureContent = new GUIContent(); private ConfigEntry[] _leftShortcutEnabled; private ConfigEntry[] _leftShortcutLabels; private ConfigEntry[] _rightShortcutEnabled; private ConfigEntry[] _rightShortcutLabels; private static readonly string[] LeftShortcutIcons = new string[4] { "theme.png", "empty1.png", "empty2.png", "f7.png" }; private static readonly string[] LeftShortcutDefaults = new string[4] { string.Empty, string.Empty, string.Empty, "Toggle UI" }; private static readonly string[] RightShortcutIcons = new string[8] { "f1.png", "f3.png", "f4.png", "f6.png", "f8.png", "f9.png", "f10.png", "free.png" }; private static readonly string[] RightShortcutDefaults = new string[8] { "Configs", "Kingdoms", "Vault", "Rumble", "Arena", "Rewards", "Factions", "Free" }; private static readonly string[] MainRealmDescriptionLines = new string[3] { "The Eternal Realm", "One Save To Rule Them All", "Market • Settlement" }; private static readonly string[] ActiveThemeNames = new string[4] { "Classic", "Vanilla", "Runestone", "DarkIron" }; private static readonly ThemeInfo[] ThemeRegistry = new ThemeInfo[10] { Theme("Classic", "Classic", new Color(0.92f, 0.68f, 0.32f, 0.92f), new Color(0.52f, 0.26f, 0.08f, 0.94f), new Color(0.82f, 0.48f, 0.16f, 0.96f), new Color(0.34f, 0.16f, 0.05f, 0.96f), new Color(0.1f, 0.055f, 0.025f, 0.85f), new Color(0.48f, 0.19f, 0.035f, 0.75f), new Color(0.56f, 0.24f, 0.06f, 0.88f), new Color(0.48f, 0.19f, 0.035f, 0.75f), new Color(0.55f, 0.18f, 0.025f), new Color(0.16f, 0.075f, 0.03f), new Color(0.4f, 0.13f, 0.02f)), Theme("Vanilla", "Vanilla", new Color(0.13f, 0.09f, 0.06f, 0.97f), new Color(0.025f, 0.022f, 0.019f, 0.98f), new Color(0.26f, 0.16f, 0.08f, 1f), new Color(0.04f, 0.032f, 0.025f, 1f), new Color(0.035f, 0.028f, 0.024f, 0.96f), new Color(0.24f, 0.14f, 0.055f, 0.98f), new Color(0.32f, 0.18f, 0.07f, 0.98f), new Color(0.78f, 0.46f, 0.18f, 0.76f), new Color(0.93f, 0.74f, 0.42f), new Color(0.9f, 0.82f, 0.66f), new Color(1f, 0.84f, 0.48f)), Theme("Nordic", "Nordic", new Color(0.18f, 0.24f, 0.29f, 0.96f), new Color(0.035f, 0.055f, 0.075f, 0.98f), new Color(0.38f, 0.48f, 0.56f, 1f), new Color(0.07f, 0.1f, 0.13f, 1f), new Color(0.055f, 0.075f, 0.095f, 0.96f), new Color(0.2f, 0.3f, 0.38f, 0.98f), new Color(0.26f, 0.38f, 0.48f, 0.98f), new Color(0.42f, 0.66f, 0.86f, 0.76f), new Color(0.78f, 0.88f, 0.95f), new Color(0.8f, 0.86f, 0.9f), new Color(0.7f, 0.86f, 1f)), Theme("Valheim", "Valheim", new Color(0.18f, 0.11f, 0.055f, 0.96f), new Color(0.035f, 0.026f, 0.018f, 0.98f), new Color(0.48f, 0.3f, 0.11f, 1f), new Color(0.07f, 0.045f, 0.025f, 1f), new Color(0.05f, 0.035f, 0.022f, 0.96f), new Color(0.3f, 0.17f, 0.055f, 0.98f), new Color(0.42f, 0.22f, 0.07f, 0.98f), new Color(0.9f, 0.52f, 0.16f, 0.76f), new Color(0.95f, 0.72f, 0.36f), new Color(0.88f, 0.78f, 0.6f), new Color(1f, 0.76f, 0.36f)), Theme("DarkIron", "Dark Iron", new Color(0.11f, 0.105f, 0.1f, 0.97f), new Color(0.012f, 0.012f, 0.014f, 0.99f), new Color(0.36f, 0.33f, 0.3f, 1f), new Color(0.035f, 0.035f, 0.04f, 1f), new Color(0.025f, 0.024f, 0.026f, 0.97f), new Color(0.3f, 0.16f, 0.045f, 0.98f), new Color(0.48f, 0.22f, 0.055f, 0.98f), new Color(1f, 0.46f, 0.11f, 0.78f), new Color(1f, 0.66f, 0.28f), new Color(0.82f, 0.78f, 0.7f), new Color(1f, 0.58f, 0.2f)), Theme("Runestone", "Runestone", new Color(0.2f, 0.21f, 0.22f, 0.96f), new Color(0.045f, 0.048f, 0.052f, 0.98f), new Color(0.44f, 0.46f, 0.48f, 1f), new Color(0.08f, 0.085f, 0.09f, 1f), new Color(0.045f, 0.048f, 0.052f, 0.96f), new Color(0.12f, 0.22f, 0.32f, 0.98f), new Color(0.16f, 0.3f, 0.44f, 0.98f), new Color(0.36f, 0.7f, 1f, 0.7f), new Color(0.72f, 0.84f, 0.94f), new Color(0.8f, 0.82f, 0.8f), new Color(0.6f, 0.82f, 1f)), Theme("Frost", "Frost", new Color(0.5f, 0.62f, 0.68f, 0.94f), new Color(0.12f, 0.18f, 0.22f, 0.97f), new Color(0.72f, 0.82f, 0.88f, 1f), new Color(0.2f, 0.28f, 0.34f, 1f), new Color(0.12f, 0.18f, 0.22f, 0.96f), new Color(0.36f, 0.52f, 0.62f, 0.98f), new Color(0.48f, 0.64f, 0.74f, 0.98f), new Color(0.68f, 0.9f, 1f, 0.76f), new Color(0.9f, 0.97f, 1f), new Color(0.88f, 0.94f, 0.96f), new Color(0.8f, 0.96f, 1f)), Theme("Ember", "Ember", new Color(0.24f, 0.075f, 0.035f, 0.96f), new Color(0.045f, 0.018f, 0.012f, 0.98f), new Color(0.68f, 0.2f, 0.06f, 1f), new Color(0.11f, 0.035f, 0.018f, 1f), new Color(0.06f, 0.022f, 0.012f, 0.96f), new Color(0.42f, 0.11f, 0.032f, 0.98f), new Color(0.64f, 0.16f, 0.04f, 0.98f), new Color(1f, 0.34f, 0.08f, 0.78f), new Color(1f, 0.64f, 0.28f), new Color(0.94f, 0.78f, 0.62f), new Color(1f, 0.48f, 0.16f)), Theme("Royal", "Royal", new Color(0.055f, 0.085f, 0.2f, 0.96f), new Color(0.018f, 0.022f, 0.055f, 0.98f), new Color(0.72f, 0.56f, 0.2f, 1f), new Color(0.08f, 0.06f, 0.12f, 1f), new Color(0.025f, 0.03f, 0.08f, 0.96f), new Color(0.16f, 0.13f, 0.32f, 0.98f), new Color(0.26f, 0.18f, 0.42f, 0.98f), new Color(0.95f, 0.72f, 0.28f, 0.78f), new Color(1f, 0.82f, 0.38f), new Color(0.86f, 0.86f, 0.96f), new Color(1f, 0.8f, 0.36f)), Theme("Ancient", "Ancient", new Color(0.18f, 0.22f, 0.16f, 0.96f), new Color(0.045f, 0.055f, 0.04f, 0.98f), new Color(0.45f, 0.42f, 0.28f, 1f), new Color(0.08f, 0.09f, 0.065f, 1f), new Color(0.045f, 0.055f, 0.04f, 0.96f), new Color(0.18f, 0.28f, 0.16f, 0.98f), new Color(0.26f, 0.38f, 0.22f, 0.98f), new Color(0.42f, 0.7f, 0.38f, 0.76f), new Color(0.82f, 0.82f, 0.6f), new Color(0.82f, 0.86f, 0.7f), new Color(0.62f, 0.84f, 0.46f)) }; private int _lastRealmAutoFitScreenWidth; private int _lastRealmAutoFitScreenHeight; private int _lastRealmAutoFitPanelWidth; private float _lastRealmAutoFitUiScale = -1f; private DateTime _lastServerQueryUtc = DateTime.MinValue; private bool _serverQueriesRunning; private readonly Queue _serverQueryQueue = new Queue(); private readonly Dictionary _activeServerQueries = new Dictionary(StringComparer.OrdinalIgnoreCase); private readonly List _activeServerQueryCancelScratch = new List(1); private int _statusGeneration; private ISteamMatchmakingPingResponse _steamPingHandler; private bool _socialIconsLoaded; private bool _liveStatusDisabledLogged; private static readonly bool IsolationI1DisableNativeServerPolling = false; private bool _isolationI1SuppressionLogged; private bool _isolationI1ShutdownLogged; private static readonly bool IsolationI2StaticRuntime = false; private bool _isolationI2StartupLogged; private bool _isolationI2RuntimeLogged; private bool _isolationI2ShutdownLogged; private static readonly bool IsolationI3MinimalShell = false; private bool _isolationI3LoadedLogged; private bool _isolationI3ShutdownLogged; private static readonly bool IsolationI4StartupOnly = false; private bool _isolationI4StartupLogged; private bool _isolationI4ShutdownLogged; private static readonly bool CrashIsolationDiagnosticBuild = false; private ConfigEntry _isoUIRoot; private ConfigEntry _isoMainPanels; private ConfigEntry _isoBottomPanels; private ConfigEntry _isoServerPanels; private ConfigEntry _isoChronicleSaga; private ConfigEntry _isoSocialShortcutPanels; private ConfigEntry _isoThemeFontsStyles; private ConfigEntry _isoIconsTexturesSprites; private ConfigEntry _isoLayoutSetup; private ConfigEntry _isoSteam; private ConfigEntry _isoRuntimeSystems; private bool _isolationSettingsLogged; private bool _isolationSceneBuilt; private bool _isolationSceneSkipLogged; private int _isolationTexturesCreated; private int _isolationSpritesCreated; private int _isolationFontsResolved; private int _isolationGuiStylesCreated; private bool _isolationAssetTotalsLogged; private readonly HashSet _isolationGroupsLogged = new HashSet(StringComparer.Ordinal); private GUIStyle _isolationLabelStyle; private GUIStyle _isolationBoxStyle; private readonly Dictionary _lastCrashDiagUtcByKey = new Dictionary(); private int _queryHandlesCreated; private int _queryHandlesReleased; private int _queryStaleCallbacks; private Texture2D _supportLogo; private Sprite _supportLogoSprite; private readonly HashSet _replacedMerch = new HashSet(); private bool _merchClickBlockedThisMenu; private static readonly bool DisableChronicleRefreshIsolation = false; private static readonly bool DisableAllRuntimeSchedulersIsolation = false; private const string ChronicleRefreshDisabledText = "Chronicle test\nRefresh disabled"; private const string SagaRpcRequestFeed = "FehuChronicles_RequestFeed"; private const string SagaRpcFeed = "FehuChronicles_Feed"; private string _sagaChronicleText; private string _lastSagaLogSignature; private DateTime _lastSagaRpcRequestUtc = DateTime.MinValue; private DateTime _lastSagaFallbackReadUtc = DateTime.MinValue; private bool _sagaRpcRegistered; private bool _chronicleRefreshInProgress; private bool _chronicleWaitingForRpc; private DateTime _nextChronicleRefreshUtc = DateTime.MinValue; private DateTime _chronicleCycleStartedUtc = DateTime.MinValue; private int _chronicleGeneration; private int _chronicleActiveGeneration; private static readonly object[] EmptyRpcArgs = new object[0]; private bool _runtimeSchedulersDisabledLogged; private void Awake() { //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Expected O, but got Unknown //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Expected O, but got Unknown //IL_0097: Expected O, but got Unknown //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Expected O, but got Unknown //IL_06ea: Unknown result type (might be due to invalid IL or missing references) //IL_06f9: Expected O, but got Unknown //IL_06f4: Unknown result type (might be due to invalid IL or missing references) //IL_06fe: Expected O, but got Unknown //IL_0744: Unknown result type (might be due to invalid IL or missing references) //IL_0753: Expected O, but got Unknown //IL_074e: Unknown result type (might be due to invalid IL or missing references) //IL_0758: Expected O, but got Unknown if (IsolationI3MinimalShell) { if (!_isolationI3LoadedLogged) { Plugin.Log.LogInfo((object)"[I3] Plugin loaded"); Plugin.Log.LogInfo((object)"[I3] Custom UI creation BYPASSED"); Plugin.Log.LogInfo((object)"[I3] Runtime systems DISABLED"); Plugin.Log.LogInfo((object)"[I3] No FehuLanding assets instantiated"); _isolationI3LoadedLogged = true; } return; } ConfigFile config = ((BaseUnityPlugin)Plugin.Instance).Config; BindCrashIsolation(config); LogCrashIsolationSettings(); if (!CrashIsolationDiagnosticBuild && !IsolationI4StartupOnly) { _steamPingHandler = new ISteamMatchmakingPingResponse(new ServerResponded(OnSteamPingResponded), new ServerFailedToRespond(OnSteamPingFailed)); } 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", false, (ConfigDescription)null); _hideShowLogButton = config.Bind("Vanilla Menu", "HideShowLogButton", false, (ConfigDescription)null); _enableLiveStatus = config.Bind("ServerStatus", "EnableLiveStatus", true, "Enable native live server status queries."); _statusRefreshIntervalSeconds = config.Bind("ServerStatus", "RefreshIntervalSeconds", 60, "Refresh while Landing is visible."); _queryTimeoutMilliseconds = config.Bind("ServerStatus", "QueryTimeoutMilliseconds", 1500, "Maximum time for one Steam query attempt."); _queryRetryCount = config.Bind("ServerStatus", "RetryCount", 1, "Number of additional query-port candidate passes before a server is treated as offline."); _retryDelayMilliseconds = config.Bind("ServerStatus", "RetryDelayMilliseconds", 250, "Short delay before status retry attempts."); _initialStaggerMilliseconds = config.Bind("ServerStatus", "InitialStaggerMilliseconds", 50, "Small delay between starting each server query."); _pauseWhenLandingHidden = config.Bind("ServerStatus", "PauseWhenLandingHidden", true, "Do not run live polling while Landing is hidden."); _logOnlyStateChanges = config.Bind("ServerStatus", "LogOnlyStateChanges", true, "Log only live status state changes by default."); _debugStatusQueries = config.Bind("ServerStatus", "DebugStatusQueries", false, "Detailed query lifecycle diagnostics."); _enableLayoutDiagnostics = config.Bind("Diagnostics", "EnableLayoutDiagnostics", false, "Enable one-shot/rate-limited layout diagnostics. Disabled by default to prevent render-loop log spam."); _keepLastKnownStatusWhileChecking = config.Bind("ServerStatus", "KeepLastKnownStatusWhileChecking", true, "Keep green/red status visible while background refresh is checking."); _offlineConfirmationCycles = config.Bind("ServerStatus", "OfflineConfirmationCycles", 2, "Failed query cycles required before showing Offline."); _onlineConfirmationCycles = config.Bind("ServerStatus", "OnlineConfirmationCycles", 1, "Successful query cycles required before showing Online."); _showPlayerCounts = config.Bind("ServerStatus", "ShowPlayerCounts", true, "Show player counts after successful live status query."); _enableSteamIdIcons = config.Bind("ServerSteamIdIcons", "EnableSteamIdIcons", true, "Master switch. true = enable SteamID icons system, false = hide all SteamID icons."); BindServerSteamIdIcons(config); _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", "Development Roadmap", (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", 535, (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", 440, (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", 460, (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); if (!IsolationI4StartupOnly) { Plugin.Log.LogInfo((object)"[TheFehu] SocialPanel config applied X/Y/W/H/IconSize/IconSpacing"); } _enablePanelDragging = config.Bind("General", "EnablePanelDragging", true, "Hold CTRL and drag FehuLanding panels to save their X/Y position."); BindMiniPanels(config); BindBottomLegend(config); InitializeShortcutLegendCaches(); BindRealmLegend(config); if (_newsTitle.Value == "Announcements") { _newsTitle.Value = "Development Roadmap"; config.Save(); } _uiScale = config.Bind("General", "UIScale", 1f, new ConfigDescription("Additional UI scale.", (AcceptableValueBase)new AcceptableValueRange(0.5f, 2f), Array.Empty())); _themeName = config.Bind("Appearance", "Theme", "Classic", new ConfigDescription("Visual theme. Invalid values fall back to Classic.", (AcceptableValueBase)new AcceptableValueList(new string[4] { "Classic", "Vanilla", "Runestone", "DarkIron" }), Array.Empty())); _contentPath = Path.Combine(Path.GetDirectoryName(typeof(Plugin).Assembly.Location), "FehuLanding.json"); if (IsolationI4StartupOnly && !_isolationI4StartupLogged) { Plugin.Log.LogInfo((object)"[I4] Config initialized"); } LoadContent(); if (IsolationI4StartupOnly && !_isolationI4StartupLogged) { Plugin.Log.LogInfo((object)"[I4] JSON initialized"); } if (IsolationI2StaticRuntime && !_isolationI2StartupLogged) { Plugin.Log.LogInfo((object)"[I2] Static UI initialized"); Plugin.Log.LogInfo((object)"[I2] Background refresh DISABLED"); Plugin.Log.LogInfo((object)"[I2] AutoFit DISABLED"); Plugin.Log.LogInfo((object)"[I2] Runtime layout refresh DISABLED"); _isolationI2StartupLogged = true; } SceneManager.sceneLoaded += OnSceneLoaded; if (IsolationI4StartupOnly && !_isolationI4StartupLogged) { Plugin.Log.LogInfo((object)"[I4] Scene subscription initialized"); Plugin.Log.LogInfo((object)"[I4] Steam systems DISABLED"); Plugin.Log.LogInfo((object)"[I4] UI and assets BYPASSED"); Plugin.Log.LogInfo((object)"[I4] Runtime systems DISABLED"); _isolationI4StartupLogged = true; } } private void OnDestroy() { if (IsolationI3MinimalShell) { if (!_isolationI3ShutdownLogged) { Plugin.Log.LogInfo((object)"[I3] shutdown/disable reached"); _isolationI3ShutdownLogged = true; } return; } SceneManager.sceneLoaded -= OnSceneLoaded; if (IsolationI4StartupOnly) { if (!_isolationI4ShutdownLogged) { Plugin.Log.LogInfo((object)"[I4] shutdown/disable reached"); _isolationI4ShutdownLogged = true; } return; } if (IsolationI1DisableNativeServerPolling && !_isolationI1ShutdownLogged) { Plugin.Log.LogInfo((object)"[FehuLanding] I1 shutdown/disable reached"); _isolationI1ShutdownLogged = true; } if (IsolationI2StaticRuntime && !_isolationI2ShutdownLogged) { Plugin.Log.LogInfo((object)"[I2] shutdown/disable reached"); _isolationI2ShutdownLogged = true; } if (CrashIsolationDiagnosticBuild) { DestroyIsolationOwnedObjects(); } else { CancelAllServerQueries("destroy"); } } private void BindCrashIsolation(ConfigFile config) { _isoUIRoot = config.Bind("Crash Isolation", "IsolationEnableUIRoot", false, (ConfigDescription)null); _isoMainPanels = config.Bind("Crash Isolation", "IsolationEnableMainPanels", false, (ConfigDescription)null); _isoBottomPanels = config.Bind("Crash Isolation", "IsolationEnableBottomPanels", false, (ConfigDescription)null); _isoServerPanels = config.Bind("Crash Isolation", "IsolationEnableServerPanels", false, (ConfigDescription)null); _isoChronicleSaga = config.Bind("Crash Isolation", "IsolationEnableChronicleSaga", false, (ConfigDescription)null); _isoSocialShortcutPanels = config.Bind("Crash Isolation", "IsolationEnableSocialShortcutPanels", false, (ConfigDescription)null); _isoThemeFontsStyles = config.Bind("Crash Isolation", "IsolationEnableThemeFontsStyles", false, (ConfigDescription)null); _isoIconsTexturesSprites = config.Bind("Crash Isolation", "IsolationEnableIconsTexturesSprites", false, (ConfigDescription)null); _isoLayoutSetup = config.Bind("Crash Isolation", "IsolationEnableLayoutSetup", false, (ConfigDescription)null); _isoSteam = config.Bind("Crash Isolation", "IsolationEnableSteam", false, (ConfigDescription)null); _isoRuntimeSystems = config.Bind("Crash Isolation", "IsolationEnableRuntimeSystems", false, (ConfigDescription)null); } private static bool Iso(ConfigEntry entry) { return entry?.Value ?? false; } private void LogCrashIsolationSettings() { if (CrashIsolationDiagnosticBuild && !_isolationSettingsLogged) { Plugin.Log.LogInfo((object)"[Isolation] Diagnostic UI build active"); Plugin.Log.LogInfo((object)("[Isolation] UIRoot=" + Iso(_isoUIRoot))); Plugin.Log.LogInfo((object)("[Isolation] MainPanels=" + Iso(_isoMainPanels))); Plugin.Log.LogInfo((object)("[Isolation] BottomPanels=" + Iso(_isoBottomPanels))); Plugin.Log.LogInfo((object)("[Isolation] ServerPanels=" + Iso(_isoServerPanels))); Plugin.Log.LogInfo((object)("[Isolation] ChronicleSaga=" + Iso(_isoChronicleSaga))); Plugin.Log.LogInfo((object)("[Isolation] SocialShortcutPanels=" + Iso(_isoSocialShortcutPanels))); Plugin.Log.LogInfo((object)("[Isolation] ThemeFontsStyles=" + Iso(_isoThemeFontsStyles))); Plugin.Log.LogInfo((object)("[Isolation] IconsTexturesSprites=" + Iso(_isoIconsTexturesSprites))); Plugin.Log.LogInfo((object)("[Isolation] LayoutSetup=" + Iso(_isoLayoutSetup))); Plugin.Log.LogInfo((object)("[Isolation] Steam=" + Iso(_isoSteam))); Plugin.Log.LogInfo((object)("[Isolation] RuntimeSystems=" + Iso(_isoRuntimeSystems))); _isolationSettingsLogged = true; } } private void BuildIsolationSceneOnce() { if (_isolationSceneBuilt) { if (!_isolationSceneSkipLogged) { Plugin.Log.LogInfo((object)"[Isolation] Scene construction skipped; already initialized"); _isolationSceneSkipLogged = true; } } else { _isolationSceneBuilt = true; } } private void DestroyIsolationOwnedObjects() { _isolationSceneBuilt = false; } private void LogIsolationWarningOnce(string key, string message) { if (_isolationGroupsLogged.Add("warn:" + key)) { Plugin.Log.LogWarning((object)message); } } private void LogIsolationGroup(string groupName, Action action) { Stopwatch stopwatch = Stopwatch.StartNew(); bool flag = false; bool flag2 = _isolationGroupsLogged.Add(groupName); if (flag2) { Plugin.Log.LogInfo((object)("[Isolation] BEGIN " + groupName)); } try { action?.Invoke(); flag = true; } catch (Exception ex) { Plugin.Log.LogWarning((object)("[Isolation] " + groupName + " failed: " + ex)); } finally { stopwatch.Stop(); if (flag2) { Plugin.Log.LogInfo((object)("[Isolation] END " + groupName + " success=" + flag + " elapsedMs=" + stopwatch.ElapsedMilliseconds)); } } } private void EnsureIsolationStyles() { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Expected O, but got Unknown //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: 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_0060: Expected O, but got Unknown if (_isolationLabelStyle == null || _isolationBoxStyle == null) { _isolationLabelStyle = new GUIStyle(GUI.skin.label) { fontSize = 14, alignment = (TextAnchor)0, wordWrap = true }; _isolationBoxStyle = new GUIStyle(GUI.skin.box) { fontSize = 14, alignment = (TextAnchor)4 }; _isolationGuiStylesCreated += 2; _isolationFontsResolved++; } } private void DrawCrashIsolationDiagnosticUi() { //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_020b: Unknown result type (might be due to invalid IL or missing references) if (!IsMainMenu() || !Iso(_isoUIRoot)) { return; } if (_content == null) { LoadContent(); } if (NeedsThemeBuild()) { if (!Iso(_isoThemeFontsStyles)) { if (Iso(_isoMainPanels) || Iso(_isoBottomPanels) || Iso(_isoServerPanels) || Iso(_isoChronicleSaga) || Iso(_isoSocialShortcutPanels)) { LogIsolationWarningOnce("ThemeFontsStylesDependency", "[Isolation] Production visual groups bypassed because IsolationEnableThemeFontsStyles=false"); } return; } LogIsolationGroup("ThemeFontsStyles", delegate { BuildTheme(); }); } 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; float logicalHeight = (float)Screen.height / num; if (Iso(_isoMainPanels) && _newsEnabled.Value && _topLeftVisible) { LogIsolationGroup("MainPanels", delegate { //IL_009d: Unknown result type (might be due to invalid IL or missing references) Rect panel = default(Rect); ((Rect)(ref panel))..ctor((float)_newsX.Value, (float)_newsY.Value, (float)_newsWidth.Value, (float)_newsHeight.Value); if (Iso(_isoLayoutSetup)) { HandlePanelDrag("TopLeft", ref panel, _newsX, _newsY, rightAnchored: false, num2, logicalHeight); } DrawStoryBoard("TopLeft", panel, string.IsNullOrEmpty(_newsTitle.Value) ? _content.newsTitle : _newsTitle.Value, _content.newsText, ref _newsScroll, ref _topLeftVisible); }); } if (Iso(_isoChronicleSaga) && _sagaEnabled.Value && _bottomLeftVisible) { LogIsolationGroup("ChronicleSaga", delegate { //IL_009d: Unknown result type (might be due to invalid IL or missing references) Rect panel = default(Rect); ((Rect)(ref panel))..ctor((float)_sagaX.Value, (float)_sagaY.Value, (float)_sagaWidth.Value, (float)_sagaHeight.Value); if (Iso(_isoLayoutSetup)) { HandlePanelDrag("BottomLeft", ref panel, _sagaX, _sagaY, rightAnchored: false, num2, logicalHeight); } DrawChronicleBoard("BottomLeft", panel, string.IsNullOrEmpty(_sagaTitle.Value) ? _content.sagaTitle : _sagaTitle.Value, ref _sagaScroll, ref _bottomLeftVisible); }); } if (Iso(_isoServerPanels)) { LogIsolationGroup("ServerPanels", delegate { //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_020c: Unknown result type (might be due to invalid IL or missing references) if (_realmsEnabled.Value && _topRightVisible) { Rect panel = default(Rect); ((Rect)(ref panel))..ctor(num2 - (float)_rightWidth.Value + (float)_rightX.Value, (float)_rightY.Value, (float)_rightWidth.Value, (float)_rightHeight.Value); if (Iso(_isoLayoutSetup)) { HandlePanelDrag("TopRight", ref panel, _rightX, _rightY, rightAnchored: true, num2, logicalHeight); } DrawRealmsBoard("TopRight", panel, string.IsNullOrEmpty(_realmsTitle.Value) ? _content.realmsTitle : _realmsTitle.Value, _fehuRealmServers, ref _topRightVisible, fehuRealm: true); } if (_otherRealmsEnabled.Value && _bottomRightVisible) { Rect panel2 = default(Rect); ((Rect)(ref panel2))..ctor(num2 - (float)_otherWidth.Value + (float)_otherX.Value, (float)_otherY.Value, (float)_otherWidth.Value, (float)_otherHeight.Value); if (Iso(_isoLayoutSetup)) { HandlePanelDrag("BottomRight", ref panel2, _otherX, _otherY, rightAnchored: true, num2, logicalHeight); } DrawRealmsBoard("BottomRight", panel2, _otherRealmsTitle.Value, _otherRealmServers, ref _bottomRightVisible, fehuRealm: false); } }); } if (Iso(_isoSocialShortcutPanels)) { LogIsolationGroup("SocialShortcutPanels", delegate { //IL_013a: Unknown result type (might be due to invalid IL or missing references) 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) { Rect panel = default(Rect); ((Rect)(ref panel))..ctor(num2 - (float)socialPanelSettings.Width + (float)socialPanelSettings.X, (float)socialPanelSettings.Y, (float)socialPanelSettings.Width, (float)socialPanelSettings.Height); if (Iso(_isoLayoutSetup)) { HandlePanelDrag("Social", ref panel, _socialX, _socialY, rightAnchored: true, num2, logicalHeight); } DrawSocial(panel, socialPanelSettings); } DrawMiniPanels(num2, logicalHeight); }); } if (Iso(_isoBottomPanels)) { LogIsolationGroup("BottomPanels", delegate { DrawBottomLegend(num2, logicalHeight); }); } GUI.matrix = matrix; GUI.depth = depth; if (!_isolationAssetTotalsLogged) { Plugin.Log.LogInfo((object)("[Isolation Assets] Texture2D created=" + _isolationTexturesCreated)); Plugin.Log.LogInfo((object)("[Isolation Assets] Sprites created=" + _isolationSpritesCreated)); Plugin.Log.LogInfo((object)("[Isolation Assets] Fonts resolved=" + _isolationFontsResolved)); Plugin.Log.LogInfo((object)("[Isolation Assets] GUIStyles created=" + _isolationGuiStylesCreated)); _isolationAssetTotalsLogged = true; } } private void OnSceneLoaded(Scene scene, LoadSceneMode mode) { if (IsolationI3MinimalShell || IsolationI4StartupOnly) { return; } if (CrashIsolationDiagnosticBuild) { if (IsMainMenu()) { _hiddenForSession = false; _topLeftVisible = (_bottomLeftVisible = (_topRightVisible = (_bottomRightVisible = (_socialVisible = true)))); SetAllMiniVisible(visible: true); if (!_isolationSceneSkipLogged) { Plugin.Log.LogInfo((object)"[Isolation] Main menu entered; production UI groups are controlled by Crash Isolation switches"); _isolationSceneSkipLogged = true; } } } else if (IsMainMenu()) { _hiddenForSession = false; _topLeftVisible = (_bottomLeftVisible = (_topRightVisible = (_bottomRightVisible = (_socialVisible = true)))); SetAllMiniVisible(visible: true); _merchClickBlockedThisMenu = false; } } 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 (IsolationI3MinimalShell || IsolationI4StartupOnly || (CrashIsolationDiagnosticBuild && !Iso(_isoRuntimeSystems))) { return; } if (Input.GetKeyDown((KeyCode)288) && IsMainMenu()) { ToggleLandingTabs(); if (_hiddenForSession && (_pauseWhenLandingHidden == null || _pauseWhenLandingHidden.Value)) { CancelAllServerQueries("landing hidden"); } Plugin.Log.LogInfo((object)"[FehuLanding] F7 toggle Landing tabs"); } if (DisableAllRuntimeSchedulersIsolation) { if (!_runtimeSchedulersDisabledLogged) { Plugin.Log.LogInfo((object)"[Isolation] Runtime schedulers disabled."); _runtimeSchedulersDisabledLogged = true; } } else if (IsMainMenu()) { if (IsolationI2StaticRuntime) { if (!_isolationI2RuntimeLogged) { Plugin.Log.LogInfo((object)"[I2] Runtime background refresh suppressed"); _isolationI2RuntimeLogged = true; } return; } if (_hiddenForSession && (_pauseWhenLandingHidden == null || _pauseWhenLandingHidden.Value)) { CancelAllServerQueries("landing hidden"); } else { BeginServerQueriesIfNeeded(); if (!IsolationI1DisableNativeServerPolling) { CheckActiveServerQueryTimeout(); PumpSteamServerQuery(); } } if (!DisableChronicleRefreshIsolation) { RunChronicleScheduler(); } } else if (_serverQueriesRunning || _activeServerQueries.Count > 0) { CancelAllServerQueries("left main menu"); } } private void OnGUI() { //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_0106: 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) //IL_01ca: Unknown result type (might be due to invalid IL or missing references) //IL_0229: Unknown result type (might be due to invalid IL or missing references) //IL_0283: Unknown result type (might be due to invalid IL or missing references) //IL_02f1: Unknown result type (might be due to invalid IL or missing references) //IL_04d8: Unknown result type (might be due to invalid IL or missing references) //IL_034c: Unknown result type (might be due to invalid IL or missing references) //IL_03ba: Unknown result type (might be due to invalid IL or missing references) //IL_046a: Unknown result type (might be due to invalid IL or missing references) //IL_04bf: Unknown result type (might be due to invalid IL or missing references) if (IsolationI3MinimalShell || IsolationI4StartupOnly) { return; } if (CrashIsolationDiagnosticBuild) { DrawCrashIsolationDiagnosticUi(); } else if (_enabled.Value && _showOnMainMenu.Value && !_hiddenForSession && IsMainMenu()) { if (_content == null) { LoadContent(); } if (_titleStyle == null) { BuildTheme(); BlockMerchStoreClickOnce(); } 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; float logicalHeight = (float)Screen.height / num; if (_newsEnabled.Value && _topLeftVisible) { Rect panel = default(Rect); ((Rect)(ref panel))..ctor((float)_newsX.Value, (float)_newsY.Value, (float)_newsWidth.Value, (float)_newsHeight.Value); HandlePanelDrag("TopLeft", ref panel, _newsX, _newsY, rightAnchored: false, num2, logicalHeight); DrawStoryBoard("TopLeft", panel, string.IsNullOrEmpty(_newsTitle.Value) ? _content.newsTitle : _newsTitle.Value, _content.newsText, ref _newsScroll, ref _topLeftVisible); } if (_sagaEnabled.Value && _bottomLeftVisible) { Rect panel2 = default(Rect); ((Rect)(ref panel2))..ctor((float)_sagaX.Value, (float)_sagaY.Value, (float)_sagaWidth.Value, (float)_sagaHeight.Value); HandlePanelDrag("BottomLeft", ref panel2, _sagaX, _sagaY, rightAnchored: false, num2, logicalHeight); DrawChronicleBoard("BottomLeft", panel2, string.IsNullOrEmpty(_sagaTitle.Value) ? _content.sagaTitle : _sagaTitle.Value, ref _sagaScroll, ref _bottomLeftVisible); } if (_realmsEnabled.Value && _topRightVisible) { Rect panel3 = default(Rect); ((Rect)(ref panel3))..ctor(num2 - (float)_rightWidth.Value + (float)_rightX.Value, (float)_rightY.Value, (float)_rightWidth.Value, (float)_rightHeight.Value); HandlePanelDrag("TopRight", ref panel3, _rightX, _rightY, rightAnchored: true, num2, logicalHeight); DrawRealmsBoard("TopRight", panel3, string.IsNullOrEmpty(_realmsTitle.Value) ? _content.realmsTitle : _realmsTitle.Value, _fehuRealmServers, ref _topRightVisible, fehuRealm: true); } if (_otherRealmsEnabled.Value && _bottomRightVisible) { Rect panel4 = default(Rect); ((Rect)(ref panel4))..ctor(num2 - (float)_otherWidth.Value + (float)_otherX.Value, (float)_otherY.Value, (float)_otherWidth.Value, (float)_otherHeight.Value); HandlePanelDrag("BottomRight", ref panel4, _otherX, _otherY, rightAnchored: true, num2, logicalHeight); DrawRealmsBoard("BottomRight", panel4, _otherRealmsTitle.Value, _otherRealmServers, ref _bottomRightVisible, fehuRealm: false); } 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) { Rect panel5 = default(Rect); ((Rect)(ref panel5))..ctor(num2 - (float)socialPanelSettings.Width + (float)socialPanelSettings.X, (float)socialPanelSettings.Y, (float)socialPanelSettings.Width, (float)socialPanelSettings.Height); HandlePanelDrag("Social", ref panel5, _socialX, _socialY, rightAnchored: true, num2, logicalHeight); DrawSocial(panel5, socialPanelSettings); } DrawMiniPanels(num2, logicalHeight); DrawBottomLegend(num2, logicalHeight); GUI.matrix = matrix; GUI.depth = depth; } } private string GetSagaChronicleText() { if (DisableChronicleRefreshIsolation) { return "Chronicle test\nRefresh disabled"; } if (!string.IsNullOrWhiteSpace(_sagaChronicleText)) { return _sagaChronicleText; } return _content.sagaText; } private void RunChronicleScheduler() { TryRegisterSagaRpc(); DateTime utcNow = DateTime.UtcNow; if (_chronicleRefreshInProgress) { if (_chronicleWaitingForRpc && (utcNow - _chronicleCycleStartedUtc).TotalSeconds >= 2.0) { ReadSagaFeedFallbackOnce(); FinishChronicleRefresh("fallback-after-rpc-timeout"); } else if ((utcNow - _chronicleCycleStartedUtc).TotalSeconds >= 5.0) { FinishChronicleRefresh("timeout"); } } else if (!(utcNow < _nextChronicleRefreshUtc)) { StartChronicleRefreshCycle(); } } private void StartChronicleRefreshCycle() { _chronicleRefreshInProgress = true; _chronicleWaitingForRpc = false; _chronicleCycleStartedUtc = DateTime.UtcNow; _chronicleGeneration++; _chronicleActiveGeneration = _chronicleGeneration; Plugin.Log.LogInfo((object)"[FehuLanding] Chronicle refresh started"); if (_sagaRpcRegistered && ZRoutedRpc.instance != null) { try { _lastSagaRpcRequestUtc = DateTime.UtcNow; _chronicleWaitingForRpc = true; ZRoutedRpc.instance.InvokeRoutedRPC("FehuChronicles_RequestFeed", EmptyRpcArgs); return; } catch (Exception ex) { LogChronicleRefreshFailure("RPC request unavailable: " + ex.Message); } } ReadSagaFeedFallbackOnce(); FinishChronicleRefresh("fallback"); } private void FinishChronicleRefresh(string reason) { _chronicleRefreshInProgress = false; _chronicleWaitingForRpc = false; _nextChronicleRefreshUtc = DateTime.UtcNow.AddSeconds(30.0); Plugin.Log.LogInfo((object)("[FehuLanding] Chronicle refresh completed: " + reason)); } private void TryRegisterSagaRpc() { if (_sagaRpcRegistered || ZRoutedRpc.instance == null) { return; } try { ZRoutedRpc.instance.Register("FehuChronicles_Feed", (Action)OnSagaFeedRpc); _sagaRpcRegistered = true; Plugin.Log.LogInfo((object)"[FehuLanding] SkaldSaga RPC receiver registered: FehuChronicles_Feed"); } catch (Exception ex) { LogChronicleRefreshFailure("RPC receiver failed: " + ex.Message); } } private void RequestSagaFeedIfNeeded() { if (!_chronicleRefreshInProgress) { StartChronicleRefreshCycle(); } } private void OnSagaFeedRpc(long sender, string json) { if (!DisableChronicleRefreshIsolation) { if (!_chronicleRefreshInProgress || !_chronicleWaitingForRpc) { Plugin.Log.LogInfo((object)"[FehuLanding] Chronicle stale RPC response ignored"); return; } ApplySagaFeedJson(json, 10); FinishChronicleRefresh("rpc"); } } private void ReadSagaFeedFallbackIfNeeded() { if (!_chronicleRefreshInProgress) { StartChronicleRefreshCycle(); } } private void ReadSagaFeedFallbackOnce() { _lastSagaFallbackReadUtc = DateTime.UtcNow; try { string path = Path.Combine(Paths.ConfigPath, "FehuChronicles", "SagaFeed.json"); if (File.Exists(path)) { ApplySagaFeedJson(File.ReadAllText(path), 10); } } catch (Exception ex) { LogChronicleRefreshFailure("SagaFeed fallback failed: " + ex.Message); } } private bool ApplySagaFeedJson(string json, int maxEntries) { List list = ParseSagaFeedEntries(json, maxEntries); if (list.Count == 0) { return false; } _chronicleEntries.Clear(); _chronicleEntries.AddRange(list); ApplySagaChronicleText(BuildSagaPlainText(list)); return true; } private void ApplySagaChronicleText(string text) { if (!string.IsNullOrWhiteSpace(text)) { _sagaChronicleText = text; LogSagaTextLoaded(text); } } private void LogChronicleRefreshFailure(string message) { Plugin.Log.LogWarning((object)("[FehuLanding] Chronicle refresh failed: " + message)); } private void LogSagaTextLoaded(string text) { if (!string.IsNullOrWhiteSpace(text)) { int num = text.Split(new char[1] { '\n' }).Length; string text2 = num + ":" + text.Length; if (!(_lastSagaLogSignature == text2)) { _lastSagaLogSignature = text2; Plugin.Log.LogInfo((object)("[FehuLanding] Saga text loaded: " + num + " lines")); } } } private static string NormalizeChronicleText(string value) { if (string.IsNullOrWhiteSpace(value)) { return value; } List list = new List(); bool flag = false; string[] array = value.Replace("\r\n", "\n").Replace('\r', '\n').Split(new char[1] { '\n' }); for (int i = 0; i < array.Length; i++) { string text = array[i].TrimEnd(Array.Empty()); if (string.IsNullOrWhiteSpace(text)) { if (!flag && list.Count > 0) { list.Add(string.Empty); flag = true; } } else { list.Add(text); flag = false; } } while (list.Count > 0 && string.IsNullOrWhiteSpace(list[list.Count - 1])) { list.RemoveAt(list.Count - 1); } return string.Join("\n", list.ToArray()); } private static string FormatSagaFeed(string json, int maxEntries) { List list = ParseSagaFeedEntries(json, maxEntries); if (list.Count == 0) { return null; } return BuildSagaPlainText(list); } private static List ParseSagaFeedEntries(string json, int maxEntries) { List list = new List(); if (string.IsNullOrWhiteSpace(json)) { return list; } foreach (Match item in Regex.Matches(json, "\\{(?[^{}]*(?:\\{[^{}]*\\}[^{}]*)*)\\}")) { string value = item.Groups["entry"].Value; if (value.Contains("\"title\"")) { SagaFeedEntry sagaFeedEntry = new SagaFeedEntry { TimestampUtc = ReadSagaDate(value, "timestampUtc"), RealmDisplayName = ReadSagaString(value, "realmDisplayName"), Category = ReadSagaString(value, "category"), Title = ReadSagaString(value, "title"), Text = ReadSagaString(value, "text"), Priority = ReadSagaString(value, "priority") }; if (sagaFeedEntry.TimestampUtc == DateTime.MinValue) { sagaFeedEntry.TimestampUtc = ReadSagaDate(value, "timestampUTC"); } if (sagaFeedEntry.TimestampUtc == DateTime.MinValue) { sagaFeedEntry.TimestampUtc = ReadSagaDate(value, "timestamp"); } if (string.IsNullOrWhiteSpace(sagaFeedEntry.RealmDisplayName)) { sagaFeedEntry.RealmDisplayName = ReadSagaString(value, "server"); } if (string.IsNullOrWhiteSpace(sagaFeedEntry.RealmDisplayName)) { sagaFeedEntry.RealmDisplayName = ReadSagaString(value, "serverName"); } if (string.IsNullOrWhiteSpace(sagaFeedEntry.Category)) { sagaFeedEntry.Category = ReadSagaString(value, "eventType"); } if (string.IsNullOrWhiteSpace(sagaFeedEntry.Priority)) { sagaFeedEntry.Priority = ReadSagaString(value, "importance"); } sagaFeedEntry.RealmDisplayName = (string.IsNullOrWhiteSpace(sagaFeedEntry.RealmDisplayName) ? "Fehu Realms" : sagaFeedEntry.RealmDisplayName.Trim()); sagaFeedEntry.Category = NormalizeChronicleCategory(sagaFeedEntry.Category); sagaFeedEntry.Priority = NormalizeChroniclePriority(sagaFeedEntry.Priority); sagaFeedEntry.Title = (string.IsNullOrWhiteSpace(sagaFeedEntry.Title) ? "Chronicle" : sagaFeedEntry.Title.Trim()); sagaFeedEntry.Text = (sagaFeedEntry.Text ?? string.Empty).Trim(); list.Add(sagaFeedEntry); } } if (list.Count == 0) { return list; } list.Sort((SagaFeedEntry a, SagaFeedEntry b) => b.TimestampUtc.CompareTo(a.TimestampUtc)); int num = Mathf.Max(1, maxEntries); if (list.Count > num) { list.RemoveRange(num, list.Count - num); } return list; } private static string BuildSagaPlainText(List entries) { if (entries == null || entries.Count == 0) { return null; } List list = new List(); for (int i = 0; i < entries.Count; i++) { SagaFeedEntry sagaFeedEntry = entries[i]; list.Add("[" + sagaFeedEntry.RealmDisplayName + "] [" + sagaFeedEntry.Category + "]"); list.Add(sagaFeedEntry.Title); if (!string.IsNullOrWhiteSpace(sagaFeedEntry.Text)) { list.Add(sagaFeedEntry.Text); } list.Add(string.Empty); } return string.Join("\n", list.ToArray()).TrimEnd(Array.Empty()); } private static string NormalizeChronicleCategory(string value) { string text = (value ?? string.Empty).Trim().ToUpperInvariant(); switch (text) { case "CLAN": case "LORE": case "ADMIN": case "EVENT": case "QUEST": case "PLAYER": case "SYSTEM": case "MARKET": case "SERVER": case "WAR": case "TERRITORY": case "KINGDOM": return text; default: return "LORE"; } } private static string NormalizeChroniclePriority(string value) { string text = (value ?? string.Empty).Trim().ToUpperInvariant(); if (text == "CRITICAL" || text == "IMPORTANT") { return text; } return "NORMAL"; } private static string ReadSagaString(string block, string name) { Match match = Regex.Match(block, "\\\"" + Regex.Escape(name) + "\\\"\\s*:\\s*\\\"(?(?:\\\\.|[^\\\"])*)\\\""); if (!match.Success) { return string.Empty; } return match.Groups["v"].Value.Replace("\\n", "\n").Replace("\\\"", "\"").Replace("\\\\", "\\"); } private static DateTime ReadSagaDate(string block, string name) { if (!DateTime.TryParse(ReadSagaString(block, name), CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal, out var result)) { return DateTime.MinValue; } return result.ToUniversalTime(); } private void SetAllMiniVisible(bool visible) { for (int i = 0; i < _miniVisible.Length; i++) { _miniVisible[i] = visible; } } private void BindServerSteamIdIcons(ConfigFile config) { _serverSteamIdIconEntries.Clear(); BindServerSteamIdIcon(config, "10thWorld", defaultValue: false); BindServerSteamIdIcon(config, "Adventure", defaultValue: true); BindServerSteamIdIcon(config, "Immersive", defaultValue: true); BindServerSteamIdIcon(config, "Conquest", defaultValue: false); BindServerSteamIdIcon(config, "Dominion", defaultValue: false); BindServerSteamIdIcon(config, "BuildersHeaven", defaultValue: true); BindServerSteamIdIcon(config, "BalrondRealm", defaultValue: false); BindServerSteamIdIcon(config, "AuroraIII", defaultValue: false); BindServerSteamIdIcon(config, "BlackYmir", defaultValue: true); BindServerSteamIdIcon(config, "TestServer", defaultValue: false); } private void BindServerSteamIdIcon(ConfigFile config, string key, bool defaultValue) { _serverSteamIdIconEntries[key] = config.Bind("ServerSteamIdIcons", key, defaultValue, "Per-server SteamID icon visibility. true = show steamID.png between Join and Copy IP, false = hide for this server."); } private bool ShouldShowSteamIdIcon(FehuServer server) { if (_enableSteamIdIcons == null || !_enableSteamIdIcons.Value || server == null) { return false; } string text = ServerSteamIdConfigKey(server.name); if (!string.IsNullOrEmpty(text) && _serverSteamIdIconEntries.TryGetValue(text, out var value)) { return value.Value; } return false; } private static string ServerSteamIdConfigKey(string serverName) { string text = Regex.Replace(serverName ?? string.Empty, "[^A-Za-z0-9]", string.Empty).ToLowerInvariant(); switch (text) { case "10thworld": case "fehu10thworld": return "10thWorld"; case "adventure": case "fehuadventure": return "Adventure"; case "immersive": case "fehuimmersive": return "Immersive"; case "conquest": case "fehuconquest": return "Conquest"; case "dominion": case "fehudominion": return "Dominion"; case "buildersheaven": case "fortecabuildersheaven": return "BuildersHeaven"; case "balrondrealm": return "BalrondRealm"; case "auroraiii": case "auroraepisodeiii": return "AuroraIII"; case "blackymir": case "fortecaymir": case "fortecaymireuserver": return "BlackYmir"; case "fehukingdomstest": case "testserver": return "TestServer"; default: return text; } } private void BindMiniPanels(ConfigFile config) { _miniEnabled = new ConfigEntry[3]; _miniX = new ConfigEntry[3]; _miniY = new ConfigEntry[3]; _miniWidth = new ConfigEntry[3]; _miniHeight = new ConfigEntry[3]; _miniText = new ConfigEntry[3]; _miniIcons = new ConfigEntry[3]; _miniUrl = new ConfigEntry[3]; MiniPanelSettings[] array = new MiniPanelSettings[3] { new MiniPanelSettings { Enabled = true, X = 20, Y = 5, Width = 460, Height = 80, Text = "Forteca", Icons = "1fehu.png,2fehu.png,3fehu.png,4fehu.png", Url = string.Empty }, new MiniPanelSettings { Enabled = true, X = 20, Y = 995, Width = 460, Height = 80, Text = "Press F7 to close all tabs.", Icons = string.Empty, Url = string.Empty }, new MiniPanelSettings { Enabled = true, X = -20, Y = 995, Width = 460, Height = 80, Text = "BLACK VIKING", Icons = string.Empty, Url = string.Empty } }; for (int i = 0; i < array.Length; i++) { string text = "MiniPanel" + (i + 1); _miniEnabled[i] = config.Bind(text, "Enabled", array[i].Enabled, (ConfigDescription)null); _miniX[i] = config.Bind(text, "X", array[i].X, (ConfigDescription)null); _miniY[i] = config.Bind(text, "Y", array[i].Y, (ConfigDescription)null); _miniWidth[i] = config.Bind(text, "Width", array[i].Width, (ConfigDescription)null); _miniHeight[i] = config.Bind(text, "Height", array[i].Height, (ConfigDescription)null); _miniText[i] = config.Bind(text, "Text", array[i].Text, (ConfigDescription)null); _miniIcons[i] = config.Bind(text, "Icons", array[i].Icons, (ConfigDescription)null); _miniUrl[i] = config.Bind(text, "Url", array[i].Url, (ConfigDescription)null); } } private void BindBottomLegend(ConfigFile config) { _bottomLegendEnabled = config.Bind("BottomLegend", "EnableBottomLegend", true, (ConfigDescription)null); _leftLegendEnabled = config.Bind("BottomLegend", "LeftPanelEnabled", true, (ConfigDescription)null); _rightLegendEnabled = config.Bind("BottomLegend", "RightPanelEnabled", true, (ConfigDescription)null); _bottomLeftLegendX = config.Bind("BottomLegend", "BottomLeftPanelX", 20, (ConfigDescription)null); _bottomLeftLegendY = config.Bind("BottomLegend", "BottomLeftPanelY", -98, (ConfigDescription)null); _bottomRightLegendX = config.Bind("BottomLegend", "BottomRightPanelX", -20, (ConfigDescription)null); _bottomRightLegendY = config.Bind("BottomLegend", "BottomRightPanelY", -98, (ConfigDescription)null); _legendF1Enabled = config.Bind("BottomLegend", "F1Enabled", true, (ConfigDescription)null); _legendF1Label = config.Bind("BottomLegend", "F1Label", "Configs", (ConfigDescription)null); _legendF3Enabled = config.Bind("BottomLegend", "F3Enabled", true, (ConfigDescription)null); _legendF3Label = config.Bind("BottomLegend", "F3Label", "Kingdoms", (ConfigDescription)null); _legendF4Enabled = config.Bind("BottomLegend", "F4Enabled", true, (ConfigDescription)null); _legendF4Label = config.Bind("BottomLegend", "F4Label", "Vault", (ConfigDescription)null); _legendF6Enabled = config.Bind("BottomLegend", "F6Enabled", true, (ConfigDescription)null); _legendF6Label = config.Bind("BottomLegend", "F6Label", "Rumble", (ConfigDescription)null); _legendF7Enabled = config.Bind("BottomLegend", "F7Enabled", true, (ConfigDescription)null); _legendF7Label = config.Bind("BottomLegend", "F7Label", "Landing", (ConfigDescription)null); _legendF8Enabled = config.Bind("BottomLegend", "F8Enabled", true, (ConfigDescription)null); _legendF8Label = config.Bind("BottomLegend", "F8Label", "Arena", (ConfigDescription)null); _legendF9Enabled = config.Bind("BottomLegend", "F9Enabled", true, (ConfigDescription)null); _legendF9Label = config.Bind("BottomLegend", "F9Label", "Rewards", (ConfigDescription)null); _legendF10Enabled = config.Bind("BottomLegend", "F10Enabled", true, (ConfigDescription)null); _legendF10Label = config.Bind("BottomLegend", "F10Label", "Factions", (ConfigDescription)null); _steamIdLegendEnabled = config.Bind("BottomLegend", "SteamIdLegendEnabled", true, (ConfigDescription)null); _steamIdLegendLabel = config.Bind("BottomLegend", "SteamIdLegendLabel", "SteamID Protected Realm", (ConfigDescription)null); } private void BindRealmLegend(ConfigFile config) { _steamIdLegendEnabled = config.Bind("RealmLegend", "ShowSteamIdLegend", true, (ConfigDescription)null); _joinLegendEnabled = config.Bind("RealmLegend", "ShowJoinLegend", true, (ConfigDescription)null); _steamIdLegendLabel = config.Bind("RealmLegend", "SteamIdTitle", "SteamID Protected Realm", (ConfigDescription)null); _steamIdLegendText = config.Bind("RealmLegend", "SteamIdText", "Become a Supporter or Contributor\nto gain access.", (ConfigDescription)null); _joinLegendTitle = config.Bind("RealmLegend", "JoinTitle", "Join a Realm", (ConfigDescription)null); _joinLegendText = config.Bind("RealmLegend", "JoinText", "Click the open gate to join.", (ConfigDescription)null); } private void HandlePanelDrag(string id, ref Rect panel, ConfigEntry xEntry, ConfigEntry yEntry, bool rightAnchored, float logicalWidth, float logicalHeight) { //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Invalid comparison between Unknown and I4 //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_008d: 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_0097: 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_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_017a: Unknown result type (might be due to invalid IL or missing references) //IL_0180: Invalid comparison between Unknown and I4 //IL_019c: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: Invalid comparison between Unknown and I4 if (IsolationI2StaticRuntime || _enablePanelDragging == null || !_enablePanelDragging.Value || xEntry == null || yEntry == null) { return; } Event current = Event.current; bool flag = current.control || Input.GetKey((KeyCode)306) || Input.GetKey((KeyCode)305); if ((int)current.type == 0 && current.button == 0 && flag && ((Rect)(ref panel)).Contains(current.mousePosition)) { _dragPanelId = id; _dragOffset = current.mousePosition - new Vector2(((Rect)(ref panel)).x, ((Rect)(ref panel)).y); current.Use(); } if (_dragPanelId == id && (int)current.type == 3 && flag) { Vector2 val = current.mousePosition - _dragOffset; ((Rect)(ref panel)).x = Mathf.Clamp(val.x, 0f, Mathf.Max(0f, logicalWidth - ((Rect)(ref panel)).width)); ((Rect)(ref panel)).y = Mathf.Clamp(val.y, 0f, Mathf.Max(0f, logicalHeight - ((Rect)(ref panel)).height)); xEntry.Value = (rightAnchored ? Mathf.RoundToInt(((Rect)(ref panel)).x - (logicalWidth - ((Rect)(ref panel)).width)) : Mathf.RoundToInt(((Rect)(ref panel)).x)); yEntry.Value = Mathf.RoundToInt(((Rect)(ref panel)).y); current.Use(); } if (_dragPanelId == id && ((int)current.type == 1 || !flag)) { ((BaseUnityPlugin)Plugin.Instance).Config.Save(); _dragPanelId = null; if ((int)current.type == 1) { current.Use(); } } } private void DrawTextureSafe(Rect rect, Texture texture, string textureName, ScaleMode scaleMode = (ScaleMode)0, bool alphaBlend = false) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) if ((Object)texture == (Object)null) { LogMissingDrawTextureOnce(textureName); } else { GUI.DrawTexture(rect, texture, scaleMode, alphaBlend); } } private void LogMissingDrawTextureOnce(string textureName) { string text = (string.IsNullOrEmpty(textureName) ? "unknown texture" : textureName); if (_missingDrawTextureLog.Add(text)) { Plugin.Log.LogWarning((object)("[FehuLanding] Missing GUI texture: " + text)); } } private unsafe void DrawSocial(Rect panel, SocialPanelSettings settings) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown //IL_0043: 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_0166: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Expected O, but got Unknown //IL_0173: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Expected O, but got Unknown //IL_01b5: Unknown result type (might be due to invalid IL or missing references) //IL_01b6: Unknown result type (might be due to invalid IL or missing references) //IL_01fd: Unknown result type (might be due to invalid IL or missing references) //IL_0203: Invalid comparison between Unknown and I4 //IL_0218: Unknown result type (might be due to invalid IL or missing references) LoadSocialIconsOnce(); DrawTextureSafe(panel, (Texture)_parchment, "_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 = ((_content != null && _content.socialLinks != null) ? _content.socialLinks : new List()); 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); if ((Object)value != (Object)null) { GUI.DrawTexture(val, (Texture)value, (ScaleMode)2, true); string key = "visible:" + socialLink.Icon; string[] array = new string[6] { "[TheFehu] Social icon rendered: ", socialLink.Icon, "\n[TheFehu] Social icon position: ", null, null, null }; Rect val2 = val; array[3] = ((object)(*(Rect*)(&val2))/*cast due to .constrained prefix*/).ToString(); array[4] = "\n[TheFehu] Social icon visible: "; array[5] = socialLink.Icon; LogSocialIcon(key, string.Concat(array)); } if (!string.IsNullOrEmpty(socialLink.Url) && (int)Event.current.type == 1 && Event.current.button == 0 && ((Rect)(ref val)).Contains(Event.current.mousePosition)) { Application.OpenURL(socialLink.Url); Event.current.Use(); } } } private void LoadSocialIconsOnce() { //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Expected O, but got Unknown if (_socialIconsLoaded) { return; } _socialIconsLoaded = true; string path = Path.Combine(Path.GetDirectoryName(typeof(Plugin).Assembly.Location), "Assets", "Social"); List obj = ((_content != null && _content.socialLinks != null) ? (from link in _content.socialLinks where !string.IsNullOrWhiteSpace(link.Icon) select link.Icon.Trim()).Distinct(StringComparer.OrdinalIgnoreCase).ToList() : new List()); int num = 0; foreach (string item in obj) { string text = Path.Combine(path, item); LogSocialIcon("exists:" + item, "[TheFehu] Social icon file exists: " + item + " " + File.Exists(text).ToString().ToLowerInvariant()); try { Texture2D val = LoadIcon(text); if ((Object)val != (Object)null) { _socialIcons[item] = val; num++; LogSocialIcon("loaded:" + text, "[TheFehu] Social icon loaded: " + item); } else { LogSocialIcon("failed:" + item, "[TheFehu] Social icon failed: " + item); } } catch (Exception ex) { LogSocialIcon("failed:" + item, "[TheFehu] Social icon failed: " + item + " " + 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 void InitializeShortcutLegendCaches() { _leftShortcutEnabled = new ConfigEntry[4] { _legendF1Enabled, _legendF3Enabled, _legendF4Enabled, _legendF6Enabled }; _leftShortcutLabels = new ConfigEntry[4] { _legendF1Label, _legendF3Label, _legendF4Label, _legendF6Label }; _rightShortcutEnabled = new ConfigEntry[4] { _legendF7Enabled, _legendF8Enabled, _legendF9Enabled, _legendF10Enabled }; _rightShortcutLabels = new ConfigEntry[4] { _legendF7Label, _legendF8Label, _legendF9Label, _legendF10Label }; } private Texture2D LoadIcon(string path) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Expected O, but got Unknown //IL_005b: Expected O, but got Unknown if (CrashIsolationDiagnosticBuild && !Iso(_isoIconsTexturesSprites)) { LogIsolationWarningOnce("IconsTexturesSpritesBypass", "[Isolation] Production icon/texture load bypassed because IsolationEnableIconsTexturesSprites=false"); return null; } if (!File.Exists(path)) { return null; } try { Texture2D val = new Texture2D(2, 2); ImageConversion.LoadImage(val, File.ReadAllBytes(path)); if (CrashIsolationDiagnosticBuild) { _isolationTexturesCreated++; } return val; } catch { return null; } } private void DrawMiniPanels(float logicalWidth, float logicalHeight) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) if (_miniEnabled == null) { return; } Rect panel = default(Rect); for (int i = 0; i < 3; i++) { if (_miniEnabled[i].Value && _miniVisible[i] && (_bottomLegendEnabled == null || !_bottomLegendEnabled.Value || i <= 0)) { MiniPanelSettings miniPanelSettings = new MiniPanelSettings { Enabled = true, X = _miniX[i].Value, Y = _miniY[i].Value, Width = _miniWidth[i].Value, Height = _miniHeight[i].Value, Text = _miniText[i].Value, Icons = _miniIcons[i].Value, Url = _miniUrl[i].Value }; bool flag = miniPanelSettings.X < 0; ((Rect)(ref panel))..ctor(flag ? (logicalWidth - (float)miniPanelSettings.Width + (float)miniPanelSettings.X) : ((float)miniPanelSettings.X), (float)miniPanelSettings.Y, (float)miniPanelSettings.Width, (float)miniPanelSettings.Height); HandlePanelDrag("MiniPanel" + (i + 1), ref panel, _miniX[i], _miniY[i], flag, logicalWidth, logicalHeight); DrawMiniPanel("MiniPanel" + (i + 1), panel, miniPanelSettings, ref _miniVisible[i]); } } } private string[] GetMiniIcons(MiniPanelSettings mini) { string text = ((mini != null) ? (mini.Icons ?? string.Empty) : string.Empty); if (_miniIconListCache.TryGetValue(text, out var value)) { return value; } if (string.IsNullOrWhiteSpace(text)) { _miniIconListCache[text] = new string[0]; return _miniIconListCache[text]; } List list = new List(4); int num = 0; for (int i = 0; i <= text.Length; i++) { if (i != text.Length && text[i] != ',') { continue; } if (i > num) { string text2 = text.Substring(num, i - num).Trim(); if (text2.Length > 0) { list.Add(text2); } } num = i + 1; } string[] array = list.ToArray(); _miniIconListCache[text] = array; return array; } private void DrawMiniPanel(string id, Rect panel, MiniPanelSettings mini, ref bool visible) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Expected O, but got Unknown //IL_003d: 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_012c: Expected O, but got Unknown //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Expected O, but got Unknown //IL_01b9: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Expected O, but got Unknown //IL_01e1: Unknown result type (might be due to invalid IL or missing references) //IL_01e7: Invalid comparison between Unknown and I4 //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Expected O, but got Unknown //IL_01fc: Unknown result type (might be due to invalid IL or missing references) DrawTextureSafe(panel, (Texture)_parchment, "_parchment", (ScaleMode)0); if (GUI.Button(new Rect(((Rect)(ref panel)).xMax - 28f, ((Rect)(ref panel)).y + 4f, 20f, 20f), "x", _buttonStyle)) { visible = false; Plugin.Log.LogInfo((object)("[TheFehu] Close panel clicked: " + id)); return; } float num = ((Rect)(ref panel)).x + 12f; string[] miniIcons = GetMiniIcons(mini); if (miniIcons.Length != 0) { float num2 = Mathf.Min(46f, ((Rect)(ref panel)).height - 22f); int num3 = Mathf.Min(4, miniIcons.Length); for (int i = 0; i < num3; i++) { Texture2D val = LoadAssetIcon(miniIcons[i]); if ((Object)val != (Object)null) { GUI.DrawTexture(new Rect(num, ((Rect)(ref panel)).y + (((Rect)(ref panel)).height - num2) * 0.5f, num2, num2), (Texture)val, (ScaleMode)2, true); } num += num2 + 8f; } } else { Texture2D val2 = LoadAssetIcon(mini.Icon); if ((Object)val2 != (Object)null) { float num4 = Mathf.Min(48f, ((Rect)(ref panel)).height - 18f); GUI.DrawTexture(new Rect(num, ((Rect)(ref panel)).y + (((Rect)(ref panel)).height - num4) * 0.5f, num4, num4), (Texture)val2, (ScaleMode)2, true); num += num4 + 10f; } } if (!string.IsNullOrEmpty(mini.Text)) { GUI.Label(new Rect(num, ((Rect)(ref panel)).y + 12f, ((Rect)(ref panel)).xMax - num - 28f, ((Rect)(ref panel)).height - 24f), mini.Text, _bodyStyle); } if (!string.IsNullOrEmpty(mini.Url) && (int)Event.current.type == 1 && Event.current.button == 0 && ((Rect)(ref panel)).Contains(Event.current.mousePosition)) { Application.OpenURL(mini.Url); Event.current.Use(); } } private void DrawBottomLegend(float logicalWidth, float logicalHeight) { //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_0173: 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_01be: Unknown result type (might be due to invalid IL or missing references) if (_bottomLegendEnabled != null && _bottomLegendEnabled.Value) { float num = Math.Max(360f, (_newsWidth != null) ? ((float)_newsWidth.Value) : 460f); float num2 = Math.Max(70f, (_socialHeight != null) ? ((float)_socialHeight.Value) : 80f); int num3 = ((_bottomLeftLegendX != null) ? _bottomLeftLegendX.Value : 20); int num4 = ((_bottomLeftLegendY != null) ? _bottomLeftLegendY.Value : (-98)); int num5 = ((_bottomRightLegendX != null) ? _bottomRightLegendX.Value : (-20)); int num6 = ((_bottomRightLegendY != null) ? _bottomRightLegendY.Value : (-98)); Rect panel = default(Rect); ((Rect)(ref panel))..ctor((float)num3, (num4 < 0) ? (logicalHeight + (float)num4) : ((float)num4), num, num2); Rect panel2 = default(Rect); ((Rect)(ref panel2))..ctor(logicalWidth - num + (float)num5, (num6 < 0) ? (logicalHeight + (float)num6) : ((float)num6), num, num2); HandlePanelDrag("BottomLegendLeft", ref panel, _bottomLeftLegendX, _bottomLeftLegendY, rightAnchored: false, logicalWidth, logicalHeight); HandlePanelDrag("BottomLegendRight", ref panel2, _bottomRightLegendX, _bottomRightLegendY, rightAnchored: true, logicalWidth, logicalHeight); if ((_leftLegendEnabled == null || _leftLegendEnabled.Value) && _bottomLeftLegendVisible) { DrawShortcutLegendPanel(panel, LeftShortcutIcons, LeftShortcutDefaults, 4, 1, leftPanel: true); DrawBottomLegendCloseButton(panel, leftPanel: true); DrawThemeSelector(panel); } else if (!_bottomLeftLegendVisible) { _themeSelectorVisible = false; } if ((_rightLegendEnabled == null || _rightLegendEnabled.Value) && _bottomRightLegendVisible) { DrawShortcutLegendPanel(panel2, RightShortcutIcons, RightShortcutDefaults, 4, 2, leftPanel: false); DrawBottomLegendCloseButton(panel2, leftPanel: false); } } } private void DrawBottomLegendCloseButton(Rect panel, bool leftPanel) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) Rect val = new Rect(((Rect)(ref panel)).xMax - 24f, ((Rect)(ref panel)).y + 4f, 20f, 20f); int fontSize = _buttonStyle.fontSize; _buttonStyle.fontSize = 12; if (GUI.Button(val, "X", _buttonStyle)) { if (leftPanel) { _bottomLeftLegendVisible = false; _themeSelectorVisible = false; } else { _bottomRightLegendVisible = false; } } _buttonStyle.fontSize = fontSize; } private void DrawShortcutLegendPanel(Rect panel, string[] icons, string[] labels, int columns, int rows, bool leftPanel) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Expected O, but got Unknown //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected O, but got Unknown //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_02a0: Unknown result type (might be due to invalid IL or missing references) //IL_01aa: Unknown result type (might be due to invalid IL or missing references) //IL_01b9: Unknown result type (might be due to invalid IL or missing references) //IL_01bf: Invalid comparison between Unknown and I4 //IL_021b: Unknown result type (might be due to invalid IL or missing references) //IL_01df: Unknown result type (might be due to invalid IL or missing references) //IL_01ea: Unknown result type (might be due to invalid IL or missing references) //IL_01fc: Unknown result type (might be due to invalid IL or missing references) //IL_020d: Expected O, but got Unknown //IL_020d: Unknown result type (might be due to invalid IL or missing references) //IL_01c3: Unknown result type (might be due to invalid IL or missing references) //IL_01c9: Invalid comparison between Unknown and I4 //IL_0253: Unknown result type (might be due to invalid IL or missing references) //IL_0241: Unknown result type (might be due to invalid IL or missing references) DrawTextureSafe(panel, (Texture)(((Object)_bottomPanel != (Object)null) ? _bottomPanel : _parchment), "_bottomPanel/_parchment", (ScaleMode)0); int fontSize = _bodyStyle.fontSize; bool wordWrap = _bodyStyle.wordWrap; TextAnchor alignment = _bodyStyle.alignment; _bodyStyle.fontSize = ((rows > 1) ? Mathf.Max(9, fontSize - 5) : Mathf.Max(10, fontSize - 4)); _bodyStyle.wordWrap = false; _bodyStyle.alignment = (TextAnchor)4; float num = (leftPanel ? 14f : 10f); float num2 = ((rows > 1) ? 5f : 7f); float num3 = (leftPanel ? 10f : 6f); float num4 = ((rows > 1) ? 2f : 0f); float num5 = (((Rect)(ref panel)).width - num * 2f - num3 * (float)(columns - 1)) / (float)columns; float num6 = (((Rect)(ref panel)).height - num2 * 2f - num4 * (float)(rows - 1)) / (float)rows; float num7 = ((rows > 1) ? Mathf.Min(22f, num6 - 10f) : Mathf.Min(44f, num6 - 8f)); num7 = Mathf.Max(14f, num7); Event current = Event.current; Rect val = default(Rect); for (int i = 0; i < labels.Length && i < icons.Length && i < rows * columns; i++) { int num8 = i % columns; int num9 = i / columns; ((Rect)(ref val))..ctor(((Rect)(ref panel)).x + num + (float)num8 * (num5 + num3), ((Rect)(ref panel)).y + num2 + (float)num9 * (num6 + num4), num5, num6); bool num10 = ((Rect)(ref val)).Contains(current.mousePosition); if (num10 && ((int)current.type == 7 || (int)current.type == 8)) { GUI.color = new Color(1f, 0.74f, 0.28f, 0.18f); DrawTextureSafe(val, (Texture)_buttonStyle.hover.background, "_buttonStyle.hover.background", (ScaleMode)0); GUI.color = Color.white; } if (num10 && (int)current.type == 0 && current.button == 0) { HandleShortcutClick(leftPanel, i); current.Use(); } if (leftPanel) { DrawLeftLandingControlCell(val, labels[i], icons[i]); } else { DrawRightShortcutCell(val, labels[i], icons[i]); } } _bodyStyle.fontSize = fontSize; _bodyStyle.wordWrap = wordWrap; _bodyStyle.alignment = alignment; } private void HandleShortcutClick(bool leftPanel, int index) { if (leftPanel) { switch (index) { case 0: OpenThemeWindow(); break; case 3: ToggleLandingTabs(); break; } } } private void ToggleLandingTabs() { if (_hiddenForSession) { RestoreLandingTabs(); } else { CloseAllLandingTabs(); } } private void RestoreLandingTabs() { _hiddenForSession = false; _topLeftVisible = true; _bottomLeftVisible = true; _topRightVisible = true; _bottomRightVisible = true; _socialVisible = true; _bottomLeftLegendVisible = true; _bottomRightLegendVisible = true; SetAllMiniVisible(visible: true); _themeSelectorVisible = false; } private void CloseAllLandingTabs() { _hiddenForSession = true; _topLeftVisible = false; _bottomLeftVisible = false; _topRightVisible = false; _bottomRightVisible = false; _socialVisible = false; _bottomLeftLegendVisible = false; _bottomRightLegendVisible = false; SetAllMiniVisible(visible: false); _themeSelectorVisible = false; } private void DrawLeftLandingControlCell(Rect cell, string label, string iconName) { //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Expected O, but got Unknown //IL_01a7: Unknown result type (might be due to invalid IL or missing references) //IL_0191: 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_01a3: Expected O, but got Unknown //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Expected O, but got Unknown //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Expected O, but got Unknown //IL_014f: Unknown result type (might be due to invalid IL or missing references) Texture2D val = (string.IsNullOrWhiteSpace(iconName) ? null : LoadStatusIcon(iconName)); bool flag = !string.IsNullOrWhiteSpace(label); float num = (flag ? Mathf.Min(34f, ((Rect)(ref cell)).height - 10f) : Mathf.Min(100f, ((Rect)(ref cell)).width - 8f)); float num2 = (flag ? Mathf.Min(34f, ((Rect)(ref cell)).height - 10f) : Mathf.Min(50f, ((Rect)(ref cell)).height - 8f)); if ((Object)val != (Object)null) { if (flag) { float x = _bodyStyle.CalcSize(new GUIContent(label)).x; float num3 = num + 6f + x; float num4 = ((Rect)(ref cell)).x + Mathf.Max(0f, (((Rect)(ref cell)).width - num3) * 0.5f); Rect val2 = default(Rect); ((Rect)(ref val2))..ctor(num4, ((Rect)(ref cell)).y + (((Rect)(ref cell)).height - num2) * 0.5f, num, num2); GUI.DrawTexture(val2, (Texture)val, (ScaleMode)2, true); GUI.Label(new Rect(((Rect)(ref val2)).xMax + 6f, ((Rect)(ref cell)).y, Mathf.Max(1f, ((Rect)(ref cell)).xMax - ((Rect)(ref val2)).xMax - 6f), ((Rect)(ref cell)).height), label, _bodyStyle); } else { GUI.DrawTexture(new Rect(((Rect)(ref cell)).x + (((Rect)(ref cell)).width - num) * 0.5f, ((Rect)(ref cell)).y + (((Rect)(ref cell)).height - num2) * 0.5f, num, num2), (Texture)val, (ScaleMode)2, true); } } else if (flag) { GUI.Label(cell, label, _bodyStyle); } } private void DrawRightShortcutCell(Rect cell, string label, string iconName) { //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Expected O, but got Unknown //IL_0135: 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) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Expected O, but got Unknown //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Expected O, but got Unknown //IL_00dd: Unknown result type (might be due to invalid IL or missing references) Texture2D val = (string.IsNullOrWhiteSpace(iconName) ? null : LoadStatusIcon(iconName)); bool flag = !string.IsNullOrWhiteSpace(label); float num = (flag ? Mathf.Min(24f, ((Rect)(ref cell)).height - 6f) : Mathf.Min(30f, ((Rect)(ref cell)).height - 6f)); if ((Object)val != (Object)null) { if (flag) { Rect val2 = default(Rect); ((Rect)(ref val2))..ctor(((Rect)(ref cell)).x + 3f, ((Rect)(ref cell)).y + (((Rect)(ref cell)).height - num) * 0.5f, num, num); GUI.DrawTexture(val2, (Texture)val, (ScaleMode)2, true); GUI.Label(new Rect(((Rect)(ref val2)).xMax + 4f, ((Rect)(ref cell)).y, Mathf.Max(1f, ((Rect)(ref cell)).xMax - ((Rect)(ref val2)).xMax - 4f), ((Rect)(ref cell)).height), label, _bodyStyle); } else { GUI.DrawTexture(new Rect(((Rect)(ref cell)).x + (((Rect)(ref cell)).width - num) * 0.5f, ((Rect)(ref cell)).y + (((Rect)(ref cell)).height - num) * 0.5f, num, num), (Texture)val, (ScaleMode)2, true); } } else if (flag) { GUI.Label(cell, label, _bodyStyle); } } private void OpenThemeWindow() { _pendingThemeName = NormalizeThemeName((_themeName != null) ? _themeName.Value : "Classic"); _themeSelectorVisible = true; } private void DrawThemeSelector(Rect anchorPanel) { //IL_0067: 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_007f: Expected O, but got Unknown //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_01c3: Unknown result type (might be due to invalid IL or missing references) //IL_0210: Unknown result type (might be due to invalid IL or missing references) //IL_0257: Unknown result type (might be due to invalid IL or missing references) //IL_0287: 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) if (_themeSelectorVisible) { if (string.IsNullOrWhiteSpace(_pendingThemeName)) { _pendingThemeName = NormalizeThemeName((_themeName != null) ? _themeName.Value : "Classic"); } Rect rect = default(Rect); ((Rect)(ref rect))..ctor(((Rect)(ref anchorPanel)).x + 48f, ((Rect)(ref anchorPanel)).y - 182f, 340f, 172f); DrawTextureSafe(rect, (Texture)_parchment, "_parchment", (ScaleMode)0); int fontSize = _titleStyle.fontSize; TextAnchor alignment = _titleStyle.alignment; int fontSize2 = _bodyStyle.fontSize; bool wordWrap = _bodyStyle.wordWrap; TextAnchor alignment2 = _bodyStyle.alignment; _titleStyle.fontSize = Mathf.Max(16, fontSize - 8); _titleStyle.alignment = (TextAnchor)4; _bodyStyle.fontSize = Mathf.Max(11, fontSize2 - 4); _bodyStyle.wordWrap = false; _bodyStyle.alignment = (TextAnchor)4; GUI.Label(new Rect(((Rect)(ref rect)).x + 10f, ((Rect)(ref rect)).y + 8f, ((Rect)(ref rect)).width - 20f, 26f), "Theme", _titleStyle); float num = 140f; float num2 = 25f; float num3 = ((Rect)(ref rect)).x + 24f; float num4 = ((Rect)(ref rect)).y + 42f; float num5 = 16f; float num6 = 8f; for (int i = 0; i < ActiveThemeNames.Length; i++) { int num7 = i % 2; int num8 = i / 2; ThemeInfo themeInfo = GetThemeInfo(ActiveThemeNames[i]); DrawThemeChoice(new Rect(num3 + (float)num7 * (num + num5), num4 + (float)num8 * (num2 + num6), num, num2), themeInfo.Name, themeInfo.DisplayName); } if (GUI.Button(new Rect(((Rect)(ref rect)).x + 52f, ((Rect)(ref rect)).yMax - 42f, 100f, 30f), "Apply", _buttonStyle)) { ApplyThemeShortcut(_pendingThemeName); } if (GUI.Button(new Rect(((Rect)(ref rect)).xMax - 152f, ((Rect)(ref rect)).yMax - 42f, 100f, 30f), "Cancel", _buttonStyle)) { _themeSelectorVisible = false; } _titleStyle.fontSize = fontSize; _titleStyle.alignment = alignment; _bodyStyle.fontSize = fontSize2; _bodyStyle.wordWrap = wordWrap; _bodyStyle.alignment = alignment2; } } private void DrawThemeChoice(Rect rect, string themeName, string displayName) { //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0077: 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_0099: Expected O, but got Unknown //IL_0099: Unknown result type (might be due to invalid IL or missing references) bool flag = string.Equals(_pendingThemeName, themeName, StringComparison.OrdinalIgnoreCase); bool flag2 = string.Equals(NormalizeThemeName((_themeName != null) ? _themeName.Value : "Classic"), themeName, StringComparison.OrdinalIgnoreCase); if (flag || flag2) { GUI.color = (flag ? new Color(1f, 0.74f, 0.28f, 0.32f) : new Color(0.55f, 0.78f, 1f, 0.18f)); DrawTextureSafe(rect, (Texture)_buttonStyle.hover.background, "_buttonStyle.hover.background", (ScaleMode)0); GUI.color = Color.white; } if (GUI.Button(rect, displayName, _buttonStyle)) { _pendingThemeName = NormalizeThemeName(themeName); } } private void ApplyThemeShortcut(string themeName) { if (_themeName != null) { _themeName.Value = NormalizeThemeName(themeName); ((BaseUnityPlugin)Plugin.Instance).Config.Save(); _loadedThemeName = null; _assetIcons.Clear(); _missingStatusIcons.Clear(); _joinIcon = null; _copyIpIcon = null; _onlineIcon = null; _offlineIcon = null; _checkIcon = null; _steamIdIcon = null; BuildTheme(); } _themeSelectorVisible = false; } private Texture2D LoadAssetIcon(string iconName) { //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Expected O, but got Unknown if (string.IsNullOrWhiteSpace(iconName)) { return null; } if (_assetIcons.TryGetValue(iconName, out var value)) { return value; } string directoryName = Path.GetDirectoryName(typeof(Plugin).Assembly.Location); Texture2D val = LoadIcon(Path.Combine(directoryName, "Assets", "Icons", iconName.Trim())); if ((Object)val == (Object)null) { val = LoadIcon(Path.Combine(directoryName, "Assets", "Icons", "placeholder.png")); } _assetIcons[iconName] = val; return val; } private Texture2D LoadServerIcon(string iconName) { //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Expected O, but got Unknown if (string.IsNullOrWhiteSpace(iconName)) { return null; } string text = iconName.Trim(); string key = "server:" + text; if (_assetIcons.TryGetValue(key, out var value)) { return value; } string directoryName = Path.GetDirectoryName(typeof(Plugin).Assembly.Location); Texture2D val = LoadIcon(Path.Combine(directoryName, "Assets", "UI", "servers", text)); if ((Object)val == (Object)null) { LogSocialIcon("missing-realm-icon:" + text, "[FehuLanding] Missing realm icon: Assets/UI/servers/" + text); } _assetIcons[key] = val; return val; } private Texture2D LoadStatusIcon(string fileName) { //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Expected O, but got Unknown //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Expected O, but got Unknown //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_0189: Expected O, but got Unknown if (string.IsNullOrWhiteSpace(fileName)) { return null; } string text = fileName.Trim(); string text2 = NormalizeThemeName((_themeName != null) ? _themeName.Value : (_loadedThemeName ?? "Classic")); string key = "status:" + text2 + ":" + text; if (_assetIcons.TryGetValue(key, out var value)) { return value; } if (_missingStatusIcons.Contains(text2 + ":" + text)) { return null; } string directoryName = Path.GetDirectoryName(typeof(Plugin).Assembly.Location); Texture2D val = null; if (!string.Equals(text2, "Classic", StringComparison.OrdinalIgnoreCase)) { val = LoadIcon(Path.Combine(directoryName, "Assets", "UI", "Themes", text2, "status", text)); } if ((Object)val == (Object)null) { val = LoadIcon(Path.Combine(directoryName, "Assets", "UI", "Themes", "Classic", "status", text)); } if ((Object)val == (Object)null) { val = LoadIcon(Path.Combine(directoryName, "Assets", "UI", "status", text)); } if ((Object)val == (Object)null) { _assetIcons[key] = null; if (_missingStatusIcons.Add(text2 + ":" + text)) { Plugin.Log.LogWarning((object)("[FehuLanding] Missing status icon: " + text)); } return null; } _assetIcons[key] = val; if (string.Equals(text, "join.png", StringComparison.OrdinalIgnoreCase)) { _joinIcon = val; } else if (string.Equals(text, "copyip.png", StringComparison.OrdinalIgnoreCase)) { _copyIpIcon = val; } else if (string.Equals(text, "online.png", StringComparison.OrdinalIgnoreCase)) { _onlineIcon = val; } else if (string.Equals(text, "offline.png", StringComparison.OrdinalIgnoreCase)) { _offlineIcon = val; } else if (string.Equals(text, "check.png", StringComparison.OrdinalIgnoreCase)) { _checkIcon = val; } else if (string.Equals(text, "steamID.png", StringComparison.OrdinalIgnoreCase)) { _steamIdIcon = val; } return val; } private string ServerStatusText(FehuServer server) { if (!IsValidServer(server)) { return string.Empty; } ServerRuntimeState value; lock (_serverStates) { if (!_serverStates.TryGetValue(ServerEndpoint(server), out value)) { return string.Empty; } } if (_showPlayerCounts != null && !_showPlayerCounts.Value) { return string.Empty; } if (!value.HasResult || !value.Online || value.Players < 0 || value.MaxPlayers <= 0) { return string.Empty; } return value.Players + " / " + value.MaxPlayers; } private bool TryGetServerState(FehuServer server, out ServerRuntimeState state) { state = null; if (!IsValidServer(server)) { return false; } lock (_serverStates) { return _serverStates.TryGetValue(ServerEndpoint(server), out state); } } private void LogCrashDiagnostic(string message) { string text = message ?? string.Empty; int num = text.IndexOf(':'); if (num > 0) { text = text.Substring(0, num); } lock (_lastCrashDiagUtcByKey) { if (_lastCrashDiagUtcByKey.TryGetValue(text, out var value) && (DateTime.UtcNow - value).TotalSeconds < 10.0) { return; } _lastCrashDiagUtcByKey[text] = DateTime.UtcNow; } Plugin.Log.LogInfo((object)("[FehuLanding] Diagnostic: " + message)); } private void BeginServerQueriesIfNeeded() { if (IsolationI1DisableNativeServerPolling) { if (!_isolationI1SuppressionLogged) { Plugin.Log.LogInfo((object)"[FehuLanding] I1 native polling suppression active"); Plugin.Log.LogInfo((object)"[FehuLanding] I1 attempted query cycle suppressed"); _isolationI1SuppressionLogged = true; } _serverQueryQueue.Clear(); _serverQueriesRunning = false; } else if (_enableLiveStatus != null && !_enableLiveStatus.Value) { if (!_liveStatusDisabledLogged) { Plugin.Log.LogInfo((object)"[FehuLanding] Live server status disabled by CFG"); _liveStatusDisabledLogged = true; } CancelAllServerQueries("live status disabled"); } else { if (_content == null || _content.servers == null) { return; } if (_pauseWhenLandingHidden != null && _pauseWhenLandingHidden.Value && _hiddenForSession) { CancelAllServerQueries("landing hidden"); return; } PumpSteamServerQuery(); int num = Mathf.Max(60, (_statusRefreshIntervalSeconds != null) ? _statusRefreshIntervalSeconds.Value : 60); if (_serverQueriesRunning && _serverQueryQueue.Count == 0 && _activeServerQueries.Count == 0) { _serverQueriesRunning = false; } LogCrashDiagnostic("Server query state: running=" + _serverQueriesRunning + " queued=" + _serverQueryQueue.Count + " active=" + _activeServerQueries.Count + " created=" + _queryHandlesCreated + " released=" + _queryHandlesReleased + " stale=" + _queryStaleCallbacks); if (!_serverQueriesRunning && _serverQueryQueue.Count == 0 && _activeServerQueries.Count == 0 && !((DateTime.UtcNow - _lastServerQueryUtc).TotalSeconds < (double)num)) { StartServerQueryCycle(); } } } private void StartServerQueryCycle() { if (_serverQueryQueue.Count > 0 || _activeServerQueries.Count > 0) { LogCrashDiagnostic("Server query cycle skipped: queued=" + _serverQueryQueue.Count + " active=" + _activeServerQueries.Count); return; } LogCrashDiagnostic("Server query cycle started"); if (_content == null || _content.servers == null) { return; } _lastServerQueryUtc = DateTime.UtcNow; _serverQueriesRunning = true; _serverQueryQueue.Clear(); _statusGeneration++; int statusGeneration = _statusGeneration; int num = Mathf.Max(0, (_initialStaggerMilliseconds != null) ? _initialStaggerMilliseconds.Value : 50); int num2 = 0; for (int i = 0; i < _content.servers.Count; i++) { FehuServer fehuServer = _content.servers[i]; if (!IsValidServer(fehuServer)) { continue; } fehuServer.address = NormalizeServerAddress(fehuServer.address); TryGetServerState(fehuServer, out var state); if (state == null || state.State == LiveStatusState.Unknown || (_keepLastKnownStatusWhileChecking != null && !_keepLastKnownStatusWhileChecking.Value)) { SetServerState(fehuServer, new ServerRuntimeState { State = LiveStatusState.Checking, QueryState = LiveQueryState.Checking, Online = false, HasResult = false, ConfirmedOffline = false, Players = -1, MaxPlayers = -1, Ping = -1 }); } else { state.QueryState = LiveQueryState.Checking; SetServerState(fehuServer, state); } if (!ResolveIPv4Both(fehuServer.address, out var hostOrder, out var networkOrder)) { Plugin.Log.LogWarning((object)("[FehuLanding] " + (fehuServer.name ?? "Unnamed") + ": invalid address " + fehuServer.address)); continue; } uint[] ipCandidates = ((hostOrder == networkOrder) ? new uint[1] { hostOrder } : new uint[2] { hostOrder, networkOrder }); int queryPort = ServerQueryPort(fehuServer); ushort[] portCandidates = BuildSteamQueryPorts(fehuServer.port, queryPort, (_queryRetryCount == null) ? 1 : _queryRetryCount.Value); ServerQueryWorkItem item = new ServerQueryWorkItem(fehuServer, ipCandidates, portCandidates) { Generation = statusGeneration, NotBeforeUtc = DateTime.UtcNow.AddMilliseconds(num2 * num) }; _serverQueryQueue.Enqueue(item); if (_debugStatusQueries != null && _debugStatusQueries.Value) { Plugin.Log.LogInfo((object)("[FehuLanding] Query started for server: " + (fehuServer.name ?? "Unnamed") + " " + fehuServer.address + ":" + fehuServer.port + " queryPort:" + queryPort)); } num2++; } PumpSteamServerQuery(); } private void CheckActiveServerQueryTimeout() { if (_activeServerQueries.Count == 0) { return; } int num = Mathf.Max(500, (_queryTimeoutMilliseconds != null) ? _queryTimeoutMilliseconds.Value : 1500); DateTime utcNow = DateTime.UtcNow; ActiveServerQuery activeServerQuery = null; lock (_activeServerQueries) { foreach (ActiveServerQuery value in _activeServerQueries.Values) { if ((utcNow - value.StartedUtc).TotalMilliseconds >= (double)num) { activeServerQuery = value; break; } } } if (activeServerQuery != null) { LogCrashDiagnostic("Query timed out: " + (activeServerQuery.Item.Server.name ?? "Unnamed")); HandleSteamPingFailed(activeServerQuery.CacheKey, activeServerQuery.Generation, "timeout"); } } private static ushort[] BuildSteamQueryPorts(int gamePort, int queryPort, int retryCount) { int num = ((queryPort > 0) ? queryPort : (gamePort + 1)); if (num <= 0 || num > 65535) { return new ushort[0]; } return new ushort[1] { (ushort)num }; } private void PumpSteamServerQuery() { DateTime utcNow = DateTime.UtcNow; while (_serverQueryQueue.Count > 0 && _activeServerQueries.Count == 0) { ServerQueryWorkItem serverQueryWorkItem = _serverQueryQueue.Peek(); if (serverQueryWorkItem.NotBeforeUtc > utcNow) { break; } _serverQueryQueue.Dequeue(); StartSteamQuery(serverQueryWorkItem); } if (_serverQueriesRunning && _serverQueryQueue.Count == 0 && _activeServerQueries.Count == 0) { _serverQueriesRunning = false; LogCrashDiagnostic("Status query cycle completed"); } } private void StartSteamQuery(ServerQueryWorkItem item) { //IL_0065: 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_007b: Expected O, but got Unknown //IL_007b: Expected O, but got Unknown //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Expected O, but got Unknown //IL_007f: 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) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) if (item == null || item.Server == null) { return; } if (!item.TryCurrent(out var ip, out var port)) { FinishServerQuery(item, unknown: false, "no query candidates"); return; } string key = item.CacheKey; CancelServerQuery(key, "replacement"); int generation = item.Generation; ISteamMatchmakingPingResponse val = null; val = new ISteamMatchmakingPingResponse((ServerResponded)delegate(gameserveritem_t data) { HandleSteamPingResponded(key, generation, data); }, (ServerFailedToRespond)delegate { HandleSteamPingFailed(key, generation, "no response"); }); try { HServerQuery val2 = SteamMatchmakingServers.PingServer(ip, port, val); _queryHandlesCreated++; LogCrashDiagnostic("Query handle created: " + (item.Server.name ?? "Unnamed") + " " + item.CacheKey + " queryPort=" + port); if (val2 == HServerQuery.Invalid) { FinishServerQuery(item, unknown: false, "invalid handle"); return; } lock (_activeServerQueries) { _activeServerQueries[key] = new ActiveServerQuery(item, key, generation, val2, val); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[FehuLanding] " + (item.Server.name ?? "Unnamed") + ": query start failed " + ex)); FinishServerQuery(item, unknown: false, "query start exception"); } } private void OnSteamPingResponded(gameserveritem_t data) { } private void HandleSteamPingResponded(string cacheKey, int generation, gameserveritem_t data) { //IL_005d: Unknown result type (might be due to invalid IL or missing references) try { ActiveServerQuery value; lock (_activeServerQueries) { if (!_activeServerQueries.TryGetValue(cacheKey, out value) || value.Generation != generation) { _queryStaleCallbacks++; return; } _activeServerQueries.Remove(cacheKey); } CancelHandle(value.Handle); TryGetServerState(value.Item.Server, out var state); int num = ((state == null) ? 1 : (state.OnlineConfirmations + 1)); int num2 = Math.Max(1, (_onlineConfirmationCycles == null) ? 1 : _onlineConfirmationCycles.Value); bool flag = num >= num2; ServerRuntimeState serverRuntimeState = new ServerRuntimeState { State = (flag ? LiveStatusState.Online : (state?.State ?? LiveStatusState.Checking)), QueryState = LiveQueryState.Idle, Online = flag, HasResult = true, ConfirmedOffline = false, Players = data.m_nPlayers, MaxPlayers = data.m_nMaxPlayers, Ping = data.m_nPing, OnlineConfirmations = num, OfflineFailures = 0 }; SetServerState(value.Item.Server, serverRuntimeState); LogCrashDiagnostic("Query completion success: " + (value.Item.Server.name ?? "Unnamed") + " " + serverRuntimeState.Players + "/" + serverRuntimeState.MaxPlayers + " " + serverRuntimeState.Ping + "ms"); if (flag) { LogStatusTransition(cacheKey, value.Item.Server.name, LiveStatusState.Online, "Online " + serverRuntimeState.Players + "/" + serverRuntimeState.MaxPlayers + " " + serverRuntimeState.Ping + "ms"); } PumpSteamServerQuery(); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[FehuLanding] callback exception: " + ex)); } } private void OnSteamPingFailed() { } private void HandleSteamPingFailed(string cacheKey, int generation, string reason) { //IL_0058: Unknown result type (might be due to invalid IL or missing references) try { ActiveServerQuery value; lock (_activeServerQueries) { if (!_activeServerQueries.TryGetValue(cacheKey, out value) || value.Generation != generation) { _queryStaleCallbacks++; return; } _activeServerQueries.Remove(cacheKey); } CancelHandle(value.Handle); if (value.Item.AdvanceAttempt((_queryRetryCount == null) ? 1 : _queryRetryCount.Value)) { value.Item.NotBeforeUtc = DateTime.UtcNow.AddMilliseconds(Mathf.Max(0, (_retryDelayMilliseconds != null) ? _retryDelayMilliseconds.Value : 250)); _serverQueryQueue.Enqueue(value.Item); PumpSteamServerQuery(); } else { FinishServerQuery(value.Item, unknown: false, reason); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[FehuLanding] failed callback exception: " + ex)); } } private void FinishActiveServerUnknown(string reason) { } private void FinishServerQuery(ServerQueryWorkItem item, bool unknown, string reason) { if (item != null && item.Server != null) { LogCrashDiagnostic("Query completion failed: " + (item.Server.name ?? "Unnamed") + " reason=" + reason); TryGetServerState(item.Server, out var state); int num = ((state == null) ? 1 : (state.OfflineFailures + 1)); int num2 = Math.Max(1, (_offlineConfirmationCycles != null) ? _offlineConfirmationCycles.Value : 2); bool flag = num >= num2; bool flag2 = state != null && (state.State == LiveStatusState.Online || state.State == LiveStatusState.Offline) && !flag && (_keepLastKnownStatusWhileChecking == null || _keepLastKnownStatusWhileChecking.Value); ServerRuntimeState state2 = new ServerRuntimeState { State = (flag2 ? state.State : ((!flag) ? LiveStatusState.Checking : LiveStatusState.Offline)), QueryState = LiveQueryState.Idle, Online = (flag2 && state.Online), HasResult = (flag || (flag2 && state.HasResult)), ConfirmedOffline = flag, Players = (flag2 ? state.Players : (-1)), MaxPlayers = (flag2 ? state.MaxPlayers : (-1)), Ping = (flag2 ? state.Ping : (-1)), OnlineConfirmations = 0, OfflineFailures = num }; SetServerState(item.Server, state2); if (flag) { LogStatusTransition(item.CacheKey, item.Server.name, LiveStatusState.Offline, "Offline"); } PumpSteamServerQuery(); } } private void SetServerState(FehuServer server, ServerRuntimeState state) { if (!IsValidServer(server) || state == null) { return; } lock (_serverStates) { _serverStates[ServerEndpoint(server)] = state; } } private void LogStatusTransition(string key, string serverName, LiveStatusState state, string message) { string key2 = "state:" + key; string text = "[FehuLanding] " + (serverName ?? "Unnamed") + ": " + message; if (_logOnlyStateChanges == null || _logOnlyStateChanges.Value) { lock (_lastQueryFailureLog) { if (_lastQueryFailureLog.TryGetValue(key2, out var value) && value == state.ToString()) { return; } _lastQueryFailureLog[key2] = state.ToString(); } } Plugin.Log.LogInfo((object)text); } private void CancelServerQuery(string cacheKey, string reason) { //IL_0048: Unknown result type (might be due to invalid IL or missing references) ActiveServerQuery value = null; lock (_activeServerQueries) { if (_activeServerQueries.TryGetValue(cacheKey, out value)) { _activeServerQueries.Remove(cacheKey); } } if (value != null) { value.Cancelled = true; CancelHandle(value.Handle); if (_debugStatusQueries != null && _debugStatusQueries.Value) { Plugin.Log.LogInfo((object)("[FehuLanding] Cancel query: " + cacheKey + " " + reason)); } } } private void CancelAllServerQueries(string reason) { //IL_00a5: Unknown result type (might be due to invalid IL or missing references) LogCrashDiagnostic("Status runtime stopped: " + reason); _activeServerQueryCancelScratch.Clear(); lock (_activeServerQueries) { foreach (ActiveServerQuery value in _activeServerQueries.Values) { _activeServerQueryCancelScratch.Add(value); } _activeServerQueries.Clear(); } for (int i = 0; i < _activeServerQueryCancelScratch.Count; i++) { ActiveServerQuery activeServerQuery = _activeServerQueryCancelScratch[i]; activeServerQuery.Cancelled = true; CancelHandle(activeServerQuery.Handle); } int count = _activeServerQueryCancelScratch.Count; _activeServerQueryCancelScratch.Clear(); _serverQueryQueue.Clear(); _serverQueriesRunning = false; if (count > 0 && _debugStatusQueries != null && _debugStatusQueries.Value) { Plugin.Log.LogInfo((object)("[FehuLanding] Cancel all status queries: " + reason + " count=" + count)); } } private void CancelHandle(HServerQuery handle) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) if (handle == HServerQuery.Invalid) { return; } try { SteamMatchmakingServers.CancelServerQuery(handle); _queryHandlesReleased++; } catch (Exception ex) { Plugin.Log.LogWarning((object)("[FehuLanding] query cleanup failed: " + ex.Message)); } } private static bool ResolveIPv4Both(string host, out uint hostOrder, out uint networkOrder) { hostOrder = 0u; networkOrder = 0u; try { IPAddress iPAddress = null; if (IPAddress.TryParse(host, out IPAddress address) && address.AddressFamily == AddressFamily.InterNetwork) { iPAddress = address; } if (iPAddress == null) { IPAddress[] addressList = Dns.GetHostEntry(host).AddressList; foreach (IPAddress iPAddress2 in addressList) { if (iPAddress2.AddressFamily == AddressFamily.InterNetwork) { iPAddress = iPAddress2; break; } } } if (iPAddress == null) { return false; } byte[] addressBytes = iPAddress.GetAddressBytes(); hostOrder = (uint)(addressBytes[0] | (addressBytes[1] << 8) | (addressBytes[2] << 16) | (addressBytes[3] << 24)); networkOrder = (uint)IPAddress.HostToNetworkOrder(BitConverter.ToInt32(addressBytes, 0)); return true; } catch (Exception ex) { Plugin.Log.LogWarning((object)("[FehuLanding] Status Unknown: resolve failed " + host + " " + ex.Message)); return false; } } private void LogQueryOnce(string key, string message, bool warning) { if (key != null && key.StartsWith("render:", StringComparison.OrdinalIgnoreCase) && (_enableLayoutDiagnostics == null || !_enableLayoutDiagnostics.Value)) { return; } lock (_lastQueryFailureLog) { if (_lastQueryFailureLog.TryGetValue(key, out var value) && value == message && _lastLogUtc.TryGetValue(key, out var value2) && (DateTime.UtcNow - value2).TotalSeconds < 10.0) { return; } _lastQueryFailureLog[key] = message; _lastLogUtc[key] = DateTime.UtcNow; } if (warning) { Plugin.Log.LogWarning((object)message); } else { Plugin.Log.LogInfo((object)message); } } [Obsolete("FehuLanding 1.0 uses SteamMatchmakingServers.PingServer for live status.")] private void QueryServer(FehuServer server) { } private static byte[] ReceiveA2SInfo(UdpClient udp) { byte[] array = BuildA2SInfoRequest(null); udp.Send(array, array.Length); IPEndPoint remoteEP = new IPEndPoint(IPAddress.Any, 0); byte[] array2 = udp.Receive(ref remoteEP); if (IsA2SChallenge(array2)) { array = BuildA2SInfoRequest(BitConverter.ToInt32(array2, 5)); udp.Send(array, array.Length); array2 = udp.Receive(ref remoteEP); } return array2; } private static bool IsA2SChallenge(byte[] data) { if (data != null && data.Length >= 9 && data[0] == byte.MaxValue && data[1] == byte.MaxValue && data[2] == byte.MaxValue && data[3] == byte.MaxValue) { return data[4] == 65; } return false; } private static byte[] BuildA2SInfoRequest(int? challenge) { byte[] bytes = Encoding.ASCII.GetBytes("Source Engine Query\0"); byte[] array = new byte[bytes.Length + 5 + (challenge.HasValue ? 4 : 0)]; byte b; array[3] = (b = byte.MaxValue); array[0] = (array[1] = (array[2] = b)); array[4] = 84; Buffer.BlockCopy(bytes, 0, array, 5, bytes.Length); if (challenge.HasValue) { Buffer.BlockCopy(BitConverter.GetBytes(challenge.Value), 0, array, 5 + bytes.Length, 4); } return array; } private static void ParseA2SInfo(byte[] data, ServerRuntimeState state) { if (data != null && data.Length >= 7) { int index = 6; SkipCString(data, ref index); SkipCString(data, ref index); SkipCString(data, ref index); SkipCString(data, ref index); index += 2; if (index < data.Length) { state.Players = data[index++]; } if (index < data.Length) { state.MaxPlayers = data[index++]; } } } private static void SkipCString(byte[] data, ref int index) { while (index < data.Length && data[index] != 0) { index++; } if (index < data.Length) { index++; } } private void DrawNews(Rect panel, string text, ref Vector2 scroll, bool sagaPanel) { //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_0111: 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_0147: 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) //IL_0150: 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_0172: Unknown result type (might be due to invalid IL or missing references) //IL_019b: Unknown result type (might be due to invalid IL or missing references) string text2 = (sagaPanel ? (text ?? string.Empty) : FormatRoadmapDisplayText(text)); float num = (sagaPanel ? 46f : 30f); float num2 = (sagaPanel ? 94f : 86f); float num3 = (sagaPanel ? 124f : 94f); Rect val = default(Rect); ((Rect)(ref val))..ctor(((Rect)(ref panel)).x + num, ((Rect)(ref panel)).y + num2, ((Rect)(ref panel)).width - num * 2f, ((Rect)(ref panel)).height - num3); int fontSize = _bodyStyle.fontSize; TextAnchor alignment = _bodyStyle.alignment; bool wordWrap = _bodyStyle.wordWrap; _bodyStyle.fontSize = (sagaPanel ? Mathf.Max(14, fontSize - 1) : Mathf.Max(13, fontSize - 3)); _bodyStyle.alignment = (TextAnchor)0; _bodyStyle.wordWrap = true; _measureContent.text = text2; float num4 = _bodyStyle.CalcHeight(_measureContent, ((Rect)(ref val)).width); Rect val2 = default(Rect); ((Rect)(ref val2))..ctor(0f, 0f, ((Rect)(ref val)).width, Mathf.Max(((Rect)(ref val)).height, num4 + 4f)); scroll = GUI.BeginScrollView(val, scroll, val2, false, false); GUI.Label(new Rect(0f, 0f, ((Rect)(ref val2)).width, ((Rect)(ref val2)).height), text2, _bodyStyle); GUI.EndScrollView(); _bodyStyle.fontSize = fontSize; _bodyStyle.alignment = alignment; _bodyStyle.wordWrap = wordWrap; } private static string FormatRoadmapDisplayText(string text) { if (string.IsNullOrWhiteSpace(text)) { return string.Empty; } string text2 = text.Replace("\r\n", "\n").Replace('\r', '\n').Trim(); text2 = text2.Replace("\nIN PROGRESS", "\n\nIN PROGRESS"); text2 = text2.Replace("\nNEXT", "\n\nNEXT"); text2 = text2.Replace("\nVISION", "\n\nVISION"); if (text2.StartsWith("COMPLETED", StringComparison.Ordinal)) { text2 = "COMPLETED" + text2.Substring(9); } return text2; } private void RebuildServerGroups() { _fehuRealmServers.Clear(); _otherRealmServers.Clear(); if (_content == null || _content.servers == null) { return; } for (int i = 0; i < _content.servers.Count; i++) { if (i < 5) { _fehuRealmServers.Add(_content.servers[i]); } else { _otherRealmServers.Add(_content.servers[i]); } } } private List ServersFrom(int start, int count) { if (start <= 0 && count == 5) { return _fehuRealmServers; } if (start == 5) { return _otherRealmServers; } return new List(); } private void DrawChronicleBoard(string id, Rect panel, string title, ref Vector2 scroll, ref bool visible) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Expected O, but got Unknown //IL_005e: 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_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Expected O, but got Unknown //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) DrawTextureSafe(panel, (Texture)_parchment, "_parchment", (ScaleMode)0); int fontSize = _titleStyle.fontSize; _titleStyle.fontSize = 24; GUI.Label(new Rect(((Rect)(ref panel)).x + 35f, ((Rect)(ref panel)).y + 31f, ((Rect)(ref panel)).width - 70f, 34f), title, _titleStyle); _titleStyle.fontSize = fontSize; DrawTextureSafe(new Rect(((Rect)(ref panel)).x + 42f, ((Rect)(ref panel)).y + 78f, ((Rect)(ref panel)).width - 84f, 2f), (Texture)_gold, "_gold", (ScaleMode)0); if (GUI.Button(new Rect(((Rect)(ref panel)).xMax - 47f, ((Rect)(ref panel)).y + 28f, 25f, 25f), "X", _buttonStyle)) { visible = false; Plugin.Log.LogInfo((object)("[TheFehu] Close panel clicked: " + id)); } if (_chronicleEntries.Count == 0) { DrawNews(panel, GetSagaChronicleText(), ref scroll, sagaPanel: true); } else { DrawChronicleEntries(panel, ref scroll); } } private void DrawChronicleEntries(Rect panel, ref Vector2 scroll) { //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_007f: 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) //IL_00b8: 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 + 94f, ((Rect)(ref panel)).width - 84f, ((Rect)(ref panel)).height - 124f); float num = CalculateChronicleContentHeight(((Rect)(ref val)).width); Rect val2 = default(Rect); ((Rect)(ref val2))..ctor(0f, 0f, ((Rect)(ref val)).width, Mathf.Max(((Rect)(ref val)).height, num + 6f)); scroll = GUI.BeginScrollView(val, scroll, val2, false, false); float num2 = 0f; for (int i = 0; i < _chronicleEntries.Count; i++) { num2 = DrawChronicleEntry(_chronicleEntries[i], new Rect(0f, num2, ((Rect)(ref val2)).width, ((Rect)(ref val2)).height - num2)); } GUI.EndScrollView(); } private float CalculateChronicleContentHeight(float width) { float num = 0f; for (int i = 0; i < _chronicleEntries.Count; i++) { num += CalculateChronicleEntryHeight(_chronicleEntries[i], width); } return num; } private float CalculateChronicleEntryHeight(SagaFeedEntry entry, float width) { int fontSize = _bodyStyle.fontSize; bool wordWrap = _bodyStyle.wordWrap; int fontSize2 = _serverStyle.fontSize; bool wordWrap2 = _serverStyle.wordWrap; try { _bodyStyle.fontSize = 13; _bodyStyle.wordWrap = true; _serverStyle.fontSize = (IsChroniclePriority(entry, "CRITICAL") ? 17 : 16); _serverStyle.wordWrap = true; _measureContent.text = entry.Title ?? string.Empty; float num = Mathf.Max(21f, _serverStyle.CalcHeight(_measureContent, width)); _measureContent.text = entry.Text ?? string.Empty; float num2 = (string.IsNullOrWhiteSpace(entry.Text) ? 0f : Mathf.Max(18f, _bodyStyle.CalcHeight(_measureContent, width))); return 50f + num + 4f + num2 + 15f; } finally { _bodyStyle.fontSize = fontSize; _bodyStyle.wordWrap = wordWrap; _serverStyle.fontSize = fontSize2; _serverStyle.wordWrap = wordWrap2; } } private float DrawChronicleEntry(SagaFeedEntry entry, Rect rect) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_03ce: Unknown result type (might be due to invalid IL or missing references) //IL_03df: Unknown result type (might be due to invalid IL or missing references) //IL_03eb: Unknown result type (might be due to invalid IL or missing references) //IL_03f7: Unknown result type (might be due to invalid IL or missing references) //IL_041e: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_01b0: Unknown result type (might be due to invalid IL or missing references) //IL_01e3: Unknown result type (might be due to invalid IL or missing references) //IL_021a: Unknown result type (might be due to invalid IL or missing references) //IL_0245: Unknown result type (might be due to invalid IL or missing references) //IL_026a: 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_0349: Unknown result type (might be due to invalid IL or missing references) //IL_0397: Unknown result type (might be due to invalid IL or missing references) //IL_03a2: Unknown result type (might be due to invalid IL or missing references) //IL_03b3: Expected O, but got Unknown float y = ((Rect)(ref rect)).y; Color textColor = _bodyStyle.normal.textColor; Color textColor2 = _serverStyle.normal.textColor; TextAnchor alignment = _bodyStyle.alignment; TextAnchor alignment2 = _serverStyle.alignment; int fontSize = _bodyStyle.fontSize; int fontSize2 = _serverStyle.fontSize; FontStyle fontStyle = _serverStyle.fontStyle; bool wordWrap = _bodyStyle.wordWrap; bool wordWrap2 = _serverStyle.wordWrap; try { _bodyStyle.alignment = (TextAnchor)0; _bodyStyle.wordWrap = true; _bodyStyle.fontSize = 13; _bodyStyle.normal.textColor = new Color(0.17f, 0.08f, 0.035f, 0.92f); _serverStyle.alignment = (TextAnchor)0; _serverStyle.wordWrap = true; _serverStyle.fontSize = (IsChroniclePriority(entry, "CRITICAL") ? 17 : 16); _serverStyle.fontStyle = (FontStyle)1; _serverStyle.normal.textColor = (IsChroniclePriority(entry, "CRITICAL") ? new Color(0.52f, 0.12f, 0.035f, 0.98f) : new Color(0.36f, 0.1f, 0.025f, 0.95f)); string text = ((entry.TimestampUtc == DateTime.MinValue) ? "--:--" : entry.TimestampUtc.ToLocalTime().ToString("HH:mm", CultureInfo.InvariantCulture)); GUI.Label(new Rect(((Rect)(ref rect)).x, y, 50f, 18f), text, _bodyStyle); y += 20f; float x = ((Rect)(ref rect)).x; x = DrawChronicleBadge(new Rect(x, y, ((Rect)(ref rect)).width, 20f), "[" + (entry.RealmDisplayName ?? "Fehu Realms") + "]", new Color(0.35f, 0.18f, 0.07f, 0.72f)); DrawChronicleBadge(new Rect(x + 6f, y, ((Rect)(ref rect)).width - x - 6f, 20f), "[" + NormalizeChronicleCategory(entry.Category) + "]", ChronicleCategoryColor(entry.Category)); y += 28f; _measureContent.text = entry.Title ?? string.Empty; float num = Mathf.Max(21f, _serverStyle.CalcHeight(_measureContent, ((Rect)(ref rect)).width)); GUI.Label(new Rect(((Rect)(ref rect)).x, y, ((Rect)(ref rect)).width, num), entry.Title ?? string.Empty, _serverStyle); y += num + 4f; if (!string.IsNullOrWhiteSpace(entry.Text)) { _measureContent.text = entry.Text; float num2 = Mathf.Max(18f, _bodyStyle.CalcHeight(_measureContent, ((Rect)(ref rect)).width)); GUI.Label(new Rect(((Rect)(ref rect)).x, y, ((Rect)(ref rect)).width, num2), entry.Text, _bodyStyle); y += num2 + 10f; } float num3 = (IsChroniclePriority(entry, "CRITICAL") ? 2f : 1f); DrawTextureSafe(new Rect(((Rect)(ref rect)).x, y, ((Rect)(ref rect)).width, num3), (Texture)_gold, "_gold", (ScaleMode)0); return y + (num3 + 12f); } finally { _bodyStyle.normal.textColor = textColor; _serverStyle.normal.textColor = textColor2; _bodyStyle.alignment = alignment; _serverStyle.alignment = alignment2; _bodyStyle.fontSize = fontSize; _serverStyle.fontSize = fontSize2; _serverStyle.fontStyle = fontStyle; _bodyStyle.wordWrap = wordWrap; _serverStyle.wordWrap = wordWrap2; } } private float DrawChronicleBadge(Rect rect, string text, Color color) { //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) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Expected O, but got Unknown //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) Color color2 = GUI.color; Color textColor = _bodyStyle.normal.textColor; TextAnchor alignment = _bodyStyle.alignment; int fontSize = _bodyStyle.fontSize; bool wordWrap = _bodyStyle.wordWrap; try { _bodyStyle.fontSize = 11; _bodyStyle.alignment = (TextAnchor)4; _bodyStyle.wordWrap = false; _measureContent.text = text ?? string.Empty; float num = Mathf.Min(((Rect)(ref rect)).width, Mathf.Max(42f, _bodyStyle.CalcSize(_measureContent).x + 12f)); Rect val = default(Rect); ((Rect)(ref val))..ctor(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, num, ((Rect)(ref rect)).height); GUI.color = color; DrawTextureSafe(val, (Texture)_fade, "_fade", (ScaleMode)0); GUI.color = color2; _bodyStyle.normal.textColor = new Color(0.08f, 0.035f, 0.015f, 0.96f); GUI.Label(val, text ?? string.Empty, _bodyStyle); return ((Rect)(ref rect)).x + num; } finally { GUI.color = color2; _bodyStyle.normal.textColor = textColor; _bodyStyle.alignment = alignment; _bodyStyle.fontSize = fontSize; _bodyStyle.wordWrap = wordWrap; } } private static Color ChronicleCategoryColor(string category) { //IL_02b2: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_01e2: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_0264: Unknown result type (might be due to invalid IL or missing references) //IL_01fc: Unknown result type (might be due to invalid IL or missing references) //IL_0216: Unknown result type (might be due to invalid IL or missing references) //IL_0230: Unknown result type (might be due to invalid IL or missing references) //IL_0298: Unknown result type (might be due to invalid IL or missing references) //IL_027e: Unknown result type (might be due to invalid IL or missing references) //IL_024a: Unknown result type (might be due to invalid IL or missing references) return (Color)(NormalizeChronicleCategory(category) switch { "WAR" => new Color(0.72f, 0.24f, 0.18f, 0.58f), "TERRITORY" => new Color(0.75f, 0.38f, 0.12f, 0.56f), "KINGDOM" => new Color(0.82f, 0.55f, 0.18f, 0.58f), "CLAN" => new Color(0.78f, 0.67f, 0.24f, 0.56f), "EVENT" => new Color(0.48f, 0.3f, 0.68f, 0.56f), "PLAYER" => new Color(0.25f, 0.66f, 0.72f, 0.55f), "MARKET" => new Color(0.32f, 0.62f, 0.28f, 0.55f), "SERVER" => new Color(0.68f, 0.66f, 0.6f, 0.55f), "ADMIN" => new Color(0.86f, 0.84f, 0.76f, 0.55f), "SYSTEM" => new Color(0.48f, 0.46f, 0.41f, 0.55f), "QUEST" => new Color(0.38f, 0.58f, 0.78f, 0.55f), _ => new Color(0.7f, 0.55f, 0.34f, 0.52f), }); } private static bool IsChroniclePriority(SagaFeedEntry entry, string priority) { if (entry != null) { return string.Equals(NormalizeChroniclePriority(entry.Priority), priority, StringComparison.OrdinalIgnoreCase); } return false; } private void DrawStoryBoard(string id, Rect panel, string title, string text, ref Vector2 scroll, ref bool visible) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Expected O, but got Unknown //IL_005e: 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_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Expected O, but got Unknown //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) DrawTextureSafe(panel, (Texture)_parchment, "_parchment", (ScaleMode)0); int fontSize = _titleStyle.fontSize; _titleStyle.fontSize = 24; GUI.Label(new Rect(((Rect)(ref panel)).x + 35f, ((Rect)(ref panel)).y + 31f, ((Rect)(ref panel)).width - 70f, 34f), title, _titleStyle); _titleStyle.fontSize = fontSize; DrawTextureSafe(new Rect(((Rect)(ref panel)).x + 42f, ((Rect)(ref panel)).y + 78f, ((Rect)(ref panel)).width - 84f, 2f), (Texture)_gold, "_gold", (ScaleMode)0); if (GUI.Button(new Rect(((Rect)(ref panel)).xMax - 47f, ((Rect)(ref panel)).y + 28f, 25f, 25f), "X", _buttonStyle)) { visible = false; Plugin.Log.LogInfo((object)("[TheFehu] Close panel clicked: " + id)); } DrawNews(panel, text, ref scroll, string.Equals(id, "BottomLeft", StringComparison.OrdinalIgnoreCase)); } private void DrawRealmsBoard(string id, Rect panel, string title, List servers, ref bool visible, bool fehuRealm) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Expected O, but got Unknown //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Expected O, but got Unknown //IL_00c3: 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) DrawTextureSafe(panel, (Texture)_parchment, "_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); DrawTextureSafe(new Rect(((Rect)(ref panel)).x + 35f, ((Rect)(ref panel)).y + 67f, ((Rect)(ref panel)).width - 70f, 2f), (Texture)_gold, "_gold", (ScaleMode)0); if (GUI.Button(new Rect(((Rect)(ref panel)).xMax - 42f, ((Rect)(ref panel)).y + 14f, 28f, 28f), "X", _buttonStyle)) { visible = false; Plugin.Log.LogInfo((object)("[TheFehu] Close panel clicked: " + id)); } DrawServers(panel, servers, fehuRealm); if (fehuRealm) { DrawSteamIdRealmLegend(panel); } } private void DrawSteamIdRealmLegend(Rect panel) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) bool flag = _steamIdLegendEnabled == null || _steamIdLegendEnabled.Value; bool flag2 = _joinLegendEnabled == null || _joinLegendEnabled.Value; if (flag || flag2) { Rect val = default(Rect); ((Rect)(ref val))..ctor(((Rect)(ref panel)).x + 26f, ((Rect)(ref panel)).yMax - 91f, ((Rect)(ref panel)).width - 52f, 78f); float num = 12f; float num2 = ((flag && flag2) ? ((((Rect)(ref val)).width - num) * 0.5f) : ((Rect)(ref val)).width); Rect val2 = default(Rect); ((Rect)(ref val2))..ctor(((Rect)(ref val)).x, ((Rect)(ref val)).y, num2, ((Rect)(ref val)).height); Rect val3 = (Rect)((flag && flag2) ? new Rect(((Rect)(ref val)).x + num2 + num, ((Rect)(ref val)).y, num2, ((Rect)(ref val)).height) : val2); if (flag) { DrawRealmLegendEntry(val2, LoadStatusIcon("steamID.png"), (_steamIdLegendLabel != null) ? _steamIdLegendLabel.Value : "SteamID Protected Realm", (_steamIdLegendText != null) ? _steamIdLegendText.Value : "Become a Supporter or Contributor\\nto gain access."); } if (flag2) { DrawRealmLegendEntry(flag ? val3 : val2, LoadStatusIcon("join.png"), (_joinLegendTitle != null) ? _joinLegendTitle.Value : "Join a Realm", (_joinLegendText != null) ? _joinLegendText.Value : "Click the open gate to join."); } } } private void DrawRealmLegendEntry(Rect rect, Texture2D icon, string title, string body) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Expected O, but got Unknown //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_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Expected O, but got Unknown //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) float num = 32f; Rect val = default(Rect); ((Rect)(ref val))..ctor(((Rect)(ref rect)).x, ((Rect)(ref rect)).y + (((Rect)(ref rect)).height - num) * 0.5f, num, num); if ((Object)icon != (Object)null) { GUI.DrawTexture(val, (Texture)icon, (ScaleMode)2, true); } TextAnchor alignment = _bodyStyle.alignment; int fontSize = _bodyStyle.fontSize; float num2 = ((Rect)(ref rect)).x + num + 9f; float num3 = Mathf.Max(20f, ((Rect)(ref rect)).xMax - num2); _bodyStyle.alignment = (TextAnchor)0; _bodyStyle.fontSize = Mathf.Max(12, fontSize - 3); GUI.Label(new Rect(num2, ((Rect)(ref rect)).y + 8f, num3, 20f), title ?? string.Empty, _bodyStyle); _bodyStyle.fontSize = Mathf.Max(11, fontSize - 5); GUI.Label(new Rect(num2, ((Rect)(ref rect)).y + 29f, num3, ((Rect)(ref rect)).height - 29f), NormalizeLegendTextForTitle(title, body), _bodyStyle); _bodyStyle.fontSize = fontSize; _bodyStyle.alignment = alignment; } private string NormalizeLegendTextForTitle(string title, string text) { string text2 = NormalizeLegendText(text); if (!string.IsNullOrEmpty(title) && title.IndexOf("SteamID", StringComparison.OrdinalIgnoreCase) >= 0) { if (text2 == "Become a Supporter or Contributor\nto gain access.") { return "Become a Supporter\nor Contributor\nto gain access."; } if (text2 == "Become a Supporter or Contributor to gain access.") { return "Become a Supporter\nor Contributor\nto gain access."; } } return text2; } private string NormalizeLegendText(string text) { if (!string.IsNullOrEmpty(text)) { return text.Replace("\\n", "\n"); } return string.Empty; } private string[] GetServerDescriptionLines(FehuServer server, bool mainRealm) { if (mainRealm) { return MainRealmDescriptionLines; } string text = ((server != null) ? (server.description ?? string.Empty) : string.Empty); string key = ServerEndpoint(server) + "\u001f" + text; if (_serverDescriptionLinesCache.TryGetValue(key, out var value)) { return value; } if (string.IsNullOrWhiteSpace(text)) { _serverDescriptionLinesCache[key] = new string[0]; return _serverDescriptionLinesCache[key]; } List list = new List(3); int num = 0; for (int i = 0; i <= text.Length; i++) { if (i != text.Length && text[i] != '\n' && text[i] != '\r') { continue; } if (i > num) { string text2 = text.Substring(num, i - num).Trim(); if (text2.Length > 0) { list.Add(text2); } } if (i + 1 < text.Length && text[i] == '\r' && text[i + 1] == '\n') { i++; } num = i + 1; } string[] array = list.ToArray(); _serverDescriptionLinesCache[key] = array; return array; } private void DrawServers(Rect panel, List servers, bool fehuRealm) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0066: 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_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Expected O, but got Unknown //IL_019d: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: 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) //IL_0150: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Expected O, but got Unknown //IL_021e: Unknown result type (might be due to invalid IL or missing references) //IL_0301: Unknown result type (might be due to invalid IL or missing references) //IL_0318: Unknown result type (might be due to invalid IL or missing references) //IL_038d: Unknown result type (might be due to invalid IL or missing references) //IL_0392: Unknown result type (might be due to invalid IL or missing references) //IL_03a4: Unknown result type (might be due to invalid IL or missing references) //IL_03a9: Unknown result type (might be due to invalid IL or missing references) //IL_03bb: Unknown result type (might be due to invalid IL or missing references) //IL_03c0: Unknown result type (might be due to invalid IL or missing references) //IL_03c3: Unknown result type (might be due to invalid IL or missing references) //IL_03dc: Unknown result type (might be due to invalid IL or missing references) //IL_03e7: Expected O, but got Unknown //IL_02b1: Unknown result type (might be due to invalid IL or missing references) //IL_03f4: Unknown result type (might be due to invalid IL or missing references) //IL_03ea: 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_044a: Unknown result type (might be due to invalid IL or missing references) //IL_0455: Unknown result type (might be due to invalid IL or missing references) //IL_0466: Expected O, but got Unknown //IL_0466: Unknown result type (might be due to invalid IL or missing references) if (servers == null) { return; } bool flag = !IsolationI2StaticRuntime && (!CrashIsolationDiagnosticBuild || Iso(_isoLayoutSetup)); if (flag) { RefreshRealmDescriptionAutoFitCacheIfNeeded(panel); } float num = ((Rect)(ref panel)).y + 82f; float num2 = (fehuRealm ? 104f : 44f); Rect row = default(Rect); Rect val = default(Rect); Rect rect = default(Rect); Rect rect2 = default(Rect); Rect val2 = default(Rect); Rect val4 = default(Rect); foreach (FehuServer server in servers) { if (IsValidServer(server)) { bool flag2 = IsMainRealm(server); float num3 = (flag2 ? 90f : 62f); if (num + num3 > ((Rect)(ref panel)).yMax - num2) { break; } row = new Rect(((Rect)(ref panel)).x + 26f, num, ((Rect)(ref panel)).width - 52f, num3); float num4 = (flag2 ? 58f : (fehuRealm ? 36f : 27f)); Texture2D val3 = LoadServerIcon(server.icon); val = new Rect(((Rect)(ref row)).x, ((Rect)(ref row)).y + (((Rect)(ref row)).height - num4) * 0.5f, num4, num4); if ((Object)val3 != (Object)null) { GUI.DrawTexture(val, (Texture)val3, (ScaleMode)2, true); } float num5 = ((Rect)(ref row)).x + num4 + 12f; float num6 = ((Rect)(ref row)).xMax - 176f; int fontSize = _serverStyle.fontSize; int fontSize2 = _bodyStyle.fontSize; TextAnchor alignment = _bodyStyle.alignment; bool wordWrap = _bodyStyle.wordWrap; _serverStyle.fontSize = (flag2 ? 18 : 18); int num7 = (flag2 ? 13 : 13); _bodyStyle.fontSize = num7; _bodyStyle.alignment = (TextAnchor)0; _bodyStyle.wordWrap = false; float num8 = Mathf.Max(40f, num6 - num5); GUI.Label(new Rect(num5, ((Rect)(ref row)).y + 2f, num8, 25f), server.name ?? string.Empty, _serverStyle); string[] serverDescriptionLines = GetServerDescriptionLines(server, flag2); float num9 = ((Rect)(ref row)).y + 29f; int num10 = ((!flag2) ? 1 : 3); for (int i = 0; i < serverDescriptionLines.Length && i < num10; i++) { ((Rect)(ref val4))..ctor(num5, num9, Mathf.Max(24f, num8 - 10f), 18f); _bodyStyle.fontSize = (flag ? GetAutoFitRealmDescriptionFontSize(serverDescriptionLines[i], ((Rect)(ref val4)).width, num7, 5) : num7); GUI.Label(val4, serverDescriptionLines[i], _bodyStyle); num9 += 19f; } _serverStyle.fontSize = fontSize; _bodyStyle.fontSize = fontSize2; _bodyStyle.alignment = alignment; _bodyStyle.wordWrap = wordWrap; DrawServerStatusBlock(server, row); Texture2D icon = LoadStatusIcon("copyip.png"); Texture2D icon2 = LoadStatusIcon("join.png"); Texture2D val5 = (ShouldShowSteamIdIcon(server) ? LoadStatusIcon("steamID.png") : null); float num11 = 30f; float num12 = 42f; float num13 = ((Rect)(ref row)).y + (((Rect)(ref row)).height - num11) * 0.5f; rect = new Rect(((Rect)(ref panel)).xMax - 56f, num13, num11, num11); rect2 = new Rect(((Rect)(ref rect)).x - num12, num13, num11, num11); val2 = new Rect(((Rect)(ref rect2)).x - num12, num13, num11, num11); if (DrawIconButton(val2, icon2, "Join")) { OpenJoin(server); } if ((Object)val5 != (Object)null) { DrawStaticIconButton(rect2, val5); } if (DrawIconButton(rect, icon, "IP")) { CopyAddress(server); } GUI.color = new Color(0.55f, 0.24f, 0.06f, 0.55f); DrawTextureSafe(new Rect(((Rect)(ref row)).x, ((Rect)(ref row)).yMax - 2f, ((Rect)(ref row)).width, 1f), (Texture)_ink, "_ink", (ScaleMode)0); GUI.color = Color.white; num += num3; } } } private int GetAutoFitRealmDescriptionFontSize(string text, float availableWidth, int normalFontSize, int minimumFontSize) { //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Expected O, but got Unknown //IL_00f9: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrEmpty(text) || availableWidth <= 1f || _bodyStyle == null) { return normalFontSize; } int num = Mathf.RoundToInt(availableWidth); float num2 = ((_uiScale != null) ? _uiScale.Value : 1f); string key = text + "\u001f" + num + "\u001f" + normalFontSize + "\u001f" + minimumFontSize + "\u001f" + num2.ToString("0.###", CultureInfo.InvariantCulture); if (_realmDescriptionFontSizeCache.TryGetValue(key, out var value)) { return value; } int fontSize = _bodyStyle.fontSize; bool wordWrap = _bodyStyle.wordWrap; try { _bodyStyle.wordWrap = false; GUIContent val = new GUIContent(text); for (int num3 = normalFontSize; num3 >= minimumFontSize; num3--) { _bodyStyle.fontSize = num3; if (_bodyStyle.CalcSize(val).x + 10f <= availableWidth) { _realmDescriptionFontSizeCache[key] = num3; return num3; } } } finally { _bodyStyle.fontSize = fontSize; _bodyStyle.wordWrap = wordWrap; } _realmDescriptionFontSizeCache[key] = minimumFontSize; return minimumFontSize; } private void RefreshRealmDescriptionAutoFitCacheIfNeeded(Rect panel) { int width = Screen.width; int height = Screen.height; int num = Mathf.RoundToInt(((Rect)(ref panel)).width); float num2 = ((_uiScale != null) ? _uiScale.Value : 1f); if (_lastRealmAutoFitScreenWidth != width || _lastRealmAutoFitScreenHeight != height || _lastRealmAutoFitPanelWidth != num || Math.Abs(_lastRealmAutoFitUiScale - num2) > 0.001f) { _realmDescriptionFontSizeCache.Clear(); _lastRealmAutoFitScreenWidth = width; _lastRealmAutoFitScreenHeight = height; _lastRealmAutoFitPanelWidth = num; _lastRealmAutoFitUiScale = num2; } } private static bool IsMainRealm(FehuServer server) { if (server != null) { return string.Equals((server.name ?? string.Empty).Trim(), "10th World", StringComparison.OrdinalIgnoreCase); } return false; } private void DrawServerStatusBlock(FehuServer server, Rect row) { //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Expected O, but got Unknown //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Expected O, but got Unknown //IL_0116: Unknown result type (might be due to invalid IL or missing references) TryGetServerState(server, out var state); Texture2D val; string text; if (state != null && state.State == LiveStatusState.Online && state.Online) { val = LoadStatusIcon("online.png"); text = ServerStatusText(server); } else if (state != null && state.State == LiveStatusState.Offline) { val = LoadStatusIcon("offline.png"); text = "--"; } else { val = LoadStatusIcon("check.png"); text = "..."; } float num = ((Rect)(ref row)).xMax - 188f; float num2 = 29f; Rect val2 = default(Rect); ((Rect)(ref val2))..ctor(num + 21f, ((Rect)(ref row)).y + 4f, num2, num2); if ((Object)val != (Object)null) { GUI.DrawTexture(val2, (Texture)val, (ScaleMode)2, true); } TextAnchor alignment = _bodyStyle.alignment; _bodyStyle.alignment = (TextAnchor)4; GUI.Label(new Rect(num, ((Rect)(ref val2)).yMax - 1f, 72f, 19f), string.IsNullOrWhiteSpace(text) ? "..." : text, _bodyStyle); _bodyStyle.alignment = alignment; } private bool DrawIconButton(Rect rect, Texture2D icon, string fallbackLabel) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: 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_00e6: Expected O, but got Unknown //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Invalid comparison between Unknown and I4 //IL_0073: 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: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Expected O, but got Unknown //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) if ((Object)icon != (Object)null) { Rect val = default(Rect); ((Rect)(ref val))..ctor(((Rect)(ref rect)).x + 2f, ((Rect)(ref rect)).y + 2f, ((Rect)(ref rect)).width - 4f, ((Rect)(ref rect)).height - 4f); if (((Rect)(ref rect)).Contains(Event.current.mousePosition)) { GUI.color = new Color(1f, 0.78f, 0.35f, 0.22f); DrawTextureSafe(new Rect(((Rect)(ref val)).x - 3f, ((Rect)(ref val)).y - 3f, ((Rect)(ref val)).width + 6f, ((Rect)(ref val)).height + 6f), (Texture)_gold, "_gold", (ScaleMode)0); GUI.color = Color.white; } GUI.DrawTexture(val, (Texture)icon, (ScaleMode)2, true); if ((int)Event.current.type == 1 && Event.current.button == 0 && ((Rect)(ref rect)).Contains(Event.current.mousePosition)) { Event.current.Use(); return true; } return false; } return GUI.Button(rect, fallbackLabel, _buttonStyle); } private void DrawStaticIconButton(Rect rect, Texture2D icon) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Expected O, but got Unknown //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Expected O, but got Unknown //IL_00d6: Unknown result type (might be due to invalid IL or missing references) if (!((Object)icon == (Object)null)) { Rect val = default(Rect); ((Rect)(ref val))..ctor(((Rect)(ref rect)).x + 2f, ((Rect)(ref rect)).y + 2f, ((Rect)(ref rect)).width - 4f, ((Rect)(ref rect)).height - 4f); if (((Rect)(ref rect)).Contains(Event.current.mousePosition)) { GUI.color = new Color(1f, 0.78f, 0.35f, 0.22f); DrawTextureSafe(new Rect(((Rect)(ref val)).x - 3f, ((Rect)(ref val)).y - 3f, ((Rect)(ref val)).width + 6f, ((Rect)(ref val)).height + 6f), (Texture)_gold, "_gold", (ScaleMode)0); GUI.color = Color.white; } GUI.DrawTexture(val, (Texture)icon, (ScaleMode)2, true); } } 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 void OpenJoin(FehuServer server) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown //IL_007f: 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_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) if (!IsValidServer(server)) { return; } string text = ServerEndpoint(server); try { if ((Object)FejdStartup.instance == (Object)null) { Plugin.Log.LogWarning((object)("[FehuLanding] Join failed, FejdStartup.instance is null: " + text)); return; } if (!TryGetSelectedProfile(out var profile)) { Plugin.Log.LogWarning((object)"[FehuLanding] Join blocked: no selected player profile"); OpenCharacterSelectionSafe(); return; } Plugin.Log.LogInfo((object)("[FehuLanding] Join allowed with profile: " + SafeProfileName(profile))); Game.SetProfile(profile.GetFilename(), profile.m_fileSource); FehuPasswordPatch.CurrentPassword = server.password ?? string.Empty; ServerJoinData serverToJoin = BuildDedicatedJoinData(server); FejdStartup.instance.SetServerToJoin(serverToJoin); Plugin.Log.LogInfo((object)("[FehuLanding] Native join selected server endpoint: " + text)); FejdStartup.instance.OnJoinStart(); } catch (Exception ex) { Plugin.Log.LogError((object)("[FehuLanding] Native join failed for " + text + ": " + ex)); } } private static bool TryGetSelectedProfile(out PlayerProfile profile) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Expected O, but got Unknown profile = null; FejdStartup instance = FejdStartup.instance; if ((Object)instance == (Object)null) { Plugin.Log.LogWarning((object)"[FehuLanding] Join profile check failed: FejdStartup.instance is null"); return false; } try { FieldInfo fieldInfo = AccessTools.Field(typeof(FejdStartup), "m_profiles"); FieldInfo fieldInfo2 = AccessTools.Field(typeof(FejdStartup), "m_profileIndex"); if (fieldInfo == null || fieldInfo2 == null) { Plugin.Log.LogWarning((object)"[FehuLanding] Join profile check failed: vanilla profile fields unavailable"); return false; } List list = fieldInfo.GetValue(instance) as List; if (list == null) { list = SaveSystem.GetAllPlayerProfiles(); fieldInfo.SetValue(instance, list); } int num = (int)fieldInfo2.GetValue(instance); if (list == null || list.Count == 0 || num < 0 || num >= list.Count) { return false; } profile = list[num]; if (profile == null) { Plugin.Log.LogWarning((object)"[FehuLanding] Join profile check failed: selected profile is null"); return false; } string text = SafeProfileName(profile); string text2 = profile.GetFilename() ?? string.Empty; if (string.IsNullOrWhiteSpace(text) || string.IsNullOrWhiteSpace(text2)) { Plugin.Log.LogWarning((object)"[FehuLanding] Join profile check failed: selected profile has empty name or filename"); profile = null; return false; } if (string.Equals(text, "Developer", StringComparison.OrdinalIgnoreCase) || string.Equals(text, "ODEV", StringComparison.OrdinalIgnoreCase) || string.Equals(text2, "Developer", StringComparison.OrdinalIgnoreCase) || string.Equals(text2, "ODEV", StringComparison.OrdinalIgnoreCase)) { Plugin.Log.LogWarning((object)("[FehuLanding] Join blocked: refused fallback developer profile " + text + " / " + text2)); profile = null; return false; } return true; } catch (Exception ex) { Plugin.Log.LogWarning((object)("[FehuLanding] Join profile check failed: " + ex.Message)); profile = null; return false; } } private static string SafeProfileName(PlayerProfile profile) { if (profile == null) { return string.Empty; } try { return profile.GetName() ?? string.Empty; } catch { return string.Empty; } } private static void OpenCharacterSelectionSafe() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown try { FejdStartup instance = FejdStartup.instance; if (!((Object)instance == (Object)null)) { AccessTools.Method(typeof(FejdStartup), "ShowCharacterSelection", (Type[])null, (Type[])null)?.Invoke(instance, null); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[FehuLanding] Could not open character selection: " + ex.Message)); } } private static ServerJoinData BuildDedicatedJoinData(FehuServer server) { //IL_00d1: 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_00f2: Unknown result type (might be due to invalid IL or missing references) ushort num = checked((ushort)server.port); string text = NormalizeServerAddress(server.address); if (!IPAddress.TryParse(text, out IPAddress address)) { IPAddress[] addressList = Dns.GetHostEntry(text).AddressList; address = addressList.FirstOrDefault((IPAddress a) => a.AddressFamily == AddressFamily.InterNetwork) ?? addressList.FirstOrDefault((IPAddress a) => a.AddressFamily == AddressFamily.InterNetworkV6); } if (address == null) { throw new InvalidOperationException("Could not resolve server address: " + text); } if (address.AddressFamily == AddressFamily.InterNetwork) { address = address.MapToIPv6(); } if (address.AddressFamily != AddressFamily.InterNetworkV6) { throw new InvalidOperationException("Unsupported server address family: " + address.AddressFamily); } SteamNetworkingIPAddr val = default(SteamNetworkingIPAddr); ((SteamNetworkingIPAddr)(ref val)).SetIPv6(address.GetAddressBytes(), num); return new ServerJoinData(new ServerJoinDataDedicated(((SteamNetworkingIPAddr)(ref val)).GetIPv4(), num)); } private static void CopyAddress(FehuServer server) { if (IsValidServer(server)) { string text = (GUIUtility.systemCopyBuffer = ServerEndpoint(server)); Plugin.Log.LogInfo((object)("[FehuLanding] Copied server IP: " + (server.name ?? "Unnamed") + " -> " + text)); } } private static bool IsValidServer(FehuServer server) { if (server != null && !string.IsNullOrWhiteSpace(server.address) && server.port > 0) { return server.port <= 65535; } return false; } private static string NormalizeServerAddress(string address) { object obj; if (!string.Equals((address ?? string.Empty).Trim(), "forteca.net", StringComparison.OrdinalIgnoreCase)) { obj = address; if (obj == null) { return string.Empty; } } else { obj = "play.forteca.net"; } return (string)obj; } private static int ServerQueryPort(FehuServer server) { if (server == null) { return 0; } if (server.queryPort > 0 && server.queryPort <= 65535) { return server.queryPort; } if (server.port <= 0 || server.port >= 65535) { return server.port; } return server.port + 1; } private static string ServerEndpoint(FehuServer server) { return NormalizeServerAddress(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 BlockMerchStoreClickOnce() { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Expected O, but got Unknown //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Expected O, but got Unknown //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Expected O, but got Unknown //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Expected O, but got Unknown //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Expected O, but got Unknown //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_018b: Expected O, but got Unknown if (_merchClickBlockedThisMenu || !IsMainMenu()) { return; } _merchClickBlockedThisMenu = true; try { Transform[] array = Resources.FindObjectsOfTypeAll(); foreach (Transform val in array) { if ((Object)val == (Object)null || (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)val2 == (Object)null) { continue; } PropertyInfo property = ((object)val2).GetType().GetProperty("text"); if (property == null || property.PropertyType != typeof(string) || !property.CanRead || !string.Equals(((property.GetValue(val2, null) as string) ?? string.Empty).Trim(), "MERCH STORE", StringComparison.OrdinalIgnoreCase)) { continue; } Transform val3 = FindSafeMerchContainer(val2.transform); if ((Object)val3 == (Object)null || IsOurObject(val3)) { val3 = val2.transform; } Button[] componentsInChildren = ((Component)val3).GetComponentsInChildren