Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of FehuLanding v420.101.24
BepInEx/plugins/FehuLanding/FehuLanding.dll
Decompiled a day ago
The result has been truncated due to the large size, download it to view full contents!
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.Cache; using System.Net.Sockets; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Serialization; using System.Runtime.Serialization.Json; using System.Runtime.Versioning; using System.Text; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using BepInEx; using BepInEx.Bootstrap; 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("420.101.20.0")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyVersion("420.101.20.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 StatusQueryCallback Callback; public readonly DateTime StartedUtc; public bool Cancelled; public ActiveServerQuery(ServerQueryWorkItem item, string cacheKey, int generation, HServerQuery handle, StatusQueryCallback callback) { //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; Callback = callback; Handler = callback.Handler; StartedUtc = DateTime.UtcNow; } public void DisposeCallback() { Callback?.Dispose(); } } [Serializable] public sealed class FehuContent { public int schemaVersion; public string telemetryUrl; public FehuUiText uiText; public List<FehuShortcutText> shortcuts; 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<SocialLink> socialLinks; public List<FehuServer> servers; public FehuLinks links; public List<MiniPanelSettings> miniPanels; public static FehuContent CreateDefault() { return new FehuContent { schemaVersion = 3, telemetryUrl = "https://www.forteca.net/", uiText = FehuUiText.CreateDefault(), shortcuts = FehuShortcutText.CreateDefaults(), newsTitle = "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<FehuServer> { new FehuServer("Fehu 10th World - MASTER", "play.forteca.net", 2456, string.Empty, string.Empty, "fehu-10th-world") { icon = "1_fehu_10th.png", description = "The Eternal Realm\nKingdoms • Clans • Territory Wars\nOne world. No wipes. Your history remains." }, new FehuServer("Fehu Conquest", "play.forteca.net", 2462, string.Empty, string.Empty, "fehu-conquest") { icon = "2_fehu_conquest.png", description = "Clans & Freeborns Warfare\nDifficulty: Hard" }, new FehuServer("Fehu Dominion", "play.forteca.net", 2464, string.Empty, string.Empty, "fehu-dominion") { icon = "3_fehu_dominion.png", description = "Freeborns & Clans Warfare\nDifficulty: Hard" }, new FehuServer("Fehu Immersive", "play.forteca.net", 2460, string.Empty, string.Empty, "fehu-immersive") { icon = "4_fehu_immersive.png", description = "Very Hard World" }, new FehuServer("Fehu Adventure", "play.forteca.net", 2458, string.Empty, string.Empty, "fehu-adventure") { icon = "5_fehu_adventure.png", queryPort = 2459, steamIdIcon = true, description = "Events and Expeditions" }, new FehuServer("BuildHeim", "play.forteca.net", 2468, string.Empty, string.Empty, "buildheim") { icon = "6_buildheim.png", queryPort = 2469, steamIdIcon = true, description = "Blueprints Valhalla" }, new FehuServer("Blackheim", "play.forteca.net", 2484, string.Empty, string.Empty, "blackheim") { icon = "7_blackheim.png", queryPort = 2485, description = "Black's Vanilla" }, new FehuServer("Warheim", "play.forteca.net", 2478, string.Empty, string.Empty, "warheim") { icon = "8_warheim.png", queryPort = 2479, description = "PvP Only" }, new FehuServer("ValBase", "play.forteca.net", 2482, string.Empty, string.Empty, "valbase") { icon = "9_valbase.png", queryPort = 2483, description = "Pure Vanilla" }, new FehuServer("Test Server", "play.forteca.net", 2480, string.Empty, string.Empty, "forteca-test") { icon = "10_test-server.png", queryPort = 2481, steamIdIcon = true, description = "Development & Testing Realm" } }, links = new FehuLinks { discord = "https://discord.gg/YOURCODE", website = "https://forteca.net", support = "https://forteca.tip4serv.com/", wiki = "https://codex.forteca.net", kingdoms = "https://forteca.net/_cw", rankings = "https://forteca.net/_modix", leaderboard = "https://forteca.net/_cw/rank/" }, ServerIconSize = 28, ServerIconSpacing = 6 }; } } internal static class FehuJson { internal const string DefaultText = "{ \"schemaVersion\": 3 }"; internal static FehuContent Parse(string json) { if (string.IsNullOrWhiteSpace(json)) { return null; } FehuContent fehuContent = FehuContent.CreateDefault(); string json2 = ReadSection(json, "uiText", '{', '}'); FehuUiText fehuUiText = fehuContent.uiText ?? FehuUiText.CreateDefault(); FehuUiText fehuUiText2 = new FehuUiText { fehuRealmsTitle = ReadString(json2, "fehuRealmsTitle", ReadString(json, "realmsTitle", fehuUiText.fehuRealmsTitle)), otherRealmsTitle = ReadString(json2, "otherRealmsTitle", ReadString(json, "otherRealmsTitle", fehuUiText.otherRealmsTitle)), roadmapTitle = ReadString(json2, "roadmapTitle", ReadString(json, "newsTitle", fehuUiText.roadmapTitle)), sagaTitle = ReadString(json2, "sagaTitle", ReadString(json, "sagaTitle", fehuUiText.sagaTitle)), play = ReadString(json2, "play", fehuUiText.play), character = ReadString(json2, "character", fehuUiText.character), settings = ReadString(json2, "settings", fehuUiText.settings), quit = ReadString(json2, "quit", fehuUiText.quit), wiki = ReadString(json2, "wiki", fehuUiText.wiki), support = ReadString(json2, "support", fehuUiText.support), kingdoms = ReadString(json2, "kingdoms", fehuUiText.kingdoms), rankings = ReadString(json2, "rankings", fehuUiText.rankings), playerLog = ReadString(json2, "playerLog", fehuUiText.playerLog), leaderboard = ReadString(json2, "leaderboard", fehuUiText.leaderboard), motto = ReadString(json2, "motto", fehuUiText.motto) }; FehuContent fehuContent2 = new FehuContent { schemaVersion = ReadInt(json, "schemaVersion", 2), telemetryUrl = ReadString(json, "telemetryUrl", fehuContent.telemetryUrl), uiText = fehuUiText2, shortcuts = new List<FehuShortcutText>(), newsTitle = fehuUiText2.roadmapTitle, newsText = ReadString(json, "roadmapText", ReadString(json, "newsText", ReadString(json, "leftText", fehuContent.newsText))), sagaTitle = fehuUiText2.sagaTitle, sagaText = NormalizeSagaText(ReadString(json, "sagaFallbackText", ReadString(json, "sagaText", fehuContent.sagaText))), realmsTitle = fehuUiText2.fehuRealmsTitle, servers = new List<FehuServer>(), links = new FehuLinks(), miniPanels = new List<MiniPanelSettings>(), 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 json3 = ReadSection(json, "SocialPanel", '{', '}'); fehuContent2.socialPanel.Enabled = ReadBool(json3, "Enabled", fehuContent2.socialPanel.Enabled); fehuContent2.socialPanel.X = ReadInt(json3, "X", fehuContent2.socialPanel.X); fehuContent2.socialPanel.Y = ReadInt(json3, "Y", fehuContent2.socialPanel.Y); fehuContent2.socialPanel.Width = ReadInt(json3, "Width", fehuContent2.socialPanel.Width); fehuContent2.socialPanel.Height = ReadInt(json3, "Height", fehuContent2.socialPanel.Height); fehuContent2.socialPanel.IconSize = ReadInt(json3, "IconSize", fehuContent2.socialPanel.IconSize); fehuContent2.socialPanel.IconSpacing = ReadInt(json3, "IconSpacing", fehuContent2.socialPanel.IconSpacing); fehuContent2.socialLinks = new List<SocialLink>(); foreach (Match item in Regex.Matches(ReadSection(json, "socialLinks", '[', ']') ?? ReadSection(json, "SocialLinks", '[', ']') ?? string.Empty, "\\{(?<item>[^{}]*)\\}")) { 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, "shortcuts", '[', ']') ?? string.Empty, "\\{(?<item>[^{}]*)\\}")) { string value2 = item2.Groups["item"].Value; string text = ReadString(value2, "key", string.Empty).Trim().ToUpperInvariant(); if (Regex.IsMatch(text, "^F(?:[1-9]|10)$")) { fehuContent2.shortcuts.Add(new FehuShortcutText { key = text, label = ReadString(value2, "label", string.Empty) }); } } if (fehuContent2.shortcuts.Count == 0) { fehuContent2.shortcuts = FehuShortcutText.CreateDefaults(); } foreach (Match item3 in Regex.Matches(ReadSection(json, "MiniPanels", '[', ']') ?? "", "\\{(?<item>[^{}]*)\\}")) { string value3 = item3.Groups["item"].Value; fehuContent2.miniPanels.Add(new MiniPanelSettings { Enabled = ReadBool(value3, "Enabled", fallback: false), X = ReadInt(value3, "X", 0), Y = ReadInt(value3, "Y", 0), Width = ReadInt(value3, "Width", fehuContent2.socialPanel.Width / 2), Height = ReadInt(value3, "Height", fehuContent2.socialPanel.Height), Icon = ReadString(value3, "Icon", ""), Icons = ReadString(value3, "Icons", ""), Url = ReadString(value3, "Url", ""), Text = ReadString(value3, "Text", "") }); } foreach (Match item4 in Regex.Matches(ReadSection(json, "servers", '[', ']') ?? string.Empty, "\\{(?<server>[^{}]*)\\}")) { string value4 = item4.Groups["server"].Value; if (ReadString(value4, "name", string.Empty).IndexOf("aurora", StringComparison.OrdinalIgnoreCase) < 0 && ReadString(value4, "id", string.Empty).IndexOf("aurora", StringComparison.OrdinalIgnoreCase) < 0) { int num = ReadInt(value4, "port", 2456); fehuContent2.servers.Add(new FehuServer(ReadString(value4, "name", "Unnamed server"), NormalizeJsonServerAddress(ReadString(value4, "address", string.Empty)), num, string.Empty, string.Empty, ReadString(value4, "id", string.Empty)) { queryPort = ReadInt(value4, "queryPort", num + 1), password = ReadString(value4, "password", string.Empty), description = ReadString(value4, "description", string.Empty), icon = ReadString(value4, "icon", string.Empty), steamIdIcon = ReadBool(value4, "steamIdIcon", fallback: false) }); } } if (fehuContent2.servers.Count == 0) { fehuContent2.servers = fehuContent.servers; } string json4 = ReadSection(json, "links", '{', '}'); fehuContent2.links.discord = ReadString(json4, "discord", fehuContent.links.discord); fehuContent2.links.website = ReadString(json4, "website", fehuContent.links.website); fehuContent2.links.support = ReadString(json4, "support", fehuContent.links.support); fehuContent2.links.wiki = ReadString(json4, "wiki", fehuContent.links.wiki); fehuContent2.links.kingdoms = ReadString(json4, "kingdoms", fehuContent.links.kingdoms); fehuContent2.links.rankings = ReadString(json4, "rankings", fehuContent.links.rankings); fehuContent2.links.leaderboard = ReadString(json4, "leaderboard", fehuContent.links.leaderboard); 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*\\\"(?<value>(?:\\\\.|[^\\\"])*)\\\""); 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*(?<value>-?\\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*(?<value>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 string wiki; public string kingdoms; public string rankings; public string leaderboard; } internal sealed class FehuLogger { private readonly ManualLogSource _source; private readonly HashSet<string> _once = new HashSet<string>(StringComparer.Ordinal); private readonly Dictionary<string, DateTime> _lastLogUtc = new Dictionary<string, DateTime>(StringComparer.Ordinal); private readonly object _sync = new object(); internal bool DebugLogging { get; private set; } internal FehuLogger(ManualLogSource source, bool debugLogging) { _source = source ?? throw new ArgumentNullException("source"); DebugLogging = debugLogging; } internal void SetDebugLogging(bool enabled) { DebugLogging = enabled; } internal void LogInfo(object message) { LogDebug(message); } internal void LogDebug(object message) { if (DebugLogging) { _source.LogDebug(message); } } internal void LogInfoOnce(string key, object message) { if (string.IsNullOrEmpty(key)) { key = Convert.ToString(message) ?? string.Empty; } lock (_sync) { if (!_once.Add(key)) { return; } } _source.LogInfo(message); } internal void LogDebugOnce(string key, object message) { if (!DebugLogging) { return; } lock (_sync) { if (!_once.Add("debug:" + key)) { return; } } _source.LogDebug(message); } internal void LogDebugThrottled(string key, object message, TimeSpan interval) { if (!DebugLogging) { return; } DateTime utcNow = DateTime.UtcNow; lock (_sync) { if (_lastLogUtc.TryGetValue(key, out var value) && utcNow - value < interval) { return; } _lastLogUtc[key] = utcNow; } _source.LogDebug(message); } internal void LogStartup(object message) { _source.LogInfo(message); } internal void LogWarning(object message) { _source.LogWarning(message); } internal void LogError(object message) { _source.LogError(message); } } 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 ClassicUiAssets { 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; } [CompilerGenerated] private static class _003C_003EO { public static UnityAction _003C1_003E__OpenSupportUrl; } private sealed class TelemetryReading { internal int? Day; internal string Name; internal string AmpName; internal int Players = -1; internal int MaxPlayers = -1; internal bool Running; internal DateTime ExpiresUtc; } private sealed class WorldDayTarget { internal string Id; internal int Port; internal int Session; internal Stopwatch Clock; internal long RequestStartedMilliseconds; } private sealed class WorldDayResult { internal WorldDayTarget Target; internal TelemetryReading Reading; } [CompilerGenerated] private static class <>O { public static UnityAction <0>__OpenSupportUrl; } private static FehuMenu _activeLandingRoot; private const float ReferenceWidth = 1920f; private const float ReferenceHeight = 1080f; private ConfigEntry<bool> _enabled; private ConfigEntry<bool> _showOnMainMenu; private ConfigEntry<bool> _hideChangelog; private ConfigEntry<bool> _hideMerchStore; private ConfigEntry<bool> _hideVersionText; private ConfigEntry<bool> _hideModdedWarningText; private ConfigEntry<bool> _hideShowLogButton; private ConfigEntry<bool> _newsEnabled; private ConfigEntry<bool> _sagaEnabled; private ConfigEntry<bool> _realmsEnabled; private ConfigEntry<bool> _otherRealmsEnabled; private ConfigEntry<bool> _socialEnabled; private ConfigEntry<bool> _enablePanelDragging; private ConfigEntry<bool> _enableSteamIdIcons; private ConfigEntry<bool> _enableLiveStatus; private ConfigEntry<int> _rightX; private ConfigEntry<int> _rightY; private ConfigEntry<int> _rightWidth; private ConfigEntry<int> _rightHeight; private ConfigEntry<int> _otherX; private ConfigEntry<int> _otherY; private ConfigEntry<int> _otherWidth; private ConfigEntry<int> _otherHeight; private ConfigEntry<int> _newsX; private ConfigEntry<int> _newsY; private ConfigEntry<int> _newsWidth; private ConfigEntry<int> _newsHeight; private ConfigEntry<int> _sagaX; private ConfigEntry<int> _sagaY; private ConfigEntry<int> _sagaWidth; private ConfigEntry<int> _sagaHeight; private ConfigEntry<int> _socialX; private ConfigEntry<int> _socialY; private ConfigEntry<int> _socialWidth; private ConfigEntry<int> _socialHeight; private ConfigEntry<int> _statusRefreshIntervalSeconds; private ConfigEntry<int> _queryTimeoutMilliseconds; private ConfigEntry<int> _queryRetryCount; private ConfigEntry<int> _retryDelayMilliseconds; private ConfigEntry<int> _initialStaggerMilliseconds; private ConfigEntry<int> _offlineConfirmationCycles; private ConfigEntry<int> _onlineConfirmationCycles; private ConfigEntry<string> _newsTitle; private ConfigEntry<string> _sagaTitle; private ConfigEntry<string> _realmsTitle; private ConfigEntry<string> _otherRealmsTitle; private ConfigEntry<float> _uiScale; private Texture2D _bottomPanel; private ConfigEntry<bool> _showPlayerCounts; private ConfigEntry<bool> _pauseWhenLandingHidden; private ConfigEntry<bool> _logOnlyStateChanges; private ConfigEntry<bool> _debugStatusQueries; private ConfigEntry<bool> _enableLayoutDiagnostics; private ConfigEntry<bool> _keepLastKnownStatusWhileChecking; private ConfigEntry<bool> _bottomLegendEnabled; private ConfigEntry<bool> _leftLegendEnabled; private ConfigEntry<bool> _rightLegendEnabled; private ConfigEntry<bool> _legendF1Enabled; private ConfigEntry<bool> _legendF3Enabled; private ConfigEntry<bool> _legendF4Enabled; private ConfigEntry<bool> _legendF6Enabled; private ConfigEntry<bool> _legendF7Enabled; private ConfigEntry<bool> _legendF8Enabled; private ConfigEntry<bool> _legendF9Enabled; private ConfigEntry<bool> _legendF10Enabled; private ConfigEntry<bool> _steamIdLegendEnabled; private ConfigEntry<bool> _joinLegendEnabled; private ConfigEntry<string> _legendF1Label; private ConfigEntry<string> _legendF3Label; private ConfigEntry<string> _legendF4Label; private ConfigEntry<string> _legendF6Label; private ConfigEntry<string> _legendF7Label; private ConfigEntry<string> _legendF8Label; private ConfigEntry<string> _legendF9Label; private ConfigEntry<string> _legendF10Label; private ConfigEntry<string> _steamIdLegendLabel; private ConfigEntry<string> _steamIdLegendText; private ConfigEntry<string> _joinLegendTitle; private ConfigEntry<string> _joinLegendText; private ConfigEntry<int> _socialIconSize; private ConfigEntry<int> _socialIconSpacing; private ConfigEntry<int> _bottomLeftLegendX; private ConfigEntry<int> _bottomLeftLegendY; private ConfigEntry<int> _bottomRightLegendX; private ConfigEntry<int> _bottomRightLegendY; private ConfigEntry<bool>[] _miniEnabled; private ConfigEntry<int>[] _miniX; private ConfigEntry<int>[] _miniY; private ConfigEntry<int>[] _miniWidth; private ConfigEntry<int>[] _miniHeight; private ConfigEntry<string>[] _miniText; private ConfigEntry<string>[] _miniIcons; private ConfigEntry<string>[] _miniUrl; private FehuContent _content; private string _contentPath; private bool _useAnchoredDefaultLayout; private ConfigEntry<int> _layoutVersion; private ConfigEntry<int> _configVersion; private ConfigEntry<bool> _resetLayout; private ConfigEntry<int> _finalLeftOffsetX; private ConfigEntry<int> _finalLeftOffsetY; private ConfigEntry<int> _finalRoadmapOffsetX; private ConfigEntry<int> _finalRoadmapOffsetY; private ConfigEntry<int> _finalSagaOffsetX; private ConfigEntry<int> _finalSagaOffsetY; private ConfigEntry<int> _finalHubOffsetX; private ConfigEntry<int> _finalHubOffsetY; private ConfigEntry<int> _finalBottomBarOffsetX; private ConfigEntry<int> _finalBottomBarOffsetY; 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 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 GUIStyle _closeButtonStyle; private Texture2D _parchment; private Texture2D _ink; private Texture2D _gold; private Texture2D _fade; private Texture2D _joinIcon; private Texture2D _onlineIcon; private Texture2D _offlineIcon; private Texture2D _checkIcon; private Texture2D _steamIdIcon; private readonly HashSet<string> _hiddenLog = new HashSet<string>(); private readonly HashSet<string> _socialIconLog = new HashSet<string>(); private readonly Dictionary<string, Texture2D> _socialIcons = new Dictionary<string, Texture2D>(); private readonly Dictionary<string, Texture2D> _assetIcons = new Dictionary<string, Texture2D>(StringComparer.OrdinalIgnoreCase); private readonly HashSet<string> _missingStatusIcons = new HashSet<string>(StringComparer.OrdinalIgnoreCase); private readonly HashSet<string> _missingDrawTextureLog = new HashSet<string>(StringComparer.OrdinalIgnoreCase); private readonly Dictionary<string, ConfigEntry<bool>> _serverSteamIdIconEntries = new Dictionary<string, ConfigEntry<bool>>(StringComparer.OrdinalIgnoreCase); private readonly Dictionary<string, ServerRuntimeState> _serverStates = new Dictionary<string, ServerRuntimeState>(); private readonly Dictionary<string, string> _lastQueryFailureLog = new Dictionary<string, string>(); private readonly Dictionary<string, DateTime> _lastLogUtc = new Dictionary<string, DateTime>(); private readonly Dictionary<string, int> _realmDescriptionFontSizeCache = new Dictionary<string, int>(StringComparer.Ordinal); private readonly Dictionary<string, string[]> _serverDescriptionLinesCache = new Dictionary<string, string[]>(StringComparer.Ordinal); private readonly Dictionary<string, string[]> _miniIconListCache = new Dictionary<string, string[]>(StringComparer.Ordinal); private readonly List<FehuServer> _fehuRealmServers = new List<FehuServer>(); private readonly List<FehuServer> _otherRealmServers = new List<FehuServer>(); private readonly List<SagaFeedEntry> _chronicleEntries = new List<SagaFeedEntry>(); private readonly float[] _shortcutEntryWidths = new float[8]; private readonly int[] _shortcutEntryIndexes = new int[8]; private readonly GUIContent _measureContent = new GUIContent(); private ConfigEntry<bool>[] _leftShortcutEnabled; private ConfigEntry<string>[] _leftShortcutLabels; private ConfigEntry<bool>[] _rightShortcutEnabled; private ConfigEntry<string>[] _rightShortcutLabels; private static readonly string[] LeftShortcutIcons = new string[4]; private static readonly string[] LeftShortcutDefaults = new string[4] { string.Empty, string.Empty, string.Empty, "Toggle UI" }; private static readonly string[] RightShortcutIcons = new string[8]; private static readonly string[] RightShortcutDefaults = new string[8] { "Configs", "Kingdoms", "Vault", "Rumble", "HERALDRY", "Rewards", "Factions", "Free" }; private static readonly string[] MainRealmDescriptionLines = new string[3] { "The Eternal Realm", "One Save To Rule Them All", "Market • Settlement" }; private int _lastRealmAutoFitScreenWidth; private int _lastRealmAutoFitScreenHeight; private int _lastRealmAutoFitPanelWidth; private float _lastRealmAutoFitUiScale = -1f; private DateTime _lastServerQueryUtc = DateTime.MinValue; private bool _serverQueriesRunning; private readonly Queue<ServerQueryWorkItem> _serverQueryQueue = new Queue<ServerQueryWorkItem>(); private readonly Dictionary<string, ActiveServerQuery> _activeServerQueries = new Dictionary<string, ActiveServerQuery>(StringComparer.OrdinalIgnoreCase); private readonly List<ActiveServerQuery> _activeServerQueryCancelScratch = new List<ActiveServerQuery>(1); private int _statusGeneration; private bool _statusRuntimeAlive = true; 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<bool> _isoUIRoot; private ConfigEntry<bool> _isoMainPanels; private ConfigEntry<bool> _isoBottomPanels; private ConfigEntry<bool> _isoServerPanels; private ConfigEntry<bool> _isoChronicleSaga; private ConfigEntry<bool> _isoSocialShortcutPanels; private ConfigEntry<bool> _isoClassicUiStyles; private ConfigEntry<bool> _isoIconsTexturesSprites; private ConfigEntry<bool> _isoLayoutSetup; private ConfigEntry<bool> _isoSteam; private ConfigEntry<bool> _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<string> _isolationGroupsLogged = new HashSet<string>(StringComparer.Ordinal); private GUIStyle _isolationLabelStyle; private GUIStyle _isolationBoxStyle; private readonly Dictionary<string, DateTime> _lastCrashDiagUtcByKey = new Dictionary<string, DateTime>(); private int _queryHandlesCreated; private int _queryHandlesReleased; private int _queryStaleCallbacks; private Texture2D _supportLogo; private Sprite _supportLogoSprite; private readonly HashSet<string> _replacedMerch = new HashSet<string>(); 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 static readonly FehuUiText DefaultFinalUiText = FehuUiText.CreateDefault(); private static readonly FieldInfo CharacterSelectScreenField = FindFejdField("m_characterSelectScreen"); private static readonly FieldInfo SettingsPopupField = FindFejdField("m_settingsPopup"); private static readonly string[] FinalShortcutKeys = new string[10] { "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10" }; private static readonly string[] FinalActionIcons = new string[4] { "join.png", null, null, null }; private static readonly string[] FinalHubIcons = new string[4] { "hub-codex.png", "hub-support.png", "hub-clanwarfare.png", "hub-modix.png" }; private static readonly Color PrimarySilver = new Color(0.847f, 0.855f, 0.875f, 1f); private static readonly Color BrightSilver = new Color(0.894f, 0.902f, 0.918f, 1f); private static readonly Color SecondarySilver = new Color(0.749f, 0.765f, 0.788f, 1f); private static readonly Color TextShadow = new Color(0.045f, 0.05f, 0.06f, 0.9f); private bool _draggingSagaScrollbar; private float _sagaScrollbarDragOffset; private Texture2D _finalSupportIcon; private Texture2D _finalTileTexture; private Texture2D _finalTitleSeparator; private Texture2D _finalHubTexture; private Texture2D _finalPanelTexture; private GUIStyle _finalButtonStyle; private GUIStyle _finalHubTitleStyle; private Font _finalDisplayFont; private bool _finalFontResolved; private string _nativeMenuAction; private float _nativeActionEarliestRestoreTime; private bool _frontendServerPanelHidden; private static readonly FieldInfo SelectCharacterPanelField = FindFejdField("m_selectCharacterPanel"); private static readonly FieldInfo NewCharacterPanelField = FindFejdField("m_newCharacterPanel"); private static readonly FieldInfo[] FejdSubmenuFields = new FieldInfo[18] { FindFejdField("m_startGamePanel"), FindFejdField("m_selectCharacterPanel"), FindFejdField("m_newCharacterPanel"), FindFejdField("m_characterSelectScreen"), FindFejdField("m_serverListPanel"), FindFejdField("m_createWorldPanel"), FindFejdField("m_worldListPanel"), FindFejdField("m_settingsPopup"), FindFejdField("m_settingsPanel"), FindFejdField("m_creditsPanel"), FindFejdField("m_manageSavesMenu"), FindFejdField("m_addServerPanel"), FindFejdField("m_connectionFailedPanel"), FindFejdField("m_newGameVersionPanel"), FindFejdField("m_playerVersionPanel"), FindFejdField("m_worldVersionPanel"), FindFejdField("m_worldSourceInfoPanel"), FindFejdField("m_ndaPanel") }; private readonly Dictionary<GameObject, Vector3> _mainMenuLogoOriginalScales = new Dictionary<GameObject, Vector3>(); private readonly HashSet<GameObject> _mainMenuLogosHiddenByFehu = new HashSet<GameObject>(); private static readonly FieldInfo NativeFavoritesField = typeof(ServerListGui).GetField("m_favoriteServersList", BindingFlags.Instance | BindingFlags.NonPublic); private static readonly FieldInfo NativeFavoritesDirtyField = typeof(ServerListGui).GetField("m_filteredListOutdated", BindingFlags.Instance | BindingFlags.NonPublic); private bool _nativeFavoritesOpened; private static readonly FieldInfo StartGamePanelField = FindFejdField("m_startGamePanel"); private RectTransform _movedWorldPanel; private Vector2 _originalWorldPanelPosition; private readonly Vector3[] _worldPanelCorners = (Vector3[])(object)new Vector3[4]; private static readonly FieldInfo ConnectingDialogField = FindFejdField("m_connectingDialog"); private static readonly FieldInfo LocalPlayerField = AccessTools.Field(typeof(Player), "m_localPlayer"); private bool _landingVisible; private const int WorldDayTimeoutMilliseconds = 3500; private readonly Dictionary<string, Task<WorldDayResult>> _worldDayRequests = new Dictionary<string, Task<WorldDayResult>>(StringComparer.OrdinalIgnoreCase); private readonly List<HttpWebRequest> _worldDayWebRequests = new List<HttpWebRequest>(); private readonly HashSet<string> _worldDayRendered = new HashSet<string>(StringComparer.OrdinalIgnoreCase); private readonly WorldDayRefreshSchedule _worldDaySchedule = new WorldDayRefreshSchedule(); private Stopwatch _worldDayClock; private int _worldDaySession; private bool _worldDayMenuActive; private bool _worldDayShutdown; private void Awake() { //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Expected O, but got Unknown //IL_01d6: Unknown result type (might be due to invalid IL or missing references) //IL_01e0: Expected O, but got Unknown //IL_0214: Unknown result type (might be due to invalid IL or missing references) //IL_021e: Expected O, but got Unknown //IL_0951: Unknown result type (might be due to invalid IL or missing references) //IL_0960: Expected O, but got Unknown //IL_095b: Unknown result type (might be due to invalid IL or missing references) //IL_096f: Expected O, but got Unknown if (IsolationI3MinimalShell) { if (!_isolationI3LoadedLogged) { Plugin.Log.LogInfo("[I3] Plugin loaded"); Plugin.Log.LogInfo("[I3] Custom UI creation BYPASSED"); Plugin.Log.LogInfo("[I3] Runtime systems DISABLED"); Plugin.Log.LogInfo("[I3] No FehuLanding assets instantiated"); _isolationI3LoadedLogged = true; } return; } ConfigFile runtimeConfig = Plugin.Instance.RuntimeConfig; bool flag = runtimeConfig.ContainsKey(new ConfigDefinition("Layout", "LayoutVersion")); _useAnchoredDefaultLayout = true; _layoutVersion = runtimeConfig.Bind<int>("Layout", "LayoutVersion", 7, "Internal schema version for the final approved mockup layout."); _resetLayout = runtimeConfig.Bind<bool>("Layout", "ResetLayout", false, "Set true once to restore all movable FehuLanding panels to their visible default positions."); _finalLeftOffsetX = runtimeConfig.Bind<int>("Layout", "LeftOffsetX", 0, "Saved horizontal offset for the unified left navigation column."); _finalLeftOffsetY = runtimeConfig.Bind<int>("Layout", "LeftOffsetY", 0, "Saved vertical offset for the unified left navigation column."); _finalRoadmapOffsetX = runtimeConfig.Bind<int>("Layout", "RoadmapOffsetX", 0, "Saved horizontal offset for Roadmap."); _finalRoadmapOffsetY = runtimeConfig.Bind<int>("Layout", "RoadmapOffsetY", 0, "Saved vertical offset for Roadmap."); _finalSagaOffsetX = runtimeConfig.Bind<int>("Layout", "SagaOffsetX", 0, "Saved horizontal offset for Saga Chronicles."); _finalSagaOffsetY = runtimeConfig.Bind<int>("Layout", "SagaOffsetY", 0, "Saved vertical offset for Saga Chronicles."); _finalHubOffsetX = runtimeConfig.Bind<int>("Layout", "HubOffsetX", 0, "Saved horizontal offset for the Forteca community hub."); _finalHubOffsetY = runtimeConfig.Bind<int>("Layout", "HubOffsetY", 0, "Saved vertical offset for the Forteca community hub."); _finalBottomBarOffsetX = runtimeConfig.Bind<int>("Layout", "BottomBarOffsetX", 0, "Saved horizontal offset for the bottom navigation bar."); _finalBottomBarOffsetY = runtimeConfig.Bind<int>("Layout", "BottomBarOffsetY", 0, "Saved vertical offset for the bottom navigation bar."); bool num = runtimeConfig.ContainsKey(new ConfigDefinition("Internal", "ConfigVersion")); _configVersion = runtimeConfig.Bind<int>("Internal", "ConfigVersion", 3, "Internal schema version for FehuLanding configuration migration."); BindCrashIsolation(runtimeConfig); LogCrashIsolationSettings(); runtimeConfig.Remove(new ConfigDefinition("Fehu Social", "Title")); runtimeConfig.Save(); _enabled = BindMigrated(runtimeConfig, "General", "Enabled", defaultValue: true, "Enable the FehuLanding main-menu interface.", "General", "EnableTheFehu"); _showOnMainMenu = runtimeConfig.Bind<bool>("General", "ShowOnMainMenu", true, "Show the boards whenever the main menu opens."); _hideChangelog = BindMigrated(runtimeConfig, "Behavior", "HideVanillaChangelog", defaultValue: true, "Hide Valheim's changelog while FehuLanding is active.", "Vanilla Menu", "HideChangelog"); _hideMerchStore = BindMigrated(runtimeConfig, "Behavior", "HideVanillaMerchStore", defaultValue: true, "Hide Valheim's Merch Store element while FehuLanding is active.", "Vanilla Menu", "HideMerchStore"); _hideVersionText = BindMigrated(runtimeConfig, "Behavior", "HideValheimVersion", defaultValue: true, "Hide the vanilla version label behind the final FehuLanding navigation.", "Vanilla Menu", "HideVersionText"); _hideModdedWarningText = BindMigrated(runtimeConfig, "Behavior", "HideVanillaModdedWarning", defaultValue: true, "Hide the vanilla modded-game information block.", "Vanilla Menu", "HideModdedWarningText"); _hideShowLogButton = BindMigrated(runtimeConfig, "Behavior", "HideShowPlayerLog", defaultValue: true, "Hide Valheim's white Show Player.log proxy; FehuLanding keeps its own Player Log button.", "Vanilla Menu", "HideShowLogButton"); if (!num || _configVersion.Value < 3) { _hideVersionText.Value = true; _hideShowLogButton.Value = true; _configVersion.Value = 3; } _enableLiveStatus = BindMigrated(runtimeConfig, "ServerStatus", "Enabled", defaultValue: true, "Enable native Steam live server status queries.", "ServerStatus", "EnableLiveStatus"); _statusRefreshIntervalSeconds = BindMigrated(runtimeConfig, "ServerStatus", "RefreshSeconds", 60, "Refresh interval while Landing is visible.", "ServerStatus", "RefreshIntervalSeconds"); _queryTimeoutMilliseconds = BindMigrated(runtimeConfig, "ServerStatus", "TimeoutMilliseconds", 1500, "Maximum time for one Steam query attempt.", "ServerStatus", "QueryTimeoutMilliseconds"); _queryRetryCount = runtimeConfig.Bind<int>("ServerStatus", "RetryCount", 1, "Number of additional query-port candidate passes before a server is treated as offline."); _retryDelayMilliseconds = runtimeConfig.Bind<int>("ServerStatus", "RetryDelayMilliseconds", 250, "Short delay before status retry attempts."); _initialStaggerMilliseconds = runtimeConfig.Bind<int>("ServerStatus", "InitialStaggerMilliseconds", 50, "Small delay between starting each server query."); _pauseWhenLandingHidden = runtimeConfig.Bind<bool>("ServerStatus", "PauseWhenLandingHidden", true, "Do not run live polling while Landing is hidden."); _logOnlyStateChanges = runtimeConfig.Bind<bool>("ServerStatus", "LogOnlyStateChanges", true, "Log only live status state changes by default."); _debugStatusQueries = runtimeConfig.Bind<bool>("ServerStatus", "DebugStatusQueries", false, "Detailed query lifecycle diagnostics."); _enableLayoutDiagnostics = runtimeConfig.Bind<bool>("Diagnostics", "EnableLayoutDiagnostics", false, "Enable one-shot/rate-limited layout diagnostics. Disabled by default to prevent render-loop log spam."); _keepLastKnownStatusWhileChecking = runtimeConfig.Bind<bool>("ServerStatus", "KeepLastKnownStatusWhileChecking", true, "Keep green/red status visible while background refresh is checking."); _offlineConfirmationCycles = runtimeConfig.Bind<int>("ServerStatus", "OfflineConfirmationCycles", 2, "Failed query cycles required before showing Offline."); _onlineConfirmationCycles = runtimeConfig.Bind<int>("ServerStatus", "OnlineConfirmationCycles", 1, "Successful query cycles required before showing Online."); _showPlayerCounts = runtimeConfig.Bind<bool>("ServerStatus", "ShowPlayerCounts", true, "Show player counts after successful live status query."); _enableSteamIdIcons = runtimeConfig.Bind<bool>("ServerSteamIdIcons", "EnableSteamIdIcons", true, "Legacy compatibility setting. Realm-card lock icons are controlled only by FehuLanding.json steamIdIcon."); BindServerSteamIdIcons(runtimeConfig); _newsEnabled = BindMigrated(runtimeConfig, "Panels", "ShowRoadmap", defaultValue: true, "Show the Roadmap panel.", "News Board", "Enabled"); _newsX = runtimeConfig.Bind<int>("News Board", "X", -20, (ConfigDescription)null); _newsY = runtimeConfig.Bind<int>("News Board", "Y", 70, (ConfigDescription)null); _newsWidth = runtimeConfig.Bind<int>("News Board", "Width", 460, (ConfigDescription)null); _newsHeight = runtimeConfig.Bind<int>("News Board", "Height", 475, (ConfigDescription)null); _newsTitle = runtimeConfig.Bind<string>("News Board", "Title", "Kingdoms - Roadmap", (ConfigDescription)null); _sagaEnabled = BindMigrated(runtimeConfig, "Panels", "ShowSaga", defaultValue: true, "Show the Saga Chronicles panel.", "Skald Saga Board", "Enabled"); _sagaX = runtimeConfig.Bind<int>("Skald Saga Board", "X", -20, (ConfigDescription)null); _sagaY = runtimeConfig.Bind<int>("Skald Saga Board", "Y", -10, (ConfigDescription)null); _sagaWidth = runtimeConfig.Bind<int>("Skald Saga Board", "Width", 460, (ConfigDescription)null); _sagaHeight = runtimeConfig.Bind<int>("Skald Saga Board", "Height", 500, (ConfigDescription)null); _sagaTitle = runtimeConfig.Bind<string>("Skald Saga Board", "Title", "Saga Chronicles", (ConfigDescription)null); _realmsEnabled = BindMigrated(runtimeConfig, "Panels", "ShowFehuRealms", defaultValue: true, "Show the Fehu Realms panel.", "Realms Board", "Enabled"); _rightX = runtimeConfig.Bind<int>("Realms Board", "X", 20, (ConfigDescription)null); _rightY = runtimeConfig.Bind<int>("Realms Board", "Y", 70, (ConfigDescription)null); _rightWidth = runtimeConfig.Bind<int>("Realms Board", "Width", 460, (ConfigDescription)null); _rightHeight = runtimeConfig.Bind<int>("Realms Board", "Height", 535, (ConfigDescription)null); _realmsTitle = runtimeConfig.Bind<string>("Realms Board", "Title", "Fehu Realms", (ConfigDescription)null); _otherRealmsEnabled = BindMigrated(runtimeConfig, "Panels", "ShowOtherRealms", defaultValue: true, "Show the Other Realms and native action panels.", "Other Realms Board", "Enabled"); _otherX = runtimeConfig.Bind<int>("Other Realms Board", "X", 20, (ConfigDescription)null); _otherY = runtimeConfig.Bind<int>("Other Realms Board", "Y", -10, (ConfigDescription)null); _otherWidth = runtimeConfig.Bind<int>("Other Realms Board", "Width", 460, (ConfigDescription)null); _otherHeight = runtimeConfig.Bind<int>("Other Realms Board", "Height", 440, (ConfigDescription)null); _otherRealmsTitle = runtimeConfig.Bind<string>("Other Realms Board", "Title", "Other Realms", (ConfigDescription)null); _socialEnabled = BindMigrated(runtimeConfig, "Panels", "ShowHub", defaultValue: true, "Show the central Forteca hub.", "SocialPanel", "Enabled"); _socialX = runtimeConfig.Bind<int>("SocialPanel", "X", -20, (ConfigDescription)null); _socialY = runtimeConfig.Bind<int>("SocialPanel", "Y", 10, (ConfigDescription)null); _socialWidth = runtimeConfig.Bind<int>("SocialPanel", "Width", 460, (ConfigDescription)null); _socialHeight = runtimeConfig.Bind<int>("SocialPanel", "Height", 80, (ConfigDescription)null); _socialIconSize = runtimeConfig.Bind<int>("SocialPanel", "SocialIconSize", 42, (ConfigDescription)null); _socialIconSpacing = runtimeConfig.Bind<int>("SocialPanel", "SocialIconSpacing", 8, (ConfigDescription)null); if (!IsolationI4StartupOnly) { Plugin.Log.LogInfo("[TheFehu] SocialPanel config applied X/Y/W/H/IconSize/IconSpacing"); } _enablePanelDragging = runtimeConfig.Bind<bool>("General", "EnablePanelDragging", true, "Hold CTRL and drag FehuLanding panels to save their X/Y position."); BindMiniPanels(runtimeConfig); BindBottomLegend(runtimeConfig); InitializeShortcutLegendCaches(); BindRealmLegend(runtimeConfig); MigrateOrResetLayout(runtimeConfig, (!flag) ? 1 : _layoutVersion.Value); if (_newsTitle.Value == "Announcements") { _newsTitle.Value = "Development Roadmap"; runtimeConfig.Save(); } _uiScale = BindMigrated(runtimeConfig, "Appearance", "UIScale", 1f, new ConfigDescription("Additional UI scale.", (AcceptableValueBase)new AcceptableValueRange<float>(0.5f, 2f), Array.Empty<object>()), "General", "UIScale"); RemoveObsoletePresentationConfig(runtimeConfig); runtimeConfig.Save(); _contentPath = Path.Combine(Plugin.RuntimeDataPath, "FehuLanding.json"); if (IsolationI4StartupOnly && !_isolationI4StartupLogged) { Plugin.Log.LogInfo("[I4] Config initialized"); } LoadContent(); if (IsolationI4StartupOnly && !_isolationI4StartupLogged) { Plugin.Log.LogInfo("[I4] JSON initialized"); } if (IsolationI2StaticRuntime && !_isolationI2StartupLogged) { Plugin.Log.LogInfo("[I2] Static UI initialized"); Plugin.Log.LogInfo("[I2] Background refresh DISABLED"); Plugin.Log.LogInfo("[I2] AutoFit DISABLED"); Plugin.Log.LogInfo("[I2] Runtime layout refresh DISABLED"); _isolationI2StartupLogged = true; } SceneManager.sceneLoaded += OnSceneLoaded; if (IsolationI4StartupOnly && !_isolationI4StartupLogged) { Plugin.Log.LogInfo("[I4] Scene subscription initialized"); Plugin.Log.LogInfo("[I4] Steam systems DISABLED"); Plugin.Log.LogInfo("[I4] UI and assets BYPASSED"); Plugin.Log.LogInfo("[I4] Runtime systems DISABLED"); _isolationI4StartupLogged = true; } } private void OnDestroy() { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Expected O, but got Unknown //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Expected O, but got Unknown RestoreNativeWorldPanelPosition(); if ((Object)(object)_activeLandingRoot == (Object)(object)this) { _activeLandingRoot = null; } RestoreMainMenuLogos(); ShutdownWorldDayTelemetry(); if ((Object)_activeLandingRoot != (Object)null && (Object)(object)_activeLandingRoot != (Object)(object)this) { Plugin.Log.LogWarning("[FehuLanding] Duplicate Landing root suppressed."); Object.Destroy((Object)((Component)this).gameObject); return; } _activeLandingRoot = this; if (IsolationI3MinimalShell) { if (!_isolationI3ShutdownLogged) { Plugin.Log.LogInfo("[I3] shutdown/disable reached"); _isolationI3ShutdownLogged = true; } return; } _statusRuntimeAlive = false; SceneManager.sceneLoaded -= OnSceneLoaded; if (IsolationI4StartupOnly) { if (!_isolationI4ShutdownLogged) { Plugin.Log.LogInfo("[I4] shutdown/disable reached"); _isolationI4ShutdownLogged = true; } return; } if (IsolationI1DisableNativeServerPolling && !_isolationI1ShutdownLogged) { Plugin.Log.LogInfo("[FehuLanding] I1 shutdown/disable reached"); _isolationI1ShutdownLogged = true; } if (IsolationI2StaticRuntime && !_isolationI2ShutdownLogged) { Plugin.Log.LogInfo("[I2] shutdown/disable reached"); _isolationI2ShutdownLogged = true; } if (CrashIsolationDiagnosticBuild) { DestroyIsolationOwnedObjects(); } else { CancelAllServerQueries("destroy"); } } private void BindCrashIsolation(ConfigFile config) { _isoUIRoot = config.Bind<bool>("Crash Isolation", "IsolationEnableUIRoot", false, (ConfigDescription)null); _isoMainPanels = config.Bind<bool>("Crash Isolation", "IsolationEnableMainPanels", false, (ConfigDescription)null); _isoBottomPanels = config.Bind<bool>("Crash Isolation", "IsolationEnableBottomPanels", false, (ConfigDescription)null); _isoServerPanels = config.Bind<bool>("Crash Isolation", "IsolationEnableServerPanels", false, (ConfigDescription)null); _isoChronicleSaga = config.Bind<bool>("Crash Isolation", "IsolationEnableChronicleSaga", false, (ConfigDescription)null); _isoSocialShortcutPanels = config.Bind<bool>("Crash Isolation", "IsolationEnableSocialShortcutPanels", false, (ConfigDescription)null); _isoClassicUiStyles = config.Bind<bool>("Crash Isolation", "IsolationEnableClassicUiStyles", false, (ConfigDescription)null); _isoIconsTexturesSprites = config.Bind<bool>("Crash Isolation", "IsolationEnableIconsTexturesSprites", false, (ConfigDescription)null); _isoLayoutSetup = config.Bind<bool>("Crash Isolation", "IsolationEnableLayoutSetup", false, (ConfigDescription)null); _isoSteam = config.Bind<bool>("Crash Isolation", "IsolationEnableSteam", false, (ConfigDescription)null); _isoRuntimeSystems = config.Bind<bool>("Crash Isolation", "IsolationEnableRuntimeSystems", false, (ConfigDescription)null); } private static bool Iso(ConfigEntry<bool> entry) { return entry?.Value ?? false; } private void LogCrashIsolationSettings() { if (CrashIsolationDiagnosticBuild && !_isolationSettingsLogged) { Plugin.Log.LogInfo("[Isolation] Diagnostic UI build active"); Plugin.Log.LogInfo("[Isolation] UIRoot=" + Iso(_isoUIRoot)); Plugin.Log.LogInfo("[Isolation] MainPanels=" + Iso(_isoMainPanels)); Plugin.Log.LogInfo("[Isolation] BottomPanels=" + Iso(_isoBottomPanels)); Plugin.Log.LogInfo("[Isolation] ServerPanels=" + Iso(_isoServerPanels)); Plugin.Log.LogInfo("[Isolation] ChronicleSaga=" + Iso(_isoChronicleSaga)); Plugin.Log.LogInfo("[Isolation] SocialShortcutPanels=" + Iso(_isoSocialShortcutPanels)); Plugin.Log.LogInfo("[Isolation] ClassicUiStyles=" + Iso(_isoClassicUiStyles)); Plugin.Log.LogInfo("[Isolation] IconsTexturesSprites=" + Iso(_isoIconsTexturesSprites)); Plugin.Log.LogInfo("[Isolation] LayoutSetup=" + Iso(_isoLayoutSetup)); Plugin.Log.LogInfo("[Isolation] Steam=" + Iso(_isoSteam)); Plugin.Log.LogInfo("[Isolation] RuntimeSystems=" + Iso(_isoRuntimeSystems)); _isolationSettingsLogged = true; } } private void BuildIsolationSceneOnce() { if (_isolationSceneBuilt) { if (!_isolationSceneSkipLogged) { Plugin.Log.LogInfo("[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(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("[Isolation] BEGIN " + groupName); } try { action?.Invoke(); flag = true; } catch (Exception ex) { Plugin.Log.LogWarning("[Isolation] " + groupName + " failed: " + ex); } finally { stopwatch.Stop(); if (flag2) { Plugin.Log.LogInfo("[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 (NeedsClassicUiBuild()) { if (!Iso(_isoClassicUiStyles)) { if (Iso(_isoMainPanels) || Iso(_isoBottomPanels) || Iso(_isoServerPanels) || Iso(_isoChronicleSaga) || Iso(_isoSocialShortcutPanels)) { LogIsolationWarningOnce("ClassicUiStylesDependency", "[Isolation] Production visual groups bypassed because IsolationEnableClassicUiStyles=false"); } return; } LogIsolationGroup("ClassicUiStyles", delegate { BuildClassicUi(); }); } 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_009e: 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_009e: 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_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_020e: 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_013b: 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("[Isolation Assets] Texture2D created=" + _isolationTexturesCreated); Plugin.Log.LogInfo("[Isolation Assets] Sprites created=" + _isolationSpritesCreated); Plugin.Log.LogInfo("[Isolation Assets] Fonts resolved=" + _isolationFontsResolved); Plugin.Log.LogInfo("[Isolation Assets] GUIStyles created=" + _isolationGuiStylesCreated); _isolationAssetTotalsLogged = true; } } private void OnSceneLoaded(Scene scene, LoadSceneMode mode) { if (!IsolationI3MinimalShell && !IsolationI4StartupOnly) { RefreshLandingVisibility(); } } 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; } RefreshLandingVisibility(); if (Input.GetKeyDown((KeyCode)291) && (_landingVisible || (IsFrontendServerPanelVisible() && !_frontendServerPanelHidden))) { ExecuteFinalShortcut(9, "keyboard"); if (_hiddenForSession && (_pauseWhenLandingHidden == null || _pauseWhenLandingHidden.Value)) { CancelAllServerQueries("landing hidden"); } } UpdateNativeMenuActionVisibility(); UpdateMainMenuLogoVisibility(); if (DisableAllRuntimeSchedulersIsolation) { if (!_runtimeSchedulersDisabledLogged) { Plugin.Log.LogInfo("[Isolation] Runtime schedulers disabled."); _runtimeSchedulersDisabledLogged = true; } } else if (_landingVisible) { if (IsolationI2StaticRuntime) { if (!_isolationI2RuntimeLogged) { Plugin.Log.LogInfo("[I2] Runtime background refresh suppressed"); _isolationI2RuntimeLogged = true; } return; } UpdateWorldDayTelemetry(); if (_hiddenForSession && (_pauseWhenLandingHidden == null || _pauseWhenLandingHidden.Value)) { CancelAllServerQueries("landing hidden"); } else { BeginServerQueriesIfNeeded(); if (!IsolationI1DisableNativeServerPolling) { CheckActiveServerQueryTimeout(); PumpSteamServerQuery(); } } if (!DisableChronicleRefreshIsolation) { RunChronicleScheduler(); } } else if (IsFrontendServerPanelVisible()) { UpdateWorldDayTelemetry(); BeginServerQueriesIfNeeded(); if (!IsolationI1DisableNativeServerPolling) { CheckActiveServerQueryTimeout(); PumpSteamServerQuery(); } } else if (_serverQueriesRunning || _activeServerQueries.Count > 0) { CancelAllServerQueries("left main menu"); } } private void OnGUI() { //IL_00c2: 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_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) RefreshLandingVisibility(); if (IsolationI3MinimalShell || IsolationI4StartupOnly) { return; } if (CrashIsolationDiagnosticBuild) { DrawCrashIsolationDiagnosticUi(); } else if (_enabled.Value && _showOnMainMenu.Value && ((!_hiddenForSession && _landingVisible) || (IsFrontendServerPanelVisible() && !_frontendServerPanelHidden))) { if (_content == null) { LoadContent(); } if (_titleStyle == null) { BuildClassicUi(); 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 logicalWidth = (float)Screen.width / num; float logicalHeight = (float)Screen.height / num; DrawFinalApprovedLayout(logicalWidth, 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("[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("[FehuLanding] Chronicle refresh completed: " + reason); } private void TryRegisterSagaRpc() { if (_sagaRpcRegistered || ZRoutedRpc.instance == null) { return; } try { ZRoutedRpc.instance.Register<string>("FehuChronicles_Feed", (Action<long, string>)OnSagaFeedRpc); _sagaRpcRegistered = true; Plugin.Log.LogInfo("[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("[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(Plugin.RuntimeDataPath, "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<SagaFeedEntry> 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("[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("[FehuLanding] Saga text loaded: " + num + " lines"); } } } private static string NormalizeChronicleText(string value) { if (string.IsNullOrWhiteSpace(value)) { return value; } List<string> list = new List<string>(); 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<char>()); 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<SagaFeedEntry> list = ParseSagaFeedEntries(json, maxEntries); if (list.Count == 0) { return null; } return BuildSagaPlainText(list); } private static List<SagaFeedEntry> ParseSagaFeedEntries(string json, int maxEntries) { List<SagaFeedEntry> list = new List<SagaFeedEntry>(); if (string.IsNullOrWhiteSpace(json)) { return list; } foreach (Match item in Regex.Matches(json, "\\{(?<entry>[^{}]*(?:\\{[^{}]*\\}[^{}]*)*)\\}")) { 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<SagaFeedEntry> entries) { if (entries == null || entries.Count == 0) { return null; } List<string> list = new List<string>(); 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<char>()); } 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*\\\"(?<v>(?:\\\\.|[^\\\"])*)\\\""); 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, "BuildHeim", defaultValue: true); BindServerSteamIdIcon(config, "Blackheim", defaultValue: true); BindServerSteamIdIcon(config, "Warheim", defaultValue: false); BindServerSteamIdIcon(config, "FortecaTest", defaultValue: true); BindServerSteamIdIcon(config, "Vanilla", defaultValue: false); } private void BindServerSteamIdIcon(ConfigFile config, string key, bool defaultValue) { _serverSteamIdIconEntries[key] = config.Bind<bool>("ServerSteamIdIcons", key, defaultValue, "Legacy compatibility setting. Realm-card lock icons are controlled only by FehuLanding.json steamIdIcon."); } private bool ShouldShowSteamIdIcon(FehuServer server) { return server?.steamIdIcon ?? false; } private static string ServerSteamIdConfigKey(string serverId, string serverName) { string text = Regex.Replace(serverId ?? string.Empty, "[^A-Za-z0-9]", string.Empty).ToLowerInvariant(); if (!string.IsNullOrEmpty(text)) { switch (text) { case "buildheim": return "BuildHeim"; case "blackheim": return "Blackheim"; case "warheim": return "Warheim"; case "fortecatest": return "FortecaTest"; case "vanilla": return "Vanilla"; } } string text2 = Regex.Replace(serverName ?? string.Empty, "[^A-Za-z0-9]", string.Empty).ToLowerInvariant(); switch (text2) { 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 "buildheim": return "BuildHeim"; case "blackheim": return "Blackheim"; case "warheim": return "Warheim"; case "fortecatest": return "FortecaTest"; case "vanilla": return "Vanilla"; default: return text2; } } private void BindMiniPanels(ConfigFile config) { _miniEnabled = new ConfigEntry<bool>[3]; _miniX = new ConfigEntry<int>[3]; _miniY = new ConfigEntry<int>[3]; _miniWidth = new ConfigEntry<int>[3]; _miniHeight = new ConfigEntry<int>[3]; _miniText = new ConfigEntry<string>[3]; _miniIcons = new ConfigEntry<string>[3]; _miniUrl = new ConfigEntry<string>[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 = -98, Width = 460, Height = 80, Text = "Press F7 to close all tabs.", Icons = string.Empty, Url = string.Empty }, new MiniPanelSettings { Enabled = true, X = -20, Y = -98, 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<bool>(text, "Enabled", array[i].Enabled, (ConfigDescription)null); _miniX[i] = config.Bind<int>(text, "X", array[i].X, (ConfigDescription)null); _miniY[i] = config.Bind<int>(text, "Y", array[i].Y, (ConfigDescription)null); _miniWidth[i] = config.Bind<int>(text, "Width", array[i].Width, (ConfigDescription)null); _miniHeight[i] = config.Bind<int>(text, "Height", array[i].Height, (ConfigDescription)null); _miniText[i] = config.Bind<string>(text, "Text", array[i].Text, (ConfigDescription)null); _miniIcons[i] = config.Bind<string>(text, "Icons", array[i].Icons, (ConfigDescription)null); _miniUrl[i] = config.Bind<string>(text, "Url", array[i].Url, (ConfigDescription)null); } } private void BindBottomLegend(ConfigFile config) { _bottomLegendEnabled = config.Bind<bool>("Panels", "ShowBottomBar", true, "Show the Player Log, F1-F10 and Leaderboard bar."); _leftLegendEnabled = config.Bind<bool>("BottomLegend", "LeftPanelEnabled", true, (ConfigDescription)null); _rightLegendEnabled = config.Bind<bool>("BottomLegend", "RightPanelEnabled", true, (ConfigDescription)null); _bottomLeftLegendX = config.Bind<int>("BottomLegend", "BottomLeftPanelX", 20, (ConfigDescription)null); _bottomLeftLegendY = config.Bind<int>("BottomLegend", "BottomLeftPanelY", -98, (ConfigDescription)null); _bottomRightLegendX = config.Bind<int>("BottomLegend", "BottomRightPanelX", -20, (ConfigDescription)null); _bottomRightLegendY = config.Bind<int>("BottomLegend", "BottomRightPanelY", -98, (ConfigDescription)null); _legendF1Enabled = config.Bind<bool>("BottomLegend", "F1Enabled", true, (ConfigDescription)null); _legendF1Label = config.Bind<string>("BottomLegend", "F1Label", "Configs", (ConfigDescription)null); _legendF3Enabled = config.Bind<bool>("BottomLegend", "F3Enabled", true, (ConfigDescription)null); _legendF3Label = config.Bind<string>("BottomLegend", "F3Label", "Clan Warfare", (ConfigDescription)null); _legendF4Enabled = config.Bind<bool>("BottomLegend", "F4Enabled", true, (ConfigDescription)null); _legendF4Label = config.Bind<string>("BottomLegend", "F4Label", "Vault", (ConfigDescription)null); _legendF6Enabled = config.Bind<bool>("BottomLegend", "F6Enabled", true, (ConfigDescription)null); _legendF6Label = config.Bind<string>("BottomLegend", "F6Label", "Rumble", (ConfigDescription)null); _legendF7Enabled = config.Bind<bool>("BottomLegend", "F7Enabled", true, (ConfigDescription)null); _legendF7Label = config.Bind<string>("BottomLegend", "F7Label", "Landing", (ConfigDescription)null); _legendF8Enabled = config.Bind<bool>("BottomLegend", "F8Enabled", true, (ConfigDescription)null); _legendF8Label = config.Bind<string>("BottomLegend", "F8Label", "HERALDRY", (ConfigDescription)null); _legendF9Enabled = config.Bind<bool>("BottomLegend", "F9Enabled", true, (ConfigDescription)null); _legendF9Label = config.Bind<string>("BottomLegend", "F9Label", "Rewards", (ConfigDescription)null); _legendF10Enabled = config.Bind<bool>("BottomLegend", "F10Enabled", true, (ConfigDescription)null); _legendF10Label = config.Bind<string>("BottomLegend", "F10Label", "Choose Race", (ConfigDescription)null); _steamIdLegendEnabled = config.Bind<bool>("BottomLegend", "SteamIdLegendEnabled", true, (ConfigDescription)null); _steamIdLegendLabel = config.Bind<string>("BottomLegend", "SteamIdLegendLabel", "SteamID Protected Realm", (ConfigDescription)null); } private void BindRealmLegend(ConfigFile config) { _steamIdLegendEnabled = config.Bind<bool>("RealmLegend", "ShowSteamIdLegend", true, (ConfigDescription)null); _joinLegendEnabled = config.Bind<bool>("RealmLegend", "ShowJoinLegend", true, (ConfigDescription)null); _steamIdLegendLabel = config.Bind<string>("RealmLegend", "SteamIdTitle", "SteamID Protected Realm", (ConfigDescription)null); _steamIdLegendText = config.Bind<string>("RealmLegend", "SteamIdText", "Become a Supporter or Contributor\nto gain access.", (ConfigDescription)null); _joinLegendTitle = config.Bind<string>("RealmLegend", "JoinTitle", "Join a Realm", (ConfigDescription)null); _joinLegendText = config.Bind<string>("RealmLegend", "JoinText", "Click the open gate to join.", (ConfigDescription)null); } private void MigrateOrResetLayout(ConfigFile config, int previousLayoutVersion) { if (_resetLayout.Value || previousLayoutVersion < 6) { ApplyCanonicalLayoutDefaults(); _resetLayout.Value = false; _layoutVersion.Value = 7; config.Save(); Plugin.Log.LogInfo("[FehuLanding] Layout migrated/reset to unified navigation schema v7."); return; } if (previousLayoutVersion < 7) { _finalBottomBarOffsetX.Value = 0; _finalBottomBarOffsetY.Value = 0; Plugin.Log.LogInfo("[FehuLanding] Bottom navigation drag position initialized for layout schema v7."); } _layoutVersion.Value = 7; config.Save(); } private static ConfigEntry<T> BindMigrated<T>(ConfigFile config, string section, string key, T defaultValue, string description, string legacySection, string legacyKey) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Expected O, but got Unknown return BindMigrated(config, section, key, defaultValue, new ConfigDescription(description, (AcceptableValueBase)null, Array.Empty<object>()), legacySection, legacyKey); } private static ConfigEntry<T> BindMigrated<T>(ConfigFile config, string section, string key, T defaultValue, ConfigDescription description, string legacySection, string legacyKey) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown ConfigDefinition val = new ConfigDefinition(section, key); ConfigDefinition val2 = new ConfigDefinition(legacySection, legacyKey); T val3 = defaultValue; if (!config.ContainsKey(val) && config.ContainsKey(val2)) { val3 = config.Bind<T>(legacySection, legacyKey, defaultValue, (ConfigDescription)null).Value; } ConfigEntry<T> result = config.Bind<T>(section, key, val3, description); config.Remove(val2); return result; } private static void RemoveObsoletePresentationConfig(ConfigFile config) { string[] obsoleteSections = new string[16] { "News Board", "Skald Saga Board", "Realms Board", "Other Realms Board", "SocialPanel", "ServerSteamIdIcons", "RealmLegend", "BottomLegend", "MiniPanel 1", "MiniPanel 2", "MiniPanel 3", "MiniPanel1", "MiniPanel2", "MiniPanel3", "Crash Isolation", "Vanilla Menu" }; List<ConfigDefinition> list = new List<ConfigDefinition>(); foreach (ConfigDefinition key in config.Keys) { if (IsObsoleteConfigSection(key.Section, obsoleteSections) || IsObsoleteThemeConfig(key)) { list.Add(key); } } for (int i = 0; i < list.Count; i++) { config.Remove(list[i]); } FieldInfo fieldInfo = AccessTools.Field(typeof(ConfigFile), "<OrphanedEntries>k__BackingField"); Dictionary<ConfigDefinition, string> dictionary = ((fieldInfo != null) ? (fieldInfo.GetValue(config) as Dictionary<ConfigDefinition, string>) : null); if (dictionary == null) { return; } list.Clear(); foreach (ConfigDefinition key2 in dictionary.Keys) { if (IsObsoleteConfigSection(key2.Section, obsoleteSections) || IsObsoleteThemeConfig(key2)) { list.Add(key2); } } for (int j = 0; j < list.Count; j++) { dictionary.Remove(list[j]); } } private static bool IsObsoleteThemeConfig(ConfigDefinition definition) { if (!string.Equals(definition.Section, "Appearance", StringComparison.OrdinalIgnoreCase)) { return false; } string a = definition.Key ?? string.Empty; if (!string.Equals(a, "Theme", StringComparison.OrdinalIgnoreCase) && !string.Equals(a, "ThemeOrder", StringComparison.OrdinalIgnoreCase) && !string.Equals(a, "SelectedTheme", StringComparison.OrdinalIgnoreCase) && !string.Equals(a, "ThemeIndex", StringComparison.OrdinalIgnoreCase) && !string.Equals(a, "AllowThemeSwitching", StringComparison.OrdinalIgnoreCase) && !string.Equals(a, "ThemeHotkey", StringComparison.OrdinalIgnoreCase) && !string.Equals(a, "PreviousTheme", StringComparison.OrdinalIgnoreCase)) { return string.Equals(a, "NextTheme", StringComparison.OrdinalIgnoreCase); } return true; } private static bool IsObsoleteConfigSection(string section, string[] obsoleteSections) { for (int i = 0; i < obsoleteSections.Length; i++) { if (string.Equals(section, obsoleteSections[i], StringComparison.OrdinalIgnoreCase)) { return true; } } return false; } private void ApplyCanonicalLayoutDefaults() { _finalLeftOffsetX.Value = 0; _finalLeftOffsetY.Value = 0; _finalRoadmapOffsetX.Value = 0; _finalRoadmapOffsetY.Value = 0; _finalSagaOffsetX.Value = 0; _finalSagaOffsetY.Value = 0; _finalHubOffsetX.Value = 0; _finalHubOffsetY.Value = 0; _finalBottomBarOffsetX.Value = 0; _finalBottomBarOffsetY.Value = 0; _rightX.Value = 20; _rightY.Value = 70; _otherX.Value = 20; _otherY.Value = -20; _newsX.Value = -20; _newsY.Value = 70; _sagaX.Value = -20; _sagaY.Value = -20; _miniX[0].Value = 20; _miniY[0].Value = 5; _miniX[1].Value = 20; _miniY[1].Value = -98; _miniX[2].Value = -20; _miniY[2].Value = -98; } private static Rect CreateAnchoredPanelRect(ConfigEntry<int> xEntry, ConfigEntry<int> yEntry, ConfigEntry<int> widthEntry, ConfigEntry<int> heightEntry, bool rightAnchored, bool bottomAnchored, float logicalWidth, float logicalHeight) { //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) float num = widthEntry.Value; float num2 = heightEntry.Value; float num3 = (rightAnchored ? (logicalWidth - num + (float)xEntry.Value) : ((float)xEntry.Value)); float num4 = (bottomAnchored ? (logicalHeight - num2 + (float)yEntry.Value) : ((float)yEntry.Value)); return ClampPanelToScreen(new Rect(num3, num4, num, num2), logicalWidth, logicalHeight); } private static Rect ClampPanelToScreen(Rect panel, float logicalWidth, float logicalHeight) { //IL_0087: Unknown result type (might be due to invalid IL or missing references) float num = Mathf.Min(160f, Mathf.Max(1f, ((Rect)(ref panel)).width)); float num2 = Mathf.Min(38f, Mathf.Max(1f, ((Rect)(ref panel)).height)); ((Rect)(ref panel)).x = Mathf.Clamp(((Rect)(ref panel)).x, 0f - (((Rect)(ref panel)).width - num), Mathf.Max(0f, logicalWidth - num)); ((Rect)(ref panel)).y = Mathf.Clamp(((Rect)(ref panel)).y, 0f, Mathf.Max(0f, logicalHeight - num2)); return panel; } private bool DrawPanelCloseButton(Rect panel, float topInset, float rightInset, float size) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) return GUI.Button(new Rect(((Rect)(ref panel)).xMax - rightInset - size, ((Rect)(ref panel)).y + topInset, size, size), "×", _closeButtonStyle ?? _buttonStyle); } private void HandlePanelDrag(string id, ref Rect panel, ConfigEntry<int> xEntry, ConfigEntry<int> yEntry, bool rightAnchored, float logicalWidth, float logicalHeight, bool bottomAnchored = false) { //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_0195: Unknown result type (might be due to invalid IL or missing references) //IL_019b: Invalid comparison between Unknown and I4 //IL_01b7: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: 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 = (bottomAnchored ? Mathf.RoundToInt(((Rect)(ref panel)).y - (logicalHeight - ((Rect)(ref panel)).height)) : Mathf.RoundToInt(((Rect)(ref panel)).y)); current.Use(); } if (_dragPanelId == id && ((int)current.type == 1 || !flag)) { Plugin.Instance.RuntimeConfig.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("[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_005e: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Expected O, but got Unknown //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Expected O, but got Unknown //IL_0179: 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_01c1: Unknown result type (might be due to invalid IL or missing references) //IL_01c7: Invalid comparison between Unknown and I4 //IL_01dc: Unknown result type (might be due to invalid IL or missing references) LoadSocialIconsOnce(); if (DrawPanelCloseButton(panel, 4f, 6f, 20f)) { _socialVisible = false; Plugin.Log.LogInfo("[TheFehu] Close panel clicked: Social"); } List<SocialLink> list = ((_content != null && _content.socialLinks != null) ? _content.socialLinks : new List<SocialLink>()); 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, 48, 72); 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_0103: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Expected O, but got Unknown if (_socialIconsLoaded) { return; } _socialIconsLoaded = true; string path = Path.Combine(Plugin.RuntimeDataPath, "Assets", "Social"); List<string> obj = ((_content != null && _content.socialLinks != null) ? (from link in _content.socialLinks where !string.IsNullOrWhiteSpace(link.Icon) select link.Icon.Trim()).Distinct<string>(StringComparer.OrdinalIgnoreCase).ToList() : new List<string>()); 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("[TheFehu] Social icon count discovered: " + num); } private void LogSocialIcon(string key, string message) { if (_socialIconLog.Add(key)) { Plugin.Log.LogInfo(message); } } private void InitializeShortcutLegendCaches() { _leftShortcutEnabled = new ConfigEntry<bool>[4] { _legendF1Enabled, _legendF3Enabled, _legendF4Enabled, _legendF6Enabled }; _leftShortcutLabels = new ConfigEntry<string>[4] { _legendF1Label, _legendF3Label, _legendF4Label, _legendF6Label }; _rightShortcutEnabled = new ConfigEntry<bool>[4] { _legendF7Enabled, _legendF8Enabled, _legendF9Enabled, _legendF10Enabled }; _rightShortcutLabels = new ConfigEntry<string>[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_014d: Unknown result type (might be due to invalid IL or missing references) //IL_0154: 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_01a4: Unknown result type (might be due to invalid IL or missing references) if (_miniEnabled == null) { return; } Rect val = 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; bool flag2 = _useAnchoredDefaultLayout && i > 0; float num = (flag2 ? (logicalHeight - (float)miniPanelSettings.Height + (float)miniPanelSettings.Y) : ((float)miniPanelSettings.Y)); val = ClampPanelToScreen(new Rect(flag ? (logicalWidth - (float)miniPanelSettings.Width + (float)miniPanelSettings.X) : ((float)min