Decompiled source of TrombLoader v2.3.0

BepInEx/plugins/TrombLoader.dll

Decompiled 6 months ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Serialization;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text.RegularExpressions;
using BaboonAPI.Hooks.Initializer;
using BaboonAPI.Hooks.Tracks;
using BaboonAPI.Utility;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using Cinemachine;
using HarmonyLib;
using JetBrains.Annotations;
using Microsoft.CodeAnalysis;
using Microsoft.FSharp.Core;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using TMPro;
using TrombLoader.CustomTracks;
using TrombLoader.CustomTracks.Backgrounds;
using TrombLoader.Data;
using TrombLoader.Helpers;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Networking;
using UnityEngine.Playables;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using UnityEngine.Video;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("TromboneChamps")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Trombone Champ Custom Chart Loader")]
[assembly: AssemblyFileVersion("2.3.0.0")]
[assembly: AssemblyInformationalVersion("2.3.0+0b4ce077bfe90d38d09b1cba1c95f50ecd12ab04")]
[assembly: AssemblyProduct("TrombLoader")]
[assembly: AssemblyTitle("TrombLoader")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/NyxTheShield/TrombLoader")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("2.3.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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 TrombLoader
{
	[BepInPlugin("TrombLoader", "TrombLoader", "2.3.0")]
	[BepInDependency("ch.offbeatwit.baboonapi.plugin", "2.1.0")]
	public class Plugin : BaseUnityPlugin
	{
		public static Plugin Instance;

		public ShaderHelper ShaderHelper;

		public ConfigEntry<int> beatsToShow;

		public ConfigEntry<bool> DeveloperMode;

		private Harmony _harmony = new Harmony("TrombLoader");

		private void Awake()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Expected O, but got Unknown
			ConfigFile val = new ConfigFile(Path.Combine(Paths.ConfigPath, "TrombLoader.cfg"), true);
			beatsToShow = val.Bind<int>("General", "Note Display Limit", 64, "The maximum amount of notes displayed on screen at once.");
			DeveloperMode = val.Bind<bool>("Charting", "Developer Mode", false, "When enabled, TrombLoader will re-read chart data from disk each time a track is loaded.");
			Instance = this;
			LogInfo("Plugin TrombLoader is loaded!");
			GameInitializationEvent.Register(((BaseUnityPlugin)this).Info, (Action)TryInitialize);
			TrackRegistrationEvent.EVENT.Register((Listener)(object)new TrackLoader());
			ShaderHelper = new ShaderHelper();
		}

		private void TryInitialize()
		{
			_harmony.PatchAll();
		}

		public IEnumerator GetAudioClipSync(string path, Action callback = null)
		{
			Uri uri = new UriBuilder(Uri.UriSchemeFile, string.Empty)
			{
				Path = path
			}.Uri;
			UnityWebRequest www = UnityWebRequestMultimedia.GetAudioClip(uri, (AudioType)14);
			((DownloadHandlerAudioClip)www.downloadHandler).streamAudio = true;
			yield return www.SendWebRequest();
			while (!www.isDone)
			{
				yield return null;
			}
			if (www.isNetworkError || www.isHttpError)
			{
				yield return www.error;
				yield break;
			}
			callback?.Invoke();
			yield return DownloadHandlerAudioClip.GetContent(www);
		}

		public void LoadGameplayScene()
		{
			SceneManager.LoadSceneAsync("gameplay", (LoadSceneMode)0);
		}

		internal static void LogDebug(string message)
		{
			Instance.Log(message, (LogLevel)32);
		}

		internal static void LogInfo(string message)
		{
			Instance.Log(message, (LogLevel)16);
		}

		internal static void LogWarning(string message)
		{
			Instance.Log(message, (LogLevel)4);
		}

		internal static void LogError(string message)
		{
			Instance.Log(message, (LogLevel)2);
		}

		private void Log(string message, LogLevel logLevel)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			((BaseUnityPlugin)this).Logger.Log(logLevel, (object)message);
		}
	}
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "TrombLoader";

		public const string PLUGIN_NAME = "TrombLoader";

		public const string PLUGIN_VERSION = "2.3.0";
	}
}
namespace TrombLoader.Patch
{
	[HarmonyPatch]
	public class BeatsToShowPatch
	{
		[HarmonyPatch(typeof(GameController), "Start")]
		[HarmonyPrefix]
		private static void PatchBeatsToShow(out int ___beatstoshow)
		{
			___beatstoshow = Plugin.Instance.beatsToShow?.Value ?? 64;
		}
	}
	[HarmonyPatch(typeof(GameController))]
	[HarmonyPatch("startDance")]
	public class GameControllerStartDancePatch
	{
		private static void DoStartDance(GameController controller, float num)
		{
			BackgroundPuppetController component = controller.bgcontroller.fullbgobject.GetComponent<BackgroundPuppetController>();
			if ((Object)(object)component != (Object)null)
			{
				component.StartPuppetBob(num);
			}
		}

		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_0002: 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_0020: Expected O, but got Unknown
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Expected O, but got Unknown
			return new CodeMatcher(instructions, (ILGenerator)null).End().InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[3]
			{
				new CodeInstruction(OpCodes.Ldarg_0, (object)null),
				new CodeInstruction(OpCodes.Ldloc_0, (object)null),
				CodeInstruction.Call(typeof(GameControllerStartDancePatch), "DoStartDance", (Type[])null, (Type[])null)
			}).InstructionEnumeration();
		}
	}
	[HarmonyPatch(typeof(GameController))]
	[HarmonyPatch("Update")]
	public class GameControllerPuppetUpdatePatch
	{
		private static MethodInfo doPuppetControl_m = AccessTools.Method(typeof(HumanPuppetController), "doPuppetControl", (Type[])null, (Type[])null);

		private static void DoPuppetControl(GameController controller, float vp, float vibratoAmount)
		{
			BackgroundPuppetController component = controller.bgcontroller.fullbgobject.GetComponent<BackgroundPuppetController>();
			if ((Object)(object)component != (Object)null)
			{
				component.DoPuppetControl(vp * 2f, vibratoAmount);
			}
		}

		private static void Postfix(GameController __instance)
		{
			BackgroundPuppetController component = __instance.bgcontroller.fullbgobject.GetComponent<BackgroundPuppetController>();
			if ((Object)(object)component != (Object)null)
			{
				if (GlobalVariables.localsettings.mousecontrolmode <= 1)
				{
					component.DoManualDance(Input.GetAxis("Mouse X") * 1.25f * GlobalVariables.localsettings.sensitivity);
				}
				else
				{
					component.DoManualDance(Input.GetAxis("Mouse Y") * -1.25f * GlobalVariables.localsettings.sensitivity);
				}
			}
		}

		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Expected O, but got Unknown
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Expected O, but got Unknown
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Expected O, but got Unknown
			CodeMatcher obj = new CodeMatcher(instructions, (ILGenerator)null).SearchForward((Func<CodeInstruction, bool>)((CodeInstruction instruction) => CodeInstructionExtensions.Calls(instruction, doPuppetControl_m))).ThrowIfInvalid("Failed to find injection point in GameController#Update");
			CodeInstruction val = obj.InstructionAt(-3);
			if (!CodeInstructionExtensions.IsLdloc(val, (LocalBuilder)null))
			{
				throw new InvalidOperationException("Failed to find ldloc in GameController#Update");
			}
			return obj.Advance(1).InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[5]
			{
				new CodeInstruction(OpCodes.Ldarg_0, (object)null),
				new CodeInstruction(OpCodes.Ldloc_S, val.operand),
				new CodeInstruction(OpCodes.Ldarg_0, (object)null),
				CodeInstruction.LoadField(typeof(GameController), "vibratoamt", false),
				CodeInstruction.Call(typeof(GameControllerPuppetUpdatePatch), "DoPuppetControl", (Type[])null, (Type[])null)
			}).InstructionEnumeration();
		}
	}
	[HarmonyPatch(typeof(GameController))]
	[HarmonyPatch("setPuppetBreath")]
	public class GameControllerPuppetBreathPatch
	{
		private static void Postfix(GameController __instance, bool hasbreath)
		{
			BackgroundPuppetController component = __instance.bgcontroller.fullbgobject.GetComponent<BackgroundPuppetController>();
			if ((Object)(object)component != (Object)null)
			{
				component.SetPuppetBreath(hasbreath);
			}
		}
	}
	[HarmonyPatch(typeof(GameController))]
	[HarmonyPatch("setPuppetShake")]
	public class GameControllerPuppetShakePatch
	{
		private static void Postfix(GameController __instance, bool shake)
		{
			BackgroundPuppetController component = __instance.bgcontroller.fullbgobject.GetComponent<BackgroundPuppetController>();
			if ((Object)(object)component != (Object)null)
			{
				component.SetPuppetShake(shake);
			}
		}
	}
	[HarmonyPatch(typeof(HumanPuppetController))]
	[HarmonyPatch("startPuppetBob")]
	public class HumanPuppetControllerPuppetBobPatch
	{
		private static bool Prefix(HumanPuppetController __instance)
		{
			return !__instance.just_testing;
		}
	}
	[HarmonyPatch(typeof(HumanPuppetController))]
	[HarmonyPatch("testMovement")]
	public class HumanPuppetControllerTestMovementPatch
	{
		private static bool Prefix()
		{
			return false;
		}
	}
	[HarmonyPatch(typeof(HumanPuppetController))]
	[HarmonyPatch("Start")]
	public class HumanPuppetControllerStartPatch
	{
		private static bool Prefix(HumanPuppetController __instance)
		{
			return !((Object)(object)((Component)__instance).gameObject.GetComponent<CustomPuppetController>() != (Object)null);
		}

		private static void Postfix(HumanPuppetController __instance, bool __runOriginal)
		{
			if (!__runOriginal)
			{
				((MonoBehaviour)__instance).Invoke("setTextures", 0.5f);
				__instance.applyFaceTex();
			}
		}
	}
	[HarmonyPatch(typeof(GameController))]
	public class TrackEndPatch
	{
		[HarmonyPatch("Start")]
		[HarmonyPostfix]
		public static void FixTrackEnd(GameController __instance)
		{
			if (!((Object)(object)__instance.musictrack == (Object)null) && !((Object)(object)__instance.musictrack.clip == (Object)null))
			{
				float length = __instance.musictrack.clip.length;
				if (__instance.levelendtime >= length)
				{
					__instance.levelendtime = length - 0.001f;
				}
			}
		}
	}
}
namespace TrombLoader.Helpers
{
	public class BeatCounter : MonoBehaviour
	{
		public List<float> targetBeats;

