Decompiled source of balrond immersiveloading v1.0.2

plugins/BalrondImmersiveLoading.dll

Decompiled a week ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using HarmonyLib;
using UnityEngine;
using UnityEngine.Audio;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("BalrondImmersiveLoading")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("BalrondImmersiveLoading")]
[assembly: AssemblyCopyright("Copyright ©  2022")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("cde312a0-cf19-4264-8616-e1c74774beed")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace BalrondImmersiveLoading;

[BepInPlugin("balrond.astafaraios.immersiveloading", "BalrondImmersiveLoading", "1.0.2")]
public class BalrondImmersiveLoading : BaseUnityPlugin
{
	[HarmonyPatch(typeof(Player), "OnSpawned")]
	private static class Player_OnSpawned_Patch
	{
		private static void Postfix()
		{
			LoadingMusicService.Stop("balrond_immersive_loading_main", immediate: false);
		}
	}

	[HarmonyPatch(typeof(Hud), "UpdateBlackScreen")]
	private static class Hud_UpdateBlackScreen_Patch
	{
		private static void Prefix(bool ___m_haveSetupLoadScreen, ref bool __state)
		{
			__state = !___m_haveSetupLoadScreen;
		}

		private static void Postfix(Hud __instance, bool ___m_haveSetupLoadScreen, bool __state)
		{
			if ((Object)(object)__instance == (Object)null || !LoadingBackgroundService.HasAny() || !__state || !___m_haveSetupLoadScreen)
			{
				return;
			}
			Image loadingImage = __instance.m_loadingImage;
			if ((Object)(object)loadingImage == (Object)null)
			{
				return;
			}
			Transform val = (((Object)(object)__instance.m_loadingProgress != (Object)null) ? __instance.m_loadingProgress.transform : null);
			Image topFadeTemplate = null;
			Image bottomFadeTemplate = null;
			if ((Object)(object)val != (Object)null)
			{
				Transform val2 = val.Find("TopFade");
				if ((Object)(object)val2 != (Object)null)
				{
					topFadeTemplate = ((Component)val2).GetComponent<Image>();
				}
				Transform val3 = val.Find("BottomFade");
				if ((Object)(object)val3 != (Object)null)
				{
					bottomFadeTemplate = ((Component)val3).GetComponent<Image>();
				}
			}
			LoadingBackgroundService.AttachToExistingImage("balrond_immersive_loading_main", loadingImage, topFadeTemplate, bottomFadeTemplate);
		}
	}

	public const string PluginGUID = "balrond.astafaraios.immersiveloading";

	public const string PluginName = "BalrondImmersiveLoading";

	public const string PluginVersion = "1.0.2";

	private const string BundleResourceName = "balrondimmersiveloading";

	private const string AssetBasePath = "Assets/Custom/BalrondImmersiveLoading/";

	private readonly Harmony harmony = new Harmony("balrond.astafaraios.immersiveloading");

	private AssetBundle assetBundle;

	private GameObject backgroundMusic;

	private readonly List<Texture2D> loadingTextures = new List<Texture2D>();

	private void Awake()
	{
		LoadAssetBundle();
		LoadBackgrounds();
		LoadingBackgroundService.Initialize(1.2f, 3f, enableSlideshow: true, avoidImmediateRepeat: true, 0.08f);
		LoadingBackgroundService.SetTextures(loadingTextures);
		LoadBackgroundMusic();
		LoadingMusicService.Initialize(0.5f, 1f, 1f);
		LoadingMusicService.SetPrefab(backgroundMusic);
		harmony.PatchAll();
	}

	private void OnDestroy()
	{
		harmony.UnpatchSelf();
	}

	private void LoadAssetBundle()
	{
		assetBundle = GetAssetBundleFromResources("balrondimmersiveloading");
		if ((Object)(object)assetBundle == (Object)null)
		{
			Debug.LogError((object)"[BalrondImmersiveLoading] Failed to load asset bundle from embedded resources: balrondimmersiveloading");
		}
		else
		{
			Debug.Log((object)"[BalrondImmersiveLoading] Asset bundle loaded: balrondimmersiveloading");
		}
	}

	private void LoadBackgroundMusic()
	{
		if ((Object)(object)assetBundle == (Object)null)
		{
			Debug.LogError((object)"[BalrondImmersiveLoading] Cannot load background music because asset bundle is null.");
			return;
		}
		string text = "Assets/Custom/BalrondImmersiveLoading/Audio/BackgroundMusic.prefab";
		backgroundMusic = assetBundle.LoadAsset<GameObject>(text);
		if ((Object)(object)backgroundMusic == (Object)null)
		{
			Debug.LogWarning((object)("[BalrondImmersiveLoading] Could not find background music prefab: " + text));
		}
		else
		{
			Debug.Log((object)("[BalrondImmersiveLoading] Background music prefab loaded: " + text));
		}
	}

	private void LoadBackgrounds()
	{
		loadingTextures.Clear();
		if ((Object)(object)assetBundle == (Object)null)
		{
			Debug.LogError((object)"[BalrondImmersiveLoading] Cannot load backgrounds because asset bundle is null.");
			return;
		}
		string text = "Assets/Custom/BalrondImmersiveLoading/Backgrounds/";
		string[] array = new string[31]
		{
			"mats-minnhagen-apple-release.jpg", "mats-minnhagen-ashlands-encounter.jpg", "mats-minnhagen-ashlands-fortress.jpg", "mats-minnhagen-ashlands-ruins.jpg", "mats-minnhagen-ashlands-ship.jpg", "mats-minnhagen-bog-witch.jpg", "mats-minnhagen-mistletoe.jpg", "mats-minnhagen-the-battle.jpg", "mats-minnhagen-valheim-base.jpg", "mats-minnhagen-valheim-dragons.jpg",
			"mats-minnhagen-valheim-gjall.jpg", "mats-minnhagen-valheim-halloween.jpg", "mats-minnhagen-valheim-halloween2.jpg", "mats-minnhagen-valheim-hildir.jpg", "mats-minnhagen-valheim-midsummer.jpg", "mats-minnhagen-valheim-mistlands.jpg", "mats-minnhagen-valheim-misunderstanding.jpg", "mats-minnhagen-valheim-seeker.jpg", "mats-minnhagen-valheim-serpent.jpg", "mats-minnhagen-valheim-valborg.jpg",
			"mats-minnhagen-valheim-valentine.jpg", "mats-minnhagen-valheim-xbox.jpg", "mats-minnhagen-valheim-yule.jpg", "mats-minnhagen-bearwithme.jpg", "mats-minnhagen-borealis.jpg", "mats-minnhagen-feast-table.jpg", "mats-minnhagen-forest-battle.jpg", "mats-minnhagen-guten-morgen.jpg", "mats-minnhagen-neck-lake.jpg", "mats-minnhagen-training.jpg",
			"mats-minnhagen-winterslip-release.jpg"
		};
		string[] array2 = array;
		foreach (string text2 in array2)
		{
			string text3 = text + text2;
			Texture2D val = assetBundle.LoadAsset<Texture2D>(text3);
			if ((Object)(object)val == (Object)null)
			{
				Debug.LogWarning((object)("[BalrondImmersiveLoading] Could not find background texture: " + text3));
			}
			else
			{
				loadingTextures.Add(val);
			}
		}
		Debug.Log((object)("[BalrondImmersiveLoading] Loaded background textures: " + loadingTextures.Count));
	}

	private static AssetBundle GetAssetBundleFromResources(string filename)
	{
		Assembly executingAssembly = Assembly.GetExecutingAssembly();
		string text = executingAssembly.GetManifestResourceNames().SingleOrDefault((string str) => str.EndsWith(filename));
		if (string.IsNullOrEmpty(text))
		{
			Debug.LogError((object)("[BalrondImmersiveLoading] Embedded resource not found: " + filename));
			return null;
		}
		using Stream stream = executingAssembly.GetManifestResourceStream(text);
		if (stream == null)
		{
			Debug.LogError((object)("[BalrondImmersiveLoading] Embedded resource stream is null: " + text));
			return null;
		}
		return AssetBundle.LoadFromStream(stream);
	}
}
public static class LoadingBackgroundService
{
	private sealed class CoroutineHost : MonoBehaviour
	{
	}

	private sealed class Slot
	{
		public string Key;

		public Image Front;

		public Image Back;

		public Image LeftFade;

		public Image RightFade;

		public CoroutineHost Host;

		public Coroutine Routine;

		public bool Running;

		public int LastIndex = -1;
	}

	private static readonly List<Texture2D> _textures = new List<Texture2D>();

	private static readonly List<Sprite> _sprites = new List<Sprite>();

	private static readonly Dictionary<string, Slot> _slots = new Dictionary<string, Slot>();

	private static bool _initialized;

	public static float FadeDuration { get; private set; } = 1f;


	public static float HoldDuration { get; private set; } = 3f;


	public static bool EnableSlideshow { get; private set; } = true;


	public static bool AvoidImmediateRepeat { get; private set; } = true;


	public static float SideFadeWidthPercent { get; private set; } = 0.12f;


	public static float SideFadeEdgeOffset { get; private set; } = 350f;


	public static void Initialize(float fadeDuration = 1f, float holdDuration = 3f, bool enableSlideshow = true, bool avoidImmediateRepeat = true, float sideFadeWidthPercent = 0.12f, float sideFadeEdgeOffset = 350f)
	{
		FadeDuration = Mathf.Max(0.01f, fadeDuration);
		HoldDuration = Mathf.Max(0.01f, holdDuration);
		EnableSlideshow = enableSlideshow;
		AvoidImmediateRepeat = avoidImmediateRepeat;
		SideFadeWidthPercent = Mathf.Clamp(sideFadeWidthPercent, 0.01f, 0.45f);
		SideFadeEdgeOffset = sideFadeEdgeOffset;
		_initialized = true;
	}

	public static bool HasAny()
	{
		return _initialized && _sprites.Count > 0;
	}

	public static void SetTextures(List<Texture2D> textures)
	{
		//IL_0077: Unknown result type (might be due to invalid IL or missing references)
		//IL_0086: Unknown result type (might be due to invalid IL or missing references)
		EnsureInitialized();
		RemoveAll();
		ClearSprites();
		_textures.Clear();
		if (textures == null || textures.Count == 0)
		{
			return;
		}
		for (int i = 0; i < textures.Count; i++)
		{
			Texture2D val = textures[i];
			if (!((Object)(object)val == (Object)null))
			{
				_textures.Add(val);
				Sprite item = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f);
				_sprites.Add(item);
			}
		}
	}

	public static void AddTextures(List<Texture2D> textures)
	{
		//IL_0060: 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)
		EnsureInitialized();
		if (textures == null || textures.Count == 0)
		{
			return;
		}
		for (int i = 0; i < textures.Count; i++)
		{
			Texture2D val = textures[i];
			if (!((Object)(object)val == (Object)null))
			{
				_textures.Add(val);
				Sprite item = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f);
				_sprites.Add(item);
			}
		}
	}

	public static void AttachToExistingImage(string key, Image target, Image topFadeTemplate = null, Image bottomFadeTemplate = null)
	{
		//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c6: Expected O, but got Unknown
		EnsureInitialized();
		if (string.IsNullOrEmpty(key) || (Object)(object)target == (Object)null || !HasAny())
		{
			return;
		}
		Remove(key);
		Transform parent = ((Component)target).transform.parent;
		if ((Object)(object)parent == (Object)null)
		{
			return;
		}
		GameObject val = Object.Instantiate<GameObject>(((Component)target).gameObject, parent);
		((Object)val).name = ((Object)((Component)target).gameObject).name + "_CustomLoading_Back";
		Image component = val.GetComponent<Image>();
		if ((Object)(object)component == (Object)null)
		{
			Object.Destroy((Object)(object)val);
			return;
		}
		CopyRectTransform(((Graphic)target).rectTransform, ((Graphic)component).rectTransform);
		CopyImageVisualSettings(target, component);
		NormalizeManagedImage(component);
		((Component)component).transform.SetSiblingIndex(((Component)target).transform.GetSiblingIndex() + 1);
		Image val2 = null;
		Image val3 = null;
		if ((Object)(object)topFadeTemplate != (Object)null || (Object)(object)bottomFadeTemplate != (Object)null)
		{
			Image fadeTemplate = (((Object)(object)topFadeTemplate != (Object)null) ? topFadeTemplate : bottomFadeTemplate);
			Image fadeTemplate2 = (((Object)(object)bottomFadeTemplate != (Object)null) ? bottomFadeTemplate : topFadeTemplate);
			val2 = CreateSideFade(target, fadeTemplate, isLeft: true);
			val3 = CreateSideFade(target, fadeTemplate2, isLeft: false);
			if ((Object)(object)val2 != (Object)null)
			{
				((Component)val2).transform.SetSiblingIndex(((Component)component).transform.GetSiblingIndex() + 1);
			}
			if ((Object)(object)val3 != (Object)null)
			{
				int siblingIndex = (((Object)(object)val2 != (Object)null) ? (((Component)val2).transform.GetSiblingIndex() + 1) : (((Component)component).transform.GetSiblingIndex() + 1));
				((Component)val3).transform.SetSiblingIndex(siblingIndex);
			}
		}
		GameObject val4 = new GameObject("CustomLoadingCoroutineHost_" + key, new Type[1] { typeof(RectTransform) });
		val4.transform.SetParent(parent, false);
		RectTransform component2 = val4.GetComponent<RectTransform>();
		CopyRectTransform(((Graphic)target).rectTransform, component2);
		int siblingIndex2 = ((Component)component).transform.GetSiblingIndex() + 1;
		if ((Object)(object)val3 != (Object)null)
		{
			siblingIndex2 = ((Component)val3).transform.GetSiblingIndex() + 1;
		}
		else if ((Object)(object)val2 != (Object)null)
		{
			siblingIndex2 = ((Component)val2).transform.GetSiblingIndex() + 1;
		}
		val4.transform.SetSiblingIndex(siblingIndex2);
		CoroutineHost coroutineHost = val4.AddComponent<CoroutineHost>();
		LoadingMusicService.Play(key, val4.transform);
		int pickedIndex;
		Sprite randomSprite = GetRandomSprite(-1, out pickedIndex);
		if ((Object)(object)randomSprite == (Object)null)
		{
			Object.Destroy((Object)(object)val);
			if ((Object)(object)val2 != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)val2).gameObject);
			}
			if ((Object)(object)val3 != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)val3).gameObject);
			}
			Object.Destroy((Object)(object)val4);
			return;
		}
		ApplySpriteToImage(target, randomSprite);
		SetAlpha(target, 1f);
		component.sprite = null;
		SetAlpha(component, 0f);
		Slot slot = new Slot
		{
			Key = key,
			Front = target,
			Back = component,
			LeftFade = val2,
			RightFade = val3,
			Host = coroutineHost,
			Running = true,
			LastIndex = pickedIndex
		};
		_slots[key] = slot;
		if (EnableSlideshow && _sprites.Count > 1)
		{
			slot.Routine = ((MonoBehaviour)coroutineHost).StartCoroutine(SlideshowLoop(slot));
		}
	}

	public static void Remove(string key)
	{
		if (!string.IsNullOrEmpty(key) && _slots.TryGetValue(key, out var value))
		{
			value.Running = false;
			LoadingMusicService.Stop(key, immediate: false);
			if ((Object)(object)value.Host != (Object)null && value.Routine != null)
			{
				((MonoBehaviour)value.Host).StopCoroutine(value.Routine);
			}
			if ((Object)(object)value.Back != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)value.Back).gameObject);
			}
			if ((Object)(object)value.LeftFade != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)value.LeftFade).gameObject);
			}
			if ((Object)(object)value.RightFade != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)value.RightFade).gameObject);
			}
			if ((Object)(object)value.Host != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)value.Host).gameObject);
			}
			_slots.Remove(key);
		}
	}

	public static void RemoveAll()
	{
		List<string> list = new List<string>(_slots.Keys);
		for (int i = 0; i < list.Count; i++)
		{
			Remove(list[i]);
		}
	}

	public static void Shutdown()
	{
		RemoveAll();
		ClearSprites();
		_textures.Clear();
		_initialized = false;
		LoadingMusicService.StopAll(immediate: true);
	}

	private static IEnumerator SlideshowLoop(Slot slot)
	{
		while (slot?.Running ?? false)
		{
			yield return (object)new WaitForSeconds(HoldDuration);
			if (!slot.Running || (Object)(object)slot.Front == (Object)null || (Object)(object)slot.Back == (Object)null)
			{
				break;
			}
			int newIndex;
			Sprite next = GetRandomSprite(slot.LastIndex, out newIndex);
			if (!((Object)(object)next == (Object)null))
			{
				ApplySpriteToImage(slot.Back, next);
				SetAlpha(slot.Back, 0f);
				yield return Fade(slot.Front, slot.Back, slot);
				if (!slot.Running)
				{
					break;
				}
				Image temp = slot.Front;
				slot.Front = slot.Back;
				slot.Back = temp;
				slot.Back.sprite = null;
				SetAlpha(slot.Back, 0f);
				SetAlpha(slot.Front, 1f);
				slot.LastIndex = newIndex;
			}
		}
	}

	private static IEnumerator Fade(Image from, Image to, Slot slot)
	{
		float time = 0f;
		SetAlpha(from, 1f);
		SetAlpha(to, 0f);
		while (time < FadeDuration)
		{
			if (slot == null || !slot.Running || (Object)(object)from == (Object)null || (Object)(object)to == (Object)null)
			{
				yield break;
			}
			time += Time.deltaTime;
			float t = Mathf.Clamp01(time / FadeDuration);
			SetAlpha(from, 1f - t);
			SetAlpha(to, t);
			yield return null;
		}
		SetAlpha(from, 0f);
		SetAlpha(to, 1f);
	}

	private static Image CreateSideFade(Image target, Image fadeTemplate, bool isLeft)
	{
		//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
		//IL_0107: Unknown result type (might be due to invalid IL or missing references)
		//IL_010c: Unknown result type (might be due to invalid IL or missing references)
		//IL_010e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0117: Unknown result type (might be due to invalid IL or missing references)
		//IL_0141: Unknown result type (might be due to invalid IL or missing references)
		//IL_014f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0166: Unknown result type (might be due to invalid IL or missing references)
		//IL_0173: Unknown result type (might be due to invalid IL or missing references)
		//IL_0180: Unknown result type (might be due to invalid IL or missing references)
		//IL_0191: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
		//IL_0207: Unknown result type (might be due to invalid IL or missing references)
		//IL_0211: Unknown result type (might be due to invalid IL or missing references)
		//IL_0237: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)target == (Object)null || (Object)(object)fadeTemplate == (Object)null)
		{
			return null;
		}
		Transform parent = ((Component)target).transform.parent;
		if ((Object)(object)parent == (Object)null)
		{
			return null;
		}
		GameObject val = Object.Instantiate<GameObject>(((Component)fadeTemplate).gameObject, parent);
		((Object)val).name = (isLeft ? "CustomLoading_LeftFade" : "CustomLoading_RightFade");
		Image component = val.GetComponent<Image>();
		if ((Object)(object)component == (Object)null)
		{
			Object.Destroy((Object)(object)val);
			return null;
		}
		RectTransform rectTransform = ((Graphic)target).rectTransform;
		RectTransform rectTransform2 = ((Graphic)component).rectTransform;
		component.sprite = fadeTemplate.sprite;
		((Graphic)component).material = ((Graphic)fadeTemplate).material;
		((Graphic)component).color = ((Graphic)fadeTemplate).color;
		component.type = fadeTemplate.type;
		component.preserveAspect = false;
		((MaskableGraphic)component).maskable = ((MaskableGraphic)fadeTemplate).maskable;
		((Graphic)component).raycastTarget = false;
		((Behaviour)component).enabled = true;
		float width = GetWidth(rectTransform);
		float height = GetHeight(rectTransform);
		Vector2 displayedSpriteSize = GetDisplayedSpriteSize(target, width, height);
		float x = displayedSpriteSize.x;
		float y = displayedSpriteSize.y;
		float num = Mathf.Max(1f, x * SideFadeWidthPercent);
		((Transform)rectTransform2).SetParent(parent, false);
		rectTransform2.anchorMin = rectTransform.anchorMin;
		rectTransform2.anchorMax = rectTransform.anchorMax;
		rectTransform2.pivot = new Vector2(0.5f, 0.5f);
		((Transform)rectTransform2).localScale = Vector3.one;
		((Transform)rectTransform2).localRotation = Quaternion.identity;
		rectTransform2.sizeDelta = new Vector2(num, y);
		float num2 = x * 0.5f;
		float num3 = Mathf.Max(2f, num * 0.08f);
		float sideFadeEdgeOffset = SideFadeEdgeOffset;
		float num4 = (isLeft ? (rectTransform.anchoredPosition.x - num2 + num * 0.5f + num3 - sideFadeEdgeOffset) : (rectTransform.anchoredPosition.x + num2 - num * 0.5f - num3 + sideFadeEdgeOffset));
		rectTransform2.anchoredPosition = new Vector2(num4, rectTransform.anchoredPosition.y);
		((Transform)rectTransform2).localEulerAngles = new Vector3(0f, 0f, isLeft ? 90f : (-90f));
		return component;
	}

	private static Vector2 GetDisplayedSpriteSize(Image image, float rectWidth, float rectHeight)
	{
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		//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)
		//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_005d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0062: Unknown result type (might be due to invalid IL or missing references)
		//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_008d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0092: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)image == (Object)null)
		{
			return new Vector2(rectWidth, rectHeight);
		}
		if ((Object)(object)image.sprite == (Object)null)
		{
			return new Vector2(rectWidth, rectHeight);
		}
		if (!image.preserveAspect)
		{
			return new Vector2(rectWidth, rectHeight);
		}
		Rect rect = image.sprite.rect;
		if (((Rect)(ref rect)).width <= 0f || ((Rect)(ref rect)).height <= 0f)
		{
			return new Vector2(rectWidth, rectHeight);
		}
		float num = ((Rect)(ref rect)).width / ((Rect)(ref rect)).height;
		float num2 = rectWidth / rectHeight;
		if (num > num2)
		{
			float num3 = rectWidth / num;
			return new Vector2(rectWidth, num3);
		}
		float num4 = rectHeight * num;
		return new Vector2(num4, rectHeight);
	}

	private static void ApplySpriteToImage(Image image, Sprite sprite)
	{
		if (!((Object)(object)image == (Object)null))
		{
			image.sprite = sprite;
			image.type = (Type)0;
			image.preserveAspect = true;
			((Behaviour)image).enabled = true;
		}
	}

	private static void NormalizeManagedImage(Image image)
	{
		if (!((Object)(object)image == (Object)null))
		{
			image.type = (Type)0;
			image.preserveAspect = true;
			((Graphic)image).raycastTarget = false;
			((Behaviour)image).enabled = true;
			((Graphic)image).material = null;
		}
	}

	private static void NormalizeFadeImage(Image image)
	{
		if (!((Object)(object)image == (Object)null))
		{
			((Graphic)image).raycastTarget = false;
			((Behaviour)image).enabled = true;
		}
	}

	private static void CopyImageVisualSettings(Image source, Image target)
	{
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)source == (Object)null) && !((Object)(object)target == (Object)null))
		{
			target.type = source.type;
			target.preserveAspect = source.preserveAspect;
			((Graphic)target).material = ((Graphic)source).material;
			((Graphic)target).color = ((Graphic)source).color;
			((Graphic)target).raycastTarget = false;
			((MaskableGraphic)target).maskable = ((MaskableGraphic)source).maskable;
			target.sprite = source.sprite;
		}
	}

	private static void CopyRectTransform(RectTransform source, RectTransform target)
	{
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		//IL_0050: Unknown result type (might be due to invalid IL or missing references)
		//IL_005d: Unknown result type (might be due to invalid IL or missing references)
		//IL_006a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0077: Unknown result type (might be due to invalid IL or missing references)
		//IL_0084: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)source == (Object)null) && !((Object)(object)target == (Object)null))
		{
			target.anchorMin = source.anchorMin;
			target.anchorMax = source.anchorMax;
			target.anchoredPosition = source.anchoredPosition;
			target.sizeDelta = source.sizeDelta;
			target.pivot = source.pivot;
			((Transform)target).localScale = ((Transform)source).localScale;
			((Transform)target).localRotation = ((Transform)source).localRotation;
			target.offsetMin = source.offsetMin;
			target.offsetMax = source.offsetMax;
		}
	}

	private static void SetAlpha(Image image, float alpha)
	{
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)image == (Object)null))
		{
			Color color = ((Graphic)image).color;
			color.a = alpha;
			((Graphic)image).color = color;
		}
	}

	private static Sprite GetRandomSprite(int lastIndex, out int pickedIndex)
	{
		pickedIndex = -1;
		if (_sprites.Count == 0)
		{
			return null;
		}
		if (_sprites.Count == 1)
		{
			pickedIndex = 0;
			return _sprites[0];
		}
		int num = Random.Range(0, _sprites.Count);
		if (AvoidImmediateRepeat)
		{
			int num2 = 0;
			while (num == lastIndex && num2 < 20)
			{
				num = Random.Range(0, _sprites.Count);
				num2++;
			}
		}
		pickedIndex = num;
		return _sprites[num];
	}

	private static float GetWidth(RectTransform rect)
	{
		//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_0036: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)rect == (Object)null)
		{
			return 0f;
		}
		Rect rect2 = rect.rect;
		float width = ((Rect)(ref rect2)).width;
		if (width > 0f)
		{
			return width;
		}
		width = rect.sizeDelta.x;
		if (width > 0f)
		{
			return width;
		}
		return 1920f;
	}

	private static float GetHeight(RectTransform rect)
	{
		//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_0036: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)rect == (Object)null)
		{
			return 0f;
		}
		Rect rect2 = rect.rect;
		float height = ((Rect)(ref rect2)).height;
		if (height > 0f)
		{
			return height;
		}
		height = rect.sizeDelta.y;
		if (height > 0f)
		{
			return height;
		}
		return 1080f;
	}

	private static void EnsureInitialized()
	{
		if (!_initialized)
		{
			Initialize();
		}
	}

	private static void ClearSprites()
	{
		for (int i = 0; i < _sprites.Count; i++)
		{
			if ((Object)(object)_sprites[i] != (Object)null)
			{
				Object.Destroy((Object)(object)_sprites[i]);
			}
		}
		_sprites.Clear();
	}
}
public static class LoadingMusicService
{
	private sealed class CoroutineHost : MonoBehaviour
	{
	}

