Decompiled source of TheFunnyBox v1.2.0

PersonalBoombox.dll

Decompiled 2 years 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 BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using PersonalBoombox.Patches;
using TMPro;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Networking;
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("PersonalBoombox")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("PersonalBoombox")]
[assembly: AssemblyCopyright("Copyright ©  2023")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("90672a7b-b084-4f8d-9d78-46affb7b97e7")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.1", FrameworkDisplayName = ".NET Framework 4.7.1")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace PersonalBoombox
{
	public static class Assets
	{
		[Serializable]
		private class PBDataJson
		{
			public string name;

			public string description;

			public int price;

			public float volume;

			public int red;

			public int blue;

			public int green;

			public Color color;

			public string feedback;

			public static PBDataJson GetData(string path)
			{
				if (File.Exists(path))
				{
					try
					{
						string json = File.ReadAllText(path);
						PBDataJson pBDataJson = CreateFromJson(json);
						pBDataJson.FillMissingValues();
						pBDataJson.AdjustValues();
						pBDataJson.feedback = "Loaded data.json file";
						return pBDataJson;
					}
					catch
					{
						return GetDefault("Error reading data.json file".CreateError());
					}
				}
				return GetDefault("Missing data.json file".CreateWarning());
			}

			public static PBDataJson GetDefault(string feedback)
			{
				//IL_0059: Unknown result type (might be due to invalid IL or missing references)
				//IL_005e: Unknown result type (might be due to invalid IL or missing references)
				PBDataJson pBDataJson = new PBDataJson();
				pBDataJson.feedback = feedback;
				pBDataJson.name = "Untitled";
				pBDataJson.description = "Missing Description";
				pBDataJson.price = 60;
				pBDataJson.volume = 0.5f;
				pBDataJson.red = 255;
				pBDataJson.blue = 255;
				pBDataJson.green = 255;
				pBDataJson.color = Color.white;
				return pBDataJson;
			}

			private void FillMissingValues()
			{
				if (string.IsNullOrWhiteSpace(name))
				{
					name = "Untitled";
				}
				if (string.IsNullOrWhiteSpace(description))
				{
					description = "Missing Description";
				}
			}

			private void AdjustValues()
			{
				//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
				int length = Mathf.Min(name.Length, 20);
				name = name.Substring(0, length);
				price = Mathf.Clamp(price, 0, 1000);
				volume = Mathf.Clamp(volume, 0f, PersonalBoomboxPlugin.Instance.maxVolumeValue);
				red = Mathf.Clamp(red, 0, 255);
				blue = Mathf.Clamp(blue, 0, 255);
				green = Mathf.Clamp(green, 0, 255);
				color = new Color((float)red / 255f, (float)green / 255f, (float)blue / 255f, 1f);
			}

			private static PBDataJson CreateFromJson(string json)
			{
				return JsonUtility.FromJson<PBDataJson>(json);
			}

			public string ToJson()
			{
				return JsonUtility.ToJson((object)this);
			}
		}

		private const string mainAssetBundleName = "personalboombox";

		public const int prefabCopyCount = 10;

		public static AssetBundle MainAssetBundle = null;

		public static GameObject originalPrefab;

		public static GameObject[] prefabCopies;

		public static GameObject canvasPrefab;

		public static Texture2D boomboxTexture;

		public static int LimitExceedCounter = 0;

		private static readonly string[] musicExts = new string[1] { "mp3" };

		private static ManualLogSource logger => PersonalBoomboxPlugin.Instance.logger;

		private static string GetAssemblyName()
		{
			return Assembly.GetExecutingAssembly().FullName.Split(new char[1] { ',' })[0];
		}

		public static void LoadAssetBundle()
		{
			if ((Object)(object)MainAssetBundle == (Object)null)
			{
				using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(GetAssemblyName() + ".personalboombox");
				MainAssetBundle = AssetBundle.LoadFromStream(stream);
			}
			originalPrefab = Assets.Load<GameObject>("prefab");
			prefabCopies = (GameObject[])(object)new GameObject[10];
			for (int i = 0; i < 10; i++)
			{
				GameObject val = Assets.Load<GameObject>($"prefab{i + 1}");
				val.AddComponent<PersonalBoomboxItem>();
				prefabCopies[i] = val;
			}
			canvasPrefab = Assets.Load<GameObject>("debugCanvas");
			boomboxTexture = Assets.Load<Texture2D>("BoomboxIcon");
		}

		public static T Load<T>(string name) where T : Object
		{
			if ((Object)(object)MainAssetBundle == (Object)null)
			{
				logger.LogError((object)"Trying to load in asset but asset bundle is missing");
				return default(T);
			}
			logger.LogInfo((object)("Loading asset " + name));
			return MainAssetBundle.LoadAsset<T>(name);
		}

		public static void LoadMusicFolders()
		{
			List<PersonalBoomboxPlugin.RequestData> requests = PersonalBoomboxPlugin.requests;
			List<PersonalBoomboxPlugin.PBData> list = new List<PersonalBoomboxPlugin.PBData>();
			int num = 0;
			foreach (PersonalBoomboxPlugin.RequestData item in requests)
			{
				string path = item.path;
				string[] directories = Directory.GetDirectories(path);
				string[] array = directories;
				foreach (string directory in array)
				{
					logger.LogInfo((object)("Reading from " + path + "!"));
					try
					{
						CreateFromDirectory(directory, list, num++, item);
					}
					catch (Exception ex)
					{
						logger.LogError((object)("Error loading at " + path));
						logger.LogError((object)ex.ToString());
					}
				}
			}
			list.Sort((PersonalBoomboxPlugin.PBData first, PersonalBoomboxPlugin.PBData second) => first.name.CompareTo(second.name));
			num = 0;
			foreach (PersonalBoomboxPlugin.PBData item2 in list)
			{
				char c = (char)(65 + num);
				item2.prefixName = $"pb{c}";
				item2.boomboxName = item2.prefixName + " " + item2.name;
				((Object)item2.prefab).name = item2.boomboxName;
				num++;
			}
			PersonalBoomboxPlugin.data = list;
		}

		private static void CreateFromDirectory(string directory, List<PersonalBoomboxPlugin.PBData> data, int index, PersonalBoomboxPlugin.RequestData request)
		{
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			if (index >= 10)
			{
				logger.LogWarning((object)$"Loading too many boomboxes. There is a limit of {10}");
				LimitExceedCounter++;
				return;
			}
			string path = Path.Combine(directory, "data.json");
			IEnumerable<string> enumerable = from file in Directory.EnumerateFiles(directory, "*.*")
				where musicExts.Any((string x) => file.EndsWith(x, StringComparison.InvariantCultureIgnoreCase))
				select file;
			string path2 = Path.Combine(directory, "decal.png");
			PBDataJson data2 = PBDataJson.GetData(path);
			char c = (char)(97 + index);
			PersonalBoomboxPlugin.PBData pBData = new PersonalBoomboxPlugin.PBData();
			pBData.request = request;
			pBData.feedback = new PersonalBoomboxPlugin.PBData.Feedback();
			pBData.feedback.AddToMain(data2.feedback);
			pBData.name = data2.name;
			pBData.description = data2.description;
			pBData.price = data2.price;
			pBData.volume = data2.volume;
			pBData.prefab = prefabCopies[index];
			pBData.script = pBData.prefab.GetComponent<PersonalBoomboxItem>();
			pBData.script.musicAudios = new List<AudioClip>();
			pBData.color = data2.color;
			List<Coroutine> list = new List<Coroutine>();
			foreach (string item3 in enumerable)
			{
				Coroutine item = MyOwnCoroutine.AddCoroutine(LoadAudioClip(pBData, item3));
				list.Add(item);
			}
			if (File.Exists(path2))
			{
				Coroutine item2 = MyOwnCoroutine.AddCoroutine(LoadTexture2D(pBData, path2));
				list.Add(item2);
			}
			else
			{
				pBData.feedback.AddToMain("Missing decal.png");
			}
			MyOwnCoroutine.AddCoroutine(WaitForDownloads(pBData, list));
			data.Add(pBData);
		}

		private static IEnumerator WaitForDownloads(PersonalBoomboxPlugin.PBData data, List<Coroutine> coroutines)
		{
			yield return null;
			int i = 0;
			foreach (Coroutine coroutine in coroutines)
			{
				yield return coroutine;
				i++;
			}
			PersonalBoomboxItem script = data.script;
			int count = script.musicAudios.Count;
			script.SortAudioClips();
			script.finishedLoading = true;
			logger.LogInfo((object)$"{data.boomboxName} is fully set up with {count} songs!");
			if (count == 0)
			{
				logger.LogWarning((object)"Boomboxes with 0 songs will be skipped in the initialization process");
			}
		}

		private static IEnumerator LoadTexture2D(PersonalBoomboxPlugin.PBData data, string path)
		{
			UnityWebRequest loader = UnityWebRequestTexture.GetTexture(path);
			loader.SendWebRequest();
			while (!loader.isDone)
			{
				yield return null;
			}
			if (loader.error != null)
			{
				string errorString2 = "Error loading decal.png. Download failed";
				logger.LogError((object)errorString2);
				logger.LogError((object)loader.error);
				data.feedback.AddToMain(errorString2.CreateError());
				yield break;
			}
			Texture2D texture = DownloadHandlerTexture.GetContent(loader);
			if ((Object)(object)texture == (Object)null)
			{
				string errorString = "Error loading decal.png. File is weird";
				data.feedback.AddToMain(errorString.CreateError());
				logger.LogError((object)errorString);
			}
			else
			{
				((Texture)texture).filterMode = (FilterMode)0;
				data.decal = texture;
				string loadString = "Loaded decal.png";
				logger.LogInfo((object)loadString);
				data.feedback.AddToMain(loadString);
			}
		}

		private static IEnumerator LoadAudioClip(PersonalBoomboxPlugin.PBData data, string path)
		{
			string fileName = Path.GetFileName(path);
			AudioType fileType = GetAudioType(path);
			if ((int)fileType == 0)
			{
				string errorString3 = "Error loading " + fileName + ". Unsupported file ext.";
				logger.LogError((object)errorString3);
				data.feedback.AddToSongs(errorString3.CreateError());
				yield break;
			}
			UnityWebRequest loader = UnityWebRequestMultimedia.GetAudioClip(path, GetAudioType(path));
			DownloadHandler downloadHandler = loader.downloadHandler;
			DownloadHandlerAudioClip handler = (DownloadHandlerAudioClip)(object)((downloadHandler is DownloadHandlerAudioClip) ? downloadHandler : null);
			handler.streamAudio = true;
			yield return loader.SendWebRequest();
			while (!loader.isDone)
			{
				yield return null;
			}
			if (loader.error != null)
			{
				string errorString2 = "Error loading " + fileName + ". Download failed";
				logger.LogError((object)errorString2);
				logger.LogError((object)loader.error);
				data.feedback.AddToSongs(errorString2.CreateError());
				yield break;
			}
			AudioClip clip = DownloadHandlerAudioClip.GetContent(loader);
			if ((Object)(object)clip == (Object)null || (int)clip.loadState != 2)
			{
				string errorString = "Error loading " + fileName + ". File is weird";
				logger.LogError((object)errorString);
				data.feedback.AddToSongs(errorString.CreateError());
			}
			else
			{
				data.script.AddAudioClip(clip);
				string loadString = "Loaded " + fileName;
				logger.LogInfo((object)loadString);
				data.feedback.AddToSongs(loadString);
			}
		}

		public static AudioType GetAudioType(string path)
		{
			//IL_0020: 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_0024: Unknown result type (might be due to invalid IL or missing references)
			string text = Path.GetExtension(path).ToLowerInvariant();
			string text2 = text;
			if (text2 == ".mp3")
			{
				return (AudioType)13;
			}
			return (AudioType)0;
		}
	}
	public class PersonalBoomboxItem : GrabbableObject
	{
		public AudioSource boomboxAudio;

		public List<AudioClip> musicAudios;

		public bool finishedLoading;

		public AudioClip[] stopAudios;

		public Random musicRandomizer;

		private StartOfRound playersManager;

		private RoundManager roundManager;

		public bool isPlayingMusic;

		private float noiseInterval;

		private int timesPlayedWithoutTurningOff;

		public int pbIndex;

		public int AudioClipCount => (musicAudios != null) ? musicAudios.Count : 0;

		public void AddAudioClip(AudioClip clip)
		{
			musicAudios.Add(clip);
		}

		public void SortAudioClips()
		{
			musicAudios.Sort((AudioClip first, AudioClip second) => ((Object)first).name.CompareTo(((Object)second).name));
		}

		public override void Start()
		{
			((GrabbableObject)this).Start();
			playersManager = Object.FindObjectOfType<StartOfRound>();
			roundManager = Object.FindObjectOfType<RoundManager>();
			musicRandomizer = new Random(playersManager.randomMapSeed - 10);
		}

		public override void ItemActivate(bool used, bool buttonDown = true)
		{
			((GrabbableObject)this).ItemActivate(used, buttonDown);
			StartMusic(used);
		}

		private void StartMusic(bool startMusic, bool pitchDown = false)
		{
			if (startMusic && musicAudios.Count > 0)
			{
				boomboxAudio.clip = musicAudios[musicRandomizer.Next(0, musicAudios.Count)];
				boomboxAudio.pitch = 1f;
				boomboxAudio.Play();
			}
			else if (isPlayingMusic)
			{
				if (pitchDown)
				{
					((MonoBehaviour)this).StartCoroutine(musicPitchDown());
				}
				else
				{
					boomboxAudio.Stop();
					boomboxAudio.PlayOneShot(stopAudios[Random.Range(0, stopAudios.Length)]);
				}
				timesPlayedWithoutTurningOff = 0;
			}
			base.isBeingUsed = startMusic;
			isPlayingMusic = startMusic;
		}

		private IEnumerator musicPitchDown()
		{
			for (int i = 0; i < 30; i++)
			{
				yield return null;
				AudioSource obj = boomboxAudio;
				obj.pitch -= 0.033f;
				if (boomboxAudio.pitch <= 0f)
				{
					break;
				}
			}
			boomboxAudio.Stop();
			boomboxAudio.PlayOneShot(stopAudios[Random.Range(0, stopAudios.Length)]);
		}

		public override void UseUpBatteries()
		{
			((GrabbableObject)this).UseUpBatteries();
			StartMusic(startMusic: false, pitchDown: true);
		}

		public override void PocketItem()
		{
			((GrabbableObject)this).PocketItem();
			StartMusic(startMusic: false);
		}

		public override void Update()
		{
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			((GrabbableObject)this).Update();
			if (isPlayingMusic)
			{
				if (noiseInterval <= 0f)
				{
					noiseInterval = 1f;
					timesPlayedWithoutTurningOff++;
					roundManager.PlayAudibleNoise(((Component)this).transform.position, 16f, 0.9f, timesPlayedWithoutTurningOff, false, 5);
				}
				else
				{
					noiseInterval -= Time.deltaTime;
				}
				if (base.insertedBattery.charge < 0.05f)
				{
					boomboxAudio.pitch = 1f - (0.05f - base.insertedBattery.charge) * 4f;
				}
			}
		}

		protected override void __initializeVariables()
		{
			((GrabbableObject)this).__initializeVariables();
		}

		protected override string __getTypeName()
		{
			return "TouhouBoomboxItem";
		}
	}
	[BepInPlugin("ImoutoSama.PersonalBoombox", "Personal Boombox", "1.2.0")]
	[BepInProcess("Lethal Company.exe")]
	public class PersonalBoomboxPlugin : BaseUnityPlugin
	{
		public class PBData
		{
			public class Feedback
			{
				private List<string> main;

				private List<string> songs;

				public Feedback()
				{
					main = new List<string>();
					songs = new List<string>();
				}

				public void AddToMain(string text)
				{
					main.Add(text);
				}

				public void AddToSongs(string text)
				{
					songs.Add(text);
				}

				public string GetReport()
				{
					string text = string.Empty;
					foreach (string item in main)
					{
						text = text + item + "\n";
					}
					if (songs.Count == 0)
					{
						text += "\nFound 0 songs\n".CreateWarning();
					}
					else
					{
						text += $"\nFound {songs.Count} songs\n";
						foreach (string song in songs)
						{
							text = text + song + "\n";
						}
					}
					return text;
				}
			}

			public RequestData request;

			public Feedback feedback;

			public string name;

			public string prefixName;

			public string boomboxName;

			public string description;

			public int price;

			public float volume;

			public Color color;

			public GameObject prefab;

			public PersonalBoomboxItem script;

			public Texture2D decal;

			public Item item;

			public int itemIndex;

			public bool addedToTerminalKeyword;

			public bool IsFinished => Object.op_Implicit((Object)(object)script) && script.finishedLoading;

			public bool IsValid => Object.op_Implicit((Object)(object)script) && script.AudioClipCount > 0;

			public int GetPrice => request.overridePriceFlag ? request.overridePriceValue : price;

			public string GetReport()
			{
				return "<b>[" + prefixName + "] " + name + "</b>\n" + feedback.GetReport();
			}
		}

		public class RequestData
		{
			public string path;

			public bool overridePriceFlag;

			public int overridePriceValue;

			public RequestData(string path)
			{
				this.path = path;
				overridePriceFlag = false;
				overridePriceValue = 0;
			}

			public RequestData(string path, bool overridePrice, int overridePriceValue)
			{
				this.path = path;
				overridePriceFlag = overridePrice;
				this.overridePriceValue = overridePriceValue;
			}
		}

		private const string modGUID = "ImoutoSama.PersonalBoombox";

		private const string modName = "Personal Boombox";

		private const string modVersion = "1.2.0";

		private readonly Harmony harmony = new Harmony("ImoutoSama.PersonalBoombox");

		internal ManualLogSource logger;

		public static List<PBData> data;

		public static List<RequestData> requests;

		public ConfigEntry<int> maxVolumeConfig;

		public float maxVolumeValue;

		public static PersonalBoomboxPlugin Instance { get; private set; }

		private void Awake()
		{
			if ((Object)(object)Instance == (Object)null)
			{
				Instance = this;
			}
			logger = Logger.CreateLogSource("ImoutoSama.PersonalBoombox");
			logger.LogInfo((object)"Plugin Personal Boombox has been added!");
			maxVolumeConfig = ConfigBindClamp("General", "Max Volume", 100, "Max possible volume value. From 0 to 100.", 0, 100);
			maxVolumeValue = (float)maxVolumeConfig.Value * 0.01f;
			harmony.PatchAll(typeof(TerminalPatch));
			harmony.PatchAll(typeof(StartOfRoundPatch));
			harmony.PatchAll(typeof(GameNetworkManagerPatch));
			harmony.PatchAll(typeof(MenuManagerPatch));
			data = new List<PBData>();
			requests = new List<RequestData>();
			Assets.LoadAssetBundle();
			AddDirectory(GetLazyPath());
		}

		public string GetLazyPath()
		{
			string text = Path.Combine(Paths.PluginPath, "Your Own Personal Boomboxes");
			if (!Directory.Exists(text))
			{
				Directory.CreateDirectory(text);
				Instance.logger.LogInfo((object)"Creaing 'Your Own Personal Boomboxes' folder in the plugin directory");
				CopyExampleZIP(text);
			}
			return text;
		}

		public void CopyExampleZIP(string targetPath)
		{
			string location = Assembly.GetExecutingAssembly().Location;
			string directoryName = Path.GetDirectoryName(location);
			string text = Path.Combine(directoryName, "EXAMPLE.zip");
			if (!File.Exists(text))
			{
				Instance.logger.LogError((object)"Tried to copy over EXAMPLE.zip file but could not find it");
				return;
			}
			string destFileName = Path.Combine(targetPath, "EXAMPLE.zip");
			File.Copy(text, destFileName);
		}

		public ConfigEntry<int> ConfigBindClamp(string section, string key, int defaultValue, string description, int min, int max)
		{
			ConfigEntry<int> val = ((BaseUnityPlugin)this).Config.Bind<int>(section, key, defaultValue, description);
			val.Value = Mathf.Clamp(val.Value, min, max);
			return val;
		}

		public static bool ContainsPath(string path)
		{
			foreach (RequestData request in requests)
			{
				if (request.path == path)
				{
					return true;
				}
			}
			return false;
		}

		public static RequestData AddFromAssemblyDll(string dllPath)
		{
			string directoryName = Path.GetDirectoryName(dllPath);
			return AddDirectory(directoryName);
		}

		public static RequestData AddDirectory(string path)
		{
			if (ContainsPath(path))
			{
				Instance.logger.LogWarning((object)("Trying to add boombox data path that's already been added: " + path));
				return null;
			}
			Instance.logger.LogInfo((object)("Adding path to read boombox data from: " + path));
			RequestData requestData = new RequestData(path);
			requests.Add(requestData);
			return requestData;
		}

		public static string GetLoadReport()
		{
			if (data == null)
			{
				return string.Empty;
			}
			string text = string.Empty;
			string text2 = new string('-', 60) + "\n";
			foreach (PBData datum in data)
			{
				text += datum.GetReport();
				text += text2;
			}
			if (Utility.IsNullOrWhiteSpace(text))
			{
				text = "No boomboxes were loaded\n";
			}
			int limitExceedCounter = Assets.LimitExceedCounter;
			if (limitExceedCounter > 0)
			{
				text += $"Ignored {limitExceedCounter} boomboxes as they exceed the limit of {10}\n".CreateWarning();
			}
			return text;
		}
	}
	public static class StringUtilities
	{
		public static string CreateWarning(this string text)
		{
			return "<color=yellow>" + text + "</color>";
		}

		public static string CreateError(this string text)
		{
			return "<color=red>" + text + "</color>";
		}
	}
	public class MyOwnCoroutine : MonoBehaviour
	{
		private static MyOwnCoroutine _Instance;

		public static MyOwnCoroutine Instance
		{
			get
			{
				//IL_0016: Unknown result type (might be due to invalid IL or missing references)
				//IL_001c: Expected O, but got Unknown
				if ((Object)(object)_Instance == (Object)null)
				{
					GameObject val = new GameObject("My Own Coroutine");
					_Instance = val.AddComponent<MyOwnCoroutine>();
					Object.DontDestroyOnLoad((Object)(object)val);
				}
				return _Instance;
			}
		}

		public static Coroutine AddCoroutine(IEnumerator c)
		{
			return ((MonoBehaviour)Instance).StartCoroutine(c);
		}
	}
}
namespace PersonalBoombox.Patches
{
	[HarmonyPatch(typeof(GameNetworkManager))]
	internal class GameNetworkManagerPatch
	{
		[HarmonyPatch("Start")]
		[HarmonyPostfix]
		public static void StartPatch(ref GameNetworkManager __instance)
		{
			PersonalBoomboxPlugin.Instance.logger.LogInfo((object)"Adding personal boomboxes to network list");
			NetworkManager component = ((Component)__instance).GetComponent<NetworkManager>();
			GameObject[] prefabCopies = Assets.prefabCopies;
			foreach (GameObject val in prefabCopies)
			{
				component.AddNetworkPrefab(val);
			}
		}
	}
	[HarmonyPatch(typeof(MenuManager))]
	internal class MenuManagerPatch
	{
		public static bool done;

		public static GameObject textMeshGameObj;

		public static TextMeshProUGUI textMesh;

		[HarmonyPatch("Awake")]
		[HarmonyPostfix]
		private static void AwakePatch(ref MenuManager __instance)
		{
			AddReportDisplay(ref __instance);
			if (!done)
			{
				done = true;
				Assets.LoadMusicFolders();
			}
		}

		private static void AddReportDisplay(ref MenuManager __instance)
		{
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Expected O, but got Unknown
			try
			{
				Transform parent = ((Component)__instance).transform.parent;
				Transform val = parent.Find("MenuContainer").Find("MainButtons");
				GameObject val2 = Object.Instantiate<GameObject>(Assets.canvasPrefab);
				Button component = ((Component)val2.transform.Find("Button")).GetComponent<Button>();
				((UnityEventBase)component.onClick).RemoveAllListeners();
				((UnityEvent)component.onClick).AddListener(new UnityAction(ToggleReportDisplay));
				textMeshGameObj = ((Component)val2.transform.Find("Scroll View")).gameObject;
				TextMeshProUGUI component2 = ((Component)val2.transform.Find("Scroll View/Viewport/Content")).GetComponent<TextMeshProUGUI>();
				textMesh = component2;
			}
			catch
			{
			}
		}

		private static void ToggleReportDisplay()
		{
			if (!textMeshGameObj.activeSelf)
			{
				((TMP_Text)textMesh).text = PersonalBoomboxPlugin.GetLoadReport();
				textMeshGameObj.SetActive(true);
			}
			else
			{
				textMeshGameObj.SetActive(false);
			}
		}

		private static void PrintTransforms(Transform parent, int counter)
		{
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Expected O, but got Unknown
			string text = new string(' ', counter);
			Canvas component = ((Component)parent).GetComponent<Canvas>();
			string text2 = (Object.op_Implicit((Object)(object)component) ? $" ({component.sortingOrder})" : string.Empty);
			PersonalBoomboxPlugin.Instance.logger.LogInfo((object)(text + ((Object)parent).name + text2));
			foreach (Transform item in parent)
			{
				Transform parent2 = item;
				PrintTransforms(parent2, counter + 1);
			}
		}
	}
	[HarmonyPatch(typeof(StartOfRound))]
	internal class StartOfRoundPatch
	{
		public static bool done;

		[HarmonyPatch("Start")]
		[HarmonyPrefix]
		public static void StartPatch(ref StartOfRound __instance)
		{
			if (done)
			{
				return;
			}
			done = true;
			PersonalBoomboxPlugin.Instance.logger.LogInfo((object)"Adding personal boomboxes to items list");
			foreach (PersonalBoomboxPlugin.PBData datum in PersonalBoomboxPlugin.data)
			{
				bool isFinished = datum.IsFinished;
				bool isValid = datum.IsValid;
				if (datum.IsFinished && datum.IsValid)
				{
					__instance.allItemsList.itemsList.Add(datum.item);
				}
			}
		}
	}
	[HarmonyPatch(typeof(Terminal))]
	internal class TerminalPatch
	{
		public static Item boomboxItem;

		public static GameObject boomboxPrefab;

		public static MeshFilter boomboxMeshFilter;

		public static MeshRenderer boomboxMeshRenderer;

		public static AudioSource boomboxAudioSource;

		public static BoomboxItem boomboxScript;

		public static Texture2D boomboxTexture1;

		public static Texture2D boomboxTexture3;

		public static TerminalKeyword buyKeyword;

		public static TerminalKeyword infoKeyword;

		public static CompatibleNoun buyNoun;

		public static CompatibleNoun infoNoun;

		[HarmonyPatch("Awake")]
		[HarmonyPostfix]
		private static void AwakePatch(ref Terminal __instance)
		{
			foreach (PersonalBoomboxPlugin.PBData datum in PersonalBoomboxPlugin.data)
			{
				bool isFinished = datum.IsFinished;
				bool isValid = datum.IsValid;
				if (datum.IsFinished && datum.IsValid)
				{
					AddToTerminal(ref __instance, datum);
					continue;
				}
				if (!datum.IsFinished)
				{
					PersonalBoomboxPlugin.Instance.logger.LogError((object)(datum.boomboxName + " has no script initialized or it is not done loading music"));
				}
				if (!datum.IsValid)
				{
					PersonalBoomboxPlugin.Instance.logger.LogError((object)(datum.boomboxName + " has no script initialized or it has no loaded music"));
				}
			}
		}

		private static void AddToTerminal(ref Terminal __instance, PersonalBoomboxPlugin.PBData data)
		{
			PersonalBoomboxPlugin.Instance.logger.LogInfo((object)("Adding " + data.boomboxName + " to terminal"));
			if ((Object)(object)data.item == (Object)null)
			{
				SetupPrefab(ref __instance, data);
			}
			List<Item> list = __instance.buyableItemsList.ToList();
			data.itemIndex = list.Count;
			list.Add(data.item);
			__instance.buyableItemsList = list.ToArray();
			if (!data.addedToTerminalKeyword)
			{
				AddToTerminalKeywords(ref __instance, data);
				data.addedToTerminalKeyword = true;
			}
		}

		private static void SetupPrefab(ref Terminal __instance, PersonalBoomboxPlugin.PBData data)
		{
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0216: Unknown result type (might be due to invalid IL or missing references)
			//IL_0220: Expected O, but got Unknown
			if ((Object)(object)boomboxItem == (Object)null)
			{
				InitializePrefab(ref __instance);
			}
			Item val = Object.Instantiate<Item>(boomboxItem);
			GameObject prefab = data.prefab;
			PersonalBoomboxItem script = data.script;
			val.creditsWorth = data.GetPrice;
			val.spawnPrefab = prefab;
			val.itemName = data.boomboxName;
			val.itemIcon = CreateSprite(val.itemIcon, data.color);
			data.item = val;
			prefab.tag = boomboxPrefab.tag;
			prefab.layer = boomboxPrefab.layer;
			MeshFilter component = prefab.GetComponent<MeshFilter>();
			component.mesh = boomboxMeshFilter.mesh;
			MeshRenderer component2 = prefab.GetComponent<MeshRenderer>();
			((Renderer)component2).materials = ((Renderer)boomboxMeshRenderer).materials;
			((Renderer)component2).materials[3].color = data.color;
			((Renderer)component2).materials[1].color = DarkenColor(data.color);
			AudioSource component3 = prefab.GetComponent<AudioSource>();
			component3.volume = data.volume;
			component3.outputAudioMixerGroup = boomboxAudioSource.outputAudioMixerGroup;
			component3.SetCustomCurve((AudioSourceCurveType)0, boomboxAudioSource.GetCustomCurve((AudioSourceCurveType)0));
			component3.SetCustomCurve((AudioSourceCurveType)1, boomboxAudioSource.GetCustomCurve((AudioSourceCurveType)1));
			component3.SetCustomCurve((AudioSourceCurveType)3, boomboxAudioSource.GetCustomCurve((AudioSourceCurveType)3));
			component3.SetCustomCurve((AudioSourceCurveType)2, boomboxAudioSource.GetCustomCurve((AudioSourceCurveType)2));
			if (Object.op_Implicit((Object)(object)data.decal))
			{
				GameObject gameObject = ((Component)prefab.transform.GetChild(0)).gameObject;
				MeshRenderer component4 = gameObject.GetComponent<MeshRenderer>();
				Material material = ((Renderer)component4).material;
				material.mainTexture = (Texture)(object)data.decal;
				((Renderer)component4).material = material;
				gameObject.SetActive(true);
			}
			((GrabbableObject)script).grabbable = true;
			((GrabbableObject)script).isInFactory = true;
			((GrabbableObject)script).grabbableToEnemies = true;
			((GrabbableObject)script).propColliders = ((Component)script).GetComponents<Collider>();
			((GrabbableObject)script).mainObjectRenderer = component2;
			script.boomboxAudio = component3;
			script.stopAudios = boomboxScript.stopAudios;
			((GrabbableObject)script).insertedBattery = new Battery(false, ((GrabbableObject)boomboxScript).insertedBattery.charge);
			((GrabbableObject)script).itemProperties = val;
			static Color DarkenColor(Color c)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_000d: 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_002a: Unknown result type (might be due to invalid IL or missing references)
				//IL_002f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0032: Unknown result type (might be due to invalid IL or missing references)
				return new Color(c.r * 0.9f, c.g * 0.9f, c.b * 0.9f, 1f);
			}
		}

		private static void InitializePrefab(ref Terminal __instance)
		{
			List<Item> list = __instance.buyableItemsList.ToList();
			int num = -1;
			for (int i = 0; i < list.Count; i++)
			{
				Item val = list[i];
				if (val.itemName.ToLowerInvariant() == "boombox")
				{
					num = i;
					break;
				}
			}
			if (num == -1)
			{
				PersonalBoomboxPlugin.Instance.logger.LogError((object)"Items has no boomerbox item to copy from");
				return;
			}
			boomboxItem = list[num];
			boomboxPrefab = boomboxItem.spawnPrefab;
			boomboxMeshFilter = boomboxPrefab.GetComponent<MeshFilter>();
			boomboxMeshRenderer = boomboxPrefab.GetComponent<MeshRenderer>();
			boomboxAudioSource = boomboxPrefab.GetComponent<AudioSource>();
			boomboxScript = boomboxPrefab.GetComponent<BoomboxItem>();
		}

		private static void AddToTerminalKeywords(ref Terminal __instance, PersonalBoomboxPlugin.PBData data)
		{
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Expected O, but got Unknown
			if ((Object)(object)buyKeyword == (Object)null)
			{
				InitializeKeyword(ref __instance);
			}
			string word = data.boomboxName.ToLowerInvariant();
			string boomboxName = data.boomboxName;
			CompatibleNoun val = CopyNoun(buyNoun);
			TerminalKeyword noun = val.noun;
			noun.word = word;
			TerminalNode result = val.result;
			result.buyItemIndex = data.itemIndex;
			result.displayText = result.displayText.Replace("boom boxes", boomboxName + " boom boxes");
			result.terminalOptions = CopyNouns(result.terminalOptions);
			TerminalNode val2 = FindNodeWithConfirm(result.terminalOptions);
			val2.buyItemIndex = data.itemIndex;
			val2.displayText = val2.displayText.Replace("boom boxes", boomboxName + " boom boxes");
			List<CompatibleNoun> list = buyKeyword.compatibleNouns.ToList();
			List<CompatibleNoun> list2 = infoKeyword.compatibleNouns.ToList();
			List<TerminalKeyword> list3 = __instance.terminalNodes.allKeywords.ToList();
			list.Add(val);
			buyKeyword.compatibleNouns = list.ToArray();
			CompatibleNoun val3 = new CompatibleNoun();
			val3.noun = val.noun;
			val3.result = CopyTerminalNode(infoNoun.result);
			val3.result.displayText = "\n" + data.description + "\n\n";
			list2.Add(val3);
			infoKeyword.compatibleNouns = list2.ToArray();
			list3.Add(noun);
			__instance.terminalNodes.allKeywords = list3.ToArray();
		}

		private static void InitializeKeyword(ref Terminal __instance)
		{
			TerminalKeyword[] allKeywords = __instance.terminalNodes.allKeywords;
			buyKeyword = ((IEnumerable<TerminalKeyword>)allKeywords).FirstOrDefault((Func<TerminalKeyword, bool>)((TerminalKeyword a) => a.word == "buy"));
			infoKeyword = ((IEnumerable<TerminalKeyword>)allKeywords).FirstOrDefault((Func<TerminalKeyword, bool>)((TerminalKeyword a) => a.word == "info"));
			buyNoun = buyKeyword.compatibleNouns.First((CompatibleNoun b) => b.noun.word == "boombox");
			infoNoun = infoKeyword.compatibleNouns.First((CompatibleNoun b) => b.noun.word == "boombox");
		}

		private static TerminalKeyword CopyTerminalKeyword(TerminalKeyword target)
		{
			return Object.Instantiate<TerminalKeyword>(target);
		}

		private static TerminalNode CopyTerminalNode(TerminalNode target)
		{
			return Object.Instantiate<TerminalNode>(target);
		}

		private static CompatibleNoun CopyNoun(CompatibleNoun target)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			CompatibleNoun val = new CompatibleNoun();
			val.noun = CopyTerminalKeyword(target.noun);
			val.result = CopyTerminalNode(target.result);
			return val;
		}

		private static CompatibleNoun[] CopyNouns(CompatibleNoun[] target)
		{
			CompatibleNoun[] array = (CompatibleNoun[])(object)new CompatibleNoun[target.Length];
			for (int i = 0; i < target.Length; i++)
			{
				array[i] = CopyNoun(target[i]);
			}
			return array;
		}

		private static TerminalNode FindNodeWithConfirm(CompatibleNoun[] nouns)
		{
			foreach (CompatibleNoun val in nouns)
			{
				if (val.noun.word.ToLowerInvariant() == "confirm")
				{
					return val.result;
				}
			}
			return null;
		}

		private static Sprite CreateSprite(Sprite copyTarget, Color color)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Expected O, but got Unknown
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: 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)
			Texture2D boomboxTexture = Assets.boomboxTexture;
			Texture2D val = new Texture2D(((Texture)boomboxTexture).width, ((Texture)boomboxTexture).height);
			Color[] pixels = boomboxTexture.GetPixels();
			for (int i = 0; i < pixels.Length; i++)
			{
				ref Color reference = ref pixels[i];
				reference *= color;
			}
			val.SetPixels(pixels);
			val.Apply();
			return Sprite.Create(val, copyTarget.rect, copyTarget.pivot, copyTarget.pixelsPerUnit);
		}
	}
}