		public float currentBeat;

		public UnityEvent actionToExecute;

		private bool isInitialized;

		public float bpm;

		public bool runOnZeroBeat;

		public void IncrementBeat()
		{
			if (!isInitialized)
			{
				isInitialized = true;
				if (!runOnZeroBeat)
				{
					return;
				}
			}
			if (targetBeats.Count == 0)
			{
				return;
			}
			float num = 0.125f;
			CheckNote(currentBeat);
			for (int i = 1; i < 8; i++)
			{
				float newTime = num * (float)i;
				float num2 = newTime * 60f / bpm;
				LeanTween.value(0f, 1f, num2).setOnComplete((Action)delegate
				{
					CheckNote(currentBeat + newTime);
				});
			}
			currentBeat += 1f;
		}

		private void CheckNote(float target)
		{
			if (targetBeats.Count != 0 && target >= targetBeats[0])
			{
				UnityEvent obj = actionToExecute;
				if (obj != null)
				{
					obj.Invoke();
				}
				targetBeats.RemoveAt(0);
			}
		}

		[ContextMenu("Parse String")]
		public void ParseFromString()
		{
			string systemCopyBuffer = GUIUtility.systemCopyBuffer;
			targetBeats = new List<float>();
			string[] array = systemCopyBuffer.Replace("[", "").Replace("]", "").Split(new char[1] { ',' });
			foreach (string s in array)
			{
				targetBeats.Add(float.Parse(s, CultureInfo.InvariantCulture));
			}
		}
	}
	public static class Globals
	{
		public static readonly string defaultChartName = "song.tmb";

		public static readonly string defaultAudioName = "song.ogg";

		public static readonly string defaultPreviewName = "preview.ogg";

		[Obsolete("No longer populated, use BaboonAPI to look up the track and cast to CustomTrack instead")]
		public static Dictionary<string, string> ChartFolders = new Dictionary<string, string>();

		[Obsolete("No longer controlled by TrombLoader")]
		public static bool SaveCreationEnabled = true;

		public static string GetCustomSongsPath()
		{
			return Path.Combine(Paths.BepInExRootPath, "CustomSongs/");
		}

		public static bool IsCustomTrack(string trackReference)
		{
			return TrackLookup.lookup(trackReference) is CustomTrack;
		}
	}
	public static class ImageHelper
	{
		public static Texture2D LoadTextureRaw(byte[] bytes)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			if (bytes.Count() > 0)
			{
				Texture2D val = new Texture2D(2, 2);
				if (ImageConversion.LoadImage(val, bytes))
				{
					return val;
				}
			}
			return null;
		}

		public static Texture2D LoadTextureFromFile(string path)
		{
			if (File.Exists(path))
			{
				return LoadTextureRaw(File.ReadAllBytes(path));
			}
			return null;
		}

		public static Texture2D LoadTextureFromResources(string resourcePath)
		{
			return LoadTextureRaw(GetResource(Assembly.GetCallingAssembly(), resourcePath));
		}

		public static Sprite LoadSpriteRaw(byte[] image, float pixelsPerUnit = 100f)
		{
			return LoadSpriteFromTexture(LoadTextureRaw(image), pixelsPerUnit);
		}

		public static Sprite LoadSpriteFromTexture(Texture2D texture, float pixelsPerUnit = 100f)
		{
			//IL_0021: 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)
			if (Object.op_Implicit((Object)(object)texture))
			{
				return Sprite.Create(texture, new Rect(0f, 0f, (float)((Texture)texture).width, (float)((Texture)texture).height), new Vector2(0.5f, 0.5f), pixelsPerUnit);
			}
			return null;
		}

		public static Sprite LoadSpriteFromFile(string path, float pixelsPerUnit = 100f)
		{
			return LoadSpriteFromTexture(LoadTextureFromFile(path), pixelsPerUnit);
		}

		public static Sprite LoadSpriteFromResources(string resourcePath, float pixelsPerUnit = 100f)
		{
			return LoadSpriteRaw(GetResource(Assembly.GetCallingAssembly(), resourcePath), pixelsPerUnit);
		}

		private static byte[] GetResource(Assembly asm, string resourcePath)
		{
			Stream manifestResourceStream = asm.GetManifestResourceStream(resourcePath);
			byte[] array = new byte[manifestResourceStream.Length];
			manifestResourceStream.Read(array, 0, (int)manifestResourceStream.Length);
			return array;
		}
	}
	public class SceneLightingHelper : MonoBehaviour
	{
		public Color ambientSkyColor = Color.black;

		public Color ambientEquatorColor = Color.black;

		public float ambientIntensity;

		public float reflectionIntensity;

		public Material skybox;

		public Light sun;

		public void Start()
		{
			//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)
			RenderSettings.ambientSkyColor = ambientSkyColor;
			RenderSettings.ambientEquatorColor = ambientEquatorColor;
			RenderSettings.ambientIntensity = ambientIntensity;
			RenderSettings.reflectionIntensity = reflectionIntensity;
			RenderSettings.skybox = skybox;
			RenderSettings.sun = sun;
		}
	}
	public class ShaderHelper
	{
		public List<string> BaseGameShaderNames = new List<string>
		{
			"Custom/WavySpriteLit", "Custom/WavySpriteUnlit", "FX/Flare", "FX/Gem", "GUI/Text Shader", "Hidden/BlitCopy", "Hidden/BlitCopyDepth", "Hidden/BlitCopyWithDepth", "Hidden/BlitToDepth", "Hidden/BlitToDepth/MSAA",
			"Hidden/Compositing", "Hidden/ConvertTexture", "Hidden/CubeBlend", "Hidden/CubeBlur", "Hidden/CubeCopy", "Hidden/FrameDebuggerRenderTargetDisplay", "Hidden/Internal-Colored", "Hidden/Internal-CombineDepthNormals", "Hidden/Internal-CubemapToEquirect", "Hidden/Internal-DeferredReflections",
			"Hidden/Internal-DeferredShading", "Hidden/Internal-DepthNormalsTexture", "Hidden/Internal-Flare", "Hidden/Internal-GUIRoundedRect", "Hidden/Internal-GUIRoundedRectWithColorPerBorder", "Hidden/Internal-GUITexture", "Hidden/Internal-GUITextureBlit", "Hidden/Internal-GUITextureClip", "Hidden/Internal-GUITextureClipText", "Hidden/Internal-Halo",
			"Hidden/Internal-MotionVectors", "Hidden/Internal-ODSWorldTexture", "Hidden/Internal-PrePassLighting", "Hidden/Internal-ScreenSpaceShadows", "Hidden/Internal-StencilWrite", "Hidden/Internal-UIRAtlasBlitCopy", "Hidden/Internal-UIRDefault", "Hidden/InternalClear", "Hidden/InternalErrorShader", "Hidden/Post FX/Ambient Occlusion",
			"Hidden/Post FX/Blit", "Hidden/Post FX/Bloom", "Hidden/Post FX/Builtin Debug Views", "Hidden/Post FX/Depth Of Field", "Hidden/Post FX/Eye Adaptation", "Hidden/Post FX/Fog", "Hidden/Post FX/FXAA", "Hidden/Post FX/Grain Generator", "Hidden/Post FX/Lut Generator", "Hidden/Post FX/Motion Blur",
			"Hidden/Post FX/Screen Space Reflection", "Hidden/Post FX/Temporal Anti-aliasing", "hidden/SuperSystems/Wireframe-Global", "hidden/SuperSystems/Wireframe-Shaded-Unlit-Global", "hidden/SuperSystems/Wireframe-Transparent-Culled-Global", "hidden/SuperSystems/Wireframe-Transparent-Global", "Hidden/TextCore/Distance Field SSD", "Hidden/VideoComposite", "Hidden/VideoDecode", "Hidden/VideoDecodeOSX",
			"Hidden/VR/BlitFromTex2DToTexArraySlice", "Hidden/VR/BlitTexArraySlice", "Legacy Shaders/Diffuse", "Legacy Shaders/Particles/Additive", "Legacy Shaders/Particles/Alpha Blended Premultiply", "Legacy Shaders/Particles/Alpha Blended", "Legacy Shaders/Transparent/VertexLit", "Legacy Shaders/VertexLit", "Mobile/Unlit (Supports Lightmap)", "Particles/Standard Unlit",
			"Skybox/Procedural", "Spaventacorvi/Glitter/Glitter F - Bumped Specular", "Spaventacorvi/Holographic/Holo D - Specular Textured", "Sprites/Default", "Sprites/Diffuse", "Sprites/Mask", "Standard (Specular setup)", "Standard", "SuperSystems/Wireframe-Transparent-Culled", "TextMeshPro/Bitmap Custom Atlas",
			"TextMeshPro/Bitmap", "TextMeshPro/Distance Field (Surface)", "TextMeshPro/Distance Field Overlay", "TextMeshPro/Distance Field", "TextMeshPro/Mobile/Bitmap", "TextMeshPro/Mobile/Distance Field (Surface)", "TextMeshPro/Mobile/Distance Field - Masking", "TextMeshPro/Mobile/Distance Field Overlay", "TextMeshPro/Mobile/Distance Field", "TextMeshPro/Sprite",
			"UI/Default", "Hidden/Post FX/Uber"
		};

		public List<string> BaseGameShadersFamiliesToNotLoad = new List<string> { "Hidden", "TextMeshPro" };

		public Dictionary<string, Shader> ShaderCache { get; }

		public Dictionary<string, Shader> BaseGameShaderCache { get; } = new Dictionary<string, Shader>();


		public ShaderHelper()
		{
			//IL_0431: Unknown result type (might be due to invalid IL or missing references)
			//IL_0437: Invalid comparison between Unknown and I4
			//IL_0450: Unknown result type (might be due to invalid IL or missing references)
			if ((int)Application.platform == 1)
			{
				LoadBaseGameShaders();
				ShaderCache = LoadShaderBundleFromPath(((BaseUnityPlugin)Plugin.Instance).Info.Location, Application.platform);
			}
			else
			{
				ShaderCache = new Dictionary<string, Shader>();
			}
		}

		private void LoadBaseGameShaders()
		{
			int num = 0;
			foreach (string baseGameShaderName in BaseGameShaderNames)
			{
				if (!BaseGameShadersFamiliesToNotLoad.Any((string e) => baseGameShaderName.ToLower().StartsWith(e.ToLower())))
				{
					Shader val = Shader.Find(baseGameShaderName);
					if ((Object)(object)val == (Object)null)
					{
						Plugin.LogInfo("Failed to cache " + baseGameShaderName);
						num++;
					}
					else
					{
						BaseGameShaderCache.Add(((Object)val).name, val);
					}
				}
			}
			Plugin.LogInfo($"{BaseGameShaderCache.Count} Base game shaders loaded. {num} failed to load.");
		}

		public Dictionary<string, Shader> LoadShaderBundleFromPath(string path, RuntimePlatform? platform = null)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Invalid comparison between Unknown and I4
			Dictionary<string, Shader> dictionary = new Dictionary<string, Shader>();
			List<string> list = new List<string> { "*.DONOTDELETE", "*.shaderbundle", "*.shaders" };
			List<string> list2 = new List<string>();
			if ((int)platform.GetValueOrDefault() == 1)
			{
				foreach (string item2 in list)
				{
					string[] files = Directory.GetFiles(Path.GetDirectoryName(path), item2, SearchOption.TopDirectoryOnly);
					foreach (string text in files)
					{
						if ((text.ToLower().Contains("macos") || text.ToLower().Contains("osx")) && !list2.Contains(text))
						{
							list2.Add(text);
						}
					}
				}
			}
			else if (!platform.HasValue)
			{
				foreach (string item3 in list)
				{
					string[] files = Directory.GetFiles(Path.GetDirectoryName(path), item3, SearchOption.TopDirectoryOnly);
					foreach (string item in files)
					{
						if (!list2.Contains(item))
						{
							list2.Add(item);
						}
					}
				}
			}
			foreach (string item4 in list2)
			{
				if (!File.Exists(item4))
				{
					continue;
				}
				AssetBundle val = AssetBundle.LoadFromFile(item4);
				Object obj = val.LoadAsset("Assets/_Shaders.prefab");
				GameObject val2 = (GameObject)(object)((obj is GameObject) ? obj : null);
				if ((Object)(object)val2 != (Object)null)
				{
					Renderer[] componentsInChildren = val2.GetComponentsInChildren<Renderer>();
					foreach (Renderer val3 in componentsInChildren)
					{
						if (!((Object)(object)val3 == (Object)null) && !((Object)(object)val3.sharedMaterial == (Object)null))
						{
							Shader shader = val3.sharedMaterial.shader;
							if (!((Object)(object)shader == (Object)null) && !dictionary.ContainsKey(((Object)shader).name) && !BaseGameShaderCache.ContainsKey(((Object)shader).name))
							{
								dictionary.Add(((Object)shader).name, shader);
							}
						}
					}
				}
				else
				{
					Plugin.LogWarning("Missing _Shaders.prefab file in bundle " + item4 + "!");
				}
				val.Unload(false);
			}
			return dictionary;
		}
	}
}
namespace TrombLoader.Data
{
	[Serializable]
	[RequireComponent(typeof(TromboneEventManager))]
	public class BackgroundEvent : MonoBehaviour
	{
		[SerializeField]
		public int BackgroundEventID;