	private sealed class MusicSlot
	{
		public string Key;

		public GameObject Instance;

		public AudioSource Source;

		public CoroutineHost Host;

		public Coroutine FadeRoutine;

		public float LocalVolume;
	}

	private static readonly Dictionary<string, MusicSlot> _slots = new Dictionary<string, MusicSlot>();

	private static GameObject _backgroundMusicPrefab;

	public static float TargetVolume { get; private set; } = 0.5f;


	public static float FadeInDuration { get; private set; } = 1.5f;


	public static float FadeOutDuration { get; private set; } = 2f;


	public static bool UseValheimMusicMixer { get; private set; } = true;


	public static void Initialize(float targetVolume = 0.5f, float fadeInDuration = 1.5f, float fadeOutDuration = 2f, bool useValheimMusicMixer = true)
	{
		TargetVolume = Mathf.Clamp01(targetVolume);
		FadeInDuration = Mathf.Max(0.01f, fadeInDuration);
		FadeOutDuration = Mathf.Max(0.01f, fadeOutDuration);
		UseValheimMusicMixer = useValheimMusicMixer;
	}

	public static void SetPrefab(GameObject backgroundMusicPrefab)
	{
		_backgroundMusicPrefab = backgroundMusicPrefab;
	}

	public static void Play(string key, Transform parent)
	{
		if (string.IsNullOrEmpty(key) || (Object)(object)_backgroundMusicPrefab == (Object)null || (Object)(object)parent == (Object)null)
		{
			return;
		}
		Stop(key, immediate: true);
		GameObject val = Object.Instantiate<GameObject>(_backgroundMusicPrefab, parent, false);
		((Object)val).name = "Balrond_LoadingMusic_" + key;
		val.SetActive(true);
		AudioSource val2 = val.GetComponent<AudioSource>();
		if ((Object)(object)val2 == (Object)null)
		{
			val2 = val.GetComponentInChildren<AudioSource>(true);
		}
		if ((Object)(object)val2 == (Object)null || (Object)(object)val2.clip == (Object)null)
		{
			Object.Destroy((Object)(object)val);
			return;
		}
		ConfigureAudioSource(val2);
		CoroutineHost coroutineHost = val.GetComponent<CoroutineHost>();
		if ((Object)(object)coroutineHost == (Object)null)
		{
			coroutineHost = val.AddComponent<CoroutineHost>();
		}
		MusicSlot musicSlot = new MusicSlot
		{
			Key = key,
			Instance = val,
			Source = val2,
			Host = coroutineHost,
			LocalVolume = 0f
		};
		_slots[key] = musicSlot;
		val2.volume = 0f;
		val2.Play();
		musicSlot.FadeRoutine = ((MonoBehaviour)coroutineHost).StartCoroutine(FadeSlotVolume(musicSlot, 0f, TargetVolume, FadeInDuration));
	}

