Decompiled source of BetonJukebox v1.0.0

Mods/BetonJukebox.dll

Decompiled 2 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using HarmonyLib;
using MelonLoader;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json.Linq;
using SoundImporter;
using SoundImporter.Managers;
using Steamworks;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UIElements;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: MelonInfo(typeof(Core), "BetonJukebox", "1.0.0", "Xannix", null)]
[assembly: MelonGame("Jan Malitschek", "BetonBrutal")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("BetonJukebox")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("BetonJukebox")]
[assembly: AssemblyTitle("BetonJukebox")]
[assembly: NeutralResourcesLanguage("en-US")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace SoundImporter
{
	public class Core : MelonMod
	{
		public override void OnInitializeMelon()
		{
			((MelonBase)this).LoggerInstance.Msg("Initialized.");
		}
	}
	[Serializable]
	public class CustomSound
	{
		public string ID;

		public string Path;

		public string Name;

		public string Category;

		public string Subcategory;
	}
}
namespace SoundImporter.Patches
{
	[HarmonyPatch(typeof(MapEditor), "LoadMap")]
	public static class OnLocalMapLoading
	{
		private static void Prefix(string mapName)
		{
			RegisterManager.ClearCustomSounds();
			string text = Path.Combine(Application.persistentDataPath, "CustomMaps", mapName);
			if (Directory.Exists(text))
			{
				SoundImporter.Managers.SoundImporter.LoadSoundsFromDirectory(text);
			}
			else
			{
				MelonLogger.Warning("Directory does not exist: " + text);
			}
		}
	}
	[HarmonyPatch(typeof(MapEditor), "LoadDownloadedMap")]
	public static class OnWorkshopMapLoading
	{
		private static void Prefix(string mapItemID)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			RegisterManager.ClearCustomSounds();
			string text = $"{SteamApps.AppInstallDir(default(AppId))}\\..\\..\\workshop\\content\\{SteamClient.AppId.Value}\\{mapItemID}";
			if (Directory.Exists(text))
			{
				SoundImporter.Managers.SoundImporter.LoadSoundsFromDirectory(text);
			}
			else
			{
				MelonLogger.Warning("Directory does not exist: " + text);
			}
		}
	}
	[HarmonyPatch(typeof(SoundPicker), "Init")]
	public static class SoundPickerInitPatch
	{
		public static void RefreshCategories(SoundPicker picker)
		{
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Expected O, but got Unknown
			if (picker == null || (Object)(object)TriggerSoundManager.Instance == (Object)null)
			{
				return;
			}
			ScrollView value = Traverse.Create((object)picker).Field<ScrollView>("categories").Value;
			List<Category> value2 = Traverse.Create((object)picker).Field<List<Category>>("categoryItems").Value;
			if (value == null || value2 == null)
			{
				return;
			}
			((VisualElement)value).Clear();
			value2.Clear();
			HashSet<string> hashSet = TriggerSoundManager.Instance.TriggerSounds.Select((TriggerSound x) => x.category).ToHashSet();
			foreach (string item in hashSet)
			{
				Category val = new Category();
				val.Populate(item);
				val.onClick += delegate(string catName)
				{
					Traverse.Create((object)picker).Method("PopulateCategory", new object[1] { catName }).GetValue();
				};
				val.Select(false);
				((VisualElement)value).Add((VisualElement)(object)val);
				value2.Add(val);
			}
			if (hashSet.Count > 0)
			{
				Traverse.Create((object)picker).Method("PopulateCategory", new object[1] { hashSet.First() }).GetValue();
			}
		}
	}
	[HarmonyPatch(typeof(MoveTriggerScreen), "PickSound")]
	public static class OnSoundMenuOpened
	{
		private static void Prefix()
		{
			UIUpdate();
		}

		private static void UIUpdate()
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			UIDocument[] array = Object.FindObjectsOfType<UIDocument>();
			UIDocument[] array2 = array;
			foreach (UIDocument val in array2)
			{
				if (val.rootVisualElement == null)
				{
					continue;
				}
				List<SoundPicker> list = UQueryExtensions.Query<SoundPicker>(val.rootVisualElement, (string)null, (string)null).ToList();
				foreach (SoundPicker item in list)
				{
					SoundPickerInitPatch.RefreshCategories(item);
				}
			}
		}
	}
}
namespace SoundImporter.Managers
{
	public static class RegisterManager
	{
		private static readonly Dictionary<string, TriggerSound> LoadedCustomSounds = new Dictionary<string, TriggerSound>();

		public static void RegisterCustomTriggerSound(CustomSound soundData, List<AudioClip> clips)
		{
			if (!((Object)(object)TriggerSoundManager.Instance == (Object)null) && clips != null && clips.Count != 0)
			{
				if (LoadedCustomSounds.ContainsKey(soundData.ID))
				{
					MelonLogger.Warning("Sounds already has " + soundData.ID + "! Skipping");
					return;
				}
				TriggerSound val = ScriptableObject.CreateInstance<TriggerSound>();
				((Object)val).name = soundData.ID;
				val.soundName = soundData.Name;
				val.category = soundData.Category;
				val.subcategory = soundData.Subcategory;
				val.sounds = clips.ToArray();
				val.mixerChannel = TriggerSoundManager.Instance.defaultMixerChannel;
				List<TriggerSound> list = new List<TriggerSound>(TriggerSoundManager.Instance.TriggerSounds) { val };
				typeof(TriggerSoundManager).GetProperty("TriggerSounds")?.SetValue(TriggerSoundManager.Instance, list.ToArray());
				LoadedCustomSounds.Add(soundData.ID, val);
				Debug.Log((object)$"Sound registered: '{soundData.ID}' ({clips.Count} files)");
			}
		}