		public UnityEvent UnityEvent;
	}
	public class BackgroundPuppetController : MonoBehaviour
	{
		public List<Tromboner> Tromboners { get; }

		public BackgroundPuppetController()
		{
			Tromboners = new List<Tromboner>();
		}

		public void StartPuppetBob(float bob)
		{
			foreach (Tromboner tromboner in Tromboners)
			{
				tromboner.controller.startPuppetBob(bob);
			}
		}

		public void DoPuppetControl(float vp, float vibrato)
		{
			foreach (Tromboner tromboner in Tromboners)
			{
				tromboner.controller.doPuppetControl(vp);
				tromboner.controller.vibrato = vibrato;
			}
		}

		public void DoManualDance(float amount)
		{
			foreach (Tromboner tromboner in Tromboners)
			{
				if (tromboner.placeholder.DanceMode == TrombonerDanceMode.ManualDance)
				{
					tromboner.controller.doManualDance(amount);
				}
			}
		}

		public void SetPuppetBreath(bool hasBreath)
		{
			foreach (Tromboner tromboner in Tromboners)
			{
				tromboner.controller.outofbreath = hasBreath;
				tromboner.controller.applyFaceTex();
			}
		}

		public void SetPuppetShake(bool shaking)
		{
			foreach (Tromboner tromboner in Tromboners)
			{
				tromboner.controller.shaking = shaking;
				tromboner.controller.applyFaceTex();
			}
		}
	}
	public class CustomPuppetController : MonoBehaviour
	{
		public Tromboner Tromboner { get; set; }

		public void Start()
		{
			HumanPuppetController controller = Tromboner.controller;
			int movementType = GetMovementType();
			LeanTween.value((movementType == 0) ? 10f : (-38f), -48f, 7f).setLoopPingPong().setEaseInOutQuart()
				.setOnUpdate((Action<float>)delegate(float val)
				{
					//IL_001b: Unknown result type (might be due to invalid IL or missing references)
					controller.p_parent.transform.localEulerAngles = new Vector3(0f, val, 0f);
				});
			controller.estudious = movementType == 1;
		}

		private int GetMovementType()
		{
			if (Tromboner.placeholder.MovementType == TrombonerMovementType.DoNotOverride)
			{
				return GlobalVariables.chosen_vibe;
			}
			return (int)Tromboner.placeholder.MovementType;
		}
	}
	[Serializable]
	public class LeanTweenHelper : MonoBehaviour
	{
		public enum LeanTweenHelperType
		{
			MOVELOCAL,
			MOVEGLOBAL,
			ROTATELOCAL,
			ROTATEGLOBAL,
			MOVEX,
			MOVEY,
			MOVEZ,
			MOVELOCALX,
			MOVELOCALY,
			MOVELOCALZ,
			SCALE
		}

		public LeanTweenHelperType tweenType;

		public Vector3 vector3Value;

		public float floatValue;

		public float time;

		public LeanTweenType easeType = (LeanTweenType)1;

		public LeanTweenType loopType = (LeanTweenType)36;

		public int loopCount;

		public bool runOnStart;

		public LeanTweenHelper invokeOnComplete;

		public Action tweenAction;