	public static void Stop(string key, bool immediate)
	{
		//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b8: Expected O, but got Unknown
		if (string.IsNullOrEmpty(key) || !_slots.TryGetValue(key, out var value))
		{
			return;
		}
		_slots.Remove(key);
		if (value != null && !((Object)(object)value.Instance == (Object)null))
		{
			if ((Object)(object)value.Host != (Object)null && value.FadeRoutine != null)
			{
				((MonoBehaviour)value.Host).StopCoroutine(value.FadeRoutine);
			}
			if (immediate || (Object)(object)value.Source == (Object)null)
			{
				Object.Destroy((Object)(object)value.Instance);
				return;
			}
			GameObject val = new GameObject("Balrond_LoadingMusic_FadeOutHost");
			CoroutineHost coroutineHost = val.AddComponent<CoroutineHost>();
			value.Instance.transform.SetParent(val.transform, true);
			((MonoBehaviour)coroutineHost).StartCoroutine(FadeOutAndDestroy(value.Instance, value.Source, val, value.LocalVolume));
		}
	}

	public static void StopAll(bool immediate)
	{
		List<string> list = new List<string>(_slots.Keys);
		for (int i = 0; i < list.Count; i++)
		{
			Stop(list[i], immediate);
		}
	}

	public static void RefreshVolumes()
	{
		foreach (MusicSlot value in _slots.Values)
		{
			if (value != null && (Object)(object)value.Source != (Object)null)
			{
				value.Source.volume = GetFinalVolume(value.LocalVolume);
			}
		}
	}

