Decompiled source of FehuBranding v420.101.21

BepInEx/plugins/BlackViking-FehuBranding/FehuBranding.dll

Decompiled 2 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using 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();
		}
	}
}