		public void SetTweenType()
		{
			switch (tweenType)
			{
			case LeanTweenHelperType.MOVELOCAL:
				tweenAction = delegate
				{
					//IL_0007: Unknown result type (might be due to invalid IL or missing references)
					//IL_0018: Unknown result type (might be due to invalid IL or missing references)
					//IL_002e: Unknown result type (might be due to invalid IL or missing references)
					LeanTween.moveLocal(((Component)this).gameObject, vector3Value, time).setEase(easeType).setLoopCount(loopCount)
						.setLoopType(loopType)
						.setOnComplete((Action)delegate
						{
							invokeOnComplete?.DoTween();
						});
				};
				break;
			case LeanTweenHelperType.MOVEGLOBAL:
				tweenAction = delegate
				{
					//IL_0007: Unknown result type (might be due to invalid IL or missing references)
					//IL_0018: Unknown result type (might be due to invalid IL or missing references)
					//IL_002e: Unknown result type (might be due to invalid IL or missing references)
					LeanTween.move(((Component)this).gameObject, vector3Value, time).setEase(easeType).setLoopCount(loopCount)
						.setLoopType(loopType)
						.setOnComplete((Action)delegate
						{
							invokeOnComplete?.DoTween();
						});
				};
				break;
			case LeanTweenHelperType.ROTATELOCAL:
				tweenAction = delegate
				{
					//IL_0007: Unknown result type (might be due to invalid IL or missing references)
					//IL_0018: Unknown result type (might be due to invalid IL or missing references)
					//IL_002e: Unknown result type (might be due to invalid IL or missing references)
					LeanTween.rotateLocal(((Component)this).gameObject, vector3Value, time).setEase(easeType).setLoopCount(loopCount)
						.setLoopType(loopType)
						.setOnComplete((Action)delegate
						{
							invokeOnComplete?.DoTween();
						});
				};
				break;
			case LeanTweenHelperType.ROTATEGLOBAL:
				tweenAction = delegate
				{
					//IL_0007: Unknown result type (might be due to invalid IL or missing references)
					//IL_0018: Unknown result type (might be due to invalid IL or missing references)
					//IL_002e: Unknown result type (might be due to invalid IL or missing references)
					LeanTween.rotate(((Component)this).gameObject, vector3Value, time).setEase(easeType).setLoopCount(loopCount)
						.setLoopType(loopType)
						.setOnComplete((Action)delegate
						{
							invokeOnComplete?.DoTween();
						});
				};
				break;
			case LeanTweenHelperType.SCALE:
				tweenAction = delegate
				{
					//IL_0007: Unknown result type (might be due to invalid IL or missing references)
					//IL_0018: Unknown result type (might be due to invalid IL or missing references)
					//IL_002e: Unknown result type (might be due to invalid IL or missing references)
					LeanTween.scale(((Component)this).gameObject, vector3Value, time).setEase(easeType).setLoopCount(loopCount)
						.setLoopType(loopType)
						.setOnComplete((Action)delegate
						{
							invokeOnComplete?.DoTween();
						});
				};
				break;
			case LeanTweenHelperType.MOVEX:
				tweenAction = delegate
				{
					//IL_0018: 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)
					LeanTween.moveX(((Component)this).gameObject, floatValue, time).setEase(easeType).setLoopCount(loopCount)
						.setLoopType(loopType)
						.setOnComplete((Action)delegate
						{
							invokeOnComplete?.DoTween();
						});
				};
				break;
			case LeanTweenHelperType.MOVEY:
				tweenAction = delegate
				{
					//IL_0018: 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)
					LeanTween.moveY(((Component)this).gameObject, floatValue, time).setEase(easeType).setLoopCount(loopCount)
						.setLoopType(loopType)
						.setOnComplete((Action)delegate
						{
							invokeOnComplete?.DoTween();
						});
				};
				break;
			case LeanTweenHelperType.MOVEZ:
				tweenAction = delegate
				{
					//IL_0018: 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)
					LeanTween.moveZ(((Component)this).gameObject, floatValue, time).setEase(easeType).setLoopCount(loopCount)
						.setLoopType(loopType)
						.setOnComplete((Action)delegate
						{
							invokeOnComplete?.DoTween();
						});
				};
				break;
			case LeanTweenHelperType.MOVELOCALX:
				tweenAction = delegate
				{
					//IL_0018: 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)
					LeanTween.moveLocalX(((Component)this).gameObject, floatValue, time).setEase(easeType).setLoopCount(loopCount)
						.setLoopType(loopType)
						.setOnComplete((Action)delegate
						{
							invokeOnComplete?.DoTween();
						});
				};
				break;
			case LeanTweenHelperType.MOVELOCALY:
				tweenAction = delegate
				{
					//IL_0018: 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)
					LeanTween.moveLocalY(((Component)this).gameObject, floatValue, time).setEase(easeType).setLoopCount(loopCount)
						.setLoopType(loopType)
						.setOnComplete((Action)delegate
						{
							invokeOnComplete?.DoTween();
						});
				};
				break;
			case LeanTweenHelperType.MOVELOCALZ:
				tweenAction = delegate
				{
					//IL_0018: 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)
					LeanTween.moveLocalZ(((Component)this).gameObject, floatValue, time).setEase(easeType).setLoopCount(loopCount)
						.setLoopType(loopType)
						.setOnComplete((Action)delegate
						{
							invokeOnComplete?.DoTween();
						});
				};
				break;
			}
		}

		public void Start()
		{
			SetTweenType();
			if (runOnStart)
			{
				DoTween();
			}
		}

		public void DoTween()
		{
			tweenAction();
		}
	}
	[RequireComponent(typeof(Text))]
	public class TextEventHandler : MonoBehaviour
	{
		public string StringToReplaceWithEventData = "{int}";

		private Text _text;

		private string _originalText;

		private int _cachedInt;

		public void ConvertIntToText(int inputInt)
		{
			_cachedInt = inputInt;
			UpdateText();
		}

		private void UpdateText()
		{
			if ((Object)(object)_text != (Object)null)
			{
				if (_originalText == null)
				{
					_originalText = _text.text;
				}
				_text.text = _originalText.Replace(StringToReplaceWithEventData, _cachedInt.ToString());
			}
		}

		public void Start()
		{
			_text = ((Component)this).GetComponent<Text>();
			UpdateText();
		}
	}
	public class TromboneEventInvoker : MonoBehaviour
	{
		[SerializeField]
		private GameController _controller;

		[SerializeField]
		private TromboneEventManager[] _eventManagers;

		[SerializeField]
		private BackgroundEvent[] _backgroundEvents;

		private bool previousNoteActiveValue;

		private bool waitingForNextTimeSigJump = true;

		private int barCount;

		private int previousCombo;

		private int previousBGDataIndex;

		private bool currentInputState;

		private bool currentChampState;

		private bool outOfBreath;

		public void InitializeInvoker(GameController controller, TromboneEventManager[] eventManagers)
		{
			_controller = controller;
			_eventManagers = eventManagers;
		}

		public void LateUpdate()
		{
			//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
			if (_controller == null)
			{
				return;
			}
			TromboneEventManager[] eventManagers;
			if (_controller.bgindex != previousBGDataIndex)
			{
				int num = (int)_controller.bgdata[previousBGDataIndex][1];
				previousBGDataIndex = _controller.bgindex;
				eventManagers = _eventManagers;
				for (int i = 0; i < eventManagers.Length; i++)
				{
					BackgroundEvent[] events = eventManagers[i].Events;
					foreach (BackgroundEvent backgroundEvent in events)
					{
						if (backgroundEvent.BackgroundEventID == num)
						{
							backgroundEvent.UnityEvent.Invoke();
						}
					}
				}
			}
			if (_controller.timesigcount == 1)
			{
				if (waitingForNextTimeSigJump)
				{
					waitingForNextTimeSigJump = false;
					eventManagers = _eventManagers;
					foreach (TromboneEventManager tromboneEventManager in eventManagers)
					{
						UnityEvent onBeat = tromboneEventManager.OnBeat;
						if (onBeat != null)
						{
							onBeat.Invoke();
						}
						if (barCount % _controller.beatspermeasure == 0)
						{
							UnityEvent onBar = tromboneEventManager.OnBar;
							if (onBar != null)
							{
								onBar.Invoke();
							}
						}
					}
					barCount++;
				}
			}
			else
			{
				waitingForNextTimeSigJump = true;
			}
			if (previousNoteActiveValue != _controller.noteactive)
			{
				previousNoteActiveValue = _controller.noteactive;
				eventManagers = _eventManagers;
				foreach (TromboneEventManager tromboneEventManager2 in eventManagers)
				{
					if (previousNoteActiveValue)
					{
						UnityEvent noteStart = tromboneEventManager2.NoteStart;
						if (noteStart != null)
						{
							noteStart.Invoke();
						}
					}
					else
					{
						UnityEvent noteEnd = tromboneEventManager2.NoteEnd;
						if (noteEnd != null)
						{
							noteEnd.Invoke();
						}
					}
				}
			}
			if (_controller.highestcombocounter != previousCombo)
			{
				previousCombo = _controller.highestcombocounter;
				eventManagers = _eventManagers;
				for (int i = 0; i < eventManagers.Length; i++)
				{
					((UnityEvent<int>)eventManagers[i].ComboUpdated)?.Invoke(previousCombo);
				}
			}
			int num2 = 0;
			foreach (KeyCode toot_key in _controller.toot_keys)
			{
				if (Input.GetKey(toot_key))
				{
					num2++;
				}
			}
			if (num2 == 1 || Input.GetMouseButton(0))
			{
				if (!currentInputState)
				{
					currentInputState = true;
					eventManagers = _eventManagers;
					for (int i = 0; i < eventManagers.Length; i++)
					{
						UnityEvent playerTootInputStart = eventManagers[i].PlayerTootInputStart;
						if (playerTootInputStart != null)
						{
							playerTootInputStart.Invoke();
						}
					}
				}
			}
			else if (currentInputState)
			{
				currentInputState = false;
				eventManagers = _eventManagers;
				for (int i = 0; i < eventManagers.Length; i++)
				{
					UnityEvent playerTootInputEnd = eventManagers[i].PlayerTootInputEnd;
					if (playerTootInputEnd != null)
					{
						playerTootInputEnd.Invoke();
					}
				}
			}
			if (_controller.rainbowcontroller.champmode != currentChampState)
			{
				currentChampState = _controller.rainbowcontroller.champmode;
				eventManagers = _eventManagers;
				foreach (TromboneEventManager tromboneEventManager3 in eventManagers)
				{
					if (currentChampState)
					{
						UnityEvent champModeActivated = tromboneEventManager3.ChampModeActivated;
						if (champModeActivated != null)
						{
							champModeActivated.Invoke();
						}
					}
					else
					{
						UnityEvent champModeDeactivated = tromboneEventManager3.ChampModeDeactivated;
						if (champModeDeactivated != null)
						{
							champModeDeactivated.Invoke();
						}
					}
				}
			}
			if (_controller.outofbreath == outOfBreath)
			{
				return;
			}
			outOfBreath = _controller.outofbreath;
			eventManagers = _eventManagers;
			foreach (TromboneEventManager tromboneEventManager4 in eventManagers)
			{
				if (outOfBreath)
				{
					UnityEvent obj = tromboneEventManager4.OutOfBreath;
					if (obj != null)
					{
						obj.Invoke();
					}
				}
			}
		}
	}
	[Serializable]
	public class Vector3Event : UnityEvent<Vector3>
	{
	}
	[Serializable]
	public class IntEvent : UnityEvent<int>
	{
	}
	[Serializable]
	[DisallowMultipleComponent]
	public class TromboneEventManager : MonoBehaviour
	{
		[NonSerialized]
		public BackgroundEvent[] Events;