	private static void ConfigureAudioSource(AudioSource source)
	{
		if ((Object)(object)source == (Object)null)
		{
			return;
		}
		source.playOnAwake = false;
		source.loop = true;
		source.spatialBlend = 0f;
		source.priority = 0;
		source.bypassReverbZones = true;
		if (UseValheimMusicMixer)
		{
			AudioMixerGroup valheimMusicMixer = GetValheimMusicMixer();
			if ((Object)(object)valheimMusicMixer != (Object)null)
			{
				source.outputAudioMixerGroup = valheimMusicMixer;
			}
		}
	}

	private static IEnumerator FadeSlotVolume(MusicSlot slot, float from, float to, float duration)
	{
		if (slot == null || (Object)(object)slot.Source == (Object)null)
		{
			yield break;
		}
		float time = 0f;
		slot.LocalVolume = from;
		slot.Source.volume = GetFinalVolume(from);
		while (time < duration)
		{
			if (slot == null || (Object)(object)slot.Source == (Object)null)
			{
				yield break;
			}
			time += Time.unscaledDeltaTime;
			float t = Mathf.Clamp01(time / duration);
			slot.LocalVolume = Mathf.Lerp(from, to, t);
			slot.Source.volume = GetFinalVolume(slot.LocalVolume);
			yield return null;
		}
		if ((Object)(object)slot.Source != (Object)null)
		{
			slot.LocalVolume = to;
			slot.Source.volume = GetFinalVolume(to);
		}
	}

