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 FehuBranding v420.101.21
BepInEx/plugins/BlackViking-FehuBranding/FehuBranding.dll
Decompiled 2 days agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using FehuBranding.Assets; using FehuBranding.Config; using FehuBranding.Lifecycle; using FehuBranding.Loading; using FehuBranding.Menu; using FehuBranding.Startup; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.SceneManagement; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("FehuBranding")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("420.101.5.0")] [assembly: AssemblyInformationalVersion("420.101.5")] [assembly: AssemblyProduct("FehuBranding")] [assembly: AssemblyTitle("FehuBranding")] [assembly: AssemblyVersion("420.101.5.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 FehuBranding { [BepInPlugin("forteca.fehubranding", "FehuBranding", "420.101.5")] public sealed class Plugin : BaseUnityPlugin { internal static Plugin Instance; private BrandingAssetCache assets; private StartupIntroController startup; private BrandingLifecycleController lifecycle; private Harmony harmony; private bool readyLogged; private void Awake() { //IL_0273: Unknown result type (might be due to invalid IL or missing references) //IL_027d: Expected O, but got Unknown Instance = this; BrandingConfig brandingConfig = new BrandingConfig(((BaseUnityPlugin)this).Config); assets = new BrandingAssetCache(typeof(Plugin).Assembly.Location, delegate(string message) { ((BaseUnityPlugin)this).Logger.LogDebug((object)message); }); ((BaseUnityPlugin)this).Logger.LogDebug((object)("[FehuBranding] DLL path: " + assets.DllPath)); ((BaseUnityPlugin)this).Logger.LogDebug((object)("[FehuBranding] Plugin root: " + assets.PluginRoot)); ((BaseUnityPlugin)this).Logger.LogDebug((object)("[FehuBranding] Asset root: " + assets.AssetRoot)); ((BaseUnityPlugin)this).Logger.LogDebug((object)("[FehuBranding] Main logo path: " + assets.MainLogoPath)); ((BaseUnityPlugin)this).Logger.LogDebug((object)("[FehuBranding] Main logo exists: " + (File.Exists(assets.MainLogoPath) ? "YES" : "NO"))); ((BaseUnityPlugin)this).Logger.LogDebug((object)("[FehuBranding] Subtitle logo exists: " + (File.Exists(assets.SubtitleLogoPath) ? "YES" : "NO"))); ((BaseUnityPlugin)this).Logger.LogDebug((object)("[FehuBranding] Loading directory: " + assets.LoadingDirectory)); ((BaseUnityPlugin)this).Logger.LogDebug((object)("[FehuBranding] Loading directory exists: " + (Directory.Exists(assets.LoadingDirectory) ? "YES" : "NO"))); if (!File.Exists(assets.MainLogoPath)) { Warn("[FehuBranding] Main logo missing: " + assets.MainLogoPath); } if (!File.Exists(assets.SubtitleLogoPath)) { Warn("[FehuBranding] Subtitle logo missing: " + assets.SubtitleLogoPath); } if (!Directory.Exists(assets.LoadingDirectory)) { Warn("[FehuBranding] Loading directory missing: " + assets.LoadingDirectory); } assets.GetLoadingSprites(); MenuBrandingController menuController = new MenuBrandingController(brandingConfig, assets, (MonoBehaviour)(object)this, delegate(string message) { ((BaseUnityPlugin)this).Logger.LogDebug((object)message); }); WorldLoadingController loadingController = new WorldLoadingController(brandingConfig, assets, delegate(string message) { ((BaseUnityPlugin)this).Logger.LogDebug((object)message); }); lifecycle = new BrandingLifecycleController(menuController, loadingController, delegate(string message) { ((BaseUnityPlugin)this).Logger.LogDebug((object)message); }); startup = new StartupIntroController(brandingConfig, delegate(string message) { ((BaseUnityPlugin)this).Logger.LogDebug((object)message); }); harmony = new Harmony("forteca.fehubranding"); PatchPostfix("FejdStartup", "Awake", "FejdStartupAwake"); PatchPrefix("FejdStartup", "Start", "FejdStartupStartPrefix"); PatchPostfix("FejdStartup", "Start", "FejdStartupStartPostfix"); PatchPostfix("FejdStartup", "SetupGui", "FejdStartupSetupGui"); PatchPostfix("FejdStartup", "OnWorldStart", "FejdStartupOnWorldStart"); PatchPostfix("FejdStartup", "OnJoinStart", "FejdStartupOnJoinStart"); PatchPrefix("FejdStartup", "TryPlayIntroCinematic", "FejdStartupTryPlayIntroPrefix"); PatchPrefix("SceneLoader", "Start", "SceneLoaderStartPrefix"); PatchPostfix("SceneLoader", "OnDestroy", "SceneLoaderOnDestroy"); PatchPostfix("Hud", "Awake", "HudAwake"); PatchPostfix("Hud", "OnDestroy", "HudOnDestroy"); PatchPostfix("Player", "OnSpawned", "PlayerOnSpawned"); PatchPostfix("FejdStartup", "ShowConnectError", "FejdStartupShowConnectError"); PatchPostfix("FejdStartup", "OnAbort", "FejdStartupOnAbort"); PatchPostfix("FejdStartup", "OnConnectionFailedOk", "FejdStartupConnectionFailedOk"); PatchPrefix("Game", "Logout", "GameLogout"); PatchPostfix("Game", "OnDestroy", "GameOnDestroy"); SceneManager.sceneLoaded += OnSceneLoaded; ((MonoBehaviour)this).StartCoroutine(WaitForStartMenu()); ((BaseUnityPlugin)this).Logger.LogDebug((object)"[FehuBranding] FehuBranding v420.101.5 loaded"); } internal void Warn(string message) { ((BaseUnityPlugin)this).Logger.LogWarning((object)message); } internal void Error(string message) { ((BaseUnityPlugin)this).Logger.LogError((object)message); } internal void ReportReady() { if (!readyLogged) { readyLogged = true; ((BaseUnityPlugin)this).Logger.LogInfo((object)("[FehuBranding] 420.101.5 READY | Loading images=" + assets.LoadingImageCount + " | Logo=OK")); } } private void OnSceneLoaded(Scene scene, LoadSceneMode mode) { if (((Scene)(ref scene)).name == "start") { ((MonoBehaviour)this).StartCoroutine(WaitForStartMenu()); } } private IEnumerator WaitForStartMenu() { float deadline = Time.realtimeSinceStartup + 10f; while (Time.realtimeSinceStartup < deadline) { Scene activeScene = SceneManager.GetActiveScene(); if (((Scene)(ref activeScene)).name == "start" && (Object)(object)FejdStartup.instance != (Object)null) { yield return null; ((BaseUnityPlugin)this).Logger.LogDebug((object)"[FehuBranding] MainLogo hook: start scene fallback"); lifecycle.OnMainMenuReady(FejdStartup.instance); yield break; } yield return null; } ((BaseUnityPlugin)this).Logger.LogDebug((object)"[FehuBranding] MainLogo scene/startup wait expired; awaiting start scene hook"); } private void PatchPrefix(string typeName, string methodName, string callback) { Patch(typeName, methodName, callback, prefix: true); } private void PatchPostfix(string typeName, string methodName, string callback) { Patch(typeName, methodName, callback, prefix: false); } private void Patch(string typeName, string methodName, string callback, bool prefix) { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Expected O, but got Unknown Type type = AccessTools.TypeByName(typeName); MethodInfo methodInfo = ((type == null) ? null : AccessTools.Method(type, methodName, (Type[])null, (Type[])null)); if (methodInfo == null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("[FehuBranding] Patch target not found: " + typeName + "." + methodName)); return; } HarmonyMethod val = new HarmonyMethod(typeof(Plugin), callback, (Type[])null); if (prefix) { harmony.Patch((MethodBase)methodInfo, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } else { harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } private static void FejdStartupAwake(FejdStartup __instance) { Instance?.lifecycle?.OnFejdStartupAwake(__instance); } private static void FejdStartupStartPrefix(FejdStartup __instance) { Instance?.startup?.PrepareBeforeStart(__instance); } private static void FejdStartupStartPostfix(FejdStartup __instance) { Plugin instance = Instance; if (instance != null) { ((BaseUnityPlugin)instance).Logger.LogDebug((object)"[FehuBranding] MainLogo hook: FejdStartup.Start"); } Instance?.lifecycle?.OnMainMenuReady(__instance); } private static void FejdStartupSetupGui(FejdStartup __instance) { Plugin instance = Instance; if (instance != null) { ((BaseUnityPlugin)instance).Logger.LogDebug((object)"[FehuBranding] MainLogo hook: FejdStartup.SetupGui"); } Instance?.lifecycle?.OnMainMenuReady(__instance); } private static void FejdStartupOnWorldStart() { Instance?.lifecycle?.OnWorldLoadingRequested("world"); } private static void FejdStartupOnJoinStart() { Instance?.lifecycle?.OnWorldLoadingRequested("server"); } private static bool FejdStartupTryPlayIntroPrefix(ref IEnumerator __result) { if (!((Object)(object)Instance == (Object)null)) { return Instance.startup.AllowCinematic(ref __result); } return true; } private static void SceneLoaderStartPrefix(SceneLoader __instance) { Instance?.lifecycle?.OnSceneLoaderStart(__instance); } private static void SceneLoaderOnDestroy(SceneLoader __instance) { Instance?.lifecycle?.OnSceneLoaderDestroyed(__instance); } private static void HudAwake(Hud __instance) { Instance?.lifecycle?.OnHudAwake(__instance); } private static void HudOnDestroy(Hud __instance) { Instance?.lifecycle?.OnHudDestroyed(__instance); } private static void PlayerOnSpawned() { Instance?.lifecycle?.OnWorldActive(); } private static void FejdStartupShowConnectError() { Instance?.lifecycle?.OnLoadingCancelled("connection error"); } private static void FejdStartupOnAbort() { Instance?.lifecycle?.OnLoadingCancelled("join aborted"); } private static void FejdStartupConnectionFailedOk(FejdStartup __instance) { Instance?.lifecycle?.OnConnectionFailureAcknowledged(__instance); } private static void GameLogout() { Instance?.lifecycle?.OnGameEnding("logout"); } private static void GameOnDestroy() { Instance?.lifecycle?.OnGameEnding("game destroyed"); } private void OnDestroy() { SceneManager.sceneLoaded -= OnSceneLoaded; lifecycle?.Shutdown(); Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } assets?.Clear(); if ((Object)(object)Instance == (Object)(object)this) { Instance = null; } } } } namespace FehuBranding.Startup { internal sealed class StartupIntroController { private readonly BrandingConfig config; private readonly Action<string> log; private bool logged; internal StartupIntroController(BrandingConfig brandingConfig, Action<string> logger) { config = brandingConfig; log = logger; } internal void PrepareBeforeStart(FejdStartup startup) { if (config.SkipIntro.Value && !((Object)(object)startup == (Object)null)) { FieldInfo fieldInfo = AccessTools.Field(typeof(FejdStartup), "m_firstStartup"); if (fieldInfo != null) { fieldInfo.SetValue(startup, false); } } } internal bool AllowCinematic(ref IEnumerator result) { if (!config.SkipIntro.Value) { return true; } result = Empty(); LogBypass(); return false; } private void LogBypass() { if (!logged) { logged = true; log("[FehuBranding] Startup intro playback prevented"); } } private static IEnumerator Empty() { yield break; } } } namespace FehuBranding.Menu { internal sealed class MenuBrandingController { private const float AcquisitionSeconds = 8f; private readonly BrandingConfig config; private readonly BrandingAssetCache assets; private readonly MonoBehaviour runner; private readonly Action<string> log; private Component nativeTarget; private Image subtitleTarget; private Coroutine acquisition; private int startupId; private bool targetLogged; private bool mainSuccessLogged; private bool subtitleSuccessLogged; private bool targetFailureLogged; private bool performanceLogged; private Stopwatch initializationWatch; internal MenuBrandingController(BrandingConfig brandingConfig, BrandingAssetCache assetLoader, MonoBehaviour coroutineRunner, Action<string> logger) { config = brandingConfig; assets = assetLoader; runner = coroutineRunner; log = logger; } internal void BeginApply(FejdStartup startup) { if ((Object)(object)startup != (Object)null && startupId == ((Object)startup).GetInstanceID() && acquisition != null) { return; } Cancel(); log("[FehuBranding] MainLogo init"); log("[FehuBranding] MainLogo expected path: " + assets.MainLogoPath); log("[FehuBranding] MainLogo file exists: " + (File.Exists(assets.MainLogoPath) ? "YES" : "NO")); if (!performanceLogged && initializationWatch == null) { initializationWatch = Stopwatch.StartNew(); } if (!config.Enabled.Value || !config.LogoEnabled.Value || (Object)(object)startup == (Object)null) { log("[FehuBranding] MainLogo applied: NO (disabled or startup unavailable)"); CompletePerformanceMeasurement(); return; } log("[FehuBranding] MainLogo texture loaded: " + (((Object)(object)assets.GetMainLogo() != (Object)null) ? "YES" : "NO")); startupId = ((Object)startup).GetInstanceID(); targetLogged = false; mainSuccessLogged = false; subtitleSuccessLogged = false; targetFailureLogged = false; if (!TryApply(startup)) { acquisition = runner.StartCoroutine(AcquireWhenAvailable(startup, startupId)); } } internal void Reset() { Cancel(); if ((Object)(object)subtitleTarget != (Object)null) { Object.Destroy((Object)(object)((Component)subtitleTarget).gameObject); } nativeTarget = null; subtitleTarget = null; startupId = 0; targetLogged = false; mainSuccessLogged = false; subtitleSuccessLogged = false; targetFailureLogged = false; } internal void Cancel() { if (acquisition != null && (Object)(object)runner != (Object)null) { runner.StopCoroutine(acquisition); } acquisition = null; } internal void Hide() { Cancel(); SetComponentEnabled(nativeTarget, enabled: false); if ((Object)(object)subtitleTarget != (Object)null) { ((Component)subtitleTarget).gameObject.SetActive(false); } } private IEnumerator AcquireWhenAvailable(FejdStartup startup, int expectedId) { float deadline = Time.realtimeSinceStartup + 8f; while (Time.realtimeSinceStartup < deadline && !((Object)(object)startup == (Object)null) && ((Object)startup).GetInstanceID() == expectedId) { yield return null; if (TryApply(startup)) { acquisition = null; yield break; } } acquisition = null; log("[FehuBranding] MainLogo target found: " + (((Object)(object)nativeTarget != (Object)null) ? "YES" : "NO")); log("[FehuBranding] MainLogo target path: " + FullPath(((Object)(object)nativeTarget == (Object)null) ? null : nativeTarget.transform)); log("[FehuBranding] MainLogo applied: " + (mainSuccessLogged ? "YES" : "NO")); if ((Object)(object)nativeTarget == (Object)null && (Object)(object)startup != (Object)null) { Scene scene = ((Component)startup).gameObject.scene; GameObject[] rootGameObjects = ((Scene)(ref scene)).GetRootGameObjects(); for (int i = 0; i < rootGameObjects.Length; i++) { Component[] componentsInChildren = rootGameObjects[i].GetComponentsInChildren<Component>(true); foreach (Component val in componentsInChildren) { if (val is Image || val is RawImage || val is SpriteRenderer) { log("[FehuBranding] MainLogo candidate: " + FullPath(val.transform) + " [" + ((object)val).GetType().Name + "] active=" + val.gameObject.activeInHierarchy + " asset=" + AssetName(val)); } } } } if ((Object)(object)nativeTarget == (Object)null && !targetFailureLogged) { targetFailureLogged = true; Plugin.Instance?.Warn("[FehuBranding] Target UI not found"); } CompletePerformanceMeasurement(); } private bool TryApply(FejdStartup startup) { //IL_0053: 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) object? obj = AccessTools.Field(typeof(FejdStartup), "m_mainMenu")?.GetValue(startup); GameObject val = (GameObject)((obj is GameObject) ? obj : null); if ((Object)(object)val == (Object)null || !val.activeInHierarchy) { return false; } if ((Object)(object)nativeTarget == (Object)null || nativeTarget.gameObject.scene != ((Component)startup).gameObject.scene) { nativeTarget = FindLogoTarget(startup, val); } if ((Object)(object)nativeTarget == (Object)null) { return false; } if (!targetLogged) { targetLogged = true; log("[FehuBranding] MainLogo target found: YES"); log("[FehuBranding] MainLogo target path: " + FullPath(nativeTarget.transform)); log("[FehuBranding] Target UI found: " + FullPath(nativeTarget.transform) + " [" + ((object)nativeTarget).GetType().Name + "] asset=" + AssetName(nativeTarget)); } Sprite mainLogo = assets.GetMainLogo(); Sprite subtitleLogo = assets.GetSubtitleLogo(); int num; if ((Object)(object)mainLogo != (Object)null) { num = (ApplyLogo(nativeTarget, mainLogo) ? 1 : 0); if (num != 0) { ConfigureMainLayout(nativeTarget); DisableCompetingLogoLayers(val.transform, nativeTarget); if (!mainSuccessLogged) { mainSuccessLogged = true; log("[FehuBranding] MainLogo applied: YES"); } } } else { num = 0; } bool flag = (Object)(object)subtitleLogo != (Object)null && ApplySubtitle(nativeTarget, subtitleLogo); if (flag && !subtitleSuccessLogged) { subtitleSuccessLogged = true; log("[FehuBranding] Subtitle logo created exactly once: " + FullPath(((Component)subtitleTarget).transform)); } if (num == 0 || !flag) { return false; } Plugin.Instance?.ReportReady(); CompletePerformanceMeasurement(); return true; } private void CompletePerformanceMeasurement() { if (!performanceLogged && initializationWatch != null) { initializationWatch.Stop(); performanceLogged = true; log("[FehuBranding] UI initialization: " + initializationWatch.ElapsedMilliseconds + " ms"); initializationWatch = null; } } private static Component FindLogoTarget(FejdStartup startup, GameObject mainMenu) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) Component best = null; int bestScore = int.MinValue; HashSet<int> visited = new HashSet<int>(); ScoreTree(mainMenu.transform, visited, ref best, ref bestScore); if ((Object)(object)startup != (Object)null) { Scene scene = ((Component)startup).gameObject.scene; GameObject[] rootGameObjects = ((Scene)(ref scene)).GetRootGameObjects(); for (int i = 0; i < rootGameObjects.Length; i++) { ScoreTree(rootGameObjects[i].transform, visited, ref best, ref bestScore); } } if (bestScore < 100) { return null; } return best; } private static void ScoreTree(Transform root, HashSet<int> visited, ref Component best, ref int bestScore) { if (!((Object)(object)root == (Object)null)) { Image[] componentsInChildren = ((Component)root).GetComponentsInChildren<Image>(true); for (int i = 0; i < componentsInChildren.Length; i++) { Score((Component)(object)componentsInChildren[i], visited, ref best, ref bestScore); } RawImage[] componentsInChildren2 = ((Component)root).GetComponentsInChildren<RawImage>(true); for (int i = 0; i < componentsInChildren2.Length; i++) { Score((Component)(object)componentsInChildren2[i], visited, ref best, ref bestScore); } SpriteRenderer[] componentsInChildren3 = ((Component)root).GetComponentsInChildren<SpriteRenderer>(true); for (int i = 0; i < componentsInChildren3.Length; i++) { Score((Component)(object)componentsInChildren3[i], visited, ref best, ref bestScore); } } } private static void Score(Component component, HashSet<int> visited, ref Component best, ref int bestScore) { //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)component == (Object)null || !visited.Add(((Object)component).GetInstanceID())) { return; } string text = (((Object)component).name ?? string.Empty).ToLowerInvariant(); string text2 = AssetName(component).ToLowerInvariant(); string text3 = FullPath(component.transform).ToLowerInvariant(); string text4 = text + "|" + text2 + "|" + text3; int num = 0; if (text4.Contains("deepnorth") || text4.Contains("deep north")) { num += 350; } if (text4.Contains("valheim")) { num += 280; } switch (text) { case "logo": case "logo_main": case "mainlogo": num += 240; break; } if (text.Contains("mainlogo") || text.Contains("main_logo")) { num += 220; } if (text4.Contains("/logo/") || text3.EndsWith("/logo")) { num += 180; } if (text4.Contains("title")) { num += 100; } if (component.gameObject.activeInHierarchy) { num += 30; } Image val = (Image)(object)((component is Image) ? component : null); if (val != null) { Rect rect = ((Graphic)val).rectTransform.rect; float width = ((Rect)(ref rect)).width; rect = ((Graphic)val).rectTransform.rect; if (width * ((Rect)(ref rect)).height > 10000f) { num += 20; } } if (text4.Contains("loading") || text4.Contains("background") || text4.Contains("button") || text4.Contains("discord") || text4.Contains("party") || text4.Contains("icon")) { num -= 500; } if (text4.Contains("subtitle")) { num -= 80; } if (text4.Contains("ember") || text4.Contains("glow") || text4.Contains("particle")) { num -= 250; } if (num > bestScore) { bestScore = num; best = component; } } private static bool ApplyLogo(Component target, Sprite logo) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) Image val = (Image)(object)((target is Image) ? target : null); if (val != null) { val.sprite = logo; val.type = (Type)0; val.preserveAspect = true; ((Graphic)val).color = Color.white; ((Behaviour)val).enabled = true; ((Component)val).gameObject.SetActive(true); return true; } RawImage val2 = (RawImage)(object)((target is RawImage) ? target : null); if (val2 != null) { val2.texture = (Texture)(object)logo.texture; ((Graphic)val2).color = Color.white; ((Behaviour)val2).enabled = true; ((Component)val2).gameObject.SetActive(true); return true; } SpriteRenderer val3 = (SpriteRenderer)(object)((target is SpriteRenderer) ? target : null); if (val3 != null) { val3.sprite = logo; val3.color = Color.white; ((Renderer)val3).enabled = true; ((Component)val3).gameObject.SetActive(true); return true; } return false; } private void ConfigureMainLayout(Component target) { //IL_001b: 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_0045: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) Transform transform = target.transform; RectTransform val = (RectTransform)(object)((transform is RectTransform) ? transform : null); if (val != null) { val.anchorMin = new Vector2(0.5f, 1f); val.anchorMax = new Vector2(0.5f, 1f); val.pivot = new Vector2(0.5f, 1f); val.anchoredPosition = new Vector2(0f, -30f); val.sizeDelta = new Vector2(820f, 307.5f); ((Transform)val).localScale = Vector3.one; } } private bool ApplySubtitle(Component mainTarget, Sprite subtitle) { //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_0196: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Expected O, but got Unknown Transform val = (((Object)(object)mainTarget == (Object)null) ? null : mainTarget.transform.parent); if ((Object)(object)val == (Object)null) { return false; } if ((Object)(object)subtitleTarget == (Object)null || (Object)(object)((Component)subtitleTarget).transform.parent != (Object)(object)val) { Transform val2 = val.Find("FehuBranding.SubtitleLogo"); subtitleTarget = (((Object)(object)val2 == (Object)null) ? null : ((Component)val2).GetComponent<Image>()); if ((Object)(object)subtitleTarget == (Object)null) { GameObject val3 = new GameObject("FehuBranding.SubtitleLogo", new Type[3] { typeof(RectTransform), typeof(CanvasRenderer), typeof(Image) }); val3.transform.SetParent(val, false); subtitleTarget = val3.GetComponent<Image>(); } } subtitleTarget.sprite = subtitle; subtitleTarget.type = (Type)0; subtitleTarget.preserveAspect = true; ((Graphic)subtitleTarget).color = Color.white; ((Graphic)subtitleTarget).raycastTarget = false; ((Behaviour)subtitleTarget).enabled = true; ((Component)subtitleTarget).gameObject.SetActive(true); RectTransform rectTransform = ((Graphic)subtitleTarget).rectTransform; rectTransform.anchorMin = new Vector2(0.5f, 1f); rectTransform.anchorMax = new Vector2(0.5f, 1f); rectTransform.pivot = new Vector2(0.5f, 1f); rectTransform.anchoredPosition = new Vector2(0f, -315f); rectTransform.sizeDelta = new Vector2(650f, 216.667f); ((Transform)rectTransform).localScale = Vector3.one; ((Component)subtitleTarget).transform.SetAsLastSibling(); return true; } private static void SetComponentEnabled(Component target, bool enabled) { Image val = (Image)(object)((target is Image) ? target : null); if (val != null) { ((Behaviour)val).enabled = enabled; return; } RawImage val2 = (RawImage)(object)((target is RawImage) ? target : null); if (val2 != null) { ((Behaviour)val2).enabled = enabled; return; } SpriteRenderer val3 = (SpriteRenderer)(object)((target is SpriteRenderer) ? target : null); if (val3 != null) { ((Renderer)val3).enabled = enabled; } } private static void DisableCompetingLogoLayers(Transform mainMenu, Component target) { Transform val = FindLogoFamilyRoot(mainMenu, target.transform); if ((Object)(object)val == (Object)null) { return; } Image[] componentsInChildren = ((Component)val).GetComponentsInChildren<Image>(true); foreach (Image val2 in componentsInChildren) { if ((Object)(object)val2 != (Object)(object)target && IsBrandingLayer((Component)(object)val2)) { ((Behaviour)val2).enabled = false; } } RawImage[] componentsInChildren2 = ((Component)val).GetComponentsInChildren<RawImage>(true); foreach (RawImage val3 in componentsInChildren2) { if ((Object)(object)val3 != (Object)(object)target && IsBrandingLayer((Component)(object)val3)) { ((Behaviour)val3).enabled = false; } } SpriteRenderer[] componentsInChildren3 = ((Component)val).GetComponentsInChildren<SpriteRenderer>(true); foreach (SpriteRenderer val4 in componentsInChildren3) { if ((Object)(object)val4 != (Object)(object)target && IsBrandingLayer((Component)(object)val4)) { ((Renderer)val4).enabled = false; } } } private static Transform FindLogoFamilyRoot(Transform mainMenu, Transform target) { Transform val = null; Transform val2 = target; while ((Object)(object)val2 != (Object)null && (Object)(object)val2 != (Object)(object)mainMenu) { if ((((Object)val2).name ?? string.Empty).ToLowerInvariant().Contains("logo")) { val = val2; } val2 = val2.parent; } return val ?? target.parent; } private static bool IsBrandingLayer(Component component) { string text = ((((Object)component).name ?? string.Empty) + "|" + AssetName(component)).ToLowerInvariant(); if (!text.Contains("logo") && !text.Contains("valheim") && !text.Contains("deepnorth") && !text.Contains("deep north") && !text.Contains("title") && !text.Contains("subtitle") && !text.Contains("ashlands") && !text.Contains("mistlands") && !text.Contains("ember")) { return text.Contains("glow"); } return true; } private static bool IsUsableTarget(Component target, Transform mainMenu) { if ((Object)(object)target == (Object)null || (Object)(object)mainMenu == (Object)null) { return false; } if (!((Object)(object)target.transform == (Object)(object)mainMenu)) { return target.transform.IsChildOf(mainMenu); } return true; } private static string AssetName(Component component) { Image val = (Image)(object)((component is Image) ? component : null); if (val != null) { string text; if (!((Object)(object)val.sprite == (Object)null)) { text = ((Object)val.sprite).name; if (text == null) { return string.Empty; } } else { text = string.Empty; } return text; } RawImage val2 = (RawImage)(object)((component is RawImage) ? component : null); if (val2 != null) { string text2; if (!((Object)(object)val2.texture == (Object)null)) { text2 = ((Object)val2.texture).name; if (text2 == null) { return string.Empty; } } else { text2 = string.Empty; } return text2; } SpriteRenderer val3 = (SpriteRenderer)(object)((component is SpriteRenderer) ? component : null); if (val3 != null) { string text3; if (!((Object)(object)val3.sprite == (Object)null)) { text3 = ((Object)val3.sprite).name; if (text3 == null) { return string.Empty; } } else { text3 = string.Empty; } return text3; } return string.Empty; } private static string FullPath(Transform transform) { if ((Object)(object)transform == (Object)null) { return "<null>"; } string text = ((Object)transform).name; Transform parent = transform.parent; while ((Object)(object)parent != (Object)null) { text = ((Object)parent).name + "/" + text; parent = parent.parent; } return text; } } } namespace FehuBranding.Loading { internal sealed class WorldLoadingController { private readonly BrandingConfig config; private readonly BrandingAssetCache assets; private readonly Action<string> log; private readonly List<Sprite> sequence = new List<Sprite>(); private readonly Dictionary<string, bool> originalLogoActivity = new Dictionary<string, bool>(); private readonly Dictionary<string, bool> originalFlags = new Dictionary<string, bool>(); private Object stageOwner; private Coroutine rotation; private Coroutine fade; private Image backgroundA; private Image backgroundB; private Image blackBackdrop; private Image activeBackground; private Image nextBackground; private Sprite originalSprite; private Color originalColor; private string originalName; private bool originalEnabled; private bool originalPreserveAspect; private Type originalType; private int originalSiblingIndex; private int nextIndex; private bool armed; private bool overlayCreated; internal WorldLoadingController(BrandingConfig brandingConfig, BrandingAssetCache assetCache, Action<string> logger) { config = brandingConfig; assets = assetCache; log = logger; } internal void Arm() { if (armed || !CanApply()) { return; } sequence.Clear(); foreach (Sprite loadingSprite in assets.GetLoadingSprites()) { if ((Object)(object)loadingSprite != (Object)null) { sequence.Add(loadingSprite); } } if (sequence.Count != 0) { nextIndex = 0; armed = true; } } internal void Attach(SceneLoader loader) { if (armed && !((Object)(object)loader == (Object)null) && !(stageOwner == (Object)(object)loader)) { Image val = FindSceneLoaderBackground(loader); if ((Object)(object)val == (Object)null) { Plugin.Instance?.Warn("[FehuBranding] SceneLoader Bkg not found."); return; } AttachTo(val, (Object)(object)loader); CaptureAndDisableNativeLogos(loader); } } internal void Attach(Hud hud) { if (armed && !((Object)(object)hud == (Object)null) && !(stageOwner == (Object)(object)hud)) { object? obj = AccessTools.Field(typeof(Hud), "m_loadingImage")?.GetValue(hud); Image val = (Image)((obj is Image) ? obj : null); if ((Object)(object)val == (Object)null) { Plugin.Instance?.Warn("[FehuBranding] Hud.m_loadingImage not found."); } else { AttachTo(val, (Object)(object)hud); } } } internal void Detach(SceneLoader loader) { if (stageOwner == (Object)(object)loader) { DetachVisuals(sessionEnded: false); } } internal void Detach(Hud hud) { if (stageOwner == (Object)(object)hud) { DetachVisuals(sessionEnded: false); } } internal void Complete() { if (armed || overlayCreated) { armed = false; DetachVisuals(sessionEnded: true); } } internal void Cancel() { Complete(); } private void AttachTo(Image target, Object owner) { DetachVisuals(sessionEnded: false); stageOwner = owner; CaptureNativeState(target); SetupLayers(target); SetSprite(activeBackground, CurrentSprite(), 1f); SetSprite(nextBackground, null, 0f); overlayCreated = true; rotation = ((MonoBehaviour)Plugin.Instance).StartCoroutine(RotateWhileLoading()); } private void CaptureNativeState(Image image) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) backgroundA = image; originalSprite = image.sprite; originalColor = ((Graphic)image).color; originalName = ((Object)image).name; originalEnabled = ((Behaviour)image).enabled; originalPreserveAspect = image.preserveAspect; originalType = image.type; originalSiblingIndex = ((Component)image).transform.GetSiblingIndex(); } private void SetupLayers(Image nativeBackground) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) Transform parent = ((Component)nativeBackground).transform.parent; blackBackdrop = CreateLayer("FehuBranding.BlackBackground", parent); ((Graphic)blackBackdrop).color = Color.black; blackBackdrop.sprite = null; ((Component)blackBackdrop).transform.SetSiblingIndex(originalSiblingIndex); backgroundA = nativeBackground; ((Object)backgroundA).name = "BackgroundA"; SetupSlideImage(backgroundA); ((Component)backgroundA).transform.SetSiblingIndex(originalSiblingIndex + 1); backgroundB = CreateLayer("BackgroundB", parent); SetupSlideImage(backgroundB); ((Component)backgroundB).transform.SetSiblingIndex(originalSiblingIndex + 2); activeBackground = backgroundA; nextBackground = backgroundB; } private void CaptureAndDisableNativeLogos(SceneLoader loader) { originalFlags.Clear(); CaptureFlag(loader, "_showLogos"); CaptureFlag(loader, "_showSaveNotification"); CaptureFlag(loader, "_showHealthWarning"); SetFlag(loader, "_showLogos", value: false); SetFlag(loader, "_showSaveNotification", value: false); SetFlag(loader, "_showHealthWarning", value: false); originalLogoActivity.Clear(); DisableObject(loader, "gameLogo"); DisableObject(loader, "coffeeStainLogo"); DisableObject(loader, "ironGateLogo"); } private IEnumerator RotateWhileLoading() { float nextSwapAt = Time.unscaledTime + Mathf.Max(0.1f, config.ImageIntervalSeconds.Value); while (armed && stageOwner != (Object)null) { if (Time.unscaledTime >= nextSwapAt) { nextIndex = (nextIndex + 1) % sequence.Count; StartFade(CurrentSprite()); nextSwapAt = Time.unscaledTime + Mathf.Max(0.1f, config.ImageIntervalSeconds.Value); } yield return (object)new WaitForSecondsRealtime(0.1f); } rotation = null; } private void StartFade(Sprite sprite) { if (!((Object)(object)sprite == (Object)null) && !((Object)(object)activeBackground == (Object)null) && !((Object)(object)nextBackground == (Object)null)) { if (fade != null) { ((MonoBehaviour)Plugin.Instance).StopCoroutine(fade); } float value = config.FadeDurationSeconds.Value; if (value <= 0f) { SetSprite(activeBackground, sprite, 1f); SetSprite(nextBackground, null, 0f); } else { fade = ((MonoBehaviour)Plugin.Instance).StartCoroutine(CrossFade(sprite, value)); } } } private IEnumerator CrossFade(Sprite sprite, float duration) { SetSprite(nextBackground, sprite, 0f); float elapsed = 0f; while (elapsed < duration && armed && stageOwner != (Object)null) { elapsed += Time.unscaledDeltaTime; float num = Mathf.Clamp01(elapsed / duration); SetAlpha(activeBackground, 1f - num); SetAlpha(nextBackground, num); yield return null; } if (armed && stageOwner != (Object)null) { SetAlpha(activeBackground, 0f); SetAlpha(nextBackground, 1f); Image val = activeBackground; activeBackground = nextBackground; nextBackground = val; } fade = null; } private void DetachVisuals(bool sessionEnded) { if (fade != null && (Object)(object)Plugin.Instance != (Object)null) { ((MonoBehaviour)Plugin.Instance).StopCoroutine(fade); } if (rotation != null && (Object)(object)Plugin.Instance != (Object)null) { ((MonoBehaviour)Plugin.Instance).StopCoroutine(rotation); } fade = null; rotation = null; RestoreNativeState(); DestroyOwnedObject((Component)(object)backgroundB); DestroyOwnedObject((Component)(object)blackBackdrop); backgroundB = (blackBackdrop = null); backgroundA = (activeBackground = (nextBackground = null)); stageOwner = null; if (sessionEnded) { sequence.Clear(); overlayCreated = false; } } private void RestoreNativeState() { //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) Object obj = stageOwner; SceneLoader val = (SceneLoader)(object)((obj is SceneLoader) ? obj : null); if (val != null) { foreach (KeyValuePair<string, bool> originalFlag in originalFlags) { SetFlag(val, originalFlag.Key, originalFlag.Value); } foreach (KeyValuePair<string, bool> item in originalLogoActivity) { object? obj2 = AccessTools.Field(typeof(SceneLoader), item.Key)?.GetValue(val); GameObject val2 = (GameObject)((obj2 is GameObject) ? obj2 : null); if ((Object)(object)val2 != (Object)null) { val2.SetActive(item.Value); } } } originalFlags.Clear(); originalLogoActivity.Clear(); if (!((Object)(object)backgroundA == (Object)null)) { ((Object)backgroundA).name = originalName; backgroundA.sprite = originalSprite; ((Graphic)backgroundA).color = originalColor; ((Behaviour)backgroundA).enabled = originalEnabled; backgroundA.preserveAspect = originalPreserveAspect; backgroundA.type = originalType; ((Component)backgroundA).transform.SetSiblingIndex(originalSiblingIndex); } } private static Image CreateLayer(string name, Transform parent) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name, new Type[3] { typeof(RectTransform), typeof(CanvasRenderer), typeof(Image) }); val.transform.SetParent(parent, false); Image component = val.GetComponent<Image>(); Stretch(((Graphic)component).rectTransform); ((Graphic)component).raycastTarget = false; return component; } private static void SetupSlideImage(Image image) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) image.type = (Type)0; image.preserveAspect = true; ((Graphic)image).color = Color.white; ((Behaviour)image).enabled = true; ((Graphic)image).raycastTarget = false; Stretch(((Graphic)image).rectTransform); } private static void Stretch(RectTransform rect) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) rect.anchorMin = Vector2.zero; rect.anchorMax = Vector2.one; rect.pivot = new Vector2(0.5f, 0.5f); rect.anchoredPosition = Vector2.zero; rect.sizeDelta = Vector2.zero; } private static void SetSprite(Image image, Sprite sprite, float alpha) { if (!((Object)(object)image == (Object)null)) { image.sprite = sprite; ((Behaviour)image).enabled = (Object)(object)sprite != (Object)null; SetAlpha(image, alpha); } } private static void SetAlpha(Image image, float alpha) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)image == (Object)null)) { Color color = ((Graphic)image).color; color.a = alpha; ((Graphic)image).color = color; } } private void CaptureFlag(SceneLoader loader, string fieldName) { FieldInfo fieldInfo = AccessTools.Field(typeof(SceneLoader), fieldName); if (fieldInfo != null && fieldInfo.GetValue(loader) is bool value) { originalFlags[fieldName] = value; } } private static void SetFlag(SceneLoader loader, string fieldName, bool value) { AccessTools.Field(typeof(SceneLoader), fieldName)?.SetValue(loader, value); } private void DisableObject(SceneLoader loader, string fieldName) { object? obj = AccessTools.Field(typeof(SceneLoader), fieldName)?.GetValue(loader); GameObject val = (GameObject)((obj is GameObject) ? obj : null); if (!((Object)(object)val == (Object)null)) { originalLogoActivity[fieldName] = val.activeSelf; val.SetActive(false); } } private static void DestroyOwnedObject(Component component) { if ((Object)(object)component != (Object)null) { Object.Destroy((Object)(object)component.gameObject); } } private bool CanApply() { if (config.Enabled.Value) { return config.LoadingEnabled.Value; } return false; } private Sprite CurrentSprite() { if (sequence.Count != 0) { return sequence[nextIndex]; } return null; } private static Image FindSceneLoaderBackground(SceneLoader loader) { object? obj = AccessTools.Field(typeof(SceneLoader), "gameLogo")?.GetValue(loader); GameObject val = (GameObject)((obj is GameObject) ? obj : null); Transform val2 = (((Object)(object)val == (Object)null || (Object)(object)val.transform.parent == (Object)null) ? null : val.transform.parent.Find("Bkg")); Image val3 = (((Object)(object)val2 == (Object)null) ? null : ((Component)val2).GetComponent<Image>()); if ((Object)(object)val3 != (Object)null) { return val3; } object? obj2 = AccessTools.Field(typeof(SceneLoader), "loadingIndicator")?.GetValue(loader); LoadingIndicator val4 = (LoadingIndicator)((obj2 is LoadingIndicator) ? obj2 : null); if (!((Object)(object)val4 == (Object)null)) { object? obj3 = AccessTools.Field(typeof(LoadingIndicator), "m_background")?.GetValue(val4); return (Image)((obj3 is Image) ? obj3 : null); } return null; } } } namespace FehuBranding.Lifecycle { internal enum BrandingState { Boot, WaitingForMainMenu, MainMenuReady, WorldLoading, WorldActive } internal sealed class BrandingLifecycleController { private readonly MenuBrandingController menu; private readonly WorldLoadingController loading; private readonly Action<string> log; private BrandingState state; internal BrandingLifecycleController(MenuBrandingController menuController, WorldLoadingController loadingController, Action<string> logger) { menu = menuController; loading = loadingController; log = logger; } internal void OnFejdStartupAwake(FejdStartup startup) { loading.Cancel(); menu.Reset(); Transition(BrandingState.WaitingForMainMenu); } internal void OnMainMenuReady(FejdStartup startup) { if (!((Object)(object)startup == (Object)null)) { loading.Cancel(); bool num = state != BrandingState.MainMenuReady; Transition(BrandingState.MainMenuReady); if (num) { log("[FehuBranding] Main menu detected"); } menu.BeginApply(startup); } } internal void OnWorldLoadingRequested(string source) { if (state != BrandingState.WorldLoading && state != BrandingState.WorldActive) { menu.Hide(); Transition(BrandingState.WorldLoading); log("[FehuBranding] Entering world loading (" + source + ")"); loading.Arm(); } } internal void OnSceneLoaderStart(SceneLoader loader) { if (state == BrandingState.WorldLoading) { loading.Attach(loader); } } internal void OnSceneLoaderDestroyed(SceneLoader loader) { loading.Detach(loader); } internal void OnHudAwake(Hud hud) { if (state == BrandingState.WorldLoading) { loading.Attach(hud); } } internal void OnHudDestroyed(Hud hud) { loading.Detach(hud); } internal void OnWorldActive() { if (state == BrandingState.WorldLoading) { Transition(BrandingState.WorldActive); log("[FehuBranding] World active"); loading.Complete(); } } internal void OnLoadingCancelled(string reason) { if (state == BrandingState.WorldLoading) { loading.Cancel(); Transition(BrandingState.WaitingForMainMenu); log("[FehuBranding] World loading cancelled (" + reason + ")"); } } internal void OnConnectionFailureAcknowledged(FejdStartup startup) { OnLoadingCancelled("connection failure acknowledged"); OnMainMenuReady(startup); } internal void OnGameEnding(string reason) { if (state == BrandingState.WorldLoading || state == BrandingState.WorldActive) { loading.Cancel(); Transition(BrandingState.WaitingForMainMenu); log("[FehuBranding] Loading cleanup (" + reason + ")"); } } internal void Shutdown() { menu.Cancel(); loading.Cancel(); } private void Transition(BrandingState next) { if (state != next) { log("[FehuBranding] State " + Format(state) + " -> " + Format(next)); state = next; } } private static string Format(BrandingState value) { return value switch { BrandingState.Boot => "BOOT", BrandingState.WaitingForMainMenu => "WAITING_FOR_MAIN_MENU", BrandingState.MainMenuReady => "MAIN_MENU_READY", BrandingState.WorldLoading => "WORLD_LOADING", BrandingState.WorldActive => "WORLD_ACTIVE", _ => value.ToString().ToUpperInvariant(), }; } } } namespace FehuBranding.Config { internal sealed class BrandingConfig { internal readonly ConfigEntry<bool> Enabled; internal readonly ConfigEntry<bool> LogoEnabled; internal readonly ConfigEntry<bool> LoadingEnabled; internal readonly ConfigEntry<float> ImageIntervalSeconds; internal readonly ConfigEntry<float> FadeDurationSeconds; internal readonly ConfigEntry<bool> SkipIntro; internal BrandingConfig(ConfigFile config) { Enabled = config.Bind<bool>("Branding", "Enabled", true, "Enable FehuBranding."); LogoEnabled = config.Bind<bool>("MainMenu", "LogoEnabled", true, "Replace the native main-menu logo."); LoadingEnabled = config.Bind<bool>("Loading", "Enabled", true, "Replace the native loading image only."); ImageIntervalSeconds = config.Bind<float>("Loading", "ImageIntervalSeconds", 4f, "Seconds each custom loading image remains visible."); FadeDurationSeconds = config.Bind<float>("Loading", "FadeDurationSeconds", 0.5f, "Crossfade duration between loading images. Set to 0 for an instant change."); SkipIntro = config.Bind<bool>("Startup", "SkipIntro", true, "Bypass the startup cinematic before it can begin playback."); } } } namespace FehuBranding.Assets { internal sealed class BrandingAssetCache { private readonly string root; private readonly Action<string> log; private readonly Dictionary<string, Sprite> logoSprites = new Dictionary<string, Sprite>(StringComparer.OrdinalIgnoreCase); private readonly List<Sprite> loadingSprites = new List<Sprite>(); private readonly List<Texture2D> loadingTextures = new List<Texture2D>(); private bool loadingDiscovered; private bool performanceLogged; internal int LoadingImageCount => loadingSprites.Count; internal string DllPath { get; } internal string PluginRoot => root; internal string AssetRoot => Path.Combine(root, "Assets"); internal string SubtitleLogoPath => Path.Combine(root, "Assets", "Logo", "subtitle_logo.png"); internal string LoadingDirectory => Path.Combine(root, "Assets", "Loading"); internal string MainLogoPath => Path.Combine(root, "Assets", "Logo", "main_logo.png"); internal BrandingAssetCache(string dllPath, Action<string> logger) { if (string.IsNullOrWhiteSpace(dllPath)) { throw new ArgumentException("Loaded FehuBranding DLL location is unavailable", "dllPath"); } DllPath = Path.GetFullPath(dllPath); root = Path.GetDirectoryName(DllPath); if (string.IsNullOrEmpty(root)) { throw new ArgumentException("Loaded FehuBranding DLL directory is unavailable", "dllPath"); } log = logger; } internal Sprite GetMainLogo() { if (logoSprites.TryGetValue("Assets/Logo/main_logo.png", out var value)) { return value; } value = LoadSprite(Path.Combine(root, "Assets/Logo/main_logo.png"), loadingAsset: false); if ((Object)(object)value != (Object)null) { logoSprites["Assets/Logo/main_logo.png"] = value; } return value; } internal Sprite GetSubtitleLogo() { if (logoSprites.TryGetValue("Assets/Logo/subtitle_logo.png", out var value)) { return value; } value = LoadSprite(Path.Combine(root, "Assets/Logo/subtitle_logo.png"), loadingAsset: false); if ((Object)(object)value != (Object)null) { logoSprites["Assets/Logo/subtitle_logo.png"] = value; } return value; } internal IReadOnlyList<Sprite> GetLoadingSprites() { if (loadingDiscovered) { return loadingSprites; } loadingDiscovered = true; string loadingDirectory = LoadingDirectory; Stopwatch stopwatch = Stopwatch.StartNew(); string[] array; try { array = (Directory.Exists(loadingDirectory) ? Directory.GetFiles(loadingDirectory) : Array.Empty<string>()); Array.Sort(array, (IComparer<string>?)StringComparer.OrdinalIgnoreCase); } catch (Exception) { array = Array.Empty<string>(); } stopwatch.Stop(); Stopwatch stopwatch2 = Stopwatch.StartNew(); string[] array2 = array; foreach (string path in array2) { string extension = Path.GetExtension(path); if (string.Equals(extension, ".png", StringComparison.OrdinalIgnoreCase) || string.Equals(extension, ".jpg", StringComparison.OrdinalIgnoreCase) || string.Equals(extension, ".jpeg", StringComparison.OrdinalIgnoreCase)) { Sprite val = LoadSprite(path, loadingAsset: true); if ((Object)(object)val != (Object)null) { loadingSprites.Add(val); } } } stopwatch2.Stop(); if (!performanceLogged) { performanceLogged = true; log("[FehuBranding] Asset discovery: " + stopwatch.ElapsedMilliseconds + " ms"); log("[FehuBranding] Image decode/cache: " + stopwatch2.ElapsedMilliseconds + " ms"); } log("[FehuBranding] Loading images discovered: " + loadingSprites.Count); return loadingSprites; } private Sprite LoadSprite(string path, bool loadingAsset) { //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Expected O, but got Unknown //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) try { if (!File.Exists(path)) { Plugin.Instance?.Warn("[FehuBranding] Image file not found: " + path); return null; } log("[FehuBranding] Logo file found: " + path); byte[] array = File.ReadAllBytes(path); Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false) { name = Path.GetFileName(path) }; if (!ImageConversion.LoadImage(val, array)) { Object.Destroy((Object)(object)val); Plugin.Instance?.Error("[FehuBranding] Failed to load image: " + Path.GetFileName(path)); return null; } log("[FehuBranding] Texture loaded: " + Path.GetFileName(path) + " (" + ((Texture)val).width + "x" + ((Texture)val).height + ")"); Sprite obj = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f)); ((Object)obj).name = ((Object)val).name; if (loadingAsset) { loadingTextures.Add(val); } return obj; } catch (Exception) { Plugin.Instance?.Error("[FehuBranding] Failed to load image: " + Path.GetFileName(path)); return null; } } internal void Clear() { foreach (Sprite loadingSprite in loadingSprites) { if ((Object)(object)loadingSprite != (Object)null) { Object.Destroy((Object)(object)loadingSprite); } } foreach (Texture2D loadingTexture in loadingTextures) { if ((Object)(object)loadingTexture != (Object)null) { Object.Destroy((Object)(object)loadingTexture); } } loadingSprites.Clear(); loadingTextures.Clear(); foreach (Sprite value in logoSprites.Values) { if (!((Object)(object)value == (Object)null)) { Texture2D texture = value.texture; Object.Destroy((Object)(object)value); if ((Object)(object)texture != (Object)null) { Object.Destroy((Object)(object)texture); } } } logoSprites.Clear(); } } }