		public UnityEvent OnBeat;

		public UnityEvent OnBar;

		public UnityEvent NoteStart;

		public UnityEvent NoteEnd;

		public UnityEvent PlayerTootInputStart;

		public UnityEvent PlayerTootInputEnd;

		public UnityEvent ChampModeActivated;

		public UnityEvent ChampModeDeactivated;

		public UnityEvent OutOfBreath;

		public IntEvent ComboUpdated;

		public Vector3Event MousePositionUpdated;

		private Vector3 mousePosition;

		[SerializeField]
		[HideInInspector]
		private string serializedMousePositionJson;

		[SerializeField]
		[HideInInspector]
		private Object[] serializedMousePositionTargets;

		[SerializeField]
		[HideInInspector]
		private string serializedComboJson;

		[SerializeField]
		[HideInInspector]
		private Object[] serializedComboTargets;

		public void SerializeAllGenericEvents()
		{
			serializedMousePositionJson = JsonUtility.ToJson((object)MousePositionUpdated);
			serializedComboJson = JsonUtility.ToJson((object)ComboUpdated);
		}

		public void DeserializeAllGenericEvents()
		{
			if (Events == null)
			{
				Events = ((Component)this).GetComponents<BackgroundEvent>();
			}
			if (!string.IsNullOrEmpty(serializedMousePositionJson))
			{
				MousePositionUpdated = JsonUtility.FromJson<Vector3Event>(serializedMousePositionJson);
				AssignTargets((UnityEventBase)(object)MousePositionUpdated, serializedMousePositionTargets);
			}
			if (!string.IsNullOrEmpty(serializedComboJson))
			{
				ComboUpdated = JsonUtility.FromJson<IntEvent>(serializedComboJson);
				AssignTargets((UnityEventBase)(object)ComboUpdated, serializedComboTargets);
			}
		}

		public static void AssignTargets(UnityEventBase unityEvent, Object[] objects)
		{
			BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
			Type? type = typeof(UnityEventBase).Assembly.GetType("UnityEngine.Events.PersistentCall");
			FieldInfo field = typeof(UnityEventBase).GetField("m_PersistentCalls", bindingAttr);
			FieldInfo? field2 = field.FieldType.GetField("m_Calls", bindingAttr);
			FieldInfo field3 = field2.FieldType.GetField("_items", bindingAttr);
			object value = field.GetValue(unityEvent);
			object value2 = field2.GetValue(value);
			object[] array = (object[])field3.GetValue(value2);
			FieldInfo field4 = type.GetField("m_Target", bindingAttr);
			for (int i = 0; i < array.Length; i++)
			{
				field4.SetValue(array[i], objects[i]);
			}
		}

		public void Update()
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			if (!string.IsNullOrEmpty(serializedMousePositionJson) && MousePositionUpdated == null)
			{
				DeserializeAllGenericEvents();
			}
			else if (!string.IsNullOrEmpty(serializedComboJson) && ComboUpdated == null)
			{
				DeserializeAllGenericEvents();
			}
			if (MousePositionUpdated != null && Input.mousePosition != mousePosition)
			{
				mousePosition = Input.mousePosition;
				((UnityEvent<Vector3>)MousePositionUpdated).Invoke(new Vector3(mousePosition.x / (float)Screen.width, mousePosition.y / (float)Screen.height, 0f));
			}
		}
	}
	public class Tromboner
	{
		public GameObject gameObject;

		public Transform transform;

		public HumanPuppetController controller;

		public TrombonerPlaceholder placeholder;

		public Tromboner(GameObject _gameObject, TrombonerPlaceholder _placeholder)
		{
			gameObject = _gameObject;
			transform = _gameObject.transform;
			controller = _gameObject.GetComponent<HumanPuppetController>();
			placeholder = _placeholder;
		}
	}
	public class TrombonerPlaceholder : MonoBehaviour
	{
		public TrombonerType TrombonerType = TrombonerType.DoNotOverride;

		public TrombonerOutfit TrombonerOutfit = TrombonerOutfit.DoNotOverride;

		public TromboneSkin TromboneSkin = TromboneSkin.DoNotOverride;

		public TromboneLength TromboneLength = TromboneLength.DoNotOverride;

		public TromboneHat TromboneHat = TromboneHat.DoNotOverride;

		public TrombonerMovementType MovementType = TrombonerMovementType.DoNotOverride;

		public TrombonerDanceMode DanceMode = TrombonerDanceMode.DoNotOverride;

		[HideInInspector]
		[SerializeField]
		public int InstanceID;
	}
	[Serializable]
	public enum TrombonerType
	{
		[InspectorName("Do Not Override (Default)")]
		DoNotOverride = -1,
		[InspectorName("Appaloosa")]
		Female1,
		[InspectorName("Beezerly")]
		Female2,
		[InspectorName("Kaizyle II")]
		Female3,
		[InspectorName("Trixiebell")]
		Female4,
		[InspectorName("Meldor")]
		Male1,
		[InspectorName("Jermajesty")]
		Male2,
		[InspectorName("Horn Lord")]
		Male3,
		[InspectorName("Soda")]
		Male4,
		[InspectorName("Polygon")]
		Female5,
		[InspectorName("Servant Of Babi")]
		Male5
	}
	[Serializable]
	public enum TrombonerOutfit
	{
		[InspectorName("Do Not Override (Default)")]
		DoNotOverride = -1,
		[InspectorName("Default")]
		Default,
		[InspectorName("Christmas")]
		Christmas
	}
	[Serializable]
	public enum TromboneSkin
	{
		[InspectorName("Do Not Override (Default)")]
		DoNotOverride = -1,
		[InspectorName("Brass")]
		Brass,
		[InspectorName("Silver")]
		Silver,
		[InspectorName("Red")]
		Red,
		[InspectorName("Blue")]
		Blue,
		[InspectorName("Green")]
		Green,
		[InspectorName("Pink")]
		Pink,
		[InspectorName("Polygon")]
		Polygon,
		[InspectorName("Champ")]
		Champ
	}
	[Serializable]
	public enum TromboneLength
	{
		[InspectorName("Do Not Override (Default)")]
		DoNotOverride = -1,
		[InspectorName("Short")]
		Short,
		[InspectorName("Long")]
		Long
	}
	[Serializable]
	public enum TromboneHat
	{
		[InspectorName("Do Not Override (Default)")]
		DoNotOverride = -1,
		[InspectorName("Disabled")]
		Disabled,
		[InspectorName("Enabled")]
		Enabled
	}
	[Serializable]
	public enum TrombonerMovementType
	{
		[InspectorName("Do Not Override (Default)")]
		DoNotOverride = -1,
		[InspectorName("Jubilant")]
		Jubilant,
		[InspectorName("Estudious")]
		Estudious
	}
	[Serializable]
	public enum TrombonerDanceMode
	{
		[InspectorName("Do Not Override (Default)")]
		DoNotOverride = -1,
		[InspectorName("Auto Dance")]
		AutoDance,
		[InspectorName("Manual Dance")]
		ManualDance
	}
}
namespace TrombLoader.CustomTracks
{
	public class ChartCompatibility
	{
		public class IntOrFloatConverter : JsonConverter<int>
		{
			private readonly string _fieldName;

			public IntOrFloatConverter(string fieldName)
			{
				_fieldName = fieldName;
			}

			public override void WriteJson(JsonWriter writer, int value, JsonSerializer serializer)
			{
				throw new NotImplementedException();
			}

			public override int ReadJson(JsonReader reader, Type objectType, int existingValue, bool hasExistingValue, JsonSerializer serializer)
			{
				//IL_0014: Unknown result type (might be due to invalid IL or missing references)
				//IL_0019: 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_001c: Unknown result type (might be due to invalid IL or missing references)
				//IL_001e: Invalid comparison between Unknown and I4
				//IL_000d: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b7: Invalid comparison between Unknown and I4
				//IL_002d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0033: Invalid comparison between Unknown and I4
				//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
				//IL_006c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0071: Unknown result type (might be due to invalid IL or missing references)
				if (reader.Value == null)
				{
					throw new JsonException("Expected number, got null");
				}
				JsonToken tokenType = reader.TokenType;
				if (tokenType - 8 <= 1)
				{
					if ((int)reader.TokenType == 8)
					{
						string text = (string)serializer.Context.Context;
						ManualLogSource logger = _logger;
						string[] obj = new string[7] { "Chart '", text, "' has invalid type ", null, null, null, null };
						tokenType = reader.TokenType;
						obj[3] = ((object)(JsonToken)(ref tokenType)).ToString();
						obj[4] = " on field ";
						obj[5] = _fieldName;
						obj[6] = " (expected an integer)";
						logger.LogWarning((object)string.Concat(obj));
					}
					return (int)Convert.ToDouble(reader.Value);
				}
				if ((int)reader.TokenType != 7)
				{
					tokenType = reader.TokenType;
					throw new JsonException("Expected number, got " + ((object)(JsonToken)(ref tokenType)).ToString());
				}
				return Convert.ToInt32(reader.Value);
			}
		}

		private static ManualLogSource _logger = Logger.CreateLogSource("TrombLoader.Compatibility");
	}
	public class ChartData
	{
		[JsonConverter(typeof(ChartCompatibility.IntOrFloatConverter), new object[] { "savednotespacing" })]
		[JsonRequired]
		public int savednotespacing;

		[JsonConverter(typeof(ChartCompatibility.IntOrFloatConverter), new object[] { "timesig" })]
		[JsonRequired]
		public int timesig;