	private static IEnumerator FadeOutAndDestroy(GameObject instance, AudioSource source, GameObject hostObject, float startLocalVolume)
	{
		if ((Object)(object)source == (Object)null)
		{
			if ((Object)(object)instance != (Object)null)
			{
				Object.Destroy((Object)(object)instance);
			}
			if ((Object)(object)hostObject != (Object)null)
			{
				Object.Destroy((Object)(object)hostObject);
			}
			yield break;
		}
		float time = 0f;
		while (time < FadeOutDuration)
		{
			if ((Object)(object)source == (Object)null)
			{
				yield break;
			}
			time += Time.unscaledDeltaTime;
			float t = Mathf.Clamp01(time / FadeOutDuration);
			float localVolume = Mathf.Lerp(startLocalVolume, 0f, t);
			source.volume = GetFinalVolume(localVolume);
			yield return null;
		}
		if ((Object)(object)source != (Object)null)
		{
			source.Stop();
		}
		if ((Object)(object)instance != (Object)null)
		{
			Object.Destroy((Object)(object)instance);
		}
		if ((Object)(object)hostObject != (Object)null)
		{
			Object.Destroy((Object)(object)hostObject);
		}
	}

	private static AudioMixerGroup GetValheimMusicMixer()
	{
		if ((Object)(object)MusicMan.instance == (Object)null)
		{
			return null;
		}
		return MusicMan.instance.m_musicMixer;
	}

	private static float GetFinalVolume(float localVolume)
	{
		return Mathf.Clamp01(localVolume) * MusicMan.m_masterMusicVolume;
	}
}