		public static void ClearCustomSounds()
		{
			if (LoadedCustomSounds.Count == 0)
			{
				return;
			}
			TriggerSoundManager instance = TriggerSoundManager.Instance;
			if ((Object)(object)instance != (Object)null && instance.TriggerSounds != null)
			{
				List<TriggerSound> list = new List<TriggerSound>(instance.TriggerSounds);
				foreach (TriggerSound value in LoadedCustomSounds.Values)
				{
					list.Remove(value);
					if (value.sounds != null)
					{
						AudioClip[] sounds = value.sounds;
						foreach (AudioClip val in sounds)
						{
							Object.Destroy((Object)(object)val);
						}
					}
					Object.Destroy((Object)(object)value);
				}
				typeof(TriggerSoundManager).GetProperty("TriggerSounds")?.SetValue(instance, list.ToArray());
			}
			LoadedCustomSounds.Clear();
			Debug.Log((object)"Custom sounds cleared.");
		}
	}
	public static class SoundImporter
	{
		public static void LoadSoundsFromDirectory(string mapFolderPath)
		{
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Invalid comparison between Unknown and I4
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Invalid comparison between Unknown and I4
			MelonLogger.Msg("Sync loading sounds for: " + mapFolderPath);
			if (!Directory.Exists(mapFolderPath))
			{
				MelonLogger.Warning("Directory does not exist: " + mapFolderPath);
				return;
			}
			string[] files;
			try
			{
				files = Directory.GetFiles(mapFolderPath, "*.json", SearchOption.AllDirectories);
				MelonLogger.Msg($"Found {files.Length} .json files.");
			}
			catch (Exception ex)
			{
				MelonLogger.Error("Failed to read directory: " + ex.Message);
				return;
			}
			string[] array = files;
			foreach (string text in array)
			{
				List<CustomSound> list = new List<CustomSound>();
				try
				{
					string text2 = File.ReadAllText(text);
					JToken val = JToken.Parse(text2);
					if ((int)val.Type == 2)
					{
						list = val.ToObject<List<CustomSound>>();
					}
					else if ((int)val.Type == 1)
					{
						CustomSound customSound = val.ToObject<CustomSound>();
						if (customSound != null)
						{
							list.Add(customSound);
						}
					}
				}
				catch
				{
					continue;
				}
				if (list == null || list.Count == 0)
				{
					continue;
				}
				foreach (CustomSound item in list)
				{
					if (string.IsNullOrEmpty(item.Name) || string.IsNullOrEmpty(item.Path))
					{
						MelonLogger.Warning("Skipping entry in " + text + ": Missing Name or Path.");
						continue;
					}
					string category = (string.IsNullOrEmpty(item.Category) ? "Custom" : item.Category);
					string subcategory = (string.IsNullOrEmpty(item.Subcategory) ? "Sounds" : item.Subcategory);
					string text3 = Path.Combine(mapFolderPath, "Sounds", item.Path);
					List<string> list2 = new List<string>();
					if (File.Exists(text3) && text3.EndsWith(".ogg", StringComparison.OrdinalIgnoreCase))
					{
						list2.Add(text3);
					}
					else if (Directory.Exists(text3))
					{
						list2.AddRange(Directory.GetFiles(text3, "*.ogg", SearchOption.AllDirectories));
					}
					if (list2.Count == 0)
					{
						MelonLogger.Warning("No .ogg files found for sound '" + item.Name + "' at path: " + text3);
						continue;
					}
					List<AudioClip> list3 = new List<AudioClip>();
					foreach (string item2 in list2)
					{
						AudioClip val2 = LoadAudioClipSync(item2);
						if ((Object)(object)val2 != (Object)null)
						{
							list3.Add(val2);
						}
					}
					if (list3.Count > 0)
					{
						item.Category = category;
						item.Subcategory = subcategory;
						item.ID = string.Join('_', item.Name.Split(" ")).ToLower();
						RegisterManager.RegisterCustomTriggerSound(item, list3);
					}
				}
			}
		}

		private static AudioClip LoadAudioClipSync(string filePath)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Invalid comparison between Unknown and I4
			string text = "file://" + filePath;
			UnityWebRequest audioClip = UnityWebRequestMultimedia.GetAudioClip(text, (AudioType)14);
			try
			{
				UnityWebRequestAsyncOperation val = audioClip.SendWebRequest();
				while (!((AsyncOperation)val).isDone)
				{
				}
				if ((int)audioClip.result != 1)
				{
					MelonLogger.Error("Failed to load " + filePath + ": " + audioClip.error);
					return null;
				}
				AudioClip content = DownloadHandlerAudioClip.GetContent(audioClip);
				if ((Object)(object)content != (Object)null)
				{
					((Object)content).name = Path.GetFileNameWithoutExtension(filePath);
				}
				return content;
			}
			finally
			{
				((IDisposable)audioClip)?.Dispose();
			}
		}
	}
}