		[JsonRequired]
		public float[][] notes;

		public List<Lyric> lyrics = new List<Lyric>();

		public float[] note_color_start = new float[3] { 1f, 0.21f, 0f };

		public float[] note_color_end = new float[3] { 1f, 0.8f, 0.3f };

		public float[][] improv_zones = new float[0][];

		public float[][] bgdata = new float[0][];

		public SavedLevel ToSavedLevel(CustomTrackData data)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Expected O, but got Unknown
			return new SavedLevel
			{
				savedleveldata = new List<float[]>(notes),
				bgdata = new List<float[]>(bgdata),
				improv_zones = new List<float[]>(improv_zones),
				endpoint = data.endpoint,
				lyricspos = lyrics.Select((Lyric lyric) => new float[2] { lyric.bar, 0f }).ToList(),
				lyricstxt = lyrics.Select((Lyric lyric) => lyric.text).ToList(),
				note_color_start = note_color_start,
				note_color_end = note_color_end,
				savednotespacing = savednotespacing,
				tempo = data.tempo,
				timesig = timesig
			};
		}
	}
	public class CustomTrack : TromboneTrack, Previewable
	{
		public class LoadedCustomTrack : LoadedTromboneTrack, IDisposable, PauseAware
		{
			private readonly CustomTrack _parent;

			private readonly AbstractBackground _background;

			public bool CanResume => _background.CanResume;

			public string trackref => _parent.trackref;

			public LoadedCustomTrack(CustomTrack parent, AbstractBackground background)
			{
				_parent = parent;
				_background = background;
			}

			public TrackAudio LoadAudio()
			{
				//IL_004b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0051: Expected O, but got Unknown
				string path = Path.Combine(_parent.folderPath, Globals.defaultAudioName);
				IEnumerator audioClipSync = Plugin.Instance.GetAudioClipSync(path);
				while (audioClipSync.MoveNext())
				{
					object current = audioClipSync.Current;
					AudioClip val = (AudioClip)((current is AudioClip) ? current : null);
					if (val == null)
					{
						if (!(current is string message))
						{
							continue;
						}
						Plugin.LogError(message);
						return null;
					}
					return new TrackAudio(val, 1f);
				}
				Plugin.LogError("Failed to load audio");
				return null;
			}

			public GameObject LoadBackground(BackgroundContext ctx)
			{
				return _background.Load(ctx);
			}

			public void SetUpBackgroundDelayed(BGController controller, GameObject bg)
			{
				GameObject obj = GameObject.Find("3dModelCamera");
				Camera val = ((obj != null) ? obj.GetComponent<Camera>() : null);
				if ((Object)(object)val != (Object)null)
				{
					val.clearFlags = (CameraClearFlags)3;
				}
				_background.SetUpBackground(controller, bg);
				controller.tickontempo = false;
				controller.doBGEffect(_parent._data.backgroundMovement);
			}

			public void OnPause(PauseContext ctx)
			{
				_background.OnPause(ctx);
			}

			public void OnResume(PauseContext ctx)
			{
				_background.OnResume(ctx);
			}

			public void Dispose()
			{
				_background.Dispose();
			}
		}

		private readonly CustomTrackData _data;

		private readonly TrackLoader _loader;

		public string folderPath { get; }

		public string trackref => _data.trackRef;

		public string trackname_long => _data.name;

		public string trackname_short => _data.shortName;

		public string year => _data.year.ToString();

		public string artist => _data.author;

		public string desc => _data.description;

		public string genre => _data.genre;

		public int difficulty => _data.difficulty;

		public int tempo => (int)_data.tempo;

		public int length => Mathf.FloorToInt(_data.endpoint / (_data.tempo / 60f));

		public CustomTrack(string folderPath, CustomTrackData data, TrackLoader loader)
		{
			this.folderPath = folderPath;
			_data = data;
			_loader = loader;
		}

		[CanBeNull]
		public ExtraData GetCustomData(Identifier identifier)
		{
			if (!_data.custom_data.TryGetValue(identifier, out var value))
			{
				return null;
			}
			return new ExtraData(identifier, value);
		}

		public SavedLevel LoadChart()
		{
			return _loader.LoadChartData(folderPath, _data);
		}

		public LoadedTromboneTrack LoadTrack()
		{
			return (LoadedTromboneTrack)(object)new LoadedCustomTrack(this, LoadBackground());
		}

		public YieldTask<FSharpResult<TrackAudio, string>> LoadClip()
		{
			string text = Path.Combine(folderPath, Globals.defaultPreviewName);
			if (!File.Exists(text))
			{
				text = Path.Combine(folderPath, Globals.defaultAudioName);
			}
			YieldTask<FSharpResult<AudioClip, string>> val = Unity.loadAudioClip(text, (AudioType)14);
			return Coroutines.map<FSharpResult<AudioClip, string>, FSharpResult<TrackAudio, string>>(FuncConvert.FromFunc<FSharpResult<AudioClip, string>, FSharpResult<TrackAudio, string>>((Func<FSharpResult<AudioClip, string>, FSharpResult<TrackAudio, string>>)((FSharpResult<AudioClip, string> res) => ResultModule.Map<AudioClip, TrackAudio, string>(FuncConvert.FromFunc<AudioClip, TrackAudio>((Func<AudioClip, TrackAudio>)((AudioClip clip) => new TrackAudio(clip, 0.9f))), res))), val);
		}

		private AbstractBackground LoadBackground()
		{
			if (File.Exists(Path.Combine(folderPath, "bg.trombackground")))
			{
				return new CustomBackground(AssetBundle.LoadFromFile(Path.Combine(folderPath, "bg.trombackground")), folderPath);
			}
			string text = Path.Combine(folderPath, "bg.mp4");
			if (File.Exists(text))
			{
				return new VideoBackground(text);
			}
			string text2 = Path.Combine(folderPath, "bg.png");
			if (File.Exists(text2))
			{
				return new ImageBackground(text2);
			}
			Plugin.LogWarning("No background for track " + trackref);
			return new EmptyBackground();
		}

		public bool IsVisible()
		{
			return true;
		}
	}
	[JsonObject]
	public class CustomTrackData
	{
		[JsonRequired]
		public string trackRef;

		[JsonRequired]
		public string name;

		[JsonRequired]
		public string shortName;

		[JsonRequired]
		public string author;

		[JsonRequired]
		public string description;

		[JsonRequired]
		public float endpoint;

		[JsonRequired]
		public int year;

		[JsonRequired]
		public string genre;

		[JsonRequired]
		public int difficulty;

		[JsonRequired]
		public float tempo;

		public string backgroundMovement = "none";

		public Dictionary<Identifier, JObject> custom_data = new Dictionary<Identifier, JObject>();
	}
	public class ExtraData
	{
		private Identifier _identifier;

		private JObject _contents;

		public Identifier Identifier => _identifier;

		public JToken this[string key] => _contents[key];

		public ExtraData(Identifier identifier, JObject contents)
		{
			_identifier = identifier;
			_contents = contents;
		}

		public JObject GetJsonObject()
		{
			return _contents;
		}
	}
	public class Identifier
	{
		private static readonly Regex IdentifierRegex = new Regex("^([a-zA-Z_-]+):([a-zA-Z0-9_-]+)$");

		public string Namespace { get; }

		public string Path { get; }

		public Identifier(string @namespace, string path)
		{
			Namespace = @namespace;
			Path = path;
		}

		[JsonConstructor]
		public Identifier(string identifier)
		{
			Match match = IdentifierRegex.Match(identifier);
			if (!match.Success)
			{
				throw new ArgumentException("Invalid identifier string: " + identifier);
			}
			Namespace = match.Captures[0].Value;
			Path = match.Captures[1].Value;
		}

		public override string ToString()
		{
			return Namespace + ":" + Path;
		}

		public override int GetHashCode()
		{
			return (Namespace.GetHashCode() * 397) ^ Path.GetHashCode();
		}

		protected bool Equals(Identifier other)
		{
			if (Namespace == other.Namespace)
			{
				return Path == other.Path;
			}
			return false;
		}

		public override bool Equals(object obj)
		{
			if (obj == null)
			{
				return false;
			}
			if (this == obj)
			{
				return true;
			}
			if (obj.GetType() != GetType())
			{
				return false;
			}
			return Equals((Identifier)obj);
		}

		public static Identifier Parse(string identifier)
		{
			return new Identifier(identifier);
		}
	}
	[JsonObject]
	public class Lyric
	{
		public string text { get; }

		public float bar { get; }

		[JsonConstructor]
		public Lyric(string text, float bar)
		{
			this.text = text;
			this.bar = bar;
		}
	}
	public class TrackLoader : Listener
	{
		private JsonSerializer _serializer = new JsonSerializer();

		public IEnumerable<TromboneTrack> OnRegisterTracks()
		{
			CreateMissingDirectories();
			IEnumerable<string> enumerable = from i in Directory.GetFiles(Globals.GetCustomSongsPath(), "song.tmb", SearchOption.AllDirectories).Concat(Directory.GetFiles(Paths.PluginPath, "song.tmb", SearchOption.AllDirectories))
				select Path.GetDirectoryName(i);
			HashSet<string> seen = new HashSet<string>();
			foreach (string item in enumerable)
			{
				string text = Path.Combine(item, Globals.defaultChartName);
				string fileName = Path.GetFileName(item.TrimEnd(new char[1] { '/' }));
				if (!File.Exists(text))
				{
					continue;
				}
				using StreamReader stream = File.OpenText(text);
				JsonTextReader reader = new JsonTextReader((TextReader)stream);
				try
				{
					CustomTrackData customTrackData;
					try
					{
						_serializer.Context = new StreamingContext(StreamingContextStates.File, fileName);
						customTrackData = _serializer.Deserialize<CustomTrackData>((JsonReader)(object)reader);
					}
					catch (Exception ex)
					{
						Plugin.LogWarning("Unable to deserialize JSON of custom chart: " + text);
						Plugin.LogWarning(ex.Message);
						goto end_IL_0102;
					}
					if (customTrackData != null)
					{
						if (seen.Add(customTrackData.trackRef))
						{
							Plugin.LogDebug("Found custom chart: " + customTrackData.trackRef);
							yield return (TromboneTrack)(object)new CustomTrack(item, customTrackData, this);
							continue;
						}
						Plugin.LogWarning("Skipping folder " + text + " as its trackref '" + customTrackData.trackRef + "' was already loaded!");
						continue;
					}
					end_IL_0102:;
				}
				finally
				{
					((IDisposable)reader)?.Dispose();
				}
			}
		}

		public SavedLevel LoadChartData(string folderPath, CustomTrackData data)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			using StreamReader streamReader = File.OpenText(Path.Combine(folderPath, Globals.defaultChartName));
			JsonTextReader val = new JsonTextReader((TextReader)streamReader);
			try
			{
				_serializer.Context = new StreamingContext(StreamingContextStates.File, data.trackRef);
				return _serializer.Deserialize<ChartData>((JsonReader)(object)val)?.ToSavedLevel(data);
			}
			finally
			{
				((IDisposable)val)?.Dispose();
			}
		}

		private static void CreateMissingDirectories()
		{
			if (!Directory.Exists(Globals.GetCustomSongsPath()))
			{
				Directory.CreateDirectory(Globals.GetCustomSongsPath());
			}
		}
	}
}
namespace TrombLoader.CustomTracks.Backgrounds
{
	public abstract class AbstractBackground : IDisposable, PauseAware
	{
		protected AssetBundle Bundle;

		public abstract bool CanResume { get; }

		protected AbstractBackground(AssetBundle bundle)
		{
			Bundle = bundle;
		}

		public abstract GameObject Load(BackgroundContext ctx);

		public abstract void SetUpBackground(BGController controller, GameObject bg);

		public abstract void OnPause(PauseContext ctx);

		public abstract void OnResume(PauseContext ctx);

		public virtual void Dispose()
		{
			if ((Object)(object)Bundle != (Object)null)
			{
				Bundle.Unload(false);
			}
		}
	}
	public class CustomBackground : AbstractBackground
	{
		private string _songPath;

		private List<VideoPlayer> _pausedVideoPlayers = new List<VideoPlayer>();

		private List<ParticleSystem> _pausedParticleSystems = new List<ParticleSystem>();

		public override bool CanResume => true;

		public CustomBackground(AssetBundle bundle, string songPath)
			: base(bundle)
		{
			_songPath = songPath;
		}

		public override GameObject Load(BackgroundContext ctx)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Invalid comparison between Unknown and I4
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = Bundle.LoadAsset<GameObject>("assets/_background.prefab");
			if ((int)Application.platform == 1)
			{
				LoadShaderBundle(val);
			}
			TromboneEventManager[] componentsInChildren = val.GetComponentsInChildren<TromboneEventManager>();
			TromboneEventManager[] array = componentsInChildren;
			for (int i = 0; i < array.Length; i++)
			{
				array[i].DeserializeAllGenericEvents();
			}
			val.AddComponent<TromboneEventInvoker>().InitializeInvoker(ctx.controller, componentsInChildren);
			VideoPlayer[] componentsInChildren2 = val.GetComponentsInChildren<VideoPlayer>();
			foreach (VideoPlayer val2 in componentsInChildren2)
			{
				if (val2.url != null && val2.url.Contains("SERIALIZED_OUTSIDE_BUNDLE"))
				{
					string path = val2.url.Replace("SERIALIZED_OUTSIDE_BUNDLE/", "");
					string url = Path.Combine(_songPath, path);
					val2.url = url;
				}
			}
			Transform child = val.transform.GetChild(1);
			while (child.childCount < 8)
			{
				new GameObject("Filler").transform.SetParent(child);
			}
			while (((Component)val.transform.GetChild(0)).GetComponentsInChildren<SpriteRenderer>().Length < 2)
			{
				GameObject val3 = new GameObject("Filler");
				val3.AddComponent<SpriteRenderer>();
				val3.transform.SetParent(val.transform.GetChild(0));
			}
			if (val.transform.childCount < 3)
			{
				new GameObject("ConfettiHolder").transform.SetParent(val.transform);
			}
			Canvas component = ((Component)ctx.controller.bottombreath.transform.parent.parent).GetComponent<Canvas>();
			if ((Object)(object)component != (Object)null)
			{
				component.planeDistance = 2f;
			}
			Canvas component2 = ((Component)ctx.controller.champcontroller.letters[0].transform.parent.parent.parent).GetComponent<Canvas>();
			if ((Object)(object)component2 != (Object)null)
			{
				component2.planeDistance = 2f;
			}
			GameObject obj = GameObject.Find("GameplayCam");
			Camera val4 = ((obj != null) ? obj.GetComponent<Camera>() : null);
			if ((Object)(object)val4 != (Object)null)
			{
				val4.depth = 99f;
			}
			Transform val5 = val.transform.Find("RemoveDefaultLights");
			if (Object.op_Implicit((Object)(object)val5))
			{
				Light[] array2 = Object.FindObjectsOfType<Light>();
				for (int i = 0; i < array2.Length; i++)
				{
					((Behaviour)array2[i]).enabled = false;
				}
				((Component)val5).gameObject.AddComponent<SceneLightingHelper>();
			}
			if (Object.op_Implicit((Object)(object)val.transform.Find("AddShadows")))
			{
				QualitySettings.shadows = (ShadowQuality)2;
				QualitySettings.shadowDistance = 100f;
			}
			return val;
		}

		public override void SetUpBackground(BGController controller, GameObject bg)
		{
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Expected O, but got Unknown
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Expected O, but got Unknown
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: 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_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0305: Unknown result type (might be due to invalid IL or missing references)
			//IL_036d: Unknown result type (might be due to invalid IL or missing references)
			//IL_03aa: Unknown result type (might be due to invalid IL or missing references)
			GameController gamecontroller = controller.gamecontroller;
			VideoPlayer[] componentsInChildren = bg.GetComponentsInChildren<VideoPlayer>();
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				componentsInChildren[i].Prepare();
			}
			BackgroundPuppetController backgroundPuppetController = bg.AddComponent<BackgroundPuppetController>();
			TrombonerPlaceholder[] componentsInChildren2 = bg.GetComponentsInChildren<TrombonerPlaceholder>();
			foreach (TrombonerPlaceholder trombonerPlaceholder in componentsInChildren2)
			{
				int num = ((trombonerPlaceholder.TrombonerType == TrombonerType.DoNotOverride) ? gamecontroller.puppetnum : ((int)trombonerPlaceholder.TrombonerType));
				foreach (Transform item in ((Component)trombonerPlaceholder).transform)
				{
					Transform val = item;
					if ((Object)(object)val != (Object)null)
					{
						((Component)val).gameObject.SetActive(false);
					}
				}
				GameObject val2 = new GameObject("RealizedTromboner");
				val2.transform.SetParent(((Component)trombonerPlaceholder).transform);
				val2.transform.SetSiblingIndex(0);
				val2.transform.localPosition = new Vector3(-0.7f, 0.45f, -1.25f);
				val2.transform.localEulerAngles = new Vector3(0f, 0f, 0f);
				((Component)trombonerPlaceholder).transform.Rotate(new Vector3(0f, 19f, 0f));
				val2.transform.localScale = Vector3.one;
				if (num > 3 && num != 8)
				{
					val2.transform.localPosition = new Vector3(-0.7f, 0.35f, -1.25f);
				}
				GameObject val3 = new GameObject("TromboneTextureRefs");
				val3.transform.SetParent(val2.transform);
				val3.transform.SetSiblingIndex(0);
				val3.AddComponent<TromboneTextureRefs>().trombmaterials = ((Component)gamecontroller.modelparent.transform.GetChild(0)).GetComponent<TromboneTextureRefs>().trombmaterials;
				GameObject obj = Object.Instantiate<GameObject>(gamecontroller.playermodels[num], val2.transform, true);
				obj.transform.localScale = Vector3.one;
				Tromboner tromboner = new Tromboner(obj, trombonerPlaceholder);
				obj.AddComponent<CustomPuppetController>().Tromboner = tromboner;
				backgroundPuppetController.Tromboners.Add(tromboner);
				tromboner.controller.setTromboneTex((trombonerPlaceholder.TromboneSkin == TromboneSkin.DoNotOverride) ? gamecontroller.textureindex : ((int)trombonerPlaceholder.TromboneSkin));
				if (trombonerPlaceholder.TrombonerOutfit == TrombonerOutfit.Christmas)
				{
					Material[] materials = ((Renderer)tromboner.controller.bodymesh).materials;
					materials[0] = tromboner.controller.costume_alt;
					((Renderer)tromboner.controller.bodymesh).materials = materials;
				}
				int num2 = ((trombonerPlaceholder.TromboneHat == TromboneHat.DoNotOverride) ? GlobalVariables.chosen_hat : ((int)trombonerPlaceholder.TromboneHat));
				if (num2 > 0)
				{
					GameObject obj2 = Object.Instantiate<GameObject>(gamecontroller.hats[num2 - 1], ((Component)tromboner.controller.bellmesh).transform, false);
					obj2.transform.localPosition = new Vector3(0.189f, 0.332f, 0.309f);
					obj2.transform.localEulerAngles = new Vector3(0f, 0f, 45f);
					obj2.transform.localScale = new Vector3(0.12f, 0.12f, 0.2f);
				}
				if (GlobalVariables.show_long_trombone && trombonerPlaceholder.TromboneLength == TromboneLength.DoNotOverride)
				{
					trombonerPlaceholder.TromboneLength = TromboneLength.Long;
				}
				switch (trombonerPlaceholder.TromboneLength)
				{
				case TromboneLength.Short:
					tromboner.controller.tube_distance = 1.1f;
					tromboner.controller.p_tube.transform.localScale = new Vector3(1f, 1f, 1f);
					break;
				case TromboneLength.Long:
					tromboner.controller.tube_distance = 3.57f;
					tromboner.controller.p_tube.transform.localScale = new Vector3(1f, 1f, 2.25f);
					break;
				}
				if ((GlobalVariables.localsave.cardcollectionstatus[36] >= 10 && GlobalVariables.show_toot_rainbow) || (GlobalVariables.localsave.cardcollectionstatus_gold[36] > 0 && GlobalVariables.show_toot_rainbow))
				{
					tromboner.controller.show_rainbow = true;
				}
				if (tromboner.placeholder.DanceMode == TrombonerDanceMode.DoNotOverride && GlobalVariables.localsave.manual_dance)
				{
					tromboner.placeholder.DanceMode = TrombonerDanceMode.ManualDance;
				}
			}
		}

		private IEnumerable<Behaviour> GetPauseableBehaviours(PauseContext ctx)
		{
			Animator[] componentsInChildren = ctx.backgroundObj.GetComponentsInChildren<Animator>();
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				yield return (Behaviour)(object)componentsInChildren[i];
			}
			Animation[] componentsInChildren2 = ctx.backgroundObj.GetComponentsInChildren<Animation>();
			for (int i = 0; i < componentsInChildren2.Length; i++)
			{
				yield return (Behaviour)(object)componentsInChildren2[i];
			}
			PlayableDirector[] componentsInChildren3 = ctx.backgroundObj.GetComponentsInChildren<PlayableDirector>();
			for (int i = 0; i < componentsInChildren3.Length; i++)
			{
				yield return (Behaviour)(object)componentsInChildren3[i];
			}
			CinemachineDollyCart[] componentsInChildren4 = ctx.backgroundObj.GetComponentsInChildren<CinemachineDollyCart>();
			for (int i = 0; i < componentsInChildren4.Length; i++)
			{
				yield return (Behaviour)(object)componentsInChildren4[i];
			}
		}

		public override void OnPause(PauseContext ctx)
		{
			foreach (Behaviour pauseableBehaviour in GetPauseableBehaviours(ctx))
			{
				pauseableBehaviour.enabled = false;
			}
			VideoPlayer[] componentsInChildren = ctx.backgroundObj.GetComponentsInChildren<VideoPlayer>();
			foreach (VideoPlayer val in componentsInChildren)
			{
				if (val.isPlaying)
				{
					val.Pause();
					_pausedVideoPlayers.Add(val);
				}
			}
			ParticleSystem[] componentsInChildren2 = ctx.backgroundObj.GetComponentsInChildren<ParticleSystem>();
			foreach (ParticleSystem val2 in componentsInChildren2)
			{
				if (val2.isPlaying)
				{
					val2.Pause();
					_pausedParticleSystems.Add(val2);
				}
			}
		}

		public override void OnResume(PauseContext ctx)
		{
			foreach (Behaviour pauseableBehaviour in GetPauseableBehaviours(ctx))
			{
				pauseableBehaviour.enabled = true;
			}
			foreach (VideoPlayer pausedVideoPlayer in _pausedVideoPlayers)
			{
				pausedVideoPlayer.Play();
			}
			foreach (ParticleSystem pausedParticleSystem in _pausedParticleSystems)
			{
				pausedParticleSystem.Play();
			}
			_pausedVideoPlayers.Clear();
			_pausedParticleSystems.Clear();
		}

		public override void Dispose()
		{
			_pausedVideoPlayers.Clear();
			base.Dispose();
		}

		private void LoadShaderBundle(GameObject bg)
		{
			Dictionary<string, Shader> dictionary = new Dictionary<string, Shader>(Plugin.Instance.ShaderHelper.BaseGameShaderCache);
			foreach (KeyValuePair<string, Shader> item in Plugin.Instance.ShaderHelper.ShaderCache)
			{
				if (!dictionary.ContainsKey(item.Key))
				{
					dictionary.Add(item.Key, item.Value);
				}
			}
			foreach (KeyValuePair<string, Shader> item2 in Plugin.Instance.ShaderHelper.LoadShaderBundleFromPath(_songPath + "/"))
			{
				dictionary[item2.Key] = item2.Value;
			}
			foreach (Material item3 in new IEnumerable<Material>[3]
			{
				bg.GetComponentsInChildren<Renderer>(true).SelectMany((Renderer renderer) => renderer.materials),
				from textMesh in bg.GetComponentsInChildren<TMP_Text>(true)
					select textMesh.fontSharedMaterial,
				from graphics in bg.GetComponentsInChildren<Graphic>(true)
					select graphics.material
			}.SelectMany((IEnumerable<Material> x) => x))
			{
				if (!((Object)(object)item3 == (Object)null) && !((Object)(object)item3.shader == (Object)null) && !(((Object)item3.shader).name == "Standard"))
				{
					if (dictionary.TryGetValue(((Object)item3.shader).name, out var value))
					{
						item3.shader = value;
						Plugin.LogDebug("Replacing shader on " + ((Object)item3).name + " (" + ((Object)value).name + ")");
					}
					else
					{
						Plugin.LogDebug("Could not find shader on " + ((Object)item3).name + " (" + ((Object)item3.shader).name + ")");
					}
				}
			}
		}
	}
	public class EmptyBackground : HijackedBackground
	{
		public override bool CanResume => true;

		public override void SetUpBackground(BGController controller, GameObject bg)
		{
			DisableParts(bg);
		}

		public override void OnPause(PauseContext ctx)
		{
		}

		public override void OnResume(PauseContext ctx)
		{
		}
	}
	public abstract class HijackedBackground : AbstractBackground
	{
		protected HijackedBackground()
			: base(AssetBundle.LoadFromFile(Application.streamingAssetsPath + "/trackassets/ballgame/contentbundle"))
		{
		}

		public override GameObject Load(BackgroundContext ctx)
		{
			return Bundle.LoadAsset<GameObject>("BGCam_ballgame");
		}

		protected void DisableParts(GameObject bg)
		{
			GameObject gameObject = ((Component)bg.transform.GetChild(0)).gameObject;
			GameObject gameObject2 = ((Component)bg.transform.GetChild(0).GetChild(1)).gameObject;
			GameObject gameObject3 = ((Component)bg.transform.GetChild(0).GetChild(0)).gameObject;
			GameObject gameObject4 = ((Component)bg.transform.GetChild(1)).gameObject;
			gameObject.SetActive(false);
			gameObject2.SetActive(false);
			gameObject3.SetActive(false);
			gameObject4.SetActive(false);
		}
	}
	public class ImageBackground : HijackedBackground
	{
		private readonly string _imagePath;

		public override bool CanResume => true;

		public ImageBackground(string imagePath)
		{
			_imagePath = imagePath;
		}

		public override void SetUpBackground(BGController controller, GameObject bg)
		{
			DisableParts(bg);
			Transform child = bg.transform.GetChild(0);
			SpriteRenderer component = ((Component)child.GetChild(0)).GetComponent<SpriteRenderer>();
			component.sprite = ImageHelper.LoadSpriteFromFile(_imagePath);
			((Component)child).gameObject.SetActive(true);
			((Component)component).gameObject.SetActive(true);
		}

		public override void OnPause(PauseContext ctx)
		{
		}

		public override void OnResume(PauseContext ctx)
		{
		}
	}
	public class VideoBackground : HijackedBackground
	{
		private readonly string _videoPath;

		private VideoPlayer _videoPlayer;

		public override bool CanResume => true;

		public VideoBackground(string videoPath)
		{
			_videoPath = videoPath;
		}

		public override void SetUpBackground(BGController controller, GameObject bg)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			DisableParts(bg);
			Transform child = bg.transform.GetChild(0);
			Transform child2 = child.GetChild(0);
			((Component)child).gameObject.SetActive(true);
			((Component)child2).gameObject.SetActive(true);
			((Component)child2).GetComponent<SpriteRenderer>().color = Color.black;
			_videoPlayer = ((Component)child2).GetComponent<VideoPlayer>() ?? ((Component)child2).gameObject.AddComponent<VideoPlayer>();
			_videoPlayer.url = _videoPath;
			_videoPlayer.isLooping = true;
			_videoPlayer.playOnAwake = false;
			_videoPlayer.skipOnDrop = true;
			_videoPlayer.renderMode = (VideoRenderMode)1;
			_videoPlayer.targetCamera = ((Component)bg.transform).GetComponent<Camera>();
			((Behaviour)_videoPlayer).enabled = true;
			_videoPlayer.Pause();
			((MonoBehaviour)controller).StartCoroutine((IEnumerator)PlayVideoDelayed(_videoPlayer).GetEnumerator());
		}

		public override void OnPause(PauseContext ctx)
		{
			_videoPlayer.Pause();
		}

		public override void OnResume(PauseContext ctx)
		{
			_videoPlayer.Play();
		}

		public static IEnumerable<YieldInstruction> PlayVideoDelayed(VideoPlayer videoPlayer)
		{
			yield return (YieldInstruction)new WaitForSeconds(2.4f);
			if ((Object)(object)videoPlayer != (Object)null)
			{
				videoPlayer.Play();
			}
		}
	}
}