Decompiled source of Mercurys Company v1.1.11
Plugins/Clementinise-CustomSounds/BepInEx/plugins/CustomSounds.dll
Decompiled 9 months agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security.Cryptography; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using CustomSounds.Networking; using CustomSounds.Patches; using GameNetcodeStuff; using HarmonyLib; using LCSoundTool; using Unity.Netcode; using UnityEngine; using UnityEngine.InputSystem; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("CustomSounds")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("CustomSounds")] [assembly: AssemblyCopyright("Copyright © 2023")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("9e086160-a7fd-4721-ba09-3e8534cb7011")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyVersion("1.0.0.0")] internal class <Module> { static <Module>() { } } namespace CustomSounds { [BepInPlugin("CustomSounds", "Custom Sounds", "2.2.0")] public class Plugin : BaseUnityPlugin { private const string PLUGIN_GUID = "CustomSounds"; private const string PLUGIN_NAME = "Custom Sounds"; private const string PLUGIN_VERSION = "2.2.0"; public static Plugin Instance; internal ManualLogSource logger; private Harmony harmony; public HashSet<string> currentSounds = new HashSet<string>(); public HashSet<string> oldSounds = new HashSet<string>(); public HashSet<string> modifiedSounds = new HashSet<string>(); public Dictionary<string, string> soundHashes = new Dictionary<string, string>(); public Dictionary<string, string> soundPacks = new Dictionary<string, string>(); public static ConfigEntry<KeyboardShortcut> AcceptSyncKey; public ConfigEntry<bool> configUseNetworking; private Dictionary<string, string> customSoundNames = new Dictionary<string, string>(); public static bool Initialized { get; private set; } private void Awake() { //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Expected O, but got Unknown if (!((Object)(object)Instance == (Object)null)) { return; } Instance = this; logger = Logger.CreateLogSource("CustomSounds"); configUseNetworking = ((BaseUnityPlugin)this).Config.Bind<bool>("Experimental", "EnableNetworking", true, "Whether or not to use the networking built into this plugin. If set to true everyone in the lobby needs CustomSounds to join and also \"EnableNetworking\" set to true."); AcceptSyncKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Experimental", "AcceptSyncKey", new KeyboardShortcut((KeyCode)289, Array.Empty<KeyCode>()), "Key to accept audio sync."); harmony = new Harmony("CustomSounds"); harmony.PatchAll(typeof(TerminalParsePlayerSentencePatch)); harmony.PatchAll(typeof(RemapKeyPatch)); if (configUseNetworking.Value) { harmony.PatchAll(typeof(NetworkObjectManager)); } modifiedSounds = new HashSet<string>(); string customSoundsFolderPath = GetCustomSoundsFolderPath(); if (!Directory.Exists(customSoundsFolderPath)) { logger.LogInfo((object)"\"CustomSounds\" folder not found. Creating it now."); Directory.CreateDirectory(customSoundsFolderPath); } string path = Path.Combine(Paths.BepInExConfigPath); try { List<string> list = File.ReadAllLines(path).ToList(); int num = list.FindIndex((string line) => line.StartsWith("HideManagerGameObject")); if (num != -1) { logger.LogInfo((object)"\"hideManagerGameObject\" value not correctly set. Fixing it now."); list[num] = "HideManagerGameObject = true"; } File.WriteAllLines(path, list); } catch (Exception ex) { logger.LogError((object)("Error modifying config file: " + ex.Message)); } Type[] types = Assembly.GetExecutingAssembly().GetTypes(); Type[] array = types; foreach (Type type in array) { MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic); MethodInfo[] array2 = methods; foreach (MethodInfo methodInfo in array2) { object[] customAttributes = methodInfo.GetCustomAttributes(typeof(RuntimeInitializeOnLoadMethodAttribute), inherit: false); if (customAttributes.Length != 0) { methodInfo.Invoke(null, null); } } } logger.LogInfo((object)"Plugin CustomSounds is loaded!"); } internal void Start() { Initialize(); } internal void OnDestroy() { Initialize(); } internal void Initialize() { if (!Initialized) { Initialized = true; DeleteTempFolder(); ReloadSounds(serverSync: false, isTemporarySync: false); } } private void OnApplicationQuit() { DeleteTempFolder(); } public GameObject LoadNetworkPrefabFromEmbeddedResource() { Assembly executingAssembly = Assembly.GetExecutingAssembly(); string name = "CustomSounds.Bundle.audionetworkhandler"; using Stream stream = executingAssembly.GetManifestResourceStream(name); if (stream == null) { Debug.LogError((object)"Asset bundle not found in embedded resources."); return null; } byte[] array = new byte[stream.Length]; stream.Read(array, 0, array.Length); AssetBundle val = AssetBundle.LoadFromMemory(array); if ((Object)(object)val == (Object)null) { Debug.LogError((object)"Failed to load AssetBundle from memory."); return null; } return val.LoadAsset<GameObject>("audionetworkhandler"); } public void DeleteTempFolder() { string customSoundsTempFolderPath = GetCustomSoundsTempFolderPath(); if (Directory.Exists(customSoundsTempFolderPath)) { try { Directory.Delete(customSoundsTempFolderPath, recursive: true); logger.LogInfo((object)"Temporary-Sync folder deleted successfully."); } catch (Exception ex) { logger.LogError((object)("Error deleting Temporary-Sync folder: " + ex.Message)); } } } public string GetCustomSoundsFolderPath() { return Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)Instance).Info.Location), "CustomSounds"); } public string GetCustomSoundsTempFolderPath() { return Path.Combine(GetCustomSoundsFolderPath(), "Temporary-Sync"); } public static byte[] SerializeWavToBytes(string filePath) { try { return File.ReadAllBytes(filePath); } catch (Exception ex) { Console.WriteLine("An error occurred: " + ex.Message); return null; } } public static string SerializeWavToBase64(string filePath) { try { byte[] inArray = File.ReadAllBytes(filePath); return Convert.ToBase64String(inArray); } catch (Exception ex) { Console.WriteLine("An error occurred: " + ex.Message); return null; } } public static void DeserializeBytesToWav(byte[] byteArray, string audioFileName) { try { string customSoundsTempFolderPath = Instance.GetCustomSoundsTempFolderPath(); if (!Directory.Exists(customSoundsTempFolderPath)) { Instance.logger.LogInfo((object)"\"Temporary-Sync\" folder not found. Creating it now."); Directory.CreateDirectory(customSoundsTempFolderPath); } File.WriteAllBytes(Path.Combine(customSoundsTempFolderPath, audioFileName), byteArray); Console.WriteLine("WAV file \"" + audioFileName + "\" created!"); } catch (Exception ex) { Console.WriteLine("An error occurred: " + ex.Message); } } public static List<byte[]> SplitAudioData(byte[] audioData, int maxSegmentSize = 62000) { List<byte[]> list = new List<byte[]>(); for (int i = 0; i < audioData.Length; i += maxSegmentSize) { int num = Mathf.Min(maxSegmentSize, audioData.Length - i); byte[] array = new byte[num]; Array.Copy(audioData, i, array, 0, num); list.Add(array); } return list; } public static byte[] CombineAudioSegments(List<byte[]> segments) { List<byte> list = new List<byte>(); foreach (byte[] segment in segments) { list.AddRange(segment); } return list.ToArray(); } public void ShowCustomTip(string header, string body, bool isWarning) { HUDManager.Instance.DisplayTip(header, body, isWarning, false, "LC_Tip1"); } public void ForceUnsync() { DeleteTempFolder(); ReloadSounds(serverSync: false, isTemporarySync: false); } public void RevertSounds() { HashSet<string> hashSet = new HashSet<string>(); foreach (string currentSound in currentSounds) { string text = currentSound; if (currentSound.Contains("-")) { text = currentSound.Substring(0, currentSound.IndexOf("-")); } if (!hashSet.Contains(text)) { logger.LogInfo((object)(text + " restored.")); SoundTool.RestoreAudioClip(text); hashSet.Add(text); } } logger.LogInfo((object)"Original game sounds restored."); } public static string CalculateMD5(string filename) { using MD5 mD = MD5.Create(); using FileStream inputStream = File.OpenRead(filename); byte[] array = mD.ComputeHash(inputStream); return BitConverter.ToString(array).Replace("-", "").ToLowerInvariant(); } public void ReloadSounds(bool serverSync, bool isTemporarySync) { oldSounds = new HashSet<string>(currentSounds); modifiedSounds.Clear(); string directoryName = Path.GetDirectoryName(Paths.PluginPath); currentSounds.Clear(); customSoundNames.Clear(); string customSoundsTempFolderPath = GetCustomSoundsTempFolderPath(); if (isTemporarySync) { logger.LogInfo((object)("Temporary folder: " + customSoundsTempFolderPath)); if (Directory.Exists(customSoundsTempFolderPath)) { ProcessDirectory(customSoundsTempFolderPath, serverSync, isTemporarySync: true); } } ProcessDirectory(directoryName, serverSync, isTemporarySync: false); } private void ProcessDirectory(string directoryPath, bool serverSync, bool isTemporarySync) { string[] directories = Directory.GetDirectories(directoryPath, "CustomSounds", SearchOption.AllDirectories); foreach (string text in directories) { string fileName = Path.GetFileName(Path.GetDirectoryName(text)); ProcessSoundFiles(text, fileName, serverSync, isTemporarySync); string[] directories2 = Directory.GetDirectories(text); foreach (string text2 in directories2) { string fileName2 = Path.GetFileName(text2); ProcessSoundFiles(text2, fileName2, serverSync, isTemporarySync); } } } private (string soundName, int? percentage, string customName) ParseSoundFileName(string fullSoundName) { string[] array = fullSoundName.Split(new char[1] { '-' }); string s = array[^1].Replace(".wav", ""); if (int.TryParse(s, out var result)) { string item = array[0]; string item2 = string.Join(" ", array.Skip(1).Take(array.Length - 2)); return (item, result, item2); } return (array[0], null, string.Join(" ", array.Skip(1)).Replace(".wav", "")); } private void ProcessSoundFiles(string directoryPath, string packName, bool serverSync, bool isTemporarySync) { string[] files = Directory.GetFiles(directoryPath, "*.wav"); foreach (string text in files) { string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(text); (string soundName, int? percentage, string customName) tuple = ParseSoundFileName(fileNameWithoutExtension); string item = tuple.soundName; int? item2 = tuple.percentage; string item3 = tuple.customName; string text2 = (item2.HasValue ? $"{item}-{item3}-{item2.Value}" : (item + "-" + item3)); string text3 = CalculateMD5(text); if (isTemporarySync || !currentSounds.Contains(text2)) { if (soundHashes.TryGetValue(text2, out var value) && value != text3) { modifiedSounds.Add(text2); } AudioClip audioClip = SoundTool.GetAudioClip(directoryPath, "", text); SoundTool.ReplaceAudioClip(item, audioClip); soundHashes[text2] = text3; currentSounds.Add(text2); soundPacks[item] = packName; string text4 = "[" + packName + "] " + item + " sound replaced!"; if (item2 > 0) { text4 += $" (Random chance: {item2}%)"; } logger.LogInfo((object)text4); string key = item + (item2.HasValue ? $"-{item2.Value}-{item3}" : ("-" + item3)); if (!string.IsNullOrEmpty(item3)) { customSoundNames[key] = item3; } if (serverSync) { string text5 = Path.Combine(directoryPath, fileNameWithoutExtension + ".wav"); logger.LogInfo((object)("[" + text5 + "] " + fileNameWithoutExtension + ".wav!")); AudioNetworkHandler.Instance.QueueAudioData(SerializeWavToBytes(text5), fileNameWithoutExtension + ".wav"); } } } } public string ListAllSounds(bool isListing) { StringBuilder stringBuilder = new StringBuilder(isListing ? "Listing all currently loaded custom sounds:\n\n" : "Customsounds reloaded.\n\n"); Dictionary<string, List<string>> soundsByPack = new Dictionary<string, List<string>>(); Action<HashSet<string>, string> action = delegate(HashSet<string> soundsSet, string status) { foreach (string item5 in soundsSet) { (string soundName, int? percentage, string customName) tuple = ParseSoundFileName(item5); string item = tuple.soundName; int? item2 = tuple.percentage; string item3 = tuple.customName; string text = (item2.HasValue ? $" (Random: {item2.Value}%)" : ""); string text2 = ""; string key = item + (item2.HasValue ? $"-{item2.Value}-{item3}" : ("-" + item3)); if (customSoundNames.TryGetValue(key, out var value)) { text2 = " [" + value + "]"; } string key2 = (soundPacks.ContainsKey(item) ? soundPacks[item] : "Unknown"); if (!soundsByPack.ContainsKey(key2)) { soundsByPack[key2] = new List<string>(); } string item4 = (isListing ? (item + text + text2) : (item + " (" + status + ")" + text + text2)); soundsByPack[key2].Add(item4); } }; if (!isListing) { action(new HashSet<string>(currentSounds.Except(oldSounds)), "N¹"); action(new HashSet<string>(oldSounds.Except(currentSounds)), "D²"); action(new HashSet<string>(oldSounds.Intersect(currentSounds).Except(modifiedSounds)), "A.E³"); action(new HashSet<string>(modifiedSounds), "M⁴"); } else { action(new HashSet<string>(currentSounds), "N¹"); } foreach (string key3 in soundsByPack.Keys) { stringBuilder.AppendLine(key3 + " :"); foreach (string item6 in soundsByPack[key3]) { stringBuilder.AppendLine("- " + item6); } stringBuilder.AppendLine(); } if (!isListing) { stringBuilder.AppendLine("Footnotes:"); stringBuilder.AppendLine("¹ N = New"); stringBuilder.AppendLine("² D = Deleted"); stringBuilder.AppendLine("³ A.E = Already Existed"); stringBuilder.AppendLine("⁴ M = Modified"); stringBuilder.AppendLine(); } return stringBuilder.ToString(); } } } namespace CustomSounds.Patches { [HarmonyPatch] public class NetworkObjectManager { private static GameObject networkPrefab; private static GameObject networkHandlerHost; [HarmonyPatch(typeof(GameNetworkManager), "Start")] [HarmonyPrefix] public static void Init() { if (!((Object)(object)networkPrefab != (Object)null)) { networkPrefab = Plugin.Instance.LoadNetworkPrefabFromEmbeddedResource(); networkPrefab.AddComponent<AudioNetworkHandler>(); NetworkManager.Singleton.AddNetworkPrefab(networkPrefab); Plugin.Instance.logger.LogInfo((object)"Created AudioNetworkHandler prefab"); } } [HarmonyPostfix] [HarmonyPatch(typeof(StartOfRound), "Awake")] private static void SpawnNetworkHandler() { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) try { if (NetworkManager.Singleton.IsHost || NetworkManager.Singleton.IsServer) { Plugin.Instance.logger.LogInfo((object)"Spawning network handler"); networkHandlerHost = Object.Instantiate<GameObject>(networkPrefab, Vector3.zero, Quaternion.identity); if (networkHandlerHost.GetComponent<NetworkObject>().IsSpawned) { Debug.Log((object)"NetworkObject is spawned and active."); } else { Debug.Log((object)"Failed to spawn NetworkObject."); } networkHandlerHost.GetComponent<NetworkObject>().Spawn(true); if ((Object)(object)AudioNetworkHandler.Instance != (Object)null) { Debug.Log((object)"Successfully accessed AudioNetworkHandler instance."); } else { Debug.Log((object)"AudioNetworkHandler instance is null."); } } } catch { Plugin.Instance.logger.LogError((object)"Failed to spawned network handler"); } } [HarmonyPostfix] [HarmonyPatch(typeof(GameNetworkManager), "StartDisconnect")] private static void DestroyNetworkHandler() { try { if (NetworkManager.Singleton.IsHost || NetworkManager.Singleton.IsServer) { Plugin.Instance.logger.LogInfo((object)"Destroying network handler"); Object.Destroy((Object)(object)networkHandlerHost); networkHandlerHost = null; } } catch { Plugin.Instance.logger.LogError((object)"Failed to destroy network handler"); } } } [HarmonyPatch] public class RemapKeyPatch { public Harmony _harmony; public static InputActionAsset asset; private static string defaultKey; private static string path; public static string actionName; public static void UpdateInputActionAsset(string thing) { asset = InputActionAsset.FromJson("\r\n {\r\n \"maps\" : [\r\n {\r\n \"name\" : \"CustomSounds\",\r\n \"actions\": [\r\n {\"name\": \"" + actionName + "\", \"type\" : \"button\"}\r\n ],\r\n \"bindings\" : [\r\n {\"path\" : \"" + thing + "\", \"action\": \"" + actionName + "\"}\r\n ]\r\n }\r\n ]\r\n }"); } [HarmonyPatch(typeof(KepRemapPanel), "LoadKeybindsUI")] [HarmonyPrefix] public static void AddRemappableKey(KepRemapPanel __instance) { //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Expected O, but got Unknown Debug.Log((object)("[CustomSounds] Default key for sync is " + defaultKey)); for (int i = 0; i < __instance.remappableKeys.Count; i++) { if (__instance.remappableKeys[i].ControlName == "Accept Sync") { return; } } RemappableKey val = new RemappableKey(); UpdateInputActionAsset(defaultKey); if ((Object)(object)asset == (Object)null) { Debug.LogError((object)"InputActionAsset is null."); return; } InputAction val2 = asset.FindAction("CustomSounds/" + actionName, false); if (val2 == null) { Debug.LogError((object)"Action 'CustomSounds/AcceptSyncAction' not found."); return; } InputActionReference currentInput = InputActionReference.Create(asset.FindAction("CustomSounds/" + actionName, false)); val.ControlName = "Accept Sync"; val.currentInput = currentInput; __instance.remappableKeys.Add(val); } [HarmonyPatch(typeof(PlayerControllerB), "Update")] [HarmonyPostfix] public static void ReadInput(PlayerControllerB __instance) { if (((((NetworkBehaviour)__instance).IsOwner && __instance.isPlayerControlled && (!((NetworkBehaviour)__instance).IsServer || __instance.isHostPlayerObject)) || __instance.isTestingPlayer) && Application.isFocused) { if (!Object.op_Implicit((Object)(object)asset) || !asset.enabled) { UpdateInputActionAsset(defaultKey); asset.Enable(); } InputAction val = asset.FindAction("CustomSounds/" + actionName, false); if (val != null && val.WasPressedThisFrame() && AudioNetworkHandler.isRequestingSync) { Plugin.Instance.ShowCustomTip("CustomSounds Sync", "Sync request accepted successfully!", isWarning: false); AudioNetworkHandler.hasAcceptedSync = true; AudioNetworkHandler.isRequestingSync = false; } } } [HarmonyPatch(typeof(IngamePlayerSettings), "CompleteRebind")] [HarmonyPrefix] public static void SavingActionRebind(IngamePlayerSettings __instance) { //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) if (!(__instance.rebindingOperation.action.name != actionName)) { string text = ((object)__instance.rebindingOperation.action).ToString(); string text2 = text.Split('[', ']')[1]; string value = text2.Replace("/Keyboard/", ""); defaultKey = text2; try { KeyCode val = (KeyCode)Enum.Parse(typeof(KeyCode), value, ignoreCase: true); Plugin.AcceptSyncKey.Value = new KeyboardShortcut(val, Array.Empty<KeyCode>()); } catch (Exception ex) { Debug.LogError((object)("Erreur lors de la conversion de la chaîne en KeyCode: " + ex.Message)); } UpdateInputActionAsset(defaultKey); } } [HarmonyPatch(typeof(KepRemapPanel), "ResetKeybindsUI")] [HarmonyPrefix] public static void ResetAcceptAction(KepRemapPanel __instance) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) Plugin.AcceptSyncKey.Value = new KeyboardShortcut((KeyCode)289, Array.Empty<KeyCode>()); defaultKey = "<Keyboard>/f8"; UpdateInputActionAsset(defaultKey); bool flag = UpdateAcceptSyncKeybind(__instance, "<Keyboard>/f8"); } private static bool UpdateAcceptSyncKeybind(KepRemapPanel panel, string defaultBinding) { foreach (RemappableKey remappableKey in panel.remappableKeys) { if (remappableKey.ControlName == "Accept Sync") { remappableKey.currentInput = InputActionReference.Create(asset.FindAction("CustomSounds/AcceptSyncAction", false)); Debug.Log((object)"[CustomSounds] Found and updated 'Accept Sync' keybinding"); return true; } } Debug.Log((object)"[CustomSounds] 'Accept Sync' keybinding not found"); return false; } static RemapKeyPatch() { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) KeyboardShortcut value = Plugin.AcceptSyncKey.Value; defaultKey = "<Keyboard>/" + ((object)(KeyboardShortcut)(ref value)).ToString(); path = Application.persistentDataPath + "/AcceptSyncButton.txt"; actionName = "AcceptSyncAction"; } } [HarmonyPatch(typeof(Terminal), "ParsePlayerSentence")] public static class TerminalParsePlayerSentencePatch { public static bool Prefix(Terminal __instance, ref TerminalNode __result) { string[] array = __instance.screenText.text.Split(new char[1] { '\n' }); if (array.Length == 0) { return true; } string[] array2 = array.Last().Trim().ToLower() .Split(new char[1] { ' ' }); if (array2.Length == 0 || (array2[0] != "customsounds" && array2[0] != "cs")) { return true; } Plugin.Instance.logger.LogInfo((object)("Received terminal command: " + string.Join(" ", array2))); if (array2.Length > 1 && (array2[0] == "customsounds" || array2[0] == "cs")) { switch (array2[1]) { case "reload": case "rl": Plugin.Instance.RevertSounds(); Plugin.Instance.ReloadSounds(serverSync: false, isTemporarySync: false); __result = CreateTerminalNode(Plugin.Instance.ListAllSounds(isListing: false)); return false; case "revert": case "rv": Plugin.Instance.RevertSounds(); __result = CreateTerminalNode("Game sounds reverted to original.\n\n"); return false; case "list": case "l": __result = CreateTerminalNode(Plugin.Instance.ListAllSounds(isListing: true)); return false; case "help": case "h": if (NetworkManager.Singleton.IsHost) { __result = CreateTerminalNode("CustomSounds commands \n(Can also be used with 'CS' as an alias).\n\n>CUSTOMSOUNDS LIST/L\nTo display all currently loaded sounds\n\n>CUSTOMSOUNDS RELOAD/RL\nTo reload and apply sounds from the 'CustomSounds' folder and its subfolders.\n\n>CUSTOMSOUNDS REVERT/RV\nTo unload all custom sounds and restore original game sounds\n\n>CUSTOMSOUNDS SYNC/S\nTo start the sync of custom sounds with clients\n\n>CUSTOMSOUNDS FORCE-UNSYNC/FU\nTo force the unsync process for all clients\n\n"); } else { __result = CreateTerminalNode("CustomSounds commands \n(Can also be used with 'CS' as an alias).\n\n>CUSTOMSOUNDS LIST/L\nTo display all currently loaded sounds\n\n>CUSTOMSOUNDS RELOAD/RL\nTo reload and apply sounds from the 'CustomSounds' folder and its subfolders.\n\n>CUSTOMSOUNDS REVERT/RV\nTo unload all custom sounds and restore original game sounds\n\n>CUSTOMSOUNDS UNSYNC/U\nUnsyncs sounds sent by the host.\n\n"); } return false; case "sync": case "s": if (NetworkManager.Singleton.IsHost) { if (Plugin.Instance.configUseNetworking.Value) { __result = CreateTerminalNode("Custom sound sync initiated. \nSyncing sounds with clients...\n\n"); Plugin.Instance.ReloadSounds(serverSync: true, isTemporarySync: false); } else { __result = CreateTerminalNode("Custom sound sync is currently disabled. \nPlease enable network support in the plugin config to use this feature.\n\n"); } } else { __result = CreateTerminalNode("/!\\ ERROR /!\\ \nThis command can only be used by the host!\n\n"); } return false; case "unsync": case "u": if (!NetworkManager.Singleton.IsHost) { __result = CreateTerminalNode("Unsyncing custom sounds. \nTemporary files deleted and original sounds reloaded.\n\n"); Plugin.Instance.DeleteTempFolder(); Plugin.Instance.ReloadSounds(serverSync: false, isTemporarySync: false); } else { __result = CreateTerminalNode("/!\\ ERROR /!\\ \nThis command cannot be used by the host!\n\n"); } return false; case "fu": case "force-unsync": if (NetworkManager.Singleton.IsHost) { __result = CreateTerminalNode("Forcing unsync for all clients. \nAll client-side temporary synced files have been deleted, and original sounds reloaded.\n\n"); AudioNetworkHandler.Instance.ForceUnsync(); } else { __result = CreateTerminalNode("/!\\ ERROR /!\\ \nThis command can only be used by the host!\n\n"); } return false; default: __result = CreateTerminalNode("Unknown customsounds command.\n\n"); return false; } } return true; } private static TerminalNode CreateTerminalNode(string message) { TerminalNode val = ScriptableObject.CreateInstance<TerminalNode>(); val.displayText = message; val.clearPreviousText = true; return val; } } } namespace CustomSounds.Networking { public class AudioNetworkHandler : NetworkBehaviour { private struct AudioData { public List<byte[]> Segments; public string FileName; public AudioData(List<byte[]> segments, string fileName) { Segments = segments; FileName = fileName; } } private List<byte[]> receivedAudioSegments = new List<byte[]>(); private string audioFileName; private int totalAudioFiles; private int processedAudioFiles; private int totalSegments; private int processedSegments; public static bool isRequestingSync; private float[] progressThresholds = new float[4] { 0.25f, 0.5f, 0.75f, 1f }; private int lastThresholdIndex = -1; public static bool hasAcceptedSync; private Queue<AudioData> audioQueue = new Queue<AudioData>(); private bool isSendingAudio = false; public static AudioNetworkHandler Instance { get; private set; } private void Awake() { if ((Object)(object)Instance == (Object)null) { Instance = this; Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject); Debug.Log((object)"AudioNetworkHandler instance created."); } else { Object.Destroy((Object)(object)((Component)this).gameObject); Debug.Log((object)"Extra AudioNetworkHandler instance destroyed."); } } public void QueueAudioData(byte[] audioData, string audioName) { List<byte[]> list = Plugin.SplitAudioData(audioData); totalSegments += list.Count; audioQueue.Enqueue(new AudioData(list, audioName)); if (!isSendingAudio) { totalAudioFiles = audioQueue.Count; processedAudioFiles = 0; ((MonoBehaviour)this).StartCoroutine(SendAudioDataQueue()); } } private IEnumerator SendAudioDataQueue() { isSendingAudio = true; totalSegments = 0; processedSegments = 0; lastThresholdIndex = -1; RequestSyncWithClients(); yield return (object)new WaitForSeconds(6f); isRequestingSync = false; DisplayStartingSyncMessageClientRpc(); yield return (object)new WaitForSeconds(2f); while (audioQueue.Count > 0) { AudioData audioData = audioQueue.Dequeue(); yield return ((MonoBehaviour)this).StartCoroutine(SendAudioDataCoroutine(audioData.Segments, audioData.FileName)); processedAudioFiles++; UpdateProgress(); } NotifyClientsQueueCompletedServerRpc(); isSendingAudio = false; } private void RequestSyncWithClients() { foreach (NetworkClient connectedClients in NetworkManager.Singleton.ConnectedClientsList) { RequestSyncClientRpc(connectedClients.ClientId); } } [ClientRpc] private void RequestSyncClientRpc(ulong clientId) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Invalid comparison between Unknown and I4 //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Invalid comparison between Unknown and I4 //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: 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) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager; if (networkManager != null && networkManager.IsListening) { if ((int)base.__rpc_exec_stage != 2 && (networkManager.IsServer || networkManager.IsHost)) { ClientRpcParams val = default(ClientRpcParams); FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendClientRpc(3186703908u, val, (RpcDelivery)0); BytePacker.WriteValueBitPacked(val2, clientId); ((NetworkBehaviour)this).__endSendClientRpc(ref val2, 3186703908u, val, (RpcDelivery)0); } if ((int)base.__rpc_exec_stage == 2 && (networkManager.IsClient || networkManager.IsHost) && !((NetworkBehaviour)this).IsServer) { Plugin.Instance.ShowCustomTip("CustomSounds Sync", $"Press {Plugin.AcceptSyncKey.Value} to accept the audio sync request.", isWarning: false); isRequestingSync = true; } } } [ServerRpc(RequireOwnership = false)] private void NotifyClientsQueueCompletedServerRpc(ServerRpcParams rpcParams = default(ServerRpcParams)) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Invalid comparison between Unknown and I4 //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Invalid comparison between Unknown and I4 //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager; if (networkManager != null && networkManager.IsListening) { if ((int)base.__rpc_exec_stage != 1 && (networkManager.IsClient || networkManager.IsHost)) { FastBufferWriter val = ((NetworkBehaviour)this).__beginSendServerRpc(152710787u, rpcParams, (RpcDelivery)0); ((NetworkBehaviour)this).__endSendServerRpc(ref val, 152710787u, rpcParams, (RpcDelivery)0); } if ((int)base.__rpc_exec_stage == 1 && (networkManager.IsServer || networkManager.IsHost)) { ProcessLastAudioFileClientRpc(); } } } public void ForceUnsync() { ForceUnsyncClientsClientRpc(); } [ClientRpc] private void ForceUnsyncClientsClientRpc() { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Invalid comparison between Unknown and I4 //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Invalid comparison between Unknown and I4 //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager; if (networkManager == null || !networkManager.IsListening) { return; } if ((int)base.__rpc_exec_stage != 2 && (networkManager.IsServer || networkManager.IsHost)) { ClientRpcParams val = default(ClientRpcParams); FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendClientRpc(3960362720u, val, (RpcDelivery)0); ((NetworkBehaviour)this).__endSendClientRpc(ref val2, 3960362720u, val, (RpcDelivery)0); } if ((int)base.__rpc_exec_stage == 2 && (networkManager.IsClient || networkManager.IsHost)) { if (((NetworkBehaviour)this).IsServer) { Debug.Log((object)"Forcing all clients to delete Temporary-Sync folder."); return; } Plugin.Instance.ShowCustomTip("CustomSounds Sync", "The CustomSounds sync has been reset by the host.\nTemporary files deleted and original sounds reloaded", isWarning: false); Plugin.Instance.DeleteTempFolder(); Plugin.Instance.RevertSounds(); Plugin.Instance.ReloadSounds(serverSync: false, isTemporarySync: false); } } [ClientRpc] private void ProcessLastAudioFileClientRpc() { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Invalid comparison between Unknown and I4 //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Invalid comparison between Unknown and I4 //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager; if (networkManager != null && networkManager.IsListening) { if ((int)base.__rpc_exec_stage != 2 && (networkManager.IsServer || networkManager.IsHost)) { ClientRpcParams val = default(ClientRpcParams); FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendClientRpc(234624598u, val, (RpcDelivery)0); ((NetworkBehaviour)this).__endSendClientRpc(ref val2, 234624598u, val, (RpcDelivery)0); } if ((int)base.__rpc_exec_stage == 2 && (networkManager.IsClient || networkManager.IsHost) && hasAcceptedSync) { hasAcceptedSync = false; ProcessLastAudioFile(); Debug.Log((object)"Reverting all sounds."); Plugin.Instance.RevertSounds(); Debug.Log((object)"All sounds reverted!"); Debug.Log((object)"Reloading all sounds."); Plugin.Instance.ReloadSounds(serverSync: false, isTemporarySync: true); Debug.Log((object)"All sounds reloaded!"); } } } private void ProcessLastAudioFile() { if (receivedAudioSegments.Count > 0 && !string.IsNullOrEmpty(audioFileName)) { byte[] byteArray = Plugin.CombineAudioSegments(receivedAudioSegments); Plugin.DeserializeBytesToWav(byteArray, audioFileName); receivedAudioSegments.Clear(); audioFileName = null; } } public void SendAudioData(byte[] audioData, string audioName) { List<byte[]> list = Plugin.SplitAudioData(audioData); audioFileName = audioName; SendAudioMetaDataToClientsServerRpc(list.Count, audioName); ((MonoBehaviour)this).StartCoroutine(SendAudioDataCoroutine(list, audioName)); } [ServerRpc] public void SendAudioMetaDataToClientsServerRpc(int totalSegments, string fileName) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Invalid comparison between Unknown and I4 //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Invalid comparison between Unknown and I4 //IL_00a5: 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_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Invalid comparison between Unknown and I4 //IL_010d: Unknown result type (might be due to invalid IL or missing references) NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager; if (networkManager == null || !networkManager.IsListening) { return; } if ((int)base.__rpc_exec_stage != 1 && (networkManager.IsClient || networkManager.IsHost)) { if (((NetworkBehaviour)this).OwnerClientId != networkManager.LocalClientId) { if ((int)networkManager.LogLevel <= 1) { Debug.LogError((object)"Only the owner can invoke a ServerRpc that requires ownership!"); } return; } ServerRpcParams val = default(ServerRpcParams); FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendServerRpc(3991320206u, val, (RpcDelivery)0); BytePacker.WriteValueBitPacked(val2, totalSegments); bool flag = fileName != null; ((FastBufferWriter)(ref val2)).WriteValueSafe<bool>(ref flag, default(ForPrimitives)); if (flag) { ((FastBufferWriter)(ref val2)).WriteValueSafe(fileName, false); } ((NetworkBehaviour)this).__endSendServerRpc(ref val2, 3991320206u, val, (RpcDelivery)0); } if ((int)base.__rpc_exec_stage == 1 && (networkManager.IsServer || networkManager.IsHost)) { Debug.Log((object)$"Sending metadata to clients: {totalSegments} segments, file name: {fileName}"); ReceiveAudioMetaDataClientRpc(totalSegments, fileName); } } private IEnumerator SendAudioDataCoroutine(List<byte[]> audioSegments, string audioName) { foreach (byte[] segment in audioSegments) { SendBytesToServerRpc(segment, audioName); processedSegments++; UpdateProgress(); yield return (object)new WaitForSeconds(0.2f); } } [ServerRpc] public void SendBytesToServerRpc(byte[] audioSegment, string audioName) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Invalid comparison between Unknown and I4 //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Invalid comparison between Unknown and I4 //IL_00a5: 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_00b3: 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_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Invalid comparison between Unknown and I4 //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Unknown result type (might be due to invalid IL or missing references) NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager; if (networkManager == null || !networkManager.IsListening) { return; } if ((int)base.__rpc_exec_stage != 1 && (networkManager.IsClient || networkManager.IsHost)) { if (((NetworkBehaviour)this).OwnerClientId != networkManager.LocalClientId) { if ((int)networkManager.LogLevel <= 1) { Debug.LogError((object)"Only the owner can invoke a ServerRpc that requires ownership!"); } return; } ServerRpcParams val = default(ServerRpcParams); FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendServerRpc(3131260794u, val, (RpcDelivery)0); bool flag = audioSegment != null; ((FastBufferWriter)(ref val2)).WriteValueSafe<bool>(ref flag, default(ForPrimitives)); if (flag) { ((FastBufferWriter)(ref val2)).WriteValueSafe<byte>(audioSegment, default(ForPrimitives)); } bool flag2 = audioName != null; ((FastBufferWriter)(ref val2)).WriteValueSafe<bool>(ref flag2, default(ForPrimitives)); if (flag2) { ((FastBufferWriter)(ref val2)).WriteValueSafe(audioName, false); } ((NetworkBehaviour)this).__endSendServerRpc(ref val2, 3131260794u, val, (RpcDelivery)0); } if ((int)base.__rpc_exec_stage == 1 && (networkManager.IsServer || networkManager.IsHost)) { Debug.Log((object)("Sending segment to server: " + audioName)); ReceiveBytesClientRpc(audioSegment, audioName); } } [ClientRpc] public void ReceiveAudioMetaDataClientRpc(int totalSegments, string fileName) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Invalid comparison between Unknown and I4 //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Invalid comparison between Unknown and I4 //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: 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) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager; if (networkManager == null || !networkManager.IsListening) { return; } if ((int)base.__rpc_exec_stage != 2 && (networkManager.IsServer || networkManager.IsHost)) { ClientRpcParams val = default(ClientRpcParams); FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendClientRpc(1027341762u, val, (RpcDelivery)0); BytePacker.WriteValueBitPacked(val2, totalSegments); bool flag = fileName != null; ((FastBufferWriter)(ref val2)).WriteValueSafe<bool>(ref flag, default(ForPrimitives)); if (flag) { ((FastBufferWriter)(ref val2)).WriteValueSafe(fileName, false); } ((NetworkBehaviour)this).__endSendClientRpc(ref val2, 1027341762u, val, (RpcDelivery)0); } if ((int)base.__rpc_exec_stage == 2 && (networkManager.IsClient || networkManager.IsHost)) { Debug.Log((object)$"Received metadata on client: {totalSegments} segments expected, file name: {fileName}"); audioFileName = fileName; receivedAudioSegments.Clear(); } } [ClientRpc] public void ReceiveBytesClientRpc(byte[] audioSegment, string audioName) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Invalid comparison between Unknown and I4 //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Invalid comparison between Unknown and I4 //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager; if (networkManager == null || !networkManager.IsListening) { return; } if ((int)base.__rpc_exec_stage != 2 && (networkManager.IsServer || networkManager.IsHost)) { ClientRpcParams val = default(ClientRpcParams); FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendClientRpc(2945580654u, val, (RpcDelivery)0); bool flag = audioSegment != null; ((FastBufferWriter)(ref val2)).WriteValueSafe<bool>(ref flag, default(ForPrimitives)); if (flag) { ((FastBufferWriter)(ref val2)).WriteValueSafe<byte>(audioSegment, default(ForPrimitives)); } bool flag2 = audioName != null; ((FastBufferWriter)(ref val2)).WriteValueSafe<bool>(ref flag2, default(ForPrimitives)); if (flag2) { ((FastBufferWriter)(ref val2)).WriteValueSafe(audioName, false); } ((NetworkBehaviour)this).__endSendClientRpc(ref val2, 2945580654u, val, (RpcDelivery)0); } if ((int)base.__rpc_exec_stage == 2 && (networkManager.IsClient || networkManager.IsHost) && !((NetworkBehaviour)this).IsServer && hasAcceptedSync) { if (!string.IsNullOrEmpty(audioName) && audioFileName != audioName) { ProcessLastAudioFile(); audioFileName = audioName; } receivedAudioSegments.Add(audioSegment); } } [ClientRpc] private void DisplayStartingSyncMessageClientRpc() { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Invalid comparison between Unknown and I4 //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Invalid comparison between Unknown and I4 //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager; if (networkManager == null || !networkManager.IsListening) { return; } if ((int)base.__rpc_exec_stage != 2 && (networkManager.IsServer || networkManager.IsHost)) { ClientRpcParams val = default(ClientRpcParams); FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendClientRpc(3964799390u, val, (RpcDelivery)0); ((NetworkBehaviour)this).__endSendClientRpc(ref val2, 3964799390u, val, (RpcDelivery)0); } if ((int)base.__rpc_exec_stage == 2 && (networkManager.IsClient || networkManager.IsHost)) { if (hasAcceptedSync) { Plugin.Instance.ShowCustomTip("CustomSounds Sync", "Starting audio synchronization. Please wait...", isWarning: false); Plugin.Instance.DeleteTempFolder(); } else if (((NetworkBehaviour)this).IsServer) { Plugin.Instance.ShowCustomTip("CustomSounds Sync", "Initiating audio synchronization. Sending files to clients...", isWarning: false); } } } private void UpdateProgress() { float progress = (float)processedSegments / (float)totalSegments; int currentThresholdIndex = GetCurrentThresholdIndex(progress); if (currentThresholdIndex > lastThresholdIndex) { lastThresholdIndex = currentThresholdIndex; UpdateProgressClientRpc(progress); } } private int GetCurrentThresholdIndex(float progress) { for (int num = progressThresholds.Length - 1; num >= 0; num--) { if (progress >= progressThresholds[num]) { return num; } } return -1; } [ClientRpc] private void UpdateProgressClientRpc(float progress) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Invalid comparison between Unknown and I4 //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Invalid comparison between Unknown and I4 //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager; if (networkManager == null || !networkManager.IsListening) { return; } if ((int)base.__rpc_exec_stage != 2 && (networkManager.IsServer || networkManager.IsHost)) { ClientRpcParams val = default(ClientRpcParams); FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendClientRpc(3902617409u, val, (RpcDelivery)0); ((FastBufferWriter)(ref val2)).WriteValueSafe<float>(ref progress, default(ForPrimitives)); ((NetworkBehaviour)this).__endSendClientRpc(ref val2, 3902617409u, val, (RpcDelivery)0); } if ((int)base.__rpc_exec_stage != 2 || (!networkManager.IsClient && !networkManager.IsHost) || (!((NetworkBehaviour)this).IsServer && !hasAcceptedSync)) { return; } string text = GenerateProgressBar(progress); if (progress < 1f) { if (!((NetworkBehaviour)this).IsServer) { Plugin.Instance.ShowCustomTip("CustomSounds Sync", "Sounds transfer progression:\n" + text, isWarning: false); } } else if (((NetworkBehaviour)this).IsServer) { Plugin.Instance.ShowCustomTip("CustomSounds Sync", "All sounds have been successfully sent!", isWarning: false); } else { Plugin.Instance.ShowCustomTip("CustomSounds Sync", "All sounds have been successfully received!", isWarning: false); } } private string GenerateProgressBar(float progress) { int num = 26; progress = Mathf.Clamp(progress, 0f, 1f); int num2 = (int)(progress * (float)num); return "[" + new string('#', num2) + new string('-', num - num2) + "] " + (int)(progress * 100f) + "%"; } protected override void __initializeVariables() { ((NetworkBehaviour)this).__initializeVariables(); } [RuntimeInitializeOnLoadMethod] internal static void InitializeRPCS_AudioNetworkHandler() { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Expected O, but got Unknown //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Expected O, but got Unknown //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Expected O, but got Unknown //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Expected O, but got Unknown //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Expected O, but got Unknown //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Expected O, but got Unknown //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Expected O, but got Unknown //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Expected O, but got Unknown NetworkManager.__rpc_func_table.Add(3186703908u, new RpcReceiveHandler(__rpc_handler_3186703908)); NetworkManager.__rpc_func_table.Add(152710787u, new RpcReceiveHandler(__rpc_handler_152710787)); NetworkManager.__rpc_func_table.Add(3960362720u, new RpcReceiveHandler(__rpc_handler_3960362720)); NetworkManager.__rpc_func_table.Add(234624598u, new RpcReceiveHandler(__rpc_handler_234624598)); NetworkManager.__rpc_func_table.Add(3991320206u, new RpcReceiveHandler(__rpc_handler_3991320206)); NetworkManager.__rpc_func_table.Add(3131260794u, new RpcReceiveHandler(__rpc_handler_3131260794)); NetworkManager.__rpc_func_table.Add(1027341762u, new RpcReceiveHandler(__rpc_handler_1027341762)); NetworkManager.__rpc_func_table.Add(2945580654u, new RpcReceiveHandler(__rpc_handler_2945580654)); NetworkManager.__rpc_func_table.Add(3964799390u, new RpcReceiveHandler(__rpc_handler_3964799390)); NetworkManager.__rpc_func_table.Add(3902617409u, new RpcReceiveHandler(__rpc_handler_3902617409)); } private static void __rpc_handler_3186703908(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) NetworkManager networkManager = target.NetworkManager; if (networkManager != null && networkManager.IsListening) { ulong clientId = default(ulong); ByteUnpacker.ReadValueBitPacked(reader, ref clientId); target.__rpc_exec_stage = (__RpcExecStage)2; ((AudioNetworkHandler)(object)target).RequestSyncClientRpc(clientId); target.__rpc_exec_stage = (__RpcExecStage)0; } } private static void __rpc_handler_152710787(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams) { //IL_0023: 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) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) NetworkManager networkManager = target.NetworkManager; if (networkManager != null && networkManager.IsListening) { ServerRpcParams server = rpcParams.Server; target.__rpc_exec_stage = (__RpcExecStage)1; ((AudioNetworkHandler)(object)target).NotifyClientsQueueCompletedServerRpc(server); target.__rpc_exec_stage = (__RpcExecStage)0; } } private static void __rpc_handler_3960362720(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) NetworkManager networkManager = target.NetworkManager; if (networkManager != null && networkManager.IsListening) { target.__rpc_exec_stage = (__RpcExecStage)2; ((AudioNetworkHandler)(object)target).ForceUnsyncClientsClientRpc(); target.__rpc_exec_stage = (__RpcExecStage)0; } } private static void __rpc_handler_234624598(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) NetworkManager networkManager = target.NetworkManager; if (networkManager != null && networkManager.IsListening) { target.__rpc_exec_stage = (__RpcExecStage)2; ((AudioNetworkHandler)(object)target).ProcessLastAudioFileClientRpc(); target.__rpc_exec_stage = (__RpcExecStage)0; } } private static void __rpc_handler_3991320206(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams) { //IL_0023: 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) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Invalid comparison between Unknown and I4 //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) NetworkManager networkManager = target.NetworkManager; if (networkManager == null || !networkManager.IsListening) { return; } if (rpcParams.Server.Receive.SenderClientId != target.OwnerClientId) { if ((int)networkManager.LogLevel <= 1) { Debug.LogError((object)"Only the owner can invoke a ServerRpc that requires ownership!"); } return; } int num = default(int); ByteUnpacker.ReadValueBitPacked(reader, ref num); bool flag = default(bool); ((FastBufferReader)(ref reader)).ReadValueSafe<bool>(ref flag, default(ForPrimitives)); string fileName = null; if (flag) { ((FastBufferReader)(ref reader)).ReadValueSafe(ref fileName, false); } target.__rpc_exec_stage = (__RpcExecStage)1; ((AudioNetworkHandler)(object)target).SendAudioMetaDataToClientsServerRpc(num, fileName); target.__rpc_exec_stage = (__RpcExecStage)0; } private static void __rpc_handler_3131260794(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams) { //IL_0023: 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) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Invalid comparison between Unknown and I4 //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) NetworkManager networkManager = target.NetworkManager; if (networkManager == null || !networkManager.IsListening) { return; } if (rpcParams.Server.Receive.SenderClientId != target.OwnerClientId) { if ((int)networkManager.LogLevel <= 1) { Debug.LogError((object)"Only the owner can invoke a ServerRpc that requires ownership!"); } return; } bool flag = default(bool); ((FastBufferReader)(ref reader)).ReadValueSafe<bool>(ref flag, default(ForPrimitives)); byte[] audioSegment = null; if (flag) { ((FastBufferReader)(ref reader)).ReadValueSafe<byte>(ref audioSegment, default(ForPrimitives)); } bool flag2 = default(bool); ((FastBufferReader)(ref reader)).ReadValueSafe<bool>(ref flag2, default(ForPrimitives)); string audioName = null; if (flag2) { ((FastBufferReader)(ref reader)).ReadValueSafe(ref audioName, false); } target.__rpc_exec_stage = (__RpcExecStage)1; ((AudioNetworkHandler)(object)target).SendBytesToServerRpc(audioSegment, audioName); target.__rpc_exec_stage = (__RpcExecStage)0; } private static void __rpc_handler_1027341762(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_006e: 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) NetworkManager networkManager = target.NetworkManager; if (networkManager != null && networkManager.IsListening) { int num = default(int); ByteUnpacker.ReadValueBitPacked(reader, ref num); bool flag = default(bool); ((FastBufferReader)(ref reader)).ReadValueSafe<bool>(ref flag, default(ForPrimitives)); string fileName = null; if (flag) { ((FastBufferReader)(ref reader)).ReadValueSafe(ref fileName, false); } target.__rpc_exec_stage = (__RpcExecStage)2; ((AudioNetworkHandler)(object)target).ReceiveAudioMetaDataClientRpc(num, fileName); target.__rpc_exec_stage = (__RpcExecStage)0; } } private static void __rpc_handler_2945580654(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams) { //IL_002f: 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_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0058: 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) //IL_00a6: 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) NetworkManager networkManager = target.NetworkManager; if (networkManager != null && networkManager.IsListening) { bool flag = default(bool); ((FastBufferReader)(ref reader)).ReadValueSafe<bool>(ref flag, default(ForPrimitives)); byte[] audioSegment = null; if (flag) { ((FastBufferReader)(ref reader)).ReadValueSafe<byte>(ref audioSegment, default(ForPrimitives)); } bool flag2 = default(bool); ((FastBufferReader)(ref reader)).ReadValueSafe<bool>(ref flag2, default(ForPrimitives)); string audioName = null; if (flag2) { ((FastBufferReader)(ref reader)).ReadValueSafe(ref audioName, false); } target.__rpc_exec_stage = (__RpcExecStage)2; ((AudioNetworkHandler)(object)target).ReceiveBytesClientRpc(audioSegment, audioName); target.__rpc_exec_stage = (__RpcExecStage)0; } } private static void __rpc_handler_3964799390(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) NetworkManager networkManager = target.NetworkManager; if (networkManager != null && networkManager.IsListening) { target.__rpc_exec_stage = (__RpcExecStage)2; ((AudioNetworkHandler)(object)target).DisplayStartingSyncMessageClientRpc(); target.__rpc_exec_stage = (__RpcExecStage)0; } } private static void __rpc_handler_3902617409(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams) { //IL_002f: 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_0044: 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) NetworkManager networkManager = target.NetworkManager; if (networkManager != null && networkManager.IsListening) { float progress = default(float); ((FastBufferReader)(ref reader)).ReadValueSafe<float>(ref progress, default(ForPrimitives)); target.__rpc_exec_stage = (__RpcExecStage)2; ((AudioNetworkHandler)(object)target).UpdateProgressClientRpc(progress); target.__rpc_exec_stage = (__RpcExecStage)0; } } protected internal override string __getTypeName() { return "AudioNetworkHandler"; } } }
Plugins/Clementinise-CustomSounds/CustomSounds.dll
Decompiled 9 months agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Logging; using CustomSounds.Networking; using CustomSounds.Patches; using HarmonyLib; using LCSoundTool; using TMPro; using Unity.Netcode; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("CustomSounds")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("CustomSounds")] [assembly: AssemblyCopyright("Copyright © 2023")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("9e086160-a7fd-4721-ba09-3e8534cb7011")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyVersion("1.0.0.0")] internal class <Module> { static <Module>() { } } namespace CustomSounds { [BepInPlugin("CustomSounds", "Custom Sounds", "2.3.2")] public class Plugin : BaseUnityPlugin { public struct SoundData { public string SoundName; public float? RandomPercentage; public string CustomName; public string FilePath; public string FileExtension; public string PackName; public string AudioSource; public string DirectoryPath; public string RelativeDirectoryPath; } public class FolderTree { public Dictionary<string, FolderTree> SubFolders { get; set; } public List<SoundData> Files { get; set; } public FolderTree() { SubFolders = new Dictionary<string, FolderTree>(); Files = new List<SoundData>(); } } public static class SoundDataProcessor { public static FolderTree BuildFolderTree(List<SoundData> soundDataList) { FolderTree folderTree = new FolderTree(); foreach (SoundData soundData in soundDataList) { string relativeDirectoryPath = soundData.RelativeDirectoryPath; string[] array = relativeDirectoryPath.Split(Path.DirectorySeparatorChar, '\u0001'); FolderTree folderTree2 = folderTree; string[] array2 = array; foreach (string key in array2) { if (!folderTree2.SubFolders.ContainsKey(key)) { folderTree2.SubFolders[key] = new FolderTree(); } folderTree2 = folderTree2.SubFolders[key]; } folderTree2.Files.Add(soundData); } return folderTree; } public static string DisplayTree(bool isListing, FolderTree tree, int indent = 0, bool isRoot = true, int soundCount = 0) { StringBuilder stringBuilder = new StringBuilder(); if (isRoot) { soundCount = CountSounds(tree); string text = (isListing ? "Listing all currently loaded custom sounds:" : "Customsounds reloaded."); stringBuilder.AppendLine(text + $" ({soundCount} sounds)"); } foreach (KeyValuePair<string, FolderTree> subFolder in tree.SubFolders) { if (isRoot) { stringBuilder.Append("\n"); } string text2 = subFolder.Key; if (text2.EndsWith("-AS")) { text2 = subFolder.Key.Substring(0, subFolder.Key.Length - 3) + " (AudioSource)"; } stringBuilder.AppendLine(new string(' ', indent * 2) + ((indent > 0) ? "∟ " : "") + text2 + " :"); stringBuilder.Append(DisplayTree(isListing, subFolder.Value, indent + 1, isRoot: false)); } foreach (SoundData file in tree.Files) { string text3 = ((!file.RandomPercentage.HasValue) ? "" : $" (Random: {file.RandomPercentage * 100f}%)"); string text4 = ((file.CustomName == "") ? "" : (" [" + file.CustomName + "]")); stringBuilder.AppendLine(new string(' ', indent * 2) + "- " + file.SoundName + text3 + text4 + " [" + file.FileExtension.ToUpper() + "]"); } return stringBuilder.ToString(); } private static int CountSounds(FolderTree tree) { int num = tree.Files.Count; foreach (KeyValuePair<string, FolderTree> subFolder in tree.SubFolders) { num += CountSounds(subFolder.Value); } return num; } } private const string PLUGIN_GUID = "CustomSounds"; private const string PLUGIN_NAME = "Custom Sounds"; private const string PLUGIN_VERSION = "2.3.2"; public static Plugin Instance; internal ManualLogSource logger; private Harmony harmony; public HashSet<string> currentSounds = new HashSet<string>(); public HashSet<string> oldSounds = new HashSet<string>(); public HashSet<string> modifiedSounds = new HashSet<string>(); public Dictionary<string, string> soundHashes = new Dictionary<string, string>(); public Dictionary<string, string> soundPacks = new Dictionary<string, string>(); public static bool hasAcceptedSync = false; public static List<SoundData> soundDataList = new List<SoundData>(); public static bool Initialized { get; private set; } private void Awake() { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Expected O, but got Unknown if (!((Object)(object)Instance == (Object)null)) { return; } Instance = this; logger = Logger.CreateLogSource("CustomSounds"); harmony = new Harmony("CustomSounds"); harmony.PatchAll(typeof(TerminalParsePlayerSentencePatch)); modifiedSounds = new HashSet<string>(); string customSoundsFolderPath = GetCustomSoundsFolderPath(); if (!Directory.Exists(customSoundsFolderPath)) { logger.LogInfo((object)"\"CustomSounds\" folder not found. Creating it now."); string path = Path.Combine(customSoundsFolderPath, "YourOwnSoundPack"); Directory.CreateDirectory(path); string contents = "If you're interested in creating your own sound pack, please refer to the 'For Sound Packs Creator' section on the CustomSounds Thunderstore page. If you simply wish to replace a few sounds on your own, you can drop the desired sounds into the 'YourOwnSoundPack' folder."; File.WriteAllText(Path.Combine(customSoundsFolderPath, "READ-ME-PLEASE.txt"), contents); } string path2 = Path.Combine(Paths.BepInExConfigPath); try { List<string> list = File.ReadAllLines(path2).ToList(); int num = list.FindIndex((string line) => line.StartsWith("HideManagerGameObject")); if (num != -1 && list[num].Contains("false")) { logger.LogInfo((object)"\"HideManagerGameObject\" value not correctly set. Fixing it now."); list[num] = "HideManagerGameObject = true"; File.WriteAllLines(path2, list); harmony.PatchAll(typeof(MenuPatcher)); } else if (num != -1) { logger.LogInfo((object)"\"HideManagerGameObject\" is correctly set to true."); } } catch (Exception ex) { logger.LogError((object)("Error modifying config file: " + ex.Message)); } Type[] types = Assembly.GetExecutingAssembly().GetTypes(); Type[] array = types; foreach (Type type in array) { MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic); MethodInfo[] array2 = methods; foreach (MethodInfo methodInfo in array2) { object[] customAttributes = methodInfo.GetCustomAttributes(typeof(RuntimeInitializeOnLoadMethodAttribute), inherit: false); if (customAttributes.Length != 0) { methodInfo.Invoke(null, null); } } } logger.LogInfo((object)"Plugin CustomSounds is loaded!"); } internal void Start() { Initialize(); } internal void OnDestroy() { Initialize(); } internal void Initialize() { if (!Initialized) { Initialized = true; ReloadSounds(); } } private void OnApplicationQuit() { } public GameObject LoadNetworkPrefabFromEmbeddedResource() { Assembly executingAssembly = Assembly.GetExecutingAssembly(); string name = "CustomSounds.Bundle.audionetworkhandler"; using Stream stream = executingAssembly.GetManifestResourceStream(name); if (stream == null) { Debug.LogError((object)"Asset bundle not found in embedded resources."); return null; } byte[] array = new byte[stream.Length]; stream.Read(array, 0, array.Length); AssetBundle val = AssetBundle.LoadFromMemory(array); if ((Object)(object)val == (Object)null) { Debug.LogError((object)"Failed to load AssetBundle from memory."); return null; } return val.LoadAsset<GameObject>("audionetworkhandler"); } public string GetCustomSoundsFolderPath() { return Path.Combine(Paths.PluginPath, "CustomSounds"); } public void RevertSounds() { if (currentSounds == null || currentSounds.Count == 0) { logger.LogInfo((object)"No sounds to revert."); return; } HashSet<string> hashSet = new HashSet<string>(); foreach (string currentSound in currentSounds) { string text = currentSound; if (currentSound.Contains("-")) { text = currentSound.Substring(0, currentSound.IndexOf("-")); } if (!hashSet.Contains(text)) { logger.LogInfo((object)(text + " restored.")); SoundTool.RestoreAudioClip(text); hashSet.Add(text); } } logger.LogInfo((object)"Original game sounds restored."); } public void ReloadSounds() { oldSounds = new HashSet<string>(currentSounds); currentSounds.Clear(); modifiedSounds.Clear(); soundDataList.Clear(); string directoryName = Path.GetDirectoryName(Paths.PluginPath); ProcessDirectory(directoryName); } private string GetRelativePathToCustomSounds(string filePath) { Debug.Log((object)("FilePath: " + filePath)); string[] array = filePath.Split(new char[1] { Path.DirectorySeparatorChar }); int num = Array.IndexOf(array, "CustomSounds"); if (num == -1 || num == array.Length - 1) { return ""; } string[] paths = array.Skip(num + 1).ToArray(); return Path.Combine(paths); } private void ProcessDirectory(string directoryPath) { string[] directories = Directory.GetDirectories(directoryPath, "*", SearchOption.AllDirectories); foreach (string text in directories) { string fileName = Path.GetFileName(text); ProcessSoundFiles(text, fileName); } } private void ProcessSoundFiles(string directoryPath, string packName) { string[] array = new string[3] { "*.wav", "*.ogg", "*.mp3" }; string[] array2 = array; foreach (string searchPattern in array2) { string[] files = Directory.GetFiles(directoryPath, searchPattern); foreach (string text in files) { if (text.Contains("CustomSounds")) { ProcessSingleFile(text, packName); } } } } private void ProcessSingleFile(string file, string packName) { string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(file); (string soundName, float? percentage, string customName) tuple = ParseSoundFileName(fileNameWithoutExtension); string item = tuple.soundName; float? item2 = tuple.percentage; string item3 = tuple.customName; string fileExtension = Path.GetExtension(file).TrimStart(new char[1] { '.' }).ToLower(); string relativePathToCustomSounds = GetRelativePathToCustomSounds(file); string fileName = Path.GetFileName(Path.GetDirectoryName(file)); string text = (fileName.EndsWith("-AS") ? fileName.Substring(0, fileName.Length - 3) : null); SoundData soundData = default(SoundData); soundData.SoundName = item; soundData.RandomPercentage = item2; soundData.CustomName = item3; soundData.FilePath = file; soundData.FileExtension = fileExtension; soundData.PackName = packName; soundData.AudioSource = text; soundData.DirectoryPath = Path.GetDirectoryName(file); soundData.RelativeDirectoryPath = Path.GetDirectoryName(relativePathToCustomSounds); SoundData item4 = soundData; soundDataList.Add(item4); string text2 = "Sound replaced: " + item; if (item4.RandomPercentage.HasValue) { text2 += $" (Percentage = {item4.RandomPercentage.Value * 100f}%)"; } if (!string.IsNullOrEmpty(item4.CustomName)) { text2 = text2 + " (Custom Name = " + item4.CustomName + ")"; } text2 = text2 + " (File Extension = " + item4.FileExtension + ")"; Debug.Log((object)text2); AudioClip audioClip = SoundTool.GetAudioClip(Path.GetDirectoryName(file), file); ((Object)audioClip).name = fileNameWithoutExtension; currentSounds.Add(item4.SoundName); if (item4.RandomPercentage.HasValue) { if (item4.AudioSource != null) { SoundTool.ReplaceAudioClip(item4.SoundName, audioClip, item4.RandomPercentage.Value, item4.AudioSource); } else { SoundTool.ReplaceAudioClip(item4.SoundName, audioClip, item4.RandomPercentage.Value); } } else if (text != null) { SoundTool.ReplaceAudioClip(item4.SoundName, audioClip, item4.AudioSource); } else { SoundTool.ReplaceAudioClip(item4.SoundName, audioClip); } } private (string soundName, float? percentage, string customName) ParseSoundFileName(string fullSoundName) { string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(fullSoundName); string[] array = fileNameWithoutExtension.Split(new char[1] { '-' }); string s = array[^1]; if (int.TryParse(s, out var result)) { string item = array[0]; string item2 = string.Join(" ", array.Skip(1).Take(array.Length - 2)); float value = (float)result / 100f; return (item, value, item2); } return (array[0], null, string.Join(" ", array.Skip(1))); } } } namespace CustomSounds.Patches { [HarmonyPatch] public class NetworkObjectManager { private static GameObject networkPrefab; private static GameObject networkHandlerHost; [HarmonyPatch(typeof(GameNetworkManager), "Start")] [HarmonyPrefix] public static void Init() { if (!((Object)(object)networkPrefab != (Object)null)) { networkPrefab = Plugin.Instance.LoadNetworkPrefabFromEmbeddedResource(); networkPrefab.AddComponent<AudioNetworkHandler>(); NetworkManager.Singleton.AddNetworkPrefab(networkPrefab); Plugin.Instance.logger.LogInfo((object)"Created AudioNetworkHandler prefab"); } } [HarmonyPostfix] [HarmonyPatch(typeof(StartOfRound), "Awake")] private static void SpawnNetworkHandler() { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) try { if (NetworkManager.Singleton.IsHost || NetworkManager.Singleton.IsServer) { Plugin.Instance.logger.LogInfo((object)"Spawning network handler"); networkHandlerHost = Object.Instantiate<GameObject>(networkPrefab, Vector3.zero, Quaternion.identity); if (networkHandlerHost.GetComponent<NetworkObject>().IsSpawned) { Debug.Log((object)"NetworkObject is spawned and active."); } else { Debug.Log((object)"Failed to spawn NetworkObject."); } networkHandlerHost.GetComponent<NetworkObject>().Spawn(true); if ((Object)(object)AudioNetworkHandler.Instance != (Object)null) { Debug.Log((object)"Successfully accessed AudioNetworkHandler instance."); } else { Debug.Log((object)"AudioNetworkHandler instance is null."); } } } catch { Plugin.Instance.logger.LogError((object)"Failed to spawned network handler"); } } [HarmonyPostfix] [HarmonyPatch(typeof(GameNetworkManager), "StartDisconnect")] private static void DestroyNetworkHandler() { try { if (NetworkManager.Singleton.IsHost || NetworkManager.Singleton.IsServer) { Plugin.Instance.logger.LogInfo((object)"Destroying network handler"); Object.Destroy((Object)(object)networkHandlerHost); networkHandlerHost = null; } } catch { Plugin.Instance.logger.LogError((object)"Failed to destroy network handler"); } } } [HarmonyPatch(typeof(MenuManager))] internal class MenuPatcher { [HarmonyPatch("Start")] [HarmonyPostfix] public static void StartPostFix(MenuManager __instance) { ((MonoBehaviour)__instance).StartCoroutine(DelayedMainMenuModification()); } private static IEnumerator DelayedMainMenuModification() { yield return (object)new WaitForSeconds(0f); ChangeHostButtonFromMainMenu(); } private static void ChangeHostButtonFromMainMenu() { Debug.Log((object)"Attempting to add a description to the Host button..."); GameObject val = GameObject.Find("MenuContainer"); Transform val2 = ((val != null) ? val.transform.Find("MainButtons") : null); object obj; if (val2 == null) { obj = null; } else { Transform obj2 = val2.Find("HostButton"); obj = ((obj2 != null) ? ((Component)obj2).gameObject : null); } GameObject val3 = (GameObject)obj; if (!((Object)(object)val == (Object)null) && !((Object)(object)val2 == (Object)null) && !((Object)(object)val3 == (Object)null)) { string text = ((TMP_Text)val3.GetComponentInChildren<TextMeshProUGUI>()).text; ((TMP_Text)val3.GetComponentInChildren<TextMeshProUGUI>()).text = "<line-height=0.28em>" + text + "\n<size=8><color=#B0B0B0> Please restart the game for <color=#E6B800>CustomSounds</color> to work properly!</color></size></line-height>"; } } } [HarmonyPatch(typeof(Terminal), "ParsePlayerSentence")] public static class TerminalParsePlayerSentencePatch { public static bool Prefix(Terminal __instance, ref TerminalNode __result) { string[] array = __instance.screenText.text.Split(new char[1] { '\n' }); if (array.Length == 0) { return true; } string[] array2 = array.Last().Trim().ToLower() .Split(new char[1] { ' ' }); if (array2.Length == 0 || (array2[0] != "customsounds" && array2[0] != "cs")) { return true; } Plugin.Instance.logger.LogInfo((object)("Received terminal command: " + string.Join(" ", array2))); if (array2.Length > 1 && (array2[0] == "customsounds" || array2[0] == "cs")) { switch (array2[1]) { case "reload": case "rl": Plugin.Instance.RevertSounds(); Plugin.Instance.ReloadSounds(); __result = CreateTerminalNode(Plugin.SoundDataProcessor.DisplayTree(isListing: false, Plugin.SoundDataProcessor.BuildFolderTree(Plugin.soundDataList))); return false; case "revert": case "rv": Plugin.Instance.RevertSounds(); __result = CreateTerminalNode("Game sounds reverted to original.\n\n"); return false; case "list": case "l": __result = CreateTerminalNode(Plugin.SoundDataProcessor.DisplayTree(isListing: true, Plugin.SoundDataProcessor.BuildFolderTree(Plugin.soundDataList))); return false; case "help": case "h": if (NetworkManager.Singleton.IsHost) { __result = CreateTerminalNode("CustomSounds commands \n(Can also be used with 'CS' as an alias).\n\n>CUSTOMSOUNDS LIST/L\nTo display all currently loaded sounds\n\n>CUSTOMSOUNDS RELOAD/RL\nTo reload and apply sounds from the 'CustomSounds' folder and its subfolders.\n\n>CUSTOMSOUNDS REVERT/RV\nTo unload all custom sounds and restore original game sounds\n\n"); } else { __result = CreateTerminalNode("CustomSounds commands \n(Can also be used with 'CS' as an alias).\n\n>CUSTOMSOUNDS LIST/L\nTo display all currently loaded sounds\n\n>CUSTOMSOUNDS RELOAD/RL\nTo reload and apply sounds from the 'CustomSounds' folder and its subfolders.\n\n>CUSTOMSOUNDS REVERT/RV\nTo unload all custom sounds and restore original game sounds\n\n"); } return false; case "sync": case "s": __result = CreateTerminalNode("/!\\ ERROR /!\\ \nThis command is not supported in this version of CustomSounds\n\n"); return false; case "unsync": case "u": __result = CreateTerminalNode("/!\\ ERROR /!\\ \nThis command is not supported in this version of CustomSounds\n\n"); return false; case "fu": case "force-unsync": __result = CreateTerminalNode("/!\\ ERROR /!\\ \nThis command is not supported in this version of CustomSounds\n\n"); return false; default: __result = CreateTerminalNode("Unknown customsounds command.\n\n"); return false; } } return true; } private static TerminalNode CreateTerminalNode(string message) { TerminalNode val = ScriptableObject.CreateInstance<TerminalNode>(); val.displayText = message; val.clearPreviousText = true; return val; } } } namespace CustomSounds.Networking { public class AudioNetworkHandler : NetworkBehaviour { public static AudioNetworkHandler Instance { get; private set; } protected override void __initializeVariables() { ((NetworkBehaviour)this).__initializeVariables(); } protected internal override string __getTypeName() { return "AudioNetworkHandler"; } } }
Plugins/femboytv-LethalPaintings-1.2.0/LethalPaintings.dll
Decompiled 9 months agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7", FrameworkDisplayName = ".NET Framework 4.7")] [assembly: AssemblyCompany("LethalPaintings")] [assembly: AssemblyConfiguration("release")] [assembly: AssemblyDescription("My first plugin")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("LethalPaintings")] [assembly: AssemblyTitle("LethalPaintings")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.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 LethalPaintings { internal class Patches { private static ManualLogSource Logger { get; set; } public static void Init(ManualLogSource logger) { Logger = logger; } [HarmonyPatch(typeof(GrabbableObject), "SetScrapValue")] [HarmonyPostfix] private static void SetScrapValuePatch(GrabbableObject __instance) { if (__instance.itemProperties.itemName == "Painting") { UpdateTexture(Plugin.PaintingFiles, __instance.itemProperties.materialVariants[0]); UpdateTexture(Plugin.PaintingFiles, __instance.itemProperties.materialVariants[1]); } } private static void UpdateTexture(IReadOnlyList<string> files, Material material) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown if (files.Count != 0) { int index = Plugin.Rand.Next(files.Count); Texture2D val = new Texture2D(2, 2); Logger.LogInfo((object)("Patching " + ((Object)material).name + " with " + files[index])); ImageConversion.LoadImage(val, File.ReadAllBytes(files[index])); material.mainTexture = (Texture)(object)val; } } } [BepInPlugin("LethalPaintings", "LethalPaintings", "1.0.0")] public class Plugin : BaseUnityPlugin { private static List<string> PosterFolders = new List<string>(); public static readonly List<string> PaintingFiles = new List<string>(); public static Random Rand = new Random(); private void Awake() { //IL_0096: Unknown result type (might be due to invalid IL or missing references) PosterFolders = Directory.GetDirectories(Paths.PluginPath, "LethalPaintings", SearchOption.AllDirectories).ToList(); foreach (string posterFolder in PosterFolders) { string[] files = Directory.GetFiles(Path.Combine(posterFolder, "paintings")); foreach (string text in files) { if (Path.GetExtension(text) != ".old") { PaintingFiles.Add(text); } } } Patches.Init(((BaseUnityPlugin)this).Logger); new Harmony("LethalPaintings").PatchAll(typeof(Patches)); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Plugin LethalPaintings is loaded!"); } } public static class PluginInfo { public const string PLUGIN_GUID = "LethalPaintings"; public const string PLUGIN_NAME = "LethalPaintings"; public const string PLUGIN_VERSION = "1.0.0"; } }
Plugins/femboytv-LethalPosters-1.2.0/LethalPosters.dll
Decompiled 9 months agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7", FrameworkDisplayName = ".NET Framework 4.7")] [assembly: AssemblyCompany("LethalPosters")] [assembly: AssemblyConfiguration("release")] [assembly: AssemblyDescription("LethalCopmany posters API")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("LethalPosters")] [assembly: AssemblyTitle("LethalPosters")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.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 LethalPosters { internal class Config { private static ConfigFile ConfigFile { get; set; } static Config() { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Expected O, but got Unknown ConfigFile = new ConfigFile(Paths.ConfigPath + "\\LethalPosters.cfg", true); foreach (string posterFolder in Plugin.PosterFolders) { int num = posterFolder.IndexOf("plugins\\", StringComparison.Ordinal) + "plugins\\".Length; int num2 = posterFolder.IndexOf("\\LethalPosters", num, StringComparison.Ordinal); string text = posterFolder.Substring(num, num2 - num); if (!ConfigFile.Bind<bool>(text, "Enabled", true, "Enable or disable " + text).Value) { Directory.Move(posterFolder, posterFolder + ".Disabled"); } } } } internal class Patches { private static ManualLogSource Logger { get; set; } public static void Init(ManualLogSource logger) { Logger = logger; } [HarmonyPatch(typeof(StartOfRound), "Start")] [HarmonyPostfix] private static void StartPatch() { Logger.LogInfo((object)"Patching Start in StartOfRound"); UpdateMaterials(0); } [HarmonyPatch(typeof(RoundManager), "GenerateNewLevelClientRpc")] [HarmonyPostfix] private static void GenerateNewLevelClientRpcPatch(int randomSeed) { Logger.LogInfo((object)"Patching GenerateNewLevelClientRpc in RoundManager"); UpdateMaterials(randomSeed); } private static void UpdateMaterials(int seed) { Logger.LogInfo((object)"Patching the textures"); Plugin.Rand = new Random(seed); Material[] materials = ((Renderer)GameObject.Find("HangarShip/Plane.001").GetComponent<MeshRenderer>()).materials; UpdateTexture(Plugin.PosterFiles, materials[0]); UpdateTexture(Plugin.TipFiles, materials[1]); } private static void UpdateTexture(IReadOnlyList<string> files, Material material) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown if (files.Count != 0) { int index = Plugin.Rand.Next(files.Count); Texture2D val = new Texture2D(2, 2); Logger.LogInfo((object)("Patching " + ((Object)material).name + " with " + files[index])); ImageConversion.LoadImage(val, File.ReadAllBytes(files[index])); material.mainTexture = (Texture)(object)val; } } } [BepInPlugin("LethalPosters", "LethalPosters", "1.0.0")] public class Plugin : BaseUnityPlugin { public static List<string> PosterFolders = new List<string>(); public static readonly List<string> PosterFiles = new List<string>(); public static readonly List<string> TipFiles = new List<string>(); public static Random Rand = new Random(); private void Awake() { //IL_00e4: Unknown result type (might be due to invalid IL or missing references) PosterFolders = Directory.GetDirectories(Paths.PluginPath, "LethalPosters", SearchOption.AllDirectories).ToList(); foreach (string posterFolder in PosterFolders) { string[] files = Directory.GetFiles(Path.Combine(posterFolder, "posters")); foreach (string text in files) { if (Path.GetExtension(text) != ".old") { PosterFiles.Add(text); } } files = Directory.GetFiles(Path.Combine(posterFolder, "tips")); foreach (string text2 in files) { if (Path.GetExtension(text2) != ".old") { TipFiles.Add(text2); } } } Patches.Init(((BaseUnityPlugin)this).Logger); new Harmony("LethalPosters").PatchAll(typeof(Patches)); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Plugin LethalPosters (1.0.0) is loaded!"); } } public static class PluginInfo { public const string PLUGIN_GUID = "LethalPosters"; public const string PLUGIN_NAME = "LethalPosters"; public const string PLUGIN_VERSION = "1.0.0"; } }
Plugins/Mercurys Company/Mercury'sCompany.dll
Decompiled 9 months agousing System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Logging; using GameNetcodeStuff; using HarmonyLib; using Mercury_sCompany.Patches; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("Mercury'sCompany")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("Mercury'sCompany")] [assembly: AssemblyCopyright("Copyright © 2024")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("b2d2e215-32f2-45ff-8501-fc91e929b6c2")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyVersion("1.0.0.0")] namespace Mercury_sCompany { [BepInPlugin("Poseidon.MercurysCompany", "Mercurys Company", "1.1.11")] public class MercurysCompanyBase : BaseUnityPlugin { private const string modGUID = "Poseidon.MercurysCompany"; private const string modName = "Mercurys Company"; private const string modVersion = "1.1.11"; private readonly Harmony harmony = new Harmony("Poseidon.MercurysCompany"); private static MercurysCompanyBase instance; internal ManualLogSource mls; internal static List<AudioClip> SoundFX; internal static AssetBundle Bundle; private void Awake() { if ((Object)(object)instance == (Object)null) { instance = this; } mls = Logger.CreateLogSource("Poseidon.MercurysCompany"); mls.LogInfo((object)"!!!MERCURYS COMPANY IS NOW ACTIVE!!!HAVE A NICE DAY :^)"); harmony.PatchAll(typeof(MercurysCompanyBase)); harmony.PatchAll(typeof(PlayerControllerBPatch)); harmony.PatchAll(typeof(StartOfRoundPatch)); mls = ((BaseUnityPlugin)this).Logger; SoundFX = new List<AudioClip>(); string location = ((BaseUnityPlugin)instance).Info.Location; location = location.TrimEnd("Mercury'sCompany.dll".ToCharArray()); Bundle = AssetBundle.LoadFromFile(location + "chiefkeefspeech"); if ((Object)(object)Bundle != (Object)null) { mls.LogInfo((object)"Successfully Loaded Asset Bundle"); SoundFX = Bundle.LoadAllAssets<AudioClip>().ToList(); } else { mls.LogError((object)"Failed To Load Asset Bundle"); } } } } namespace Mercury_sCompany.Patches { [HarmonyPatch(typeof(PlayerControllerB))] internal class PlayerControllerBPatch { [HarmonyPatch("Update")] [HarmonyPostfix] private static void PatchMovementUpdate(ref float ___movementSpeed) { ___movementSpeed = 8f; } private static void PatchSprintUpdate(ref float ___sprintMultiplier) { ___sprintMultiplier = 1.25f; } private static void PatchSprintMeterPatch(ref float ___sprintMeter) { ___sprintMeter = -25f; } } [HarmonyPatch(typeof(StartOfRound))] internal class StartOfRoundPatch { [HarmonyPatch("Start")] [HarmonyPostfix] private static void OverrideAudio(StartOfRound __instance) { __instance.shipIntroSpeechSFX = MercurysCompanyBase.SoundFX[0]; } } }
Plugins/no00ob-LCSoundTool/BepInEx/plugins/LC_SoundTool.dll
Decompiled 9 months ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.CodeDom.Compiler; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Globalization; 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 BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using LCSoundTool.Networking; using LCSoundTool.Patches; using LCSoundTool.Resources; using LCSoundTool.Utilities; using LCSoundToolMod.Properties; using Microsoft.CodeAnalysis; using Unity.Netcode; using UnityEngine; using UnityEngine.Networking; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("LC_SoundTool")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyDescription("Various audio related functions. Mainly logs all sounds that are playing and what type of playback they're into the BepInEx console.")] [assembly: AssemblyFileVersion("1.5.0.0")] [assembly: AssemblyInformationalVersion("1.5.0")] [assembly: AssemblyProduct("LC_SoundTool")] [assembly: AssemblyTitle("LC_SoundTool")] [assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/no00ob/LCSoundTool")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.5.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] internal class <Module> { static <Module>() { } } 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 LCSoundToolMod { public static class PluginInfo { public const string PLUGIN_GUID = "LC_SoundTool"; public const string PLUGIN_NAME = "LC_SoundTool"; public const string PLUGIN_VERSION = "1.5.0"; } } namespace LCSoundToolMod.Properties { [GeneratedCode("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] [DebuggerNonUserCode] [CompilerGenerated] internal class Resources { private static ResourceManager resourceMan; private static CultureInfo resourceCulture; [EditorBrowsable(EditorBrowsableState.Advanced)] internal static ResourceManager ResourceManager { get { if (resourceMan == null) { ResourceManager resourceManager = new ResourceManager("LCSoundToolMod.Properties.Resources", typeof(Resources).Assembly); resourceMan = resourceManager; } return resourceMan; } } [EditorBrowsable(EditorBrowsableState.Advanced)] internal static CultureInfo Culture { get { return resourceCulture; } set { resourceCulture = value; } } internal static byte[] soundtool { get { object @object = ResourceManager.GetObject("soundtool", resourceCulture); return (byte[])@object; } } internal Resources() { } } } namespace LCSoundTool { public class AudioSourceExtension : MonoBehaviour { public AudioSource audioSource; public bool playOnAwake = false; public bool loop = false; private bool updateHasBeenLogged = false; private bool hasPlayed = false; private void OnEnable() { if (!((Object)(object)audioSource == (Object)null) && !audioSource.isPlaying) { if (playOnAwake) { audioSource.Play(); } if (SoundTool.infoDebugging) { SoundTool.Instance.logger.LogDebug((object)$"(AudioSourceExtension) Started playback of {audioSource} with clip {audioSource.clip} in OnEnable function!"); } updateHasBeenLogged = false; hasPlayed = false; } } private void OnDisable() { if (!((Object)(object)audioSource == (Object)null) && audioSource.isPlaying) { if (playOnAwake) { audioSource.Stop(); } if (SoundTool.infoDebugging) { SoundTool.Instance.logger.LogDebug((object)$"(AudioSourceExtension) Stopped playback of {audioSource} with clip {audioSource.clip} in OnDisable function!"); } updateHasBeenLogged = false; hasPlayed = false; } } private void Update() { if ((Object)(object)audioSource == (Object)null) { return; } if ((Object)(object)audioSource.clip == (Object)null) { hasPlayed = false; } if (audioSource.isPlaying) { updateHasBeenLogged = false; } else if (!((Behaviour)audioSource).isActiveAndEnabled) { hasPlayed = false; } else { if (!playOnAwake) { return; } if ((Object)(object)audioSource.clip != (Object)null && !hasPlayed) { audioSource.Play(); if (SoundTool.infoDebugging) { SoundTool.Instance.logger.LogDebug((object)$"(AudioSourceExtension) Started playback of {audioSource} with clip {audioSource.clip} in Update function!"); } updateHasBeenLogged = false; hasPlayed = true; } else if (!updateHasBeenLogged) { updateHasBeenLogged = true; if (SoundTool.infoDebugging) { SoundTool.Instance.logger.LogDebug((object)$"(AudioSourceExtension) Can not start playback of {audioSource} with missing clip in Update function!"); } } } } } public class RandomAudioClip { public AudioClip clip; [Range(0f, 1f)] public float chance = 1f; public RandomAudioClip(AudioClip clip, float chance) { this.clip = clip; this.chance = chance; } } public class ReplacementAudioClip { public List<RandomAudioClip> clips; public string source = string.Empty; public bool canPlay = true; private bool initialized = false; public ReplacementAudioClip(AudioClip clip, float chance, string source) { if (!initialized) { Initialize(); } RandomAudioClip randomAudioClip = new RandomAudioClip(clip, chance); if (!clips.ContainsThisRandomAudioClip(randomAudioClip)) { clips.Add(randomAudioClip); this.source = source; } else if (SoundTool.infoDebugging) { SoundTool.Instance.logger.LogDebug((object)$"RandomAudioClip {randomAudioClip.clip.GetName()} ({Mathf.RoundToInt(chance * 100f)}%) already exists withing this AudioClipContainer!"); SoundTool.Instance.logger.LogDebug((object)"- This AudioClipContainer contains the following clip(s):"); for (int i = 0; i < clips.Count; i++) { SoundTool.Instance.logger.LogDebug((object)$"-- Clip {i + 1} - {clips[i].clip.GetName()} with a chance of {Mathf.RoundToInt(clips[i].chance * 100f)}"); } } } public ReplacementAudioClip(string source) { Initialize(); this.source = source; } public ReplacementAudioClip() { Initialize(); source = string.Empty; } public void AddClip(AudioClip clip, float chance) { if (!initialized) { Initialize(); } RandomAudioClip randomAudioClip = new RandomAudioClip(clip, chance); if (!clips.ContainsThisRandomAudioClip(randomAudioClip)) { clips.Add(randomAudioClip); } else if (SoundTool.infoDebugging) { SoundTool.Instance.logger.LogDebug((object)$"RandomAudioClip {randomAudioClip.clip.GetName()} ({Mathf.RoundToInt(chance * 100f)}%) already exists withing this AudioClipContainer!"); SoundTool.Instance.logger.LogDebug((object)"- This AudioClipContainer contains the following clip(s):"); for (int i = 0; i < clips.Count; i++) { SoundTool.Instance.logger.LogDebug((object)$"-- Clip {i + 1} - {clips[i].clip.GetName()} with a chance of {Mathf.RoundToInt(clips[i].chance * 100f)}"); } } } public bool Full() { if (!initialized) { Initialize(); } float num = 0f; for (int i = 0; i < clips.Count; i++) { num += clips[i].chance; } return num >= 1f; } public bool ContainsClip(AudioClip clip, float chance) { if (!initialized) { Initialize(); } RandomAudioClip thisClip = new RandomAudioClip(clip, chance); return clips.ContainsThisRandomAudioClip(thisClip); } private void Initialize() { clips = new List<RandomAudioClip>(); initialized = true; } } [BepInPlugin("LCSoundTool", "LC Sound Tool", "1.5.0")] public class SoundTool : BaseUnityPlugin { public enum AudioType { wav, ogg, mp3 } private const string PLUGIN_GUID = "LCSoundTool"; private const string PLUGIN_NAME = "LC Sound Tool"; private ConfigEntry<bool> configUseNetworking; private ConfigEntry<bool> configSyncRandomSeed; private ConfigEntry<float> configPlayOnAwakePatchRepeatDelay; private ConfigEntry<bool> configPrintInfoByDefault; private readonly Harmony harmony = new Harmony("LCSoundTool"); public static SoundTool Instance; internal ManualLogSource logger; public KeyboardShortcut toggleAudioSourceDebugLog; public KeyboardShortcut toggleIndepthDebugLog; public KeyboardShortcut toggleInformationalDebugLog; public KeyboardShortcut printAllSoundsDebugLog; public bool wasKeyDown; public bool wasKeyDown2; public bool wasKeyDown3; public bool wasKeyDown4; public static bool debugAudioSources; public static bool indepthDebugging; public static bool infoDebugging; public static bool networkingInitialized { get; private set; } public static bool networkingAvailable { get; private set; } public static Dictionary<string, ReplacementAudioClip> replacedClips { get; private set; } public static Dictionary<string, AudioClip> networkedClips => NetworkHandler.networkedAudioClips; public static Dictionary<string, AudioType> clipTypes { get; private set; } public static event Action ClientNetworkedAudioChanged { add { NetworkHandler.ClientNetworkedAudioChanged += value; } remove { NetworkHandler.ClientNetworkedAudioChanged -= value; } } public static event Action HostNetworkedAudioChanged { add { NetworkHandler.HostNetworkedAudioChanged += value; } remove { NetworkHandler.HostNetworkedAudioChanged -= value; } } public static bool IsDebuggingOn() { if (debugAudioSources || indepthDebugging || infoDebugging) { return true; } return false; } private void Awake() { //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0154: 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_0172: Unknown result type (might be due to invalid IL or missing references) //IL_018b: Unknown result type (might be due to invalid IL or missing references) //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_01a9: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Unknown result type (might be due to invalid IL or missing references) networkingAvailable = true; if ((Object)(object)Instance == (Object)null) { Instance = this; } configUseNetworking = ((BaseUnityPlugin)this).Config.Bind<bool>("Experimental", "EnableNetworking", false, "Whether or not to use the networking built into this plugin. If set to true everyone in the lobby needs LCSoundTool installed and networking enabled to join."); configSyncRandomSeed = ((BaseUnityPlugin)this).Config.Bind<bool>("Experimental", "SyncUnityRandomSeed", false, "Whether or not to sync the default Unity randomization seed with all clients. For this feature, networking has to be set to true. Will send the UnityEngine.Random.seed from the host to all clients automatically upon loading a networked scene."); configPlayOnAwakePatchRepeatDelay = ((BaseUnityPlugin)this).Config.Bind<float>("Experimental", "NewPlayOnAwakePatchRepeatDelay", 90f, "How long to wait between checks for new playOnAwake AudioSources. Runs the same patching that is done when each scene is loaded with this delay between each run. DO NOT set too low or high. Anything below 10 or above 600 can cause issues. This time is in seconds. Set to 0 to disable rerunning the patch, but be warned that this might break runtime initialized playOnAwake AudioSources."); configPrintInfoByDefault = ((BaseUnityPlugin)this).Config.Bind<bool>("Logging", "PrintInfoByDefault", false, "Whether or not to print additional information logs created by this mod by default. If set to false, informational logs may be toggled on any time with LeftAlt + F5."); Type[] types = Assembly.GetExecutingAssembly().GetTypes(); Type[] array = types; foreach (Type type in array) { MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic); MethodInfo[] array2 = methods; foreach (MethodInfo methodInfo in array2) { object[] customAttributes = methodInfo.GetCustomAttributes(typeof(RuntimeInitializeOnLoadMethodAttribute), inherit: false); if (customAttributes.Length != 0) { methodInfo.Invoke(null, null); } } } logger = Logger.CreateLogSource("LCSoundTool"); logger.LogInfo((object)"Plugin LCSoundTool is loaded!"); toggleAudioSourceDebugLog = new KeyboardShortcut((KeyCode)286, (KeyCode[])(object)new KeyCode[0]); toggleIndepthDebugLog = new KeyboardShortcut((KeyCode)286, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }); toggleInformationalDebugLog = new KeyboardShortcut((KeyCode)286, (KeyCode[])(object)new KeyCode[1] { (KeyCode)306 }); printAllSoundsDebugLog = new KeyboardShortcut((KeyCode)286, (KeyCode[])(object)new KeyCode[1] { (KeyCode)304 }); debugAudioSources = false; indepthDebugging = false; if (configPrintInfoByDefault.Value) { infoDebugging = true; } else { infoDebugging = false; } replacedClips = new Dictionary<string, ReplacementAudioClip>(); clipTypes = new Dictionary<string, AudioType>(); } private void Start() { if (!configUseNetworking.Value) { networkingAvailable = false; Instance.logger.LogWarning((object)"Networking disabled. Mod in fully client side mode, but no networked actions can take place! You can safely ignore this if you want the mod to run fully client side."); } else { networkingAvailable = true; } if (configUseNetworking.Value) { logger.LogDebug((object)"Loading SoundTool AssetBundle..."); Assets.bundle = AssetBundle.LoadFromMemory(LCSoundToolMod.Properties.Resources.soundtool); if ((Object)(object)Assets.bundle == (Object)null) { logger.LogError((object)"Failed to load SoundTool AssetBundle!"); } else { logger.LogDebug((object)"Finished loading SoundTool AssetBundle!"); } } harmony.PatchAll(typeof(AudioSourcePatch)); if (configUseNetworking.Value) { harmony.PatchAll(typeof(GameNetworkManagerPatch)); harmony.PatchAll(typeof(StartOfRoundPatch)); } SceneManager.sceneLoaded += OnSceneLoaded; } private void Update() { if (configUseNetworking.Value) { if (!networkingInitialized) { if ((Object)(object)NetworkHandler.Instance != (Object)null) { networkingInitialized = true; } } else if ((Object)(object)NetworkHandler.Instance == (Object)null) { networkingInitialized = false; } } else { networkingInitialized = false; } if (((KeyboardShortcut)(ref printAllSoundsDebugLog)).IsDown() && !wasKeyDown4) { wasKeyDown4 = true; } if (((KeyboardShortcut)(ref printAllSoundsDebugLog)).IsUp() && wasKeyDown4) { wasKeyDown4 = false; Instance.logger.LogDebug((object)"Printing all currently replaced sounds..."); Instance.logger.LogDebug((object)" "); string[] array = replacedClips.Keys.ToArray(); for (int i = 0; i < replacedClips.Count; i++) { ReplacementAudioClip replacementAudioClip = replacedClips[array[i]]; Instance.logger.LogDebug((object)$"Clip named {array[i]} with {replacementAudioClip.clips.Count} replacement clip(s)"); Instance.logger.LogDebug((object)$"- Clip can play? {replacementAudioClip.canPlay}"); Instance.logger.LogDebug((object)("- Clip audio source(s)? " + replacementAudioClip.source)); Instance.logger.LogDebug((object)$"- All {replacementAudioClip.clips.Count} clip(s):"); for (int j = 0; j < replacementAudioClip.clips.Count; j++) { Instance.logger.LogDebug((object)$"-- Clip {j + 1} - {replacementAudioClip.clips[j].clip.GetName()} with chance of {Mathf.RoundToInt(replacementAudioClip.clips[j].chance * 100f)}%"); } } Instance.logger.LogDebug((object)" "); Instance.logger.LogDebug((object)"Finished printing all currently replaced sounds!"); } if (((KeyboardShortcut)(ref toggleInformationalDebugLog)).IsDown() && !wasKeyDown3) { wasKeyDown3 = true; wasKeyDown2 = false; wasKeyDown = false; } if (((KeyboardShortcut)(ref toggleInformationalDebugLog)).IsUp() && wasKeyDown3) { wasKeyDown3 = false; wasKeyDown2 = false; wasKeyDown = false; infoDebugging = !infoDebugging; Instance.logger.LogDebug((object)$"Toggling informational debug logs {infoDebugging}!"); return; } if (((KeyboardShortcut)(ref toggleIndepthDebugLog)).IsDown() && !wasKeyDown2) { wasKeyDown2 = true; wasKeyDown = false; } if (((KeyboardShortcut)(ref toggleIndepthDebugLog)).IsUp() && wasKeyDown2) { wasKeyDown2 = false; wasKeyDown = false; debugAudioSources = !debugAudioSources; indepthDebugging = debugAudioSources; infoDebugging = debugAudioSources; Instance.logger.LogDebug((object)$"Toggling in-depth AudioSource debug logs {debugAudioSources}!"); return; } if (!wasKeyDown2 && !((KeyboardShortcut)(ref toggleIndepthDebugLog)).IsDown() && ((KeyboardShortcut)(ref toggleAudioSourceDebugLog)).IsDown() && !wasKeyDown) { wasKeyDown = true; wasKeyDown2 = false; } if (((KeyboardShortcut)(ref toggleAudioSourceDebugLog)).IsUp() && wasKeyDown) { wasKeyDown = false; wasKeyDown2 = false; debugAudioSources = !debugAudioSources; if (indepthDebugging && !debugAudioSources) { indepthDebugging = false; } Instance.logger.LogDebug((object)$"Toggling AudioSource debug logs {debugAudioSources}!"); } } private void OnDestroy() { SceneManager.sceneLoaded -= OnSceneLoaded; } private void OnSceneLoaded(Scene scene, LoadSceneMode mode) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)Instance == (Object)null)) { PatchPlayOnAwakeAudio(scene); OnSceneLoadedNetworking(); if (((Scene)(ref scene)).name.ToLower().Contains("level")) { ((MonoBehaviour)this).StopAllCoroutines(); ((MonoBehaviour)this).StartCoroutine(PatchPlayOnAwakeDelayed(scene, 1f)); } } } private IEnumerator PatchPlayOnAwakeDelayed(Scene scene, float wait) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) if (infoDebugging) { logger.LogDebug((object)$"Started playOnAwake patch coroutine with delay of {wait} seconds"); } yield return (object)new WaitForSecondsRealtime(wait); if (infoDebugging) { logger.LogDebug((object)"Running playOnAwake patch coroutine!"); } PatchPlayOnAwakeAudio(scene); float repeatWait = configPlayOnAwakePatchRepeatDelay.Value; if (repeatWait != 0f) { if (repeatWait < 10f) { repeatWait = 10f; } if (repeatWait > 600f) { repeatWait = 600f; } ((MonoBehaviour)this).StartCoroutine(PatchPlayOnAwakeDelayed(scene, repeatWait)); } } private void PatchPlayOnAwakeAudio(Scene scene) { if (infoDebugging) { Instance.logger.LogDebug((object)("Grabbing all playOnAwake AudioSources for loaded scene " + ((Scene)(ref scene)).name)); } AudioSource[] allPlayOnAwakeAudioSources = GetAllPlayOnAwakeAudioSources(); if (infoDebugging) { Instance.logger.LogDebug((object)$"Found a total of {allPlayOnAwakeAudioSources.Length} playOnAwake AudioSource(s)!"); Instance.logger.LogDebug((object)$"Starting setup on {allPlayOnAwakeAudioSources.Length} playOnAwake AudioSource(s)..."); } AudioSource[] array = allPlayOnAwakeAudioSources; AudioSourceExtension audioSourceExtension = default(AudioSourceExtension); foreach (AudioSource val in array) { val.Stop(); if (((Component)((Component)val).transform).TryGetComponent<AudioSourceExtension>(ref audioSourceExtension)) { audioSourceExtension.audioSource = val; audioSourceExtension.playOnAwake = true; audioSourceExtension.loop = val.loop; val.playOnAwake = false; if (infoDebugging) { Instance.logger.LogDebug((object)$"-Set- {Array.IndexOf(allPlayOnAwakeAudioSources, val) + 1} {val} done!"); } continue; } AudioSourceExtension audioSourceExtension2 = ((Component)val).gameObject.AddComponent<AudioSourceExtension>(); audioSourceExtension2.audioSource = val; audioSourceExtension2.playOnAwake = true; audioSourceExtension2.loop = val.loop; val.playOnAwake = false; if (infoDebugging) { Instance.logger.LogDebug((object)$"-Add- {Array.IndexOf(allPlayOnAwakeAudioSources, val) + 1} {val} done!"); } } if (infoDebugging) { Instance.logger.LogDebug((object)$"Done setting up {allPlayOnAwakeAudioSources.Length} playOnAwake AudioSources!"); } } private void OnSceneLoadedNetworking() { if (networkingAvailable && networkingInitialized && configSyncRandomSeed.Value) { int num = (int)DateTime.Now.Ticks; Random.InitState(num); SendUnityRandomSeed(num); } } public AudioSource[] GetAllPlayOnAwakeAudioSources() { AudioSource[] array = Object.FindObjectsOfType<AudioSource>(true); List<AudioSource> list = new List<AudioSource>(); for (int i = 0; i < array.Length; i++) { if (array[i].playOnAwake) { list.Add(array[i]); } } return list.ToArray(); } public static void ReplaceAudioClip(string originalName, AudioClip newClip) { if (string.IsNullOrEmpty(originalName)) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to replace an audio clip without original clip specified! This is not allowed."); return; } if ((Object)(object)newClip == (Object)null) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to replace an audio clip without new clip specified! This is not allowed."); return; } string text = originalName; string name = newClip.GetName(); string text2 = string.Empty; float num = 100f; if (name.Contains("-")) { string[] array = name.Split('-'); if (array.Length > 1) { if (array.Length > 2) { string text3 = array[^2]; if (!string.IsNullOrEmpty(text3) && text3.StartsWith("_")) { text2 = text3.Substring(1); } } string text4 = array[^1]; if (int.TryParse(text4, out var result)) { num = (float)result * 0.01f; } else if (!string.IsNullOrEmpty(text4) && text4.StartsWith("_")) { text2 = text4.Substring(1); } name = string.Join("-", array, 0, array.Length - 1); } else if (infoDebugging) { Instance.logger.LogDebug((object)("Clip " + name + " does not contain a '-' character for source name or chance")); } } if (!string.IsNullOrEmpty(text2)) { text = originalName + "#" + text2; } if (replacedClips.ContainsKey(text) && num >= 100f) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to replace an audio clip that already has been replaced with new clip that has 100% chance of playback! This is not allowed."); return; } num = Mathf.Clamp01(num); if (replacedClips.ContainsKey(text)) { replacedClips[text].AddClip(newClip, num); } else { replacedClips.Add(text, new ReplacementAudioClip(newClip, num, text2)); } float num2 = 0f; for (int i = 0; i < replacedClips[text].clips.Count(); i++) { num2 += replacedClips[text].clips[i].chance; } int num3 = Mathf.RoundToInt(num2 * 100f); if ((num3 < 100 || num3 > 100) && replacedClips[text].clips.Count() > 1) { if (infoDebugging) { Instance.logger.LogDebug((object)$"The current total combined chance for replaced {replacedClips[text].clips.Count()} random audio clips for audio clip {text} does not equal 100%. Currently {num3}% (at least yet?)"); } } else if (num3 == 100 && replacedClips[text].clips.Count() > 1 && infoDebugging) { Instance.logger.LogDebug((object)$"The current total combined chance for replaced {replacedClips[text].clips.Count()} random audio clips for audio clip {text} is equal to 100%"); } } public static void ReplaceAudioClip(AudioClip originalClip, AudioClip newClip) { if ((Object)(object)originalClip == (Object)null) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to replace an audio clip without original clip specified! This is not allowed."); } else if ((Object)(object)newClip == (Object)null) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to replace an audio clip without new clip specified! This is not allowed."); } else { ReplaceAudioClip(originalClip.GetName(), newClip); } } public static void ReplaceAudioClip(string originalName, AudioClip newClip, float chance) { if (string.IsNullOrEmpty(originalName)) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to replace an audio clip without original clip specified! This is not allowed."); return; } if ((Object)(object)newClip == (Object)null) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to replace an audio clip without new clip specified! This is not allowed."); return; } string text = originalName; string name = newClip.GetName(); string text2 = string.Empty; if (name.Contains("-")) { string[] array = name.Split('-'); if (array.Length > 1) { if (array.Length > 2) { string text3 = array[^2]; if (!string.IsNullOrEmpty(text3) && text3.StartsWith("_")) { text2 = text3.Substring(1); } } string text4 = array[^1]; if (int.TryParse(text4, out var result)) { Instance.logger.LogDebug((object)$"Clip {name} contains random chance specified in it's name ({result}%) but you're using the manually function to assign it's chance. ({Mathf.RoundToInt(chance * 100f)}%) The file name will be ignored."); } else if (!string.IsNullOrEmpty(text4) && text4.StartsWith("_")) { text2 = text4.Substring(1); } name = string.Join("-", array, 0, array.Length - 1); } else if (infoDebugging) { Instance.logger.LogDebug((object)("Clip " + name + " does not contain a '-' character for source name or chance")); } } if (!string.IsNullOrEmpty(text2)) { text = originalName + "#" + text2; } if (replacedClips.ContainsKey(text) && chance >= 100f) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to replace an audio clip that already has been replaced with new clip that has 100% chance of playback! This is not allowed."); return; } chance = Mathf.Clamp01(chance); if (replacedClips.ContainsKey(text)) { replacedClips[text].AddClip(newClip, chance); } else { replacedClips.Add(text, new ReplacementAudioClip(newClip, chance, text2)); } float num = 0f; for (int i = 0; i < replacedClips[text].clips.Count(); i++) { num += replacedClips[text].clips[i].chance; } int num2 = Mathf.RoundToInt(num * 100f); if ((num2 < 100 || num2 > 100) && replacedClips[text].clips.Count() > 1) { Instance.logger.LogDebug((object)$"The current total combined chance for replaced {replacedClips[text].clips.Count()} random audio clips for audio clip {text} does not equal 100% (at least yet?)"); } else if (num2 == 100 && replacedClips[text].clips.Count() > 1) { Instance.logger.LogDebug((object)$"The current total combined chance for replaced {replacedClips[text].clips.Count()} random audio clips for audio clip {text} is equal to 100%"); } } public static void ReplaceAudioClip(AudioClip originalClip, AudioClip newClip, float chance) { if ((Object)(object)originalClip == (Object)null) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to replace an audio clip without original clip specified! This is not allowed."); } else if ((Object)(object)newClip == (Object)null) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to replace an audio clip without new clip specified! This is not allowed."); } else { ReplaceAudioClip(originalClip.GetName(), newClip, chance); } } public static void ReplaceAudioClip(string originalName, AudioClip newClip, string source) { if (string.IsNullOrEmpty(originalName)) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to replace an audio clip without original clip specified! This is not allowed."); return; } if ((Object)(object)newClip == (Object)null) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to replace an audio clip without new clip specified! This is not allowed."); return; } if (string.IsNullOrEmpty(source)) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to replace an audio clip without allowed audio source specified! This is not allowed."); return; } string text = originalName; string name = newClip.GetName(); float num = 100f; if (name.Contains("-")) { string[] array = name.Split('-'); if (array.Length > 1) { if (array.Length > 2) { string text2 = array[^2]; if (!string.IsNullOrEmpty(text2) && text2.StartsWith("_")) { Instance.logger.LogDebug((object)("Clip " + name + " contains source specified in it's name (" + text2.Substring(1) + ") but you're using the manual function to assign it's source. (" + source + ") The file name will be ignored.")); } } string text3 = array[^1]; if (int.TryParse(text3, out var result)) { num = (float)result * 0.01f; } else if (!string.IsNullOrEmpty(text3) && text3.StartsWith("_")) { Instance.logger.LogDebug((object)("Clip " + name + " contains source specified in it's name (" + text3.Substring(1) + ") but you're using the manual function to assign it's source. (" + source + ") The file name will be ignored.")); } name = string.Join("-", array, 0, array.Length - 1); } else if (infoDebugging) { Instance.logger.LogDebug((object)("Clip " + name + " does not contain a '-' character for source name or chance")); } } if (!string.IsNullOrEmpty(source)) { text = originalName + "#" + source; } if (replacedClips.ContainsKey(text) && num >= 100f) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to replace an audio clip that already has been replaced with new clip that has 100% chance of playback! This is not allowed."); return; } num = Mathf.Clamp01(num); if (replacedClips.ContainsKey(text)) { replacedClips[text].AddClip(newClip, num); } else { replacedClips.Add(text, new ReplacementAudioClip(newClip, num, source)); } float num2 = 0f; for (int i = 0; i < replacedClips[text].clips.Count(); i++) { num2 += replacedClips[text].clips[i].chance; } int num3 = Mathf.RoundToInt(num2 * 100f); if ((num3 < 100 || num3 > 100) && replacedClips[text].clips.Count() > 1) { if (infoDebugging) { Instance.logger.LogDebug((object)$"The current total combined chance for replaced {replacedClips[text].clips.Count()} random audio clips for audio clip {text} does not equal 100%. Currently {num3}% (at least yet?)"); } } else if (num3 == 100 && replacedClips[text].clips.Count() > 1 && infoDebugging) { Instance.logger.LogDebug((object)$"The current total combined chance for replaced {replacedClips[text].clips.Count()} random audio clips for audio clip {text} is equal to 100%"); } } public static void ReplaceAudioClip(AudioClip originalClip, AudioClip newClip, string source) { if ((Object)(object)originalClip == (Object)null) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to replace an audio clip without original clip specified! This is not allowed."); } else if ((Object)(object)newClip == (Object)null) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to replace an audio clip without new clip specified! This is not allowed."); } else { ReplaceAudioClip(originalClip.GetName(), newClip, source); } } public static void ReplaceAudioClip(string originalName, AudioClip newClip, string[] source) { string text = string.Empty; if (source != null && source.Length != 0) { for (int i = 0; i < source.Length; i++) { if (!string.IsNullOrEmpty(source[i])) { text = text + "," + source[i]; } } } if (string.IsNullOrEmpty(originalName)) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to replace an audio clip without original clip specified! This is not allowed."); return; } if ((Object)(object)newClip == (Object)null) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to replace an audio clip without new clip specified! This is not allowed."); return; } if (string.IsNullOrEmpty(text)) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to replace an audio clip without allowed audio source specified! This is not allowed."); return; } string text2 = originalName; string name = newClip.GetName(); float num = 100f; if (name.Contains("-")) { string[] array = name.Split('-'); if (array.Length > 1) { if (array.Length > 2) { string text3 = array[^2]; if (!string.IsNullOrEmpty(text3) && text3.StartsWith("_")) { Instance.logger.LogDebug((object)("Clip " + name + " contains source specified in it's name (" + text3.Substring(1) + ") but you're using the manual function to assign it's source. (" + text + ") The file name will be ignored.")); } } string text4 = array[^1]; if (int.TryParse(text4, out var result)) { num = (float)result * 0.01f; } else if (!string.IsNullOrEmpty(text4) && text4.StartsWith("_")) { Instance.logger.LogDebug((object)("Clip " + name + " contains source specified in it's name (" + text4.Substring(1) + ") but you're using the manual function to assign it's source. (" + text + ") The file name will be ignored.")); } name = string.Join("-", array, 0, array.Length - 1); } else if (infoDebugging) { Instance.logger.LogDebug((object)("Clip " + name + " does not contain a '-' character for source name or chance")); } } if (!string.IsNullOrEmpty(text)) { text2 = originalName + "#" + text; } if (replacedClips.ContainsKey(text2) && num >= 100f) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to replace an audio clip that already has been replaced with new clip that has 100% chance of playback! This is not allowed."); return; } num = Mathf.Clamp01(num); if (replacedClips.ContainsKey(text2)) { replacedClips[text2].AddClip(newClip, num); } else { replacedClips.Add(text2, new ReplacementAudioClip(newClip, num, text)); } float num2 = 0f; for (int j = 0; j < replacedClips[text2].clips.Count(); j++) { num2 += replacedClips[text2].clips[j].chance; } int num3 = Mathf.RoundToInt(num2 * 100f); if ((num3 < 100 || num3 > 100) && replacedClips[text2].clips.Count() > 1) { if (infoDebugging) { Instance.logger.LogDebug((object)$"The current total combined chance for replaced {replacedClips[text2].clips.Count()} random audio clips for audio clip {text2} does not equal 100%. Currently {num3}% (at least yet?)"); } } else if (num3 == 100 && replacedClips[text2].clips.Count() > 1 && infoDebugging) { Instance.logger.LogDebug((object)$"The current total combined chance for replaced {replacedClips[text2].clips.Count()} random audio clips for audio clip {text2} is equal to 100%"); } } public static void ReplaceAudioClip(AudioClip originalClip, AudioClip newClip, string[] source) { if ((Object)(object)originalClip == (Object)null) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to replace an audio clip without original clip specified! This is not allowed."); } else if ((Object)(object)newClip == (Object)null) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to replace an audio clip without new clip specified! This is not allowed."); } else { ReplaceAudioClip(originalClip.GetName(), newClip, source); } } public static void ReplaceAudioClip(string originalName, AudioClip newClip, float chance, string source) { if (string.IsNullOrEmpty(originalName)) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to replace an audio clip without original clip specified! This is not allowed."); return; } if ((Object)(object)newClip == (Object)null) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to replace an audio clip without new clip specified! This is not allowed."); return; } if (string.IsNullOrEmpty(source)) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to replace an audio clip without allowed audio source specified! This is not allowed."); return; } string text = originalName; string name = newClip.GetName(); if (name.Contains("-")) { string[] array = name.Split('-'); if (array.Length > 1) { if (array.Length > 2) { string text2 = array[^2]; if (!string.IsNullOrEmpty(text2) && text2.StartsWith("_")) { Instance.logger.LogDebug((object)("Clip " + name + " contains source specified in it's name (" + text2.Substring(1) + ") but you're using the manual function to assign it's source. (" + source + ") The file name will be ignored.")); } } string text3 = array[^1]; if (int.TryParse(text3, out var result)) { Instance.logger.LogDebug((object)$"Clip {name} contains random chance specified in it's name ({result}%) but you're using the manual function to assign it's chance. ({Mathf.RoundToInt(chance * 100f)}%) The file name will be ignored."); } else if (!string.IsNullOrEmpty(text3) && text3.StartsWith("_")) { Instance.logger.LogDebug((object)("Clip " + name + " contains source specified in it's name (" + text3.Substring(1) + ") but you're using the manual function to assign it's source. (" + source + ") The file name will be ignored.")); } name = string.Join("-", array, 0, array.Length - 1); } else if (infoDebugging) { Instance.logger.LogDebug((object)("Clip " + name + " does not contain a '-' character for source name or chance")); } } if (!string.IsNullOrEmpty(source)) { text = originalName + "#" + source; } if (replacedClips.ContainsKey(text) && chance >= 100f) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to replace an audio clip that already has been replaced with new clip that has 100% chance of playback! This is not allowed."); return; } chance = Mathf.Clamp01(chance); if (replacedClips.ContainsKey(text)) { replacedClips[text].AddClip(newClip, chance); } else { replacedClips.Add(text, new ReplacementAudioClip(newClip, chance, source)); } float num = 0f; for (int i = 0; i < replacedClips[text].clips.Count(); i++) { num += replacedClips[text].clips[i].chance; } int num2 = Mathf.RoundToInt(num * 100f); if ((num2 < 100 || num2 > 100) && replacedClips[text].clips.Count() > 1) { if (infoDebugging) { Instance.logger.LogDebug((object)$"The current total combined chance for replaced {replacedClips[text].clips.Count()} random audio clips for audio clip {text} does not equal 100%. Currently {num2}% (at least yet?)"); } } else if (num2 == 100 && replacedClips[text].clips.Count() > 1 && infoDebugging) { Instance.logger.LogDebug((object)$"The current total combined chance for replaced {replacedClips[text].clips.Count()} random audio clips for audio clip {text} is equal to 100%"); } } public static void ReplaceAudioClip(AudioClip originalClip, AudioClip newClip, float chance, string source) { if ((Object)(object)originalClip == (Object)null) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to replace an audio clip without original clip specified! This is not allowed."); } else if ((Object)(object)newClip == (Object)null) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to replace an audio clip without new clip specified! This is not allowed."); } else { ReplaceAudioClip(originalClip.GetName(), newClip, chance, source); } } public static void ReplaceAudioClip(string originalName, AudioClip newClip, float chance, string[] source) { string text = string.Empty; if (source != null && source.Length != 0) { for (int i = 0; i < source.Length; i++) { if (!string.IsNullOrEmpty(source[i])) { text = text + "," + source[i]; } } } if (string.IsNullOrEmpty(originalName)) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to replace an audio clip without original clip specified! This is not allowed."); return; } if ((Object)(object)newClip == (Object)null) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to replace an audio clip without new clip specified! This is not allowed."); return; } if (string.IsNullOrEmpty(text)) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to replace an audio clip without allowed audio source specified! This is not allowed."); return; } string text2 = originalName; string name = newClip.GetName(); if (name.Contains("-")) { string[] array = name.Split('-'); if (array.Length > 1) { if (array.Length > 2) { string text3 = array[^2]; if (!string.IsNullOrEmpty(text3) && text3.StartsWith("_")) { Instance.logger.LogDebug((object)("Clip " + name + " contains source specified in it's name (" + text3.Substring(1) + ") but you're using the manual function to assign it's source. (" + text + ") The file name will be ignored.")); } } string text4 = array[^1]; if (int.TryParse(text4, out var result)) { Instance.logger.LogDebug((object)$"Clip {name} contains random chance specified in it's name ({result}%) but you're using the manual function to assign it's chance. ({Mathf.RoundToInt(chance * 100f)}%) The file name will be ignored."); } else if (!string.IsNullOrEmpty(text4) && text4.StartsWith("_")) { Instance.logger.LogDebug((object)("Clip " + name + " contains source specified in it's name (" + text4.Substring(1) + ") but you're using the manual function to assign it's source. (" + text + ") The file name will be ignored.")); } name = string.Join("-", array, 0, array.Length - 1); } else if (infoDebugging) { Instance.logger.LogDebug((object)("Clip " + name + " does not contain a '-' character for source name or chance")); } } if (!string.IsNullOrEmpty(text)) { text2 = originalName + "#" + text; } if (replacedClips.ContainsKey(text2) && chance >= 100f) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to replace an audio clip that already has been replaced with new clip that has 100% chance of playback! This is not allowed."); return; } chance = Mathf.Clamp01(chance); if (replacedClips.ContainsKey(text2)) { replacedClips[text2].AddClip(newClip, chance); } else { replacedClips.Add(text2, new ReplacementAudioClip(newClip, chance, text)); } float num = 0f; for (int j = 0; j < replacedClips[text2].clips.Count(); j++) { num += replacedClips[text2].clips[j].chance; } int num2 = Mathf.RoundToInt(num * 100f); if ((num2 < 100 || num2 > 100) && replacedClips[text2].clips.Count() > 1) { if (infoDebugging) { Instance.logger.LogDebug((object)$"The current total combined chance for replaced {replacedClips[text2].clips.Count()} random audio clips for audio clip {text2} does not equal 100%. Currently {num2}% (at least yet?)"); } } else if (num2 == 100 && replacedClips[text2].clips.Count() > 1 && infoDebugging) { Instance.logger.LogDebug((object)$"The current total combined chance for replaced {replacedClips[text2].clips.Count()} random audio clips for audio clip {text2} is equal to 100%"); } } public static void ReplaceAudioClip(AudioClip originalClip, AudioClip newClip, float chance, string[] source) { if ((Object)(object)originalClip == (Object)null) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to replace an audio clip without original clip specified! This is not allowed."); } else if ((Object)(object)newClip == (Object)null) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to replace an audio clip without new clip specified! This is not allowed."); } else { ReplaceAudioClip(originalClip.GetName(), newClip, chance, source); } } public static void RemoveRandomAudioClip(string name, float chance) { if (string.IsNullOrEmpty(name)) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to restore an audio clip without original clip specified! This is not allowed."); } else if (!replacedClips.ContainsKey(name)) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to restore an audio clip that does not exist! This is not allowed."); } else { if (!(chance > 0f)) { return; } for (int i = 0; i < replacedClips[name].clips.Count(); i++) { if (replacedClips[name].clips[i].chance == chance) { replacedClips[name].clips.RemoveAt(i); if (replacedClips[name].clips.Count <= 0) { Instance.logger.LogDebug((object)("Removed replaced AudioClip " + name + " completely as all of it's random clips have been removed.")); replacedClips.Remove(name); } break; } } } } public static void RemoveRandomAudioClip(string name, string source, float chance) { string text = name; if (!string.IsNullOrEmpty(text)) { text = name + "#" + source; } if (string.IsNullOrEmpty(text)) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to restore an audio clip without original clip specified! This is not allowed."); } else if (!replacedClips.ContainsKey(text)) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to restore an audio clip that does not exist! This is not allowed."); } else { if (!(chance > 0f)) { return; } for (int i = 0; i < replacedClips[text].clips.Count(); i++) { if (replacedClips[text].clips[i].chance == chance) { replacedClips[text].clips.RemoveAt(i); if (replacedClips[text].clips.Count <= 0) { Instance.logger.LogDebug((object)("Removed replaced AudioClip " + text + " completely as all of it's random clips have been removed.")); replacedClips.Remove(text); } break; } } } } public static void RemoveRandomAudioClip(string name, string[] source, float chance) { string text = name; string text2 = string.Empty; if (source != null && source.Length != 0) { for (int i = 0; i < source.Length; i++) { if (!string.IsNullOrEmpty(source[i])) { text2 = text2 + "," + source[i]; } } } if (!string.IsNullOrEmpty(text2)) { text = name + "#" + text2; } if (string.IsNullOrEmpty(text)) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to restore an audio clip without original clip specified! This is not allowed."); } else if (!replacedClips.ContainsKey(text)) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to restore an audio clip that does not exist! This is not allowed."); } else { if (!(chance > 0f)) { return; } for (int j = 0; j < replacedClips[text].clips.Count(); j++) { if (replacedClips[text].clips[j].chance == chance) { replacedClips[text].clips.RemoveAt(j); if (replacedClips[text].clips.Count <= 0) { Instance.logger.LogDebug((object)("Removed replaced AudioClip " + text + " completely as all of it's random clips have been removed.")); replacedClips.Remove(text); } break; } } } } public static void RestoreAudioClip(string name) { if (string.IsNullOrEmpty(name)) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to restore an audio clip without original clip specified! This is not allowed."); } else if (!replacedClips.ContainsKey(name)) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to restore an audio clip that does not exist! This is not allowed."); } else { replacedClips.Remove(name); } } public static void RestoreAudioClip(string name, string source) { string text = name; if (!string.IsNullOrEmpty(source)) { text = name + "#" + source; } if (string.IsNullOrEmpty(text)) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to restore an audio clip without original clip specified! This is not allowed."); } else if (!replacedClips.ContainsKey(text)) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to restore an audio clip that does not exist! This is not allowed."); } else { replacedClips.Remove(text); } } public static void RestoreAudioClip(string name, string[] source) { string text = name; string text2 = string.Empty; if (source != null && source.Length != 0) { for (int i = 0; i < source.Length; i++) { if (!string.IsNullOrEmpty(source[i])) { text2 = text2 + "," + source[i]; } } } if (!string.IsNullOrEmpty(text2)) { text = name + "#" + text2; } if (string.IsNullOrEmpty(text)) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to restore an audio clip without original clip specified! This is not allowed."); } else if (!replacedClips.ContainsKey(text)) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to restore an audio clip that does not exist! This is not allowed."); } else { replacedClips.Remove(text); } } public static void RestoreAudioClip(AudioClip clip) { if ((Object)(object)clip == (Object)null) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to restore an audio clip without vanilla clip name specified! This is not allowed."); } else { RestoreAudioClip(clip.GetName()); } } public static void RestoreAudioClip(string name, AudioClip replacementClip) { if ((Object)(object)replacementClip == (Object)null) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to restore an audio clip without replacement clip specified! This is not allowed."); return; } if (string.IsNullOrEmpty(name)) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to restore an audio clip without vanilla clip name specified! This is not allowed."); return; } string name2 = replacementClip.GetName(); string text = string.Empty; float num = 0f; if (name2.Contains("-")) { string[] array = name2.Split('-'); if (array.Length > 1) { if (array.Length > 2) { string text2 = array[^2]; if (!string.IsNullOrEmpty(text2) && text2.StartsWith("_")) { text = text2.Substring(1); } } string text3 = array[^1]; if (int.TryParse(text3, out var result)) { num = (float)result * 0.01f; } else if (!string.IsNullOrEmpty(text3) && text3.StartsWith("_")) { text = text3.Substring(1); } name2 = string.Join("-", array, 0, array.Length - 1); } else if (infoDebugging) { Instance.logger.LogDebug((object)("Clip " + name2 + " does not contain a '-' character for source name or chance")); } } string text4 = name + "#" + text; if (!replacedClips.ContainsKey(text4)) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to restore an audio clip that does not exist! This is not allowed."); } else { RestoreAudioClip(text4); } } public static AudioClip GetAudioClip(string modFolder, string soundName) { return GetAudioClip(modFolder, string.Empty, soundName); } public static AudioClip GetAudioClip(string modFolder, string subFolder, string soundName) { AudioType audioType = AudioType.wav; bool flag = true; string text = " "; string text2 = Path.Combine(Paths.PluginPath, modFolder, subFolder, soundName); string text3 = Path.Combine(Paths.PluginPath, modFolder, soundName); string path = Path.Combine(Paths.PluginPath, modFolder, subFolder); string text4 = Path.Combine(Paths.PluginPath, subFolder, soundName); string path2 = Path.Combine(Paths.PluginPath, subFolder); if (!Directory.Exists(path)) { if (!string.IsNullOrEmpty(subFolder)) { Instance.logger.LogWarning((object)("Requested directory at BepInEx/Plugins/" + modFolder + "/" + subFolder + " does not exist!")); } else { Instance.logger.LogWarning((object)("Requested directory at BepInEx/Plugins/" + modFolder + " does not exist!")); if (!modFolder.Contains("-")) { Instance.logger.LogWarning((object)"This sound mod might not be compatable with mod managers. You should contact the sound mod's author."); } } flag = false; } if (!File.Exists(text2)) { Instance.logger.LogWarning((object)("Requested audio file does not exist at path " + text2 + "!")); flag = false; Instance.logger.LogDebug((object)("Looking for audio file from mod root instead at " + text3 + "...")); if (File.Exists(text3)) { Instance.logger.LogDebug((object)("Found audio file at path " + text3 + "!")); text2 = text3; flag = true; } else { Instance.logger.LogWarning((object)("Requested audio file does not exist at mod root path " + text3 + "!")); } } if (Directory.Exists(path2)) { if (!string.IsNullOrEmpty(subFolder)) { Instance.logger.LogWarning((object)("Legacy directory location at BepInEx/Plugins/" + subFolder + " found!")); } else if (!modFolder.Contains("-")) { Instance.logger.LogWarning((object)"Legacy directory location at BepInEx/Plugins found!"); } } if (File.Exists(text4)) { Instance.logger.LogWarning((object)("Legacy path contains the requested audio file at path " + text4 + "!")); text = " legacy "; text2 = text4; flag = true; } string[] array = soundName.Split('.'); if (array[^1].ToLower().Contains("wav")) { audioType = AudioType.wav; if (infoDebugging) { Instance.logger.LogDebug((object)"File detected as a PCM WAVE file!"); } } else if (array[^1].ToLower().Contains("ogg")) { audioType = AudioType.ogg; if (infoDebugging) { Instance.logger.LogDebug((object)"File detected as an Ogg Vorbis file!"); } } else if (array[^1].ToLower().Contains("mp3")) { audioType = AudioType.mp3; if (infoDebugging) { Instance.logger.LogDebug((object)"File detected as a MPEG MP3 file!"); } } else { Instance.logger.LogWarning((object)("Failed to detect file type of a sound file! This may cause issues with other mod functionality. Sound: " + soundName)); } AudioClip val = null; if (flag) { Instance.logger.LogDebug((object)("Loading AudioClip " + soundName + " from" + text + "path: " + text2)); switch (audioType) { case AudioType.wav: val = WavUtility.LoadFromDiskToAudioClip(text2); break; case AudioType.ogg: val = OggUtility.LoadFromDiskToAudioClip(text2); break; case AudioType.mp3: val = Mp3Utility.LoadFromDiskToAudioClip(text2); break; } Instance.logger.LogDebug((object)$"Finished loading AudioClip {soundName} with length of {val.length}!"); } else { Instance.logger.LogWarning((object)("Failed to load AudioClip " + soundName + " from invalid" + text + "path at " + text2 + "!")); } if (string.IsNullOrEmpty(val.GetName())) { string empty = string.Empty; string[] array2 = new string[0]; switch (audioType) { case AudioType.wav: empty = soundName.Replace(".wav", ""); array2 = empty.Split('/'); if (array2.Length <= 1) { array2 = empty.Split('\\'); } empty = array2[^1]; ((Object)val).name = empty; break; case AudioType.ogg: empty = soundName.Replace(".ogg", ""); array2 = empty.Split('/'); if (array2.Length <= 1) { array2 = empty.Split('\\'); } empty = array2[^1]; ((Object)val).name = empty; break; case AudioType.mp3: empty = soundName.Replace(".mp3", ""); array2 = empty.Split('/'); if (array2.Length <= 1) { array2 = empty.Split('\\'); } empty = array2[^1]; ((Object)val).name = empty; break; } } if ((Object)(object)val != (Object)null) { string name = val.GetName(); if (clipTypes.ContainsKey(name)) { clipTypes[name] = audioType; } else { clipTypes.Add(name, audioType); } } return val; } public static AudioClip GetAudioClip(string modFolder, string soundName, AudioType audioType) { return GetAudioClip(modFolder, string.Empty, soundName, audioType); } public static AudioClip GetAudioClip(string modFolder, string subFolder, string soundName, AudioType audioType) { bool flag = true; string text = " "; string text2 = Path.Combine(Paths.PluginPath, modFolder, subFolder, soundName); string text3 = Path.Combine(Paths.PluginPath, modFolder, soundName); string path = Path.Combine(Paths.PluginPath, modFolder, subFolder); string text4 = Path.Combine(Paths.PluginPath, subFolder, soundName); string path2 = Path.Combine(Paths.PluginPath, subFolder); if (!Directory.Exists(path)) { if (!string.IsNullOrEmpty(subFolder)) { Instance.logger.LogWarning((object)("Requested directory at BepInEx/Plugins/" + modFolder + "/" + subFolder + " does not exist!")); } else { Instance.logger.LogWarning((object)("Requested directory at BepInEx/Plugins/" + modFolder + " does not exist!")); if (!modFolder.Contains("-")) { Instance.logger.LogWarning((object)"This sound mod might not be compatable with mod managers. You should contact the sound mod's author."); } } flag = false; } if (!File.Exists(text2)) { Instance.logger.LogWarning((object)("Requested audio file does not exist at path " + text2 + "!")); flag = false; Instance.logger.LogDebug((object)("Looking for audio file from mod root instead at " + text3 + "...")); if (File.Exists(text3)) { Instance.logger.LogDebug((object)("Found audio file at path " + text3 + "!")); text2 = text3; flag = true; } else { Instance.logger.LogWarning((object)("Requested audio file does not exist at mod root path " + text3 + "!")); } } if (Directory.Exists(path2)) { if (!string.IsNullOrEmpty(subFolder)) { Instance.logger.LogWarning((object)("Legacy directory location at BepInEx/Plugins/" + subFolder + " found!")); } else if (!modFolder.Contains("-")) { Instance.logger.LogWarning((object)"Legacy directory location at BepInEx/Plugins found!"); } } if (File.Exists(text4)) { Instance.logger.LogWarning((object)("Legacy path contains the requested audio file at path " + text4 + "!")); text = " legacy "; text2 = text4; flag = true; } switch (audioType) { case AudioType.wav: if (infoDebugging) { Instance.logger.LogDebug((object)"File defined as a WAV file!"); } break; case AudioType.ogg: if (infoDebugging) { Instance.logger.LogDebug((object)"File defined as an Ogg Vorbis file!"); } break; case AudioType.mp3: if (infoDebugging) { Instance.logger.LogDebug((object)"File defined as a MPEG MP3 file!"); } break; } AudioClip val = null; if (flag) { Instance.logger.LogDebug((object)("Loading AudioClip " + soundName + " from" + text + "path: " + text2)); switch (audioType) { case AudioType.wav: val = WavUtility.LoadFromDiskToAudioClip(text2); break; case AudioType.ogg: val = OggUtility.LoadFromDiskToAudioClip(text2); break; case AudioType.mp3: val = Mp3Utility.LoadFromDiskToAudioClip(text2); break; } Instance.logger.LogDebug((object)$"Finished loading AudioClip {soundName} with length of {val.length}!"); } else { Instance.logger.LogWarning((object)("Failed to load AudioClip " + soundName + " from invalid" + text + "path at " + text2 + "!")); } if (string.IsNullOrEmpty(val.GetName())) { string empty = string.Empty; string[] array = new string[0]; switch (audioType) { case AudioType.wav: empty = soundName.Replace(".wav", ""); array = empty.Split('/'); if (array.Length <= 1) { array = empty.Split('\\'); } empty = array[^1]; ((Object)val).name = empty; break; case AudioType.ogg: empty = soundName.Replace(".ogg", ""); array = empty.Split('/'); if (array.Length <= 1) { array = empty.Split('\\'); } empty = array[^1]; ((Object)val).name = empty; break; case AudioType.mp3: empty = soundName.Replace(".mp3", ""); array = empty.Split('/'); if (array.Length <= 1) { array = empty.Split('\\'); } empty = array[^1]; ((Object)val).name = empty; break; } } if ((Object)(object)val != (Object)null) { string name = val.GetName(); if (clipTypes.ContainsKey(name)) { clipTypes[name] = audioType; } else { clipTypes.Add(name, audioType); } } return val; } public static void SendNetworkedAudioClip(AudioClip audioClip) { if (!Instance.configUseNetworking.Value) { Instance.logger.LogWarning((object)$"Networking disabled! Failed to send {audioClip}!"); return; } if ((Object)(object)audioClip == (Object)null) { Instance.logger.LogWarning((object)$"audioClip variable of SendAudioClip not assigned! Failed to send {audioClip}!"); return; } if ((Object)(object)Instance == (Object)null || (Object)(object)GameNetworkManagerPatch.networkHandlerHost == (Object)null || (Object)(object)NetworkHandler.Instance == (Object)null) { Instance.logger.LogWarning((object)$"Instance of SoundTool not found or networking has not finished initializing. Failed to send {audioClip}! If you're sending things in Awake or in a scene such as the main menu it might be too early, please try some of the other built-in Unity methods and make sure your networked audio runs only after the player setups a networked connection!"); return; } string name = audioClip.GetName(); if (clipTypes.ContainsKey(name)) { if (clipTypes[name] == AudioType.ogg) { NetworkHandler.Instance.SendAudioClipServerRpc(name, OggUtility.AudioClipToByteArray(audioClip, out var _)); return; } if (clipTypes[name] == AudioType.mp3) { NetworkHandler.Instance.SendAudioClipServerRpc(name, Mp3Utility.AudioClipToByteArray(audioClip, out var _)); return; } } NetworkHandler.Instance.SendAudioClipServerRpc(name, WavUtility.AudioClipToByteArray(audioClip, out var _)); } public static void RemoveNetworkedAudioClip(AudioClip audioClip) { RemoveNetworkedAudioClip(audioClip.GetName()); } public static void RemoveNetworkedAudioClip(string audioClip) { if (!Instance.configUseNetworking.Value) { Instance.logger.LogWarning((object)("Networking disabled! Failed to remove " + audioClip + "!")); } else if (string.IsNullOrEmpty(audioClip)) { Instance.logger.LogWarning((object)("audioClip variable of RemoveAudioClip not assigned! Failed to remove " + audioClip + "!")); } else if ((Object)(object)Instance == (Object)null || (Object)(object)GameNetworkManagerPatch.networkHandlerHost == (Object)null || (Object)(object)NetworkHandler.Instance == (Object)null) { Instance.logger.LogWarning((object)("Instance of SoundTool not found or networking has not finished initializing. Failed to remove " + audioClip + "! If you're removing things in Awake or in a scene such as the main menu it might be too early, please try some of the other built-in Unity methods and make sure your networked audio runs only after the player setups a networked connection!")); } else { NetworkHandler.Instance.RemoveAudioClipServerRpc(audioClip); } } public static void SyncNetworkedAudioClips() { if (!Instance.configUseNetworking.Value) { Instance.logger.LogWarning((object)"Networking disabled! Failed to sync audio clips!"); } else if ((Object)(object)Instance == (Object)null || (Object)(object)GameNetworkManagerPatch.networkHandlerHost == (Object)null || (Object)(object)NetworkHandler.Instance == (Object)null) { Instance.logger.LogWarning((object)"Instance of SoundTool not found or networking has not finished initializing. Failed to sync networked audio! If you're syncing things in Awake or in a scene such as the main menu it might be too early, please try some of the other built-in Unity methods and make sure your networked audio runs only after the player setups a networked connection!"); } else { NetworkHandler.Instance.SyncAudioClipsServerRpc(); } } public static void SendUnityRandomSeed(int seed) { if (!Instance.configUseNetworking.Value) { Instance.logger.LogWarning((object)"Networking disabled! Failed to send Unity random seed!"); } else if ((Object)(object)Instance == (Object)null || (Object)(object)GameNetworkManagerPatch.networkHandlerHost == (Object)null || (Object)(object)NetworkHandler.Instance == (Object)null) { Instance.logger.LogWarning((object)"Instance of SoundTool not found or networking has not finished initializing. Failed to send Unity Random seed! If you're sending the seed in Awake or in a scene such as the main menu it might be too early, please try some of the other built-in Unity methods and make sure your networked methods run only after the player setups a networked connection!"); } else { NetworkHandler.Instance.SendSeedToClientsServerRpc(seed); } } } } namespace LCSoundTool.Utilities { public static class Extensions { public static bool ContainsThisRandomAudioClip(this List<RandomAudioClip> list, RandomAudioClip thisClip) { for (int i = 0; i < list.Count; i++) { if (list[i].chance == thisClip.chance && list[i].clip.GetName() == thisClip.clip.GetName()) { return true; } } return false; } } public static class Mp3Utility { public static byte[] AudioClipToByteArray(AudioClip audioClip, out float[] samples) { samples = new float[audioClip.samples * audioClip.channels]; audioClip.GetData(samples, 0); byte[] array = new byte[samples.Length * 2]; int num = 32767; for (int i = 0; i < samples.Length; i++) { short value = (short)(samples[i] * (float)num); BitConverter.GetBytes(value).CopyTo(array, i * 2); } return array; } public static AudioClip ByteArrayToAudioClip(byte[] byteArray, string clipName) { int num = 16; int num2 = num / 8; AudioClip val = AudioClip.Create(clipName, byteArray.Length / num2, 1, 44100, false); val.SetData(ConvertByteArrayToFloatArray(byteArray), 0); return val; } private static float[] ConvertByteArrayToFloatArray(byte[] byteArray) { float[] array = new float[byteArray.Length / 2]; int num = 32767; for (int i = 0; i < array.Length; i++) { short num2 = BitConverter.ToInt16(byteArray, i * 2); array[i] = (float)num2 / (float)num; } return array; } public static AudioClip LoadFromDiskToAudioClip(string path) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Invalid comparison between Unknown and I4 AudioClip result = null; UnityWebRequest audioClip = UnityWebRequestMultimedia.GetAudioClip(path, (AudioType)13); try { audioClip.SendWebRequest(); try { while (!audioClip.isDone) { } if ((int)audioClip.result != 1) { SoundTool.Instance.logger.LogError((object)("Failed to load MP3 AudioClip from path: " + path + " Full error: " + audioClip.error)); } else { result = DownloadHandlerAudioClip.GetContent(audioClip); } } catch (Exception ex) { SoundTool.Instance.logger.LogError((object)(ex.Message + ", " + ex.StackTrace)); } } finally { ((IDisposable)audioClip)?.Dispose(); } return result; } } public static class OggUtility { public static byte[] AudioClipToByteArray(AudioClip audioClip, out float[] samples) { samples = new float[audioClip.samples * audioClip.channels]; audioClip.GetData(samples, 0); byte[] array = new byte[samples.Length * 2]; int num = 32767; for (int i = 0; i < samples.Length; i++) { short value = (short)(samples[i] * (float)num); BitConverter.GetBytes(value).CopyTo(array, i * 2); } return array; } public static AudioClip ByteArrayToAudioClip(byte[] byteArray, string clipName) { int num = 16; int num2 = num / 8; AudioClip val = AudioClip.Create(clipName, byteArray.Length / num2, 1, 44100, false); val.SetData(ConvertByteArrayToFloatArray(byteArray), 0); return val; } private static float[] ConvertByteArrayToFloatArray(byte[] byteArray) { float[] array = new float[byteArray.Length / 2]; int num = 32767; for (int i = 0; i < array.Length; i++) { short num2 = BitConverter.ToInt16(byteArray, i * 2); array[i] = (float)num2 / (float)num; } return array; } public static AudioClip LoadFromDiskToAudioClip(string path) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Invalid comparison between Unknown and I4 AudioClip result = null; UnityWebRequest audioClip = UnityWebRequestMultimedia.GetAudioClip(path, (AudioType)14); try { audioClip.SendWebRequest(); try { while (!audioClip.isDone) { } if ((int)audioClip.result != 1) { SoundTool.Instance.logger.LogError((object)("Failed to load OGGVORBIS AudioClip from path: " + path + " Full error: " + audioClip.error)); } else { result = DownloadHandlerAudioClip.GetContent(audioClip); } } catch (Exception ex) { SoundTool.Instance.logger.LogError((object)(ex.Message + ", " + ex.StackTrace)); } } finally { ((IDisposable)audioClip)?.Dispose(); } return result; } } public static class WavUtility { public static byte[] AudioClipToByteArray(AudioClip audioClip, out float[] samples) { samples = new float[audioClip.samples * audioClip.channels]; audioClip.GetData(samples, 0); byte[] array = new byte[samples.Length * 2]; int num = 32767; for (int i = 0; i < samples.Length; i++) { short value = (short)(samples[i] * (float)num); BitConverter.GetBytes(value).CopyTo(array, i * 2); } return array; } public static AudioClip ByteArrayToAudioClip(byte[] byteArray, string clipName) { int num = 16; int num2 = num / 8; AudioClip val = AudioClip.Create(clipName, byteArray.Length / num2, 1, 44100, false); val.SetData(ConvertByteArrayToFloatArray(byteArray), 0); return val; } private static float[] ConvertByteArrayToFloatArray(byte[] byteArray) { float[] array = new float[byteArray.Length / 2]; int num = 32767; for (int i = 0; i < array.Length; i++) { short num2 = BitConverter.ToInt16(byteArray, i * 2); array[i] = (float)num2 / (float)num; } return array; } public static AudioClip LoadFromDiskToAudioClip(string path) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Invalid comparison between Unknown and I4 AudioClip result = null; UnityWebRequest audioClip = UnityWebRequestMultimedia.GetAudioClip(path, (AudioType)20); try { audioClip.SendWebRequest(); try { while (!audioClip.isDone) { } if ((int)audioClip.result != 1) { SoundTool.Instance.logger.LogError((object)("Failed to load WAV AudioClip from path: " + path + " Full error: " + audioClip.error)); } else { result = DownloadHandlerAudioClip.GetContent(audioClip); } } catch (Exception ex) { SoundTool.Instance.logger.LogError((object)(ex.Message + ", " + ex.StackTrace)); } } finally { ((IDisposable)audioClip)?.Dispose(); } return result; } } } namespace LCSoundTool.Patches { [HarmonyPatch(typeof(AudioSource))] internal class AudioSourcePatch { private static Dictionary<string, AudioClip> originalClips = new Dictionary<string, AudioClip>(); [HarmonyPatch("Play", new Type[] { })] [HarmonyPrefix] public static void Play_Patch(AudioSource __instance) { RunDynamicClipReplacement(__instance); DebugPlayMethod(__instance); } [HarmonyPatch("Play", new Type[] { typeof(ulong) })] [HarmonyPrefix] public static void Play_UlongPatch(AudioSource __instance) { RunDynamicClipReplacement(__instance); DebugPlayMethod(__instance); } [HarmonyPatch("Play", new Type[] { typeof(double) })] [HarmonyPrefix] public static void Play_DoublePatch(AudioSource __instance) { RunDynamicClipReplacement(__instance); DebugPlayMethod(__instance); } [HarmonyPatch("PlayDelayed", new Type[] { typeof(float) })] [HarmonyPrefix] public static void PlayDelayed_Patch(AudioSource __instance) { RunDynamicClipReplacement(__instance); DebugPlayDelayedMethod(__instance); } [HarmonyPatch("PlayClipAtPoint", new Type[] { typeof(AudioClip), typeof(Vector3), typeof(float) })] [HarmonyPrefix] public static bool PlayClipAtPoint_Patch(AudioClip clip, Vector3 position, float volume) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject($"ClipAtPoint_{clip}"); val.transform.position = position; AudioSource val2 = val.AddComponent<AudioSource>(); val2.clip = clip; val2.spatialBlend = 1f; val2.volume = volume; val2.Play(); DebugPlayClipAtPointMethod(val2, position); Object.Destroy((Object)(object)val, clip.length * ((Time.timeScale < 0.01f) ? 0.01f : Time.timeScale)); return false; } [HarmonyPatch("PlayOneShotHelper", new Type[] { typeof(AudioSource), typeof(AudioClip), typeof(float) })] [HarmonyPrefix] public static void PlayOneShotHelper_Patch(AudioSource source, ref AudioClip clip, float volumeScale) { clip = ReplaceClipWithNew(clip, source); DebugPlayOneShotMethod(source, clip); } private static void DebugPlayMethod(AudioSource instance) { if ((Object)(object)instance == (Object)null) { return; } if (SoundTool.debugAudioSources && !SoundTool.indepthDebugging && (Object)(object)instance != (Object)null) { SoundTool.Instance.logger.LogDebug((object)$"{instance} at {((Component)instance).transform.root} is playing {((Object)instance.clip).name}"); } else if (SoundTool.indepthDebugging && (Object)(object)instance != (Object)null) { SoundTool.Instance.logger.LogDebug((object)$"{instance} is playing {((Object)instance.clip).name} at"); Transform val = ((Component)instance).transform; while ((Object)(object)val.parent != (Object)null || (Object)(object)val != (Object)(object)((Component)instance).transform.root) { SoundTool.Instance.logger.LogDebug((object)$"--- {val.parent}"); val = val.parent; } if ((Object)(object)val == (Object)(object)((Component)instance).transform.root) { SoundTool.Instance.logger.LogDebug((object)$"--- {((Component)instance).transform.root}"); } } } private static void DebugPlayDelayedMethod(AudioSource instance) { if ((Object)(object)instance == (Object)null) { return; } if (SoundTool.debugAudioSources && !SoundTool.indepthDebugging && (Object)(object)instance != (Object)null) { SoundTool.Instance.logger.LogDebug((object)$"{instance} at {((Component)instance).transform.root} is playing {((Object)instance.clip).name} with delay"); } else if (SoundTool.indepthDebugging && (Object)(object)instance != (Object)null) { SoundTool.Instance.logger.LogDebug((object)$"{instance} is playing {((Object)instance.clip).name} with delay at"); Transform val = ((Component)instance).transform; while ((Object)(object)val.parent != (Object)null || (Object)(object)val != (Object)(object)((Component)instance).transform.root) { SoundTool.Instance.logger.LogDebug((object)$"--- {val.parent}"); val = val.parent; } if ((Object)(object)val == (Object)(object)((Component)instance).transform.root) { SoundTool.Instance.logger.LogDebug((object)$"--- {((Component)instance).transform.root}"); } } } private static void DebugPlayClipAtPointMethod(AudioSource audioSource, Vector3 position) { //IL_0065: 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) if ((Object)(object)audioSource == (Object)null) { return; } if (SoundTool.debugAudioSources && !SoundTool.indepthDebugging && (Object)(object)audioSource != (Object)null) { SoundTool.Instance.logger.LogDebug((object)$"{audioSource} at {((Component)audioSource).transform.root} is playing {((Object)audioSource.clip).name} at point {position}"); } else if (SoundTool.indepthDebugging && (Object)(object)audioSource != (Object)null) { SoundTool.Instance.logger.LogDebug((object)$"{audioSource} is playing {((Object)audioSource.clip).name} located at point {position} within "); Transform val = ((Component)audioSource).transform; while ((Object)(object)val.parent != (Object)null || (Object)(object)val != (Object)(object)((Component)audioSource).transform.root) { SoundTool.Instance.logger.LogDebug((object)$"--- {val.parent}"); val = val.parent; } if ((Object)(object)val == (Object)(object)((Component)audioSource).transform.root) { SoundTool.Instance.logger.LogDebug((object)$"--- {((Component)audioSource).transform.root}"); } } } private static void DebugPlayOneShotMethod(AudioSource source, AudioClip clip) { if ((Object)(object)source == (Object)null || (Object)(object)clip == (Object)null) { return; } if (SoundTool.debugAudioSources && !SoundTool.indepthDebugging && (Object)(object)source != (Object)null) { SoundTool.Instance.logger.LogDebug((object)$"{source} at {((Component)source).transform.root} is playing one shot {((Object)clip).name}"); } else if (SoundTool.indepthDebugging && (Object)(object)source != (Object)null) { SoundTool.Instance.logger.LogDebug((object)$"{source} is playing one shot {((Object)clip).name} at"); Transform val = ((Component)source).transform; while ((Object)(object)val.parent != (Object)null || (Object)(object)val != (Object)(object)((Component)source).transform.root) { SoundTool.Instance.logger.LogDebug((object)$"--- {val.parent}"); val = val.parent; } if ((Object)(object)val == (Object)(object)((Component)source).transform.root) { SoundTool.Instance.logger.LogDebug((object)$"--- {((Component)source).transform.root}"); } } } private static void RunDynamicClipReplacement(AudioSource instance) { if ((Object)(object)instance == (Object)null || (Object)(object)instance.clip == (Object)null) { return; } string name = ((Object)((Component)instance).gameObject).name; bool flag = true; AudioClip value; string text = ((!originalClips.TryGetValue(name, out value)) ? instance.clip.GetName() : value.GetName()); string key = text; if (SoundTool.replacedClips.Keys.Count > 0) { string[] array = SoundTool.replacedClips.Keys.ToArray(); if (array.Length != 0) { for (int i = 0; i < array.Length; i++) { string[] array2 = array[i].Split("#"); if (array2.Length == 2 && array2[1].Contains(((Object)((Component)instance).gameObject).name)) { key = text + "#" + array2[1]; } } } } if (SoundTool.replacedClips.ContainsKey(key)) { if (!SoundTool.replacedClips[key].canPlay) { return; } if (!originalClips.ContainsKey(name)) { originalClips.Add(name, instance.clip); } if (!string.IsNullOrEmpty(SoundTool.replacedClips[key].source)) { flag = false; string[] array3 = SoundTool.replacedClips[key].source.Split(','); if ((Object)(object)instance != (Object)null && ((Object)((Component)instance).gameObject).name != null) { if (array3.Length > 1) { for (int j = 0; j < array3.Length; j++) { if (array3[j] == ((Object)((Component)instance).gameObject).name) { flag = true; } } } else if (array3[0] == ((Object)((Component)instance).gameObject).name) { flag = true; } } } List<RandomAudioClip> clips = SoundTool.replacedClips[key].clips; float num = 0f; foreach (RandomAudioClip item in clips) { num += item.chance; } float num2 = Random.Range(0f, num); { foreach (RandomAudioClip item2 in clips) { if (num2 <= item2.chance) { if (flag) { instance.clip = item2.clip; } else if (originalClips.ContainsKey(name)) { instance.clip = originalClips[name]; originalClips.Remove(name); } break; } num2 -= item2.chance; } return; } } if (originalClips.ContainsKey(name)) { instance.clip = originalClips[name]; originalClips.Remove(name); } } private static AudioClip ReplaceClipWithNew(AudioClip original, AudioSource source = null) { if ((Object)(object)original == (Object)null) { return original; } string name = original.GetName(); bool flag = true; string key = name; if ((Object)(object)source != (Object)null && SoundTool.replacedClips.Keys.Count > 0) { string[] array = SoundTool.replacedClips.Keys.ToArray(); if (array.Length != 0) { for (int i = 0; i < array.Length; i++) { string[] array2 = array[i].Split("#"); if (array2.Length == 2 && array2[1].Contains(((Object)((Component)source).gameObject).name)) { key = name + "#" + array2[1]; } } } } if (SoundTool.replacedClips.ContainsKey(key)) { if (!SoundTool.replacedClips[key].canPlay) { return original; } if (!originalClips.ContainsKey(key)) { originalClips.Add(key, original); } if (!string.IsNullOrEmpty(SoundTool.replacedClips[key].source)) { flag = false; string[] array3 = SoundTool.replacedClips[key].source.Split(','); if ((Object)(object)source != (Object)null && ((Object)((Component)source).gameObject).name != null) { if (array3.Length > 1) { for (int j = 0; j < array3.Length; j++) { if (array3[j] == ((Object)((Component)source).gameObject).name) { flag = true; } } } else if (array3[0] == ((Object)((Component)source).gameObject).name) { flag = true; } } } List<RandomAudioClip> clips = SoundTool.replacedClips[key].clips; float num = 0f; foreach (RandomAudioClip item in clips) { num += item.chance; } float num2 = Random.Range(0f, num); foreach (RandomAudioClip item2 in clips) { if (num2 <= item2.chance) { if (flag) { return item2.clip; } if (originalClips.ContainsKey(key)) { AudioClip result = originalClips[key]; originalClips.Remove(key); return result; } return original; } num2 -= item2.chance; } } else if (originalClips.ContainsKey(key)) { AudioClip result2 = originalClips[key]; originalClips.Remove(key); return result2; } return original; } } [HarmonyPatch(typeof(GameNetworkManager))] internal class GameNetworkManagerPatch { public static GameObject networkPrefab; public static GameObject networkHandlerHost; [HarmonyPatch("Start")] [HarmonyPrefix] public static void Start_Patch() { if (!((Object)(object)networkPrefab != (Object)null)) { SoundTool.Instance.logger.LogDebug((object)"Loading NetworkHandler prefab..."); networkPrefab = Assets.bundle.LoadAsset<GameObject>("SoundToolNetworkHandler.prefab"); if ((Object)(object)networkPrefab == (Object)null) { SoundTool.Instance.logger.LogError((object)"Failed to load NetworkHandler prefab!"); } if ((Object)(object)networkPrefab != (Object)null) { NetworkManager.Singleton.AddNetworkPrefab(networkPrefab); SoundTool.Instance.logger.LogDebug((object)"Registered NetworkHandler prefab!"); } else { SoundTool.Instance.logger.LogWarning((object)"Failed to registered NetworkHandler prefab! No networking can take place."); } } } [HarmonyPatch("StartDisconnect")] [HarmonyPostfix] private static void StartDisconnect_Patch() { try { if (NetworkManager.Singleton.IsHost || NetworkManager.Singleton.IsServer) { SoundTool.Instance.logger.LogDebug((object)"Destroying NetworkHandler prefab!"); Object.Destroy((Object)(object)networkHandlerHost); networkHandlerHost = null; } } catch { SoundTool.Instance.logger.LogError((object)"Failed to destroy NetworkHandler prefab!"); } } } [HarmonyPatch(typeof(StartOfRound))] internal class StartOfRoundPatch { [HarmonyPatch("Awake")] [HarmonyPostfix] private static void SpawnNetworkHandler() { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) try { if (NetworkManager.Singleton.IsHost || NetworkManager.Singleton.IsServer) { SoundTool.Instance.logger.LogDebug((object)"Spawning NetworkHandler prefab!"); GameNetworkManagerPatch.networkHandlerHost = Object.Instantiate<GameObject>(GameNetworkManagerPatch.networkPrefab, Vector3.zero, Quaternion.identity); GameNetworkManagerPatch.networkHandlerHost.GetComponent<NetworkObject>().Spawn(true); } } catch { SoundTool.Instance.logger.LogError((object)"Failed to spawn NetworkHandler prefab!"); } } } } namespace LCSoundTool.Networking { public class NetworkHandler : NetworkBehaviour { public static NetworkHandler Instance { get; private set; } public static Dictionary<string, AudioClip> networkedAudioClips { get; private set; } public static event Action ClientNetworkedAudioChanged; public static event Action HostNetworkedAudioChanged; public override void OnNetworkSpawn() { Debug.Log((object)"LCSoundTool - NetworkHandler created!"); NetworkHandler.ClientNetworkedAudioChanged = null; NetworkHandler.HostNetworkedAudioChanged = null; networkedAudioClips = new Dictionary<string, AudioClip>(); Instance = this; } [ClientRpc] public void ReceiveAudioClipClientRpc(string clipName, byte[] audioData) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Invalid comparison between Unknown and I4 //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Invalid comparison between Unknown and I4 //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008e: 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_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager; if (networkManager == null || !networkManager.IsListening) { return; } if ((int)base.__rpc_exec_stage != 2 && (networkManager.IsServer || networkManager.IsHost)) { ClientRpcParams val = default(ClientRpcParams); FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendClientRpc(2736638642u, val, (RpcDelivery)0); bool flag = clipName != null; ((FastBufferWriter)(ref val2)).WriteValueSafe<bool>(ref flag, default(ForPrimitives)); if (flag) { ((FastBufferWriter)(ref val2)).WriteValueSafe(clipName, false); } bool flag2 = audioData != null; ((FastBufferWriter)(ref val2)).WriteValueSafe<bool>(ref flag2, default(ForPrimitives)); if (flag2) { ((FastBufferWriter)(ref val2)).WriteValueSafe<byte>(audioData, default(ForPrimitives)); } ((NetworkBehaviour)this).__endSendClientRpc(ref val2, 2736638642u, val, (RpcDelivery)0); } if ((int)base.__rpc_exec_stage != 2 || (!networkManager.IsClient && !networkManager.IsHost)) { return; } if (!networkedAudioClips.ContainsKey(clipName)) { AudioClip val3 = null; if (SoundTool.clipTypes.ContainsKey(clipName)) { if (SoundTool.clipTypes[clipName] == SoundTool.AudioType.ogg) { val3 = OggUtility.ByteArrayToAudioClip(audioData, clipName); } else if (SoundTool.clipTypes[clipName] == SoundTool.AudioType.mp3) { val3 = Mp3Utility.ByteArrayToAudioClip(audioData, clipName); } } if ((Object)(object)val3 == (Object)null) { val3 = WavUtility.ByteArrayToAudioClip(audioData, clipName); } networkedAudioClips.Add(clipName, val3); NetworkHandler.ClientNetworkedAudioChanged?.Invoke(); } else { SoundTool.Instance.logger.LogDebug((object)("Sound " + clipName + " already exists for this client! Skipping addition of this sound for this client.")); } } [ClientRpc] public void RemoveAudioClipClientRpc(string clipName) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Invalid comparison between Unknown and I4 //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Invalid comparison between Unknown and I4 //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008e: 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) NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager; if (networkManager == null || !networkManager.IsListening) { return; } if ((int)base.__rpc_exec_stage != 2 && (networkManager.IsServer || networkManager.IsHost)) { ClientRpcParams val = default(ClientRpcParams); FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendClientRpc(1355469546u, val, (RpcDelivery)0); bool flag = clipName != null; ((FastBufferWriter)(ref val2)).WriteValueSafe<bool>(ref flag, default(ForPrimitives)); if (flag) { ((FastBufferWriter)(ref val2)).WriteValueSafe(clipName, false); } ((NetworkBehaviour)this).__endSendClientRpc(ref val2, 1355469546u, val, (RpcDelivery)0); } if ((int)base.__rpc_exec_stage == 2 && (networkManager.IsClient || networkManager.IsHost) && networkedAudioClips.ContainsKey(clipName)) { networkedAudioClips.Remove(clipName); NetworkHandler.ClientNetworkedAudioChanged?.Invoke(); } } [ClientRpc] public void SyncAudioClipsClientRpc(Strings clipNames) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Invalid comparison between Unknown and I4 //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Invalid comparison between Unknown and I4 //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager; if (networkManager == null || !networkManager.IsListening) { return; } if ((int)base.__rpc_exec_stage != 2 && (networkManager.IsServer || networkManager.IsHost)) { ClientRpcParams val = default(ClientRpcParams); FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendClientRpc(3300200130u, val, (RpcDelivery)0); ((FastBufferWriter)(ref val2)).WriteValueSafe<Strings>(ref clipNames, default(ForNetworkSerializable)); ((NetworkBehaviour)this).__endSendClientRpc(ref val2, 3300200130u, val, (RpcDelivery)0); } if ((int)base.__rpc_exec_stage != 2 || (!networkManager.IsClient && !networkManager.IsHost)) { return; } string[] myStrings = clipNames.MyStrings; for (int i = 0; i < myStrings.Length; i++) { if (!networkedAudioClips.ContainsKey(myStrings[i])) { SendExistingAudioClipServerRpc(myStrings[i]); } } } [ClientRpc] public void ReceiveSeedClientRpc(int seed) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Invalid comparison between Unknown and I4 //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Invalid comparison between Unknown and I4 //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: 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) //IL_0089: Unknown result type (might be due to invalid IL or missing references) NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager; if (networkManager != null && networkManager.IsListening) { if ((int)base.__rpc_exec_stage != 2 && (networkManager.IsServer || networkManager.IsHost)) { ClientRpcParams val = default(ClientRpcParams); FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendClientRpc(1556253924u, val, (RpcDelivery)0); BytePacker.WriteValueBitPacked(val2, seed); ((NetworkBehaviour)this).__endSendClientRpc(ref val2, 1556253924u, val, (RpcDelivery)0); } if ((int)base.__rpc_exec_stage == 2 && (networkManager.IsClient || networkManager.IsHost)) { Random.InitState(seed); SoundTool.Instance.logger.LogDebug((object)$"Client received a new Unity Random seed of {seed}!"); } } } [ServerRpc(RequireOwnership = false)] public void SendAudioClipServerRpc(string clipName, byte[] audioData) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Invalid comparison between Unknown and I4 //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Invalid comparison between Unknown and I4 //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008e: 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_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager; if (networkManager == null || !networkManager.IsListening) { return; } if ((int)base.__rpc_exec_stage != 1 && (networkManager.IsClient || networkManager.IsHost)) { ServerRpcParams val = default(ServerRpcParams); FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendServerRpc(867452943u, val, (RpcDelivery)0); bool flag = clipName != null; ((FastBufferWriter)(ref val2)).WriteValueSafe<bool>(ref flag, default(ForPrimitives)); if (flag) { ((FastBufferWriter)(ref val2)).WriteValueSafe(clipName, false); } bool flag2 = audioData != null; ((FastBufferWriter)(ref val2)).WriteValueSafe<bool>(ref flag2, default(ForPrimitives)); if (flag2) { ((FastBufferWriter)(ref val2)).WriteValueSafe<byte>(audioData, default(ForPrimitives)); } ((NetworkBehaviour)this).__endSendServerRpc(ref val2, 867452943u, val, (RpcDelivery)0); } if ((int)base.__rpc_exec_stage == 1 && (networkManager.IsServer || networkManager.IsHost)) { ReceiveAudioClipClientRpc(clipName, audioData); NetworkHandler.HostNetworkedAudioChanged?.Invoke(); } } [ServerRpc(RequireOwnership = false)] public void RemoveAudioClipServerRpc(string clipName) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Invalid comparison between Unknown and I4 //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Invalid comparison between Unknown and I4 //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008e: 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) NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager; if (networkManager == null || !networkManager.IsListening) { return; } if ((int)base.__rpc_exec_stage != 1 && (networkManager.IsClient || networkManager.IsHost)) { ServerRpcParams val = default(ServerRpcParams); FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendServerRpc(3103497155u, val, (RpcDelivery)0); bool flag = clipName != null; ((FastBufferWriter)(ref val2)).WriteValueSafe<bool>(ref flag, default(ForPrimitives)); if (flag) { ((FastBufferWriter)(ref val2)).WriteValueSafe(clipName, false); } ((Ne
Plugins/no00ob-LCSoundTool/LC_SoundTool.dll
Decompiled 9 months ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.CodeDom.Compiler; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Globalization; 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 BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using LCSoundTool.Networking; using LCSoundTool.Patches; using LCSoundTool.Resources; using LCSoundTool.Utilities; using LCSoundToolMod.Properties; using Microsoft.CodeAnalysis; using Unity.Netcode; using UnityEngine; using UnityEngine.Networking; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("LC_SoundTool")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyDescription("Various audio related functions. Mainly logs all sounds that are playing and what type of playback they're into the BepInEx console.")] [assembly: AssemblyFileVersion("1.5.0.0")] [assembly: AssemblyInformationalVersion("1.5.0")] [assembly: AssemblyProduct("LC_SoundTool")] [assembly: AssemblyTitle("LC_SoundTool")] [assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/no00ob/LCSoundTool")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.5.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] internal class <Module> { static <Module>() { } } 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 LCSoundToolMod { public static class PluginInfo { public const string PLUGIN_GUID = "LC_SoundTool"; public const string PLUGIN_NAME = "LC_SoundTool"; public const string PLUGIN_VERSION = "1.5.0"; } } namespace LCSoundToolMod.Properties { [GeneratedCode("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] [DebuggerNonUserCode] [CompilerGenerated] internal class Resources { private static ResourceManager resourceMan; private static CultureInfo resourceCulture; [EditorBrowsable(EditorBrowsableState.Advanced)] internal static ResourceManager ResourceManager { get { if (resourceMan == null) { ResourceManager resourceManager = new ResourceManager("LCSoundToolMod.Properties.Resources", typeof(Resources).Assembly); resourceMan = resourceManager; } return resourceMan; } } [EditorBrowsable(EditorBrowsableState.Advanced)] internal static CultureInfo Culture { get { return resourceCulture; } set { resourceCulture = value; } } internal static byte[] soundtool { get { object @object = ResourceManager.GetObject("soundtool", resourceCulture); return (byte[])@object; } } internal Resources() { } } } namespace LCSoundTool { public class AudioSourceExtension : MonoBehaviour { public AudioSource audioSource; public bool playOnAwake = false; public bool loop = false; private bool updateHasBeenLogged = false; private bool hasPlayed = false; private void OnEnable() { if (!((Object)(object)audioSource == (Object)null) && !audioSource.isPlaying) { if (playOnAwake) { audioSource.Play(); } if (SoundTool.infoDebugging) { SoundTool.Instance.logger.LogDebug((object)$"(AudioSourceExtension) Started playback of {audioSource} with clip {audioSource.clip} in OnEnable function!"); } updateHasBeenLogged = false; hasPlayed = false; } } private void OnDisable() { if (!((Object)(object)audioSource == (Object)null) && audioSource.isPlaying) { if (playOnAwake) { audioSource.Stop(); } if (SoundTool.infoDebugging) { SoundTool.Instance.logger.LogDebug((object)$"(AudioSourceExtension) Stopped playback of {audioSource} with clip {audioSource.clip} in OnDisable function!"); } updateHasBeenLogged = false; hasPlayed = false; } } private void Update() { if ((Object)(object)audioSource == (Object)null) { return; } if ((Object)(object)audioSource.clip == (Object)null) { hasPlayed = false; } if (audioSource.isPlaying) { updateHasBeenLogged = false; } else if (!((Behaviour)audioSource).isActiveAndEnabled) { hasPlayed = false; } else { if (!playOnAwake) { return; } if ((Object)(object)audioSource.clip != (Object)null && !hasPlayed) { audioSource.Play(); if (SoundTool.infoDebugging) { SoundTool.Instance.logger.LogDebug((object)$"(AudioSourceExtension) Started playback of {audioSource} with clip {audioSource.clip} in Update function!"); } updateHasBeenLogged = false; hasPlayed = true; } else if (!updateHasBeenLogged) { updateHasBeenLogged = true; if (SoundTool.infoDebugging) { SoundTool.Instance.logger.LogDebug((object)$"(AudioSourceExtension) Can not start playback of {audioSource} with missing clip in Update function!"); } } } } } public class RandomAudioClip { public AudioClip clip; [Range(0f, 1f)] public float chance = 1f; public RandomAudioClip(AudioClip clip, float chance) { this.clip = clip; this.chance = chance; } } public class ReplacementAudioClip { public List<RandomAudioClip> clips; public string source = string.Empty; public bool canPlay = true; private bool initialized = false; public ReplacementAudioClip(AudioClip clip, float chance, string source) { if (!initialized) { Initialize(); } RandomAudioClip randomAudioClip = new RandomAudioClip(clip, chance); if (!clips.ContainsThisRandomAudioClip(randomAudioClip)) { clips.Add(randomAudioClip); this.source = source; } else if (SoundTool.infoDebugging) { SoundTool.Instance.logger.LogDebug((object)$"RandomAudioClip {randomAudioClip.clip.GetName()} ({Mathf.RoundToInt(chance * 100f)}%) already exists withing this AudioClipContainer!"); SoundTool.Instance.logger.LogDebug((object)"- This AudioClipContainer contains the following clip(s):"); for (int i = 0; i < clips.Count; i++) { SoundTool.Instance.logger.LogDebug((object)$"-- Clip {i + 1} - {clips[i].clip.GetName()} with a chance of {Mathf.RoundToInt(clips[i].chance * 100f)}"); } } } public ReplacementAudioClip(string source) { Initialize(); this.source = source; } public ReplacementAudioClip() { Initialize(); source = string.Empty; } public void AddClip(AudioClip clip, float chance) { if (!initialized) { Initialize(); } RandomAudioClip randomAudioClip = new RandomAudioClip(clip, chance); if (!clips.ContainsThisRandomAudioClip(randomAudioClip)) { clips.Add(randomAudioClip); } else if (SoundTool.infoDebugging) { SoundTool.Instance.logger.LogDebug((object)$"RandomAudioClip {randomAudioClip.clip.GetName()} ({Mathf.RoundToInt(chance * 100f)}%) already exists withing this AudioClipContainer!"); SoundTool.Instance.logger.LogDebug((object)"- This AudioClipContainer contains the following clip(s):"); for (int i = 0; i < clips.Count; i++) { SoundTool.Instance.logger.LogDebug((object)$"-- Clip {i + 1} - {clips[i].clip.GetName()} with a chance of {Mathf.RoundToInt(clips[i].chance * 100f)}"); } } } public bool Full() { if (!initialized) { Initialize(); } float num = 0f; for (int i = 0; i < clips.Count; i++) { num += clips[i].chance; } return num >= 1f; } public bool ContainsClip(AudioClip clip, float chance) { if (!initialized) { Initialize(); } RandomAudioClip thisClip = new RandomAudioClip(clip, chance); return clips.ContainsThisRandomAudioClip(thisClip); } private void Initialize() { clips = new List<RandomAudioClip>(); initialized = true; } } [BepInPlugin("LCSoundTool", "LC Sound Tool", "1.5.0")] public class SoundTool : BaseUnityPlugin { public enum AudioType { wav, ogg, mp3 } private const string PLUGIN_GUID = "LCSoundTool"; private const string PLUGIN_NAME = "LC Sound Tool"; private ConfigEntry<bool> configUseNetworking; private ConfigEntry<bool> configSyncRandomSeed; private ConfigEntry<float> configPlayOnAwakePatchRepeatDelay; private ConfigEntry<bool> configPrintInfoByDefault; private readonly Harmony harmony = new Harmony("LCSoundTool"); public static SoundTool Instance; internal ManualLogSource logger; public KeyboardShortcut toggleAudioSourceDebugLog; public KeyboardShortcut toggleIndepthDebugLog; public KeyboardShortcut toggleInformationalDebugLog; public KeyboardShortcut printAllSoundsDebugLog; public bool wasKeyDown; public bool wasKeyDown2; public bool wasKeyDown3; public bool wasKeyDown4; public static bool debugAudioSources; public static bool indepthDebugging; public static bool infoDebugging; public static bool networkingInitialized { get; private set; } public static bool networkingAvailable { get; private set; } public static Dictionary<string, ReplacementAudioClip> replacedClips { get; private set; } public static Dictionary<string, AudioClip> networkedClips => NetworkHandler.networkedAudioClips; public static Dictionary<string, AudioType> clipTypes { get; private set; } public static event Action ClientNetworkedAudioChanged { add { NetworkHandler.ClientNetworkedAudioChanged += value; } remove { NetworkHandler.ClientNetworkedAudioChanged -= value; } } public static event Action HostNetworkedAudioChanged { add { NetworkHandler.HostNetworkedAudioChanged += value; } remove { NetworkHandler.HostNetworkedAudioChanged -= value; } } public static bool IsDebuggingOn() { if (debugAudioSources || indepthDebugging || infoDebugging) { return true; } return false; } private void Awake() { //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0154: 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_0172: Unknown result type (might be due to invalid IL or missing references) //IL_018b: Unknown result type (might be due to invalid IL or missing references) //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_01a9: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Unknown result type (might be due to invalid IL or missing references) networkingAvailable = true; if ((Object)(object)Instance == (Object)null) { Instance = this; } configUseNetworking = ((BaseUnityPlugin)this).Config.Bind<bool>("Experimental", "EnableNetworking", false, "Whether or not to use the networking built into this plugin. If set to true everyone in the lobby needs LCSoundTool installed and networking enabled to join."); configSyncRandomSeed = ((BaseUnityPlugin)this).Config.Bind<bool>("Experimental", "SyncUnityRandomSeed", false, "Whether or not to sync the default Unity randomization seed with all clients. For this feature, networking has to be set to true. Will send the UnityEngine.Random.seed from the host to all clients automatically upon loading a networked scene."); configPlayOnAwakePatchRepeatDelay = ((BaseUnityPlugin)this).Config.Bind<float>("Experimental", "NewPlayOnAwakePatchRepeatDelay", 90f, "How long to wait between checks for new playOnAwake AudioSources. Runs the same patching that is done when each scene is loaded with this delay between each run. DO NOT set too low or high. Anything below 10 or above 600 can cause issues. This time is in seconds. Set to 0 to disable rerunning the patch, but be warned that this might break runtime initialized playOnAwake AudioSources."); configPrintInfoByDefault = ((BaseUnityPlugin)this).Config.Bind<bool>("Logging", "PrintInfoByDefault", false, "Whether or not to print additional information logs created by this mod by default. If set to false, informational logs may be toggled on any time with LeftAlt + F5."); Type[] types = Assembly.GetExecutingAssembly().GetTypes(); Type[] array = types; foreach (Type type in array) { MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic); MethodInfo[] array2 = methods; foreach (MethodInfo methodInfo in array2) { object[] customAttributes = methodInfo.GetCustomAttributes(typeof(RuntimeInitializeOnLoadMethodAttribute), inherit: false); if (customAttributes.Length != 0) { methodInfo.Invoke(null, null); } } } logger = Logger.CreateLogSource("LCSoundTool"); logger.LogInfo((object)"Plugin LCSoundTool is loaded!"); toggleAudioSourceDebugLog = new KeyboardShortcut((KeyCode)286, (KeyCode[])(object)new KeyCode[0]); toggleIndepthDebugLog = new KeyboardShortcut((KeyCode)286, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }); toggleInformationalDebugLog = new KeyboardShortcut((KeyCode)286, (KeyCode[])(object)new KeyCode[1] { (KeyCode)306 }); printAllSoundsDebugLog = new KeyboardShortcut((KeyCode)286, (KeyCode[])(object)new KeyCode[1] { (KeyCode)304 }); debugAudioSources = false; indepthDebugging = false; if (configPrintInfoByDefault.Value) { infoDebugging = true; } else { infoDebugging = false; } replacedClips = new Dictionary<string, ReplacementAudioClip>(); clipTypes = new Dictionary<string, AudioType>(); } private void Start() { if (!configUseNetworking.Value) { networkingAvailable = false; Instance.logger.LogWarning((object)"Networking disabled. Mod in fully client side mode, but no networked actions can take place! You can safely ignore this if you want the mod to run fully client side."); } else { networkingAvailable = true; } if (configUseNetworking.Value) { logger.LogDebug((object)"Loading SoundTool AssetBundle..."); Assets.bundle = AssetBundle.LoadFromMemory(LCSoundToolMod.Properties.Resources.soundtool); if ((Object)(object)Assets.bundle == (Object)null) { logger.LogError((object)"Failed to load SoundTool AssetBundle!"); } else { logger.LogDebug((object)"Finished loading SoundTool AssetBundle!"); } } harmony.PatchAll(typeof(AudioSourcePatch)); if (configUseNetworking.Value) { harmony.PatchAll(typeof(GameNetworkManagerPatch)); harmony.PatchAll(typeof(StartOfRoundPatch)); } SceneManager.sceneLoaded += OnSceneLoaded; } private void Update() { if (configUseNetworking.Value) { if (!networkingInitialized) { if ((Object)(object)NetworkHandler.Instance != (Object)null) { networkingInitialized = true; } } else if ((Object)(object)NetworkHandler.Instance == (Object)null) { networkingInitialized = false; } } else { networkingInitialized = false; } if (((KeyboardShortcut)(ref printAllSoundsDebugLog)).IsDown() && !wasKeyDown4) { wasKeyDown4 = true; } if (((KeyboardShortcut)(ref printAllSoundsDebugLog)).IsUp() && wasKeyDown4) { wasKeyDown4 = false; Instance.logger.LogDebug((object)"Printing all currently replaced sounds..."); Instance.logger.LogDebug((object)" "); string[] array = replacedClips.Keys.ToArray(); for (int i = 0; i < replacedClips.Count; i++) { ReplacementAudioClip replacementAudioClip = replacedClips[array[i]]; Instance.logger.LogDebug((object)$"Clip named {array[i]} with {replacementAudioClip.clips.Count} replacement clip(s)"); Instance.logger.LogDebug((object)$"- Clip can play? {replacementAudioClip.canPlay}"); Instance.logger.LogDebug((object)("- Clip audio source(s)? " + replacementAudioClip.source)); Instance.logger.LogDebug((object)$"- All {replacementAudioClip.clips.Count} clip(s):"); for (int j = 0; j < replacementAudioClip.clips.Count; j++) { Instance.logger.LogDebug((object)$"-- Clip {j + 1} - {replacementAudioClip.clips[j].clip.GetName()} with chance of {Mathf.RoundToInt(replacementAudioClip.clips[j].chance * 100f)}%"); } } Instance.logger.LogDebug((object)" "); Instance.logger.LogDebug((object)"Finished printing all currently replaced sounds!"); } if (((KeyboardShortcut)(ref toggleInformationalDebugLog)).IsDown() && !wasKeyDown3) { wasKeyDown3 = true; wasKeyDown2 = false; wasKeyDown = false; } if (((KeyboardShortcut)(ref toggleInformationalDebugLog)).IsUp() && wasKeyDown3) { wasKeyDown3 = false; wasKeyDown2 = false; wasKeyDown = false; infoDebugging = !infoDebugging; Instance.logger.LogDebug((object)$"Toggling informational debug logs {infoDebugging}!"); return; } if (((KeyboardShortcut)(ref toggleIndepthDebugLog)).IsDown() && !wasKeyDown2) { wasKeyDown2 = true; wasKeyDown = false; } if (((KeyboardShortcut)(ref toggleIndepthDebugLog)).IsUp() && wasKeyDown2) { wasKeyDown2 = false; wasKeyDown = false; debugAudioSources = !debugAudioSources; indepthDebugging = debugAudioSources; infoDebugging = debugAudioSources; Instance.logger.LogDebug((object)$"Toggling in-depth AudioSource debug logs {debugAudioSources}!"); return; } if (!wasKeyDown2 && !((KeyboardShortcut)(ref toggleIndepthDebugLog)).IsDown() && ((KeyboardShortcut)(ref toggleAudioSourceDebugLog)).IsDown() && !wasKeyDown) { wasKeyDown = true; wasKeyDown2 = false; } if (((KeyboardShortcut)(ref toggleAudioSourceDebugLog)).IsUp() && wasKeyDown) { wasKeyDown = false; wasKeyDown2 = false; debugAudioSources = !debugAudioSources; if (indepthDebugging && !debugAudioSources) { indepthDebugging = false; } Instance.logger.LogDebug((object)$"Toggling AudioSource debug logs {debugAudioSources}!"); } } private void OnDestroy() { SceneManager.sceneLoaded -= OnSceneLoaded; } private void OnSceneLoaded(Scene scene, LoadSceneMode mode) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)Instance == (Object)null)) { PatchPlayOnAwakeAudio(scene); OnSceneLoadedNetworking(); if (((Scene)(ref scene)).name.ToLower().Contains("level")) { ((MonoBehaviour)this).StopAllCoroutines(); ((MonoBehaviour)this).StartCoroutine(PatchPlayOnAwakeDelayed(scene, 1f)); } } } private IEnumerator PatchPlayOnAwakeDelayed(Scene scene, float wait) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) if (infoDebugging) { logger.LogDebug((object)$"Started playOnAwake patch coroutine with delay of {wait} seconds"); } yield return (object)new WaitForSecondsRealtime(wait); if (infoDebugging) { logger.LogDebug((object)"Running playOnAwake patch coroutine!"); } PatchPlayOnAwakeAudio(scene); float repeatWait = configPlayOnAwakePatchRepeatDelay.Value; if (repeatWait != 0f) { if (repeatWait < 10f) { repeatWait = 10f; } if (repeatWait > 600f) { repeatWait = 600f; } ((MonoBehaviour)this).StartCoroutine(PatchPlayOnAwakeDelayed(scene, repeatWait)); } } private void PatchPlayOnAwakeAudio(Scene scene) { if (infoDebugging) { Instance.logger.LogDebug((object)("Grabbing all playOnAwake AudioSources for loaded scene " + ((Scene)(ref scene)).name)); } AudioSource[] allPlayOnAwakeAudioSources = GetAllPlayOnAwakeAudioSources(); if (infoDebugging) { Instance.logger.LogDebug((object)$"Found a total of {allPlayOnAwakeAudioSources.Length} playOnAwake AudioSource(s)!"); Instance.logger.LogDebug((object)$"Starting setup on {allPlayOnAwakeAudioSources.Length} playOnAwake AudioSource(s)..."); } AudioSource[] array = allPlayOnAwakeAudioSources; AudioSourceExtension audioSourceExtension = default(AudioSourceExtension); foreach (AudioSource val in array) { val.Stop(); if (((Component)((Component)val).transform).TryGetComponent<AudioSourceExtension>(ref audioSourceExtension)) { audioSourceExtension.audioSource = val; audioSourceExtension.playOnAwake = true; audioSourceExtension.loop = val.loop; val.playOnAwake = false; if (infoDebugging) { Instance.logger.LogDebug((object)$"-Set- {Array.IndexOf(allPlayOnAwakeAudioSources, val) + 1} {val} done!"); } continue; } AudioSourceExtension audioSourceExtension2 = ((Component)val).gameObject.AddComponent<AudioSourceExtension>(); audioSourceExtension2.audioSource = val; audioSourceExtension2.playOnAwake = true; audioSourceExtension2.loop = val.loop; val.playOnAwake = false; if (infoDebugging) { Instance.logger.LogDebug((object)$"-Add- {Array.IndexOf(allPlayOnAwakeAudioSources, val) + 1} {val} done!"); } } if (infoDebugging) { Instance.logger.LogDebug((object)$"Done setting up {allPlayOnAwakeAudioSources.Length} playOnAwake AudioSources!"); } } private void OnSceneLoadedNetworking() { if (networkingAvailable && networkingInitialized && configSyncRandomSeed.Value) { int num = (int)DateTime.Now.Ticks; Random.InitState(num); SendUnityRandomSeed(num); } } public AudioSource[] GetAllPlayOnAwakeAudioSources() { AudioSource[] array = Object.FindObjectsOfType<AudioSource>(true); List<AudioSource> list = new List<AudioSource>(); for (int i = 0; i < array.Length; i++) { if (array[i].playOnAwake) { list.Add(array[i]); } } return list.ToArray(); } public static void ReplaceAudioClip(string originalName, AudioClip newClip) { if (string.IsNullOrEmpty(originalName)) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to replace an audio clip without original clip specified! This is not allowed."); return; } if ((Object)(object)newClip == (Object)null) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to replace an audio clip without new clip specified! This is not allowed."); return; } string text = originalName; string name = newClip.GetName(); string text2 = string.Empty; float num = 100f; if (name.Contains("-")) { string[] array = name.Split('-'); if (array.Length > 1) { if (array.Length > 2) { string text3 = array[^2]; if (!string.IsNullOrEmpty(text3) && text3.StartsWith("_")) { text2 = text3.Substring(1); } } string text4 = array[^1]; if (int.TryParse(text4, out var result)) { num = (float)result * 0.01f; } else if (!string.IsNullOrEmpty(text4) && text4.StartsWith("_")) { text2 = text4.Substring(1); } name = string.Join("-", array, 0, array.Length - 1); } else if (infoDebugging) { Instance.logger.LogDebug((object)("Clip " + name + " does not contain a '-' character for source name or chance")); } } if (!string.IsNullOrEmpty(text2)) { text = originalName + "#" + text2; } if (replacedClips.ContainsKey(text) && num >= 100f) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to replace an audio clip that already has been replaced with new clip that has 100% chance of playback! This is not allowed."); return; } num = Mathf.Clamp01(num); if (replacedClips.ContainsKey(text)) { replacedClips[text].AddClip(newClip, num); } else { replacedClips.Add(text, new ReplacementAudioClip(newClip, num, text2)); } float num2 = 0f; for (int i = 0; i < replacedClips[text].clips.Count(); i++) { num2 += replacedClips[text].clips[i].chance; } int num3 = Mathf.RoundToInt(num2 * 100f); if ((num3 < 100 || num3 > 100) && replacedClips[text].clips.Count() > 1) { if (infoDebugging) { Instance.logger.LogDebug((object)$"The current total combined chance for replaced {replacedClips[text].clips.Count()} random audio clips for audio clip {text} does not equal 100%. Currently {num3}% (at least yet?)"); } } else if (num3 == 100 && replacedClips[text].clips.Count() > 1 && infoDebugging) { Instance.logger.LogDebug((object)$"The current total combined chance for replaced {replacedClips[text].clips.Count()} random audio clips for audio clip {text} is equal to 100%"); } } public static void ReplaceAudioClip(AudioClip originalClip, AudioClip newClip) { if ((Object)(object)originalClip == (Object)null) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to replace an audio clip without original clip specified! This is not allowed."); } else if ((Object)(object)newClip == (Object)null) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to replace an audio clip without new clip specified! This is not allowed."); } else { ReplaceAudioClip(originalClip.GetName(), newClip); } } public static void ReplaceAudioClip(string originalName, AudioClip newClip, float chance) { if (string.IsNullOrEmpty(originalName)) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to replace an audio clip without original clip specified! This is not allowed."); return; } if ((Object)(object)newClip == (Object)null) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to replace an audio clip without new clip specified! This is not allowed."); return; } string text = originalName; string name = newClip.GetName(); string text2 = string.Empty; if (name.Contains("-")) { string[] array = name.Split('-'); if (array.Length > 1) { if (array.Length > 2) { string text3 = array[^2]; if (!string.IsNullOrEmpty(text3) && text3.StartsWith("_")) { text2 = text3.Substring(1); } } string text4 = array[^1]; if (int.TryParse(text4, out var result)) { Instance.logger.LogDebug((object)$"Clip {name} contains random chance specified in it's name ({result}%) but you're using the manually function to assign it's chance. ({Mathf.RoundToInt(chance * 100f)}%) The file name will be ignored."); } else if (!string.IsNullOrEmpty(text4) && text4.StartsWith("_")) { text2 = text4.Substring(1); } name = string.Join("-", array, 0, array.Length - 1); } else if (infoDebugging) { Instance.logger.LogDebug((object)("Clip " + name + " does not contain a '-' character for source name or chance")); } } if (!string.IsNullOrEmpty(text2)) { text = originalName + "#" + text2; } if (replacedClips.ContainsKey(text) && chance >= 100f) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to replace an audio clip that already has been replaced with new clip that has 100% chance of playback! This is not allowed."); return; } chance = Mathf.Clamp01(chance); if (replacedClips.ContainsKey(text)) { replacedClips[text].AddClip(newClip, chance); } else { replacedClips.Add(text, new ReplacementAudioClip(newClip, chance, text2)); } float num = 0f; for (int i = 0; i < replacedClips[text].clips.Count(); i++) { num += replacedClips[text].clips[i].chance; } int num2 = Mathf.RoundToInt(num * 100f); if ((num2 < 100 || num2 > 100) && replacedClips[text].clips.Count() > 1) { Instance.logger.LogDebug((object)$"The current total combined chance for replaced {replacedClips[text].clips.Count()} random audio clips for audio clip {text} does not equal 100% (at least yet?)"); } else if (num2 == 100 && replacedClips[text].clips.Count() > 1) { Instance.logger.LogDebug((object)$"The current total combined chance for replaced {replacedClips[text].clips.Count()} random audio clips for audio clip {text} is equal to 100%"); } } public static void ReplaceAudioClip(AudioClip originalClip, AudioClip newClip, float chance) { if ((Object)(object)originalClip == (Object)null) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to replace an audio clip without original clip specified! This is not allowed."); } else if ((Object)(object)newClip == (Object)null) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to replace an audio clip without new clip specified! This is not allowed."); } else { ReplaceAudioClip(originalClip.GetName(), newClip, chance); } } public static void ReplaceAudioClip(string originalName, AudioClip newClip, string source) { if (string.IsNullOrEmpty(originalName)) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to replace an audio clip without original clip specified! This is not allowed."); return; } if ((Object)(object)newClip == (Object)null) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to replace an audio clip without new clip specified! This is not allowed."); return; } if (string.IsNullOrEmpty(source)) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to replace an audio clip without allowed audio source specified! This is not allowed."); return; } string text = originalName; string name = newClip.GetName(); float num = 100f; if (name.Contains("-")) { string[] array = name.Split('-'); if (array.Length > 1) { if (array.Length > 2) { string text2 = array[^2]; if (!string.IsNullOrEmpty(text2) && text2.StartsWith("_")) { Instance.logger.LogDebug((object)("Clip " + name + " contains source specified in it's name (" + text2.Substring(1) + ") but you're using the manual function to assign it's source. (" + source + ") The file name will be ignored.")); } } string text3 = array[^1]; if (int.TryParse(text3, out var result)) { num = (float)result * 0.01f; } else if (!string.IsNullOrEmpty(text3) && text3.StartsWith("_")) { Instance.logger.LogDebug((object)("Clip " + name + " contains source specified in it's name (" + text3.Substring(1) + ") but you're using the manual function to assign it's source. (" + source + ") The file name will be ignored.")); } name = string.Join("-", array, 0, array.Length - 1); } else if (infoDebugging) { Instance.logger.LogDebug((object)("Clip " + name + " does not contain a '-' character for source name or chance")); } } if (!string.IsNullOrEmpty(source)) { text = originalName + "#" + source; } if (replacedClips.ContainsKey(text) && num >= 100f) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to replace an audio clip that already has been replaced with new clip that has 100% chance of playback! This is not allowed."); return; } num = Mathf.Clamp01(num); if (replacedClips.ContainsKey(text)) { replacedClips[text].AddClip(newClip, num); } else { replacedClips.Add(text, new ReplacementAudioClip(newClip, num, source)); } float num2 = 0f; for (int i = 0; i < replacedClips[text].clips.Count(); i++) { num2 += replacedClips[text].clips[i].chance; } int num3 = Mathf.RoundToInt(num2 * 100f); if ((num3 < 100 || num3 > 100) && replacedClips[text].clips.Count() > 1) { if (infoDebugging) { Instance.logger.LogDebug((object)$"The current total combined chance for replaced {replacedClips[text].clips.Count()} random audio clips for audio clip {text} does not equal 100%. Currently {num3}% (at least yet?)"); } } else if (num3 == 100 && replacedClips[text].clips.Count() > 1 && infoDebugging) { Instance.logger.LogDebug((object)$"The current total combined chance for replaced {replacedClips[text].clips.Count()} random audio clips for audio clip {text} is equal to 100%"); } } public static void ReplaceAudioClip(AudioClip originalClip, AudioClip newClip, string source) { if ((Object)(object)originalClip == (Object)null) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to replace an audio clip without original clip specified! This is not allowed."); } else if ((Object)(object)newClip == (Object)null) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to replace an audio clip without new clip specified! This is not allowed."); } else { ReplaceAudioClip(originalClip.GetName(), newClip, source); } } public static void ReplaceAudioClip(string originalName, AudioClip newClip, string[] source) { string text = string.Empty; if (source != null && source.Length != 0) { for (int i = 0; i < source.Length; i++) { if (!string.IsNullOrEmpty(source[i])) { text = text + "," + source[i]; } } } if (string.IsNullOrEmpty(originalName)) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to replace an audio clip without original clip specified! This is not allowed."); return; } if ((Object)(object)newClip == (Object)null) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to replace an audio clip without new clip specified! This is not allowed."); return; } if (string.IsNullOrEmpty(text)) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to replace an audio clip without allowed audio source specified! This is not allowed."); return; } string text2 = originalName; string name = newClip.GetName(); float num = 100f; if (name.Contains("-")) { string[] array = name.Split('-'); if (array.Length > 1) { if (array.Length > 2) { string text3 = array[^2]; if (!string.IsNullOrEmpty(text3) && text3.StartsWith("_")) { Instance.logger.LogDebug((object)("Clip " + name + " contains source specified in it's name (" + text3.Substring(1) + ") but you're using the manual function to assign it's source. (" + text + ") The file name will be ignored.")); } } string text4 = array[^1]; if (int.TryParse(text4, out var result)) { num = (float)result * 0.01f; } else if (!string.IsNullOrEmpty(text4) && text4.StartsWith("_")) { Instance.logger.LogDebug((object)("Clip " + name + " contains source specified in it's name (" + text4.Substring(1) + ") but you're using the manual function to assign it's source. (" + text + ") The file name will be ignored.")); } name = string.Join("-", array, 0, array.Length - 1); } else if (infoDebugging) { Instance.logger.LogDebug((object)("Clip " + name + " does not contain a '-' character for source name or chance")); } } if (!string.IsNullOrEmpty(text)) { text2 = originalName + "#" + text; } if (replacedClips.ContainsKey(text2) && num >= 100f) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to replace an audio clip that already has been replaced with new clip that has 100% chance of playback! This is not allowed."); return; } num = Mathf.Clamp01(num); if (replacedClips.ContainsKey(text2)) { replacedClips[text2].AddClip(newClip, num); } else { replacedClips.Add(text2, new ReplacementAudioClip(newClip, num, text)); } float num2 = 0f; for (int j = 0; j < replacedClips[text2].clips.Count(); j++) { num2 += replacedClips[text2].clips[j].chance; } int num3 = Mathf.RoundToInt(num2 * 100f); if ((num3 < 100 || num3 > 100) && replacedClips[text2].clips.Count() > 1) { if (infoDebugging) { Instance.logger.LogDebug((object)$"The current total combined chance for replaced {replacedClips[text2].clips.Count()} random audio clips for audio clip {text2} does not equal 100%. Currently {num3}% (at least yet?)"); } } else if (num3 == 100 && replacedClips[text2].clips.Count() > 1 && infoDebugging) { Instance.logger.LogDebug((object)$"The current total combined chance for replaced {replacedClips[text2].clips.Count()} random audio clips for audio clip {text2} is equal to 100%"); } } public static void ReplaceAudioClip(AudioClip originalClip, AudioClip newClip, string[] source) { if ((Object)(object)originalClip == (Object)null) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to replace an audio clip without original clip specified! This is not allowed."); } else if ((Object)(object)newClip == (Object)null) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to replace an audio clip without new clip specified! This is not allowed."); } else { ReplaceAudioClip(originalClip.GetName(), newClip, source); } } public static void ReplaceAudioClip(string originalName, AudioClip newClip, float chance, string source) { if (string.IsNullOrEmpty(originalName)) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to replace an audio clip without original clip specified! This is not allowed."); return; } if ((Object)(object)newClip == (Object)null) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to replace an audio clip without new clip specified! This is not allowed."); return; } if (string.IsNullOrEmpty(source)) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to replace an audio clip without allowed audio source specified! This is not allowed."); return; } string text = originalName; string name = newClip.GetName(); if (name.Contains("-")) { string[] array = name.Split('-'); if (array.Length > 1) { if (array.Length > 2) { string text2 = array[^2]; if (!string.IsNullOrEmpty(text2) && text2.StartsWith("_")) { Instance.logger.LogDebug((object)("Clip " + name + " contains source specified in it's name (" + text2.Substring(1) + ") but you're using the manual function to assign it's source. (" + source + ") The file name will be ignored.")); } } string text3 = array[^1]; if (int.TryParse(text3, out var result)) { Instance.logger.LogDebug((object)$"Clip {name} contains random chance specified in it's name ({result}%) but you're using the manual function to assign it's chance. ({Mathf.RoundToInt(chance * 100f)}%) The file name will be ignored."); } else if (!string.IsNullOrEmpty(text3) && text3.StartsWith("_")) { Instance.logger.LogDebug((object)("Clip " + name + " contains source specified in it's name (" + text3.Substring(1) + ") but you're using the manual function to assign it's source. (" + source + ") The file name will be ignored.")); } name = string.Join("-", array, 0, array.Length - 1); } else if (infoDebugging) { Instance.logger.LogDebug((object)("Clip " + name + " does not contain a '-' character for source name or chance")); } } if (!string.IsNullOrEmpty(source)) { text = originalName + "#" + source; } if (replacedClips.ContainsKey(text) && chance >= 100f) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to replace an audio clip that already has been replaced with new clip that has 100% chance of playback! This is not allowed."); return; } chance = Mathf.Clamp01(chance); if (replacedClips.ContainsKey(text)) { replacedClips[text].AddClip(newClip, chance); } else { replacedClips.Add(text, new ReplacementAudioClip(newClip, chance, source)); } float num = 0f; for (int i = 0; i < replacedClips[text].clips.Count(); i++) { num += replacedClips[text].clips[i].chance; } int num2 = Mathf.RoundToInt(num * 100f); if ((num2 < 100 || num2 > 100) && replacedClips[text].clips.Count() > 1) { if (infoDebugging) { Instance.logger.LogDebug((object)$"The current total combined chance for replaced {replacedClips[text].clips.Count()} random audio clips for audio clip {text} does not equal 100%. Currently {num2}% (at least yet?)"); } } else if (num2 == 100 && replacedClips[text].clips.Count() > 1 && infoDebugging) { Instance.logger.LogDebug((object)$"The current total combined chance for replaced {replacedClips[text].clips.Count()} random audio clips for audio clip {text} is equal to 100%"); } } public static void ReplaceAudioClip(AudioClip originalClip, AudioClip newClip, float chance, string source) { if ((Object)(object)originalClip == (Object)null) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to replace an audio clip without original clip specified! This is not allowed."); } else if ((Object)(object)newClip == (Object)null) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to replace an audio clip without new clip specified! This is not allowed."); } else { ReplaceAudioClip(originalClip.GetName(), newClip, chance, source); } } public static void ReplaceAudioClip(string originalName, AudioClip newClip, float chance, string[] source) { string text = string.Empty; if (source != null && source.Length != 0) { for (int i = 0; i < source.Length; i++) { if (!string.IsNullOrEmpty(source[i])) { text = text + "," + source[i]; } } } if (string.IsNullOrEmpty(originalName)) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to replace an audio clip without original clip specified! This is not allowed."); return; } if ((Object)(object)newClip == (Object)null) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to replace an audio clip without new clip specified! This is not allowed."); return; } if (string.IsNullOrEmpty(text)) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to replace an audio clip without allowed audio source specified! This is not allowed."); return; } string text2 = originalName; string name = newClip.GetName(); if (name.Contains("-")) { string[] array = name.Split('-'); if (array.Length > 1) { if (array.Length > 2) { string text3 = array[^2]; if (!string.IsNullOrEmpty(text3) && text3.StartsWith("_")) { Instance.logger.LogDebug((object)("Clip " + name + " contains source specified in it's name (" + text3.Substring(1) + ") but you're using the manual function to assign it's source. (" + text + ") The file name will be ignored.")); } } string text4 = array[^1]; if (int.TryParse(text4, out var result)) { Instance.logger.LogDebug((object)$"Clip {name} contains random chance specified in it's name ({result}%) but you're using the manual function to assign it's chance. ({Mathf.RoundToInt(chance * 100f)}%) The file name will be ignored."); } else if (!string.IsNullOrEmpty(text4) && text4.StartsWith("_")) { Instance.logger.LogDebug((object)("Clip " + name + " contains source specified in it's name (" + text4.Substring(1) + ") but you're using the manual function to assign it's source. (" + text + ") The file name will be ignored.")); } name = string.Join("-", array, 0, array.Length - 1); } else if (infoDebugging) { Instance.logger.LogDebug((object)("Clip " + name + " does not contain a '-' character for source name or chance")); } } if (!string.IsNullOrEmpty(text)) { text2 = originalName + "#" + text; } if (replacedClips.ContainsKey(text2) && chance >= 100f) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to replace an audio clip that already has been replaced with new clip that has 100% chance of playback! This is not allowed."); return; } chance = Mathf.Clamp01(chance); if (replacedClips.ContainsKey(text2)) { replacedClips[text2].AddClip(newClip, chance); } else { replacedClips.Add(text2, new ReplacementAudioClip(newClip, chance, text)); } float num = 0f; for (int j = 0; j < replacedClips[text2].clips.Count(); j++) { num += replacedClips[text2].clips[j].chance; } int num2 = Mathf.RoundToInt(num * 100f); if ((num2 < 100 || num2 > 100) && replacedClips[text2].clips.Count() > 1) { if (infoDebugging) { Instance.logger.LogDebug((object)$"The current total combined chance for replaced {replacedClips[text2].clips.Count()} random audio clips for audio clip {text2} does not equal 100%. Currently {num2}% (at least yet?)"); } } else if (num2 == 100 && replacedClips[text2].clips.Count() > 1 && infoDebugging) { Instance.logger.LogDebug((object)$"The current total combined chance for replaced {replacedClips[text2].clips.Count()} random audio clips for audio clip {text2} is equal to 100%"); } } public static void ReplaceAudioClip(AudioClip originalClip, AudioClip newClip, float chance, string[] source) { if ((Object)(object)originalClip == (Object)null) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to replace an audio clip without original clip specified! This is not allowed."); } else if ((Object)(object)newClip == (Object)null) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to replace an audio clip without new clip specified! This is not allowed."); } else { ReplaceAudioClip(originalClip.GetName(), newClip, chance, source); } } public static void RemoveRandomAudioClip(string name, float chance) { if (string.IsNullOrEmpty(name)) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to restore an audio clip without original clip specified! This is not allowed."); } else if (!replacedClips.ContainsKey(name)) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to restore an audio clip that does not exist! This is not allowed."); } else { if (!(chance > 0f)) { return; } for (int i = 0; i < replacedClips[name].clips.Count(); i++) { if (replacedClips[name].clips[i].chance == chance) { replacedClips[name].clips.RemoveAt(i); if (replacedClips[name].clips.Count <= 0) { Instance.logger.LogDebug((object)("Removed replaced AudioClip " + name + " completely as all of it's random clips have been removed.")); replacedClips.Remove(name); } break; } } } } public static void RemoveRandomAudioClip(string name, string source, float chance) { string text = name; if (!string.IsNullOrEmpty(text)) { text = name + "#" + source; } if (string.IsNullOrEmpty(text)) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to restore an audio clip without original clip specified! This is not allowed."); } else if (!replacedClips.ContainsKey(text)) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to restore an audio clip that does not exist! This is not allowed."); } else { if (!(chance > 0f)) { return; } for (int i = 0; i < replacedClips[text].clips.Count(); i++) { if (replacedClips[text].clips[i].chance == chance) { replacedClips[text].clips.RemoveAt(i); if (replacedClips[text].clips.Count <= 0) { Instance.logger.LogDebug((object)("Removed replaced AudioClip " + text + " completely as all of it's random clips have been removed.")); replacedClips.Remove(text); } break; } } } } public static void RemoveRandomAudioClip(string name, string[] source, float chance) { string text = name; string text2 = string.Empty; if (source != null && source.Length != 0) { for (int i = 0; i < source.Length; i++) { if (!string.IsNullOrEmpty(source[i])) { text2 = text2 + "," + source[i]; } } } if (!string.IsNullOrEmpty(text2)) { text = name + "#" + text2; } if (string.IsNullOrEmpty(text)) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to restore an audio clip without original clip specified! This is not allowed."); } else if (!replacedClips.ContainsKey(text)) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to restore an audio clip that does not exist! This is not allowed."); } else { if (!(chance > 0f)) { return; } for (int j = 0; j < replacedClips[text].clips.Count(); j++) { if (replacedClips[text].clips[j].chance == chance) { replacedClips[text].clips.RemoveAt(j); if (replacedClips[text].clips.Count <= 0) { Instance.logger.LogDebug((object)("Removed replaced AudioClip " + text + " completely as all of it's random clips have been removed.")); replacedClips.Remove(text); } break; } } } } public static void RestoreAudioClip(string name) { if (string.IsNullOrEmpty(name)) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to restore an audio clip without original clip specified! This is not allowed."); } else if (!replacedClips.ContainsKey(name)) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to restore an audio clip that does not exist! This is not allowed."); } else { replacedClips.Remove(name); } } public static void RestoreAudioClip(string name, string source) { string text = name; if (!string.IsNullOrEmpty(source)) { text = name + "#" + source; } if (string.IsNullOrEmpty(text)) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to restore an audio clip without original clip specified! This is not allowed."); } else if (!replacedClips.ContainsKey(text)) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to restore an audio clip that does not exist! This is not allowed."); } else { replacedClips.Remove(text); } } public static void RestoreAudioClip(string name, string[] source) { string text = name; string text2 = string.Empty; if (source != null && source.Length != 0) { for (int i = 0; i < source.Length; i++) { if (!string.IsNullOrEmpty(source[i])) { text2 = text2 + "," + source[i]; } } } if (!string.IsNullOrEmpty(text2)) { text = name + "#" + text2; } if (string.IsNullOrEmpty(text)) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to restore an audio clip without original clip specified! This is not allowed."); } else if (!replacedClips.ContainsKey(text)) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to restore an audio clip that does not exist! This is not allowed."); } else { replacedClips.Remove(text); } } public static void RestoreAudioClip(AudioClip clip) { if ((Object)(object)clip == (Object)null) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to restore an audio clip without vanilla clip name specified! This is not allowed."); } else { RestoreAudioClip(clip.GetName()); } } public static void RestoreAudioClip(string name, AudioClip replacementClip) { if ((Object)(object)replacementClip == (Object)null) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to restore an audio clip without replacement clip specified! This is not allowed."); return; } if (string.IsNullOrEmpty(name)) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to restore an audio clip without vanilla clip name specified! This is not allowed."); return; } string name2 = replacementClip.GetName(); string text = string.Empty; float num = 0f; if (name2.Contains("-")) { string[] array = name2.Split('-'); if (array.Length > 1) { if (array.Length > 2) { string text2 = array[^2]; if (!string.IsNullOrEmpty(text2) && text2.StartsWith("_")) { text = text2.Substring(1); } } string text3 = array[^1]; if (int.TryParse(text3, out var result)) { num = (float)result * 0.01f; } else if (!string.IsNullOrEmpty(text3) && text3.StartsWith("_")) { text = text3.Substring(1); } name2 = string.Join("-", array, 0, array.Length - 1); } else if (infoDebugging) { Instance.logger.LogDebug((object)("Clip " + name2 + " does not contain a '-' character for source name or chance")); } } string text4 = name + "#" + text; if (!replacedClips.ContainsKey(text4)) { Instance.logger.LogWarning((object)"Plugin LCSoundTool is trying to restore an audio clip that does not exist! This is not allowed."); } else { RestoreAudioClip(text4); } } public static AudioClip GetAudioClip(string modFolder, string soundName) { return GetAudioClip(modFolder, string.Empty, soundName); } public static AudioClip GetAudioClip(string modFolder, string subFolder, string soundName) { AudioType audioType = AudioType.wav; bool flag = true; string text = " "; string text2 = Path.Combine(Paths.PluginPath, modFolder, subFolder, soundName); string text3 = Path.Combine(Paths.PluginPath, modFolder, soundName); string path = Path.Combine(Paths.PluginPath, modFolder, subFolder); string text4 = Path.Combine(Paths.PluginPath, subFolder, soundName); string path2 = Path.Combine(Paths.PluginPath, subFolder); if (!Directory.Exists(path)) { if (!string.IsNullOrEmpty(subFolder)) { Instance.logger.LogWarning((object)("Requested directory at BepInEx/Plugins/" + modFolder + "/" + subFolder + " does not exist!")); } else { Instance.logger.LogWarning((object)("Requested directory at BepInEx/Plugins/" + modFolder + " does not exist!")); if (!modFolder.Contains("-")) { Instance.logger.LogWarning((object)"This sound mod might not be compatable with mod managers. You should contact the sound mod's author."); } } flag = false; } if (!File.Exists(text2)) { Instance.logger.LogWarning((object)("Requested audio file does not exist at path " + text2 + "!")); flag = false; Instance.logger.LogDebug((object)("Looking for audio file from mod root instead at " + text3 + "...")); if (File.Exists(text3)) { Instance.logger.LogDebug((object)("Found audio file at path " + text3 + "!")); text2 = text3; flag = true; } else { Instance.logger.LogWarning((object)("Requested audio file does not exist at mod root path " + text3 + "!")); } } if (Directory.Exists(path2)) { if (!string.IsNullOrEmpty(subFolder)) { Instance.logger.LogWarning((object)("Legacy directory location at BepInEx/Plugins/" + subFolder + " found!")); } else if (!modFolder.Contains("-")) { Instance.logger.LogWarning((object)"Legacy directory location at BepInEx/Plugins found!"); } } if (File.Exists(text4)) { Instance.logger.LogWarning((object)("Legacy path contains the requested audio file at path " + text4 + "!")); text = " legacy "; text2 = text4; flag = true; } string[] array = soundName.Split('.'); if (array[^1].ToLower().Contains("wav")) { audioType = AudioType.wav; if (infoDebugging) { Instance.logger.LogDebug((object)"File detected as a PCM WAVE file!"); } } else if (array[^1].ToLower().Contains("ogg")) { audioType = AudioType.ogg; if (infoDebugging) { Instance.logger.LogDebug((object)"File detected as an Ogg Vorbis file!"); } } else if (array[^1].ToLower().Contains("mp3")) { audioType = AudioType.mp3; if (infoDebugging) { Instance.logger.LogDebug((object)"File detected as a MPEG MP3 file!"); } } else { Instance.logger.LogWarning((object)("Failed to detect file type of a sound file! This may cause issues with other mod functionality. Sound: " + soundName)); } AudioClip val = null; if (flag) { Instance.logger.LogDebug((object)("Loading AudioClip " + soundName + " from" + text + "path: " + text2)); switch (audioType) { case AudioType.wav: val = WavUtility.LoadFromDiskToAudioClip(text2); break; case AudioType.ogg: val = OggUtility.LoadFromDiskToAudioClip(text2); break; case AudioType.mp3: val = Mp3Utility.LoadFromDiskToAudioClip(text2); break; } Instance.logger.LogDebug((object)$"Finished loading AudioClip {soundName} with length of {val.length}!"); } else { Instance.logger.LogWarning((object)("Failed to load AudioClip " + soundName + " from invalid" + text + "path at " + text2 + "!")); } if (string.IsNullOrEmpty(val.GetName())) { string empty = string.Empty; string[] array2 = new string[0]; switch (audioType) { case AudioType.wav: empty = soundName.Replace(".wav", ""); array2 = empty.Split('/'); if (array2.Length <= 1) { array2 = empty.Split('\\'); } empty = array2[^1]; ((Object)val).name = empty; break; case AudioType.ogg: empty = soundName.Replace(".ogg", ""); array2 = empty.Split('/'); if (array2.Length <= 1) { array2 = empty.Split('\\'); } empty = array2[^1]; ((Object)val).name = empty; break; case AudioType.mp3: empty = soundName.Replace(".mp3", ""); array2 = empty.Split('/'); if (array2.Length <= 1) { array2 = empty.Split('\\'); } empty = array2[^1]; ((Object)val).name = empty; break; } } if ((Object)(object)val != (Object)null) { string name = val.GetName(); if (clipTypes.ContainsKey(name)) { clipTypes[name] = audioType; } else { clipTypes.Add(name, audioType); } } return val; } public static AudioClip GetAudioClip(string modFolder, string soundName, AudioType audioType) { return GetAudioClip(modFolder, string.Empty, soundName, audioType); } public static AudioClip GetAudioClip(string modFolder, string subFolder, string soundName, AudioType audioType) { bool flag = true; string text = " "; string text2 = Path.Combine(Paths.PluginPath, modFolder, subFolder, soundName); string text3 = Path.Combine(Paths.PluginPath, modFolder, soundName); string path = Path.Combine(Paths.PluginPath, modFolder, subFolder); string text4 = Path.Combine(Paths.PluginPath, subFolder, soundName); string path2 = Path.Combine(Paths.PluginPath, subFolder); if (!Directory.Exists(path)) { if (!string.IsNullOrEmpty(subFolder)) { Instance.logger.LogWarning((object)("Requested directory at BepInEx/Plugins/" + modFolder + "/" + subFolder + " does not exist!")); } else { Instance.logger.LogWarning((object)("Requested directory at BepInEx/Plugins/" + modFolder + " does not exist!")); if (!modFolder.Contains("-")) { Instance.logger.LogWarning((object)"This sound mod might not be compatable with mod managers. You should contact the sound mod's author."); } } flag = false; } if (!File.Exists(text2)) { Instance.logger.LogWarning((object)("Requested audio file does not exist at path " + text2 + "!")); flag = false; Instance.logger.LogDebug((object)("Looking for audio file from mod root instead at " + text3 + "...")); if (File.Exists(text3)) { Instance.logger.LogDebug((object)("Found audio file at path " + text3 + "!")); text2 = text3; flag = true; } else { Instance.logger.LogWarning((object)("Requested audio file does not exist at mod root path " + text3 + "!")); } } if (Directory.Exists(path2)) { if (!string.IsNullOrEmpty(subFolder)) { Instance.logger.LogWarning((object)("Legacy directory location at BepInEx/Plugins/" + subFolder + " found!")); } else if (!modFolder.Contains("-")) { Instance.logger.LogWarning((object)"Legacy directory location at BepInEx/Plugins found!"); } } if (File.Exists(text4)) { Instance.logger.LogWarning((object)("Legacy path contains the requested audio file at path " + text4 + "!")); text = " legacy "; text2 = text4; flag = true; } switch (audioType) { case AudioType.wav: if (infoDebugging) { Instance.logger.LogDebug((object)"File defined as a WAV file!"); } break; case AudioType.ogg: if (infoDebugging) { Instance.logger.LogDebug((object)"File defined as an Ogg Vorbis file!"); } break; case AudioType.mp3: if (infoDebugging) { Instance.logger.LogDebug((object)"File defined as a MPEG MP3 file!"); } break; } AudioClip val = null; if (flag) { Instance.logger.LogDebug((object)("Loading AudioClip " + soundName + " from" + text + "path: " + text2)); switch (audioType) { case AudioType.wav: val = WavUtility.LoadFromDiskToAudioClip(text2); break; case AudioType.ogg: val = OggUtility.LoadFromDiskToAudioClip(text2); break; case AudioType.mp3: val = Mp3Utility.LoadFromDiskToAudioClip(text2); break; } Instance.logger.LogDebug((object)$"Finished loading AudioClip {soundName} with length of {val.length}!"); } else { Instance.logger.LogWarning((object)("Failed to load AudioClip " + soundName + " from invalid" + text + "path at " + text2 + "!")); } if (string.IsNullOrEmpty(val.GetName())) { string empty = string.Empty; string[] array = new string[0]; switch (audioType) { case AudioType.wav: empty = soundName.Replace(".wav", ""); array = empty.Split('/'); if (array.Length <= 1) { array = empty.Split('\\'); } empty = array[^1]; ((Object)val).name = empty; break; case AudioType.ogg: empty = soundName.Replace(".ogg", ""); array = empty.Split('/'); if (array.Length <= 1) { array = empty.Split('\\'); } empty = array[^1]; ((Object)val).name = empty; break; case AudioType.mp3: empty = soundName.Replace(".mp3", ""); array = empty.Split('/'); if (array.Length <= 1) { array = empty.Split('\\'); } empty = array[^1]; ((Object)val).name = empty; break; } } if ((Object)(object)val != (Object)null) { string name = val.GetName(); if (clipTypes.ContainsKey(name)) { clipTypes[name] = audioType; } else { clipTypes.Add(name, audioType); } } return val; } public static void SendNetworkedAudioClip(AudioClip audioClip) { if (!Instance.configUseNetworking.Value) { Instance.logger.LogWarning((object)$"Networking disabled! Failed to send {audioClip}!"); return; } if ((Object)(object)audioClip == (Object)null) { Instance.logger.LogWarning((object)$"audioClip variable of SendAudioClip not assigned! Failed to send {audioClip}!"); return; } if ((Object)(object)Instance == (Object)null || (Object)(object)GameNetworkManagerPatch.networkHandlerHost == (Object)null || (Object)(object)NetworkHandler.Instance == (Object)null) { Instance.logger.LogWarning((object)$"Instance of SoundTool not found or networking has not finished initializing. Failed to send {audioClip}! If you're sending things in Awake or in a scene such as the main menu it might be too early, please try some of the other built-in Unity methods and make sure your networked audio runs only after the player setups a networked connection!"); return; } string name = audioClip.GetName(); if (clipTypes.ContainsKey(name)) { if (clipTypes[name] == AudioType.ogg) { NetworkHandler.Instance.SendAudioClipServerRpc(name, OggUtility.AudioClipToByteArray(audioClip, out var _)); return; } if (clipTypes[name] == AudioType.mp3) { NetworkHandler.Instance.SendAudioClipServerRpc(name, Mp3Utility.AudioClipToByteArray(audioClip, out var _)); return; } } NetworkHandler.Instance.SendAudioClipServerRpc(name, WavUtility.AudioClipToByteArray(audioClip, out var _)); } public static void RemoveNetworkedAudioClip(AudioClip audioClip) { RemoveNetworkedAudioClip(audioClip.GetName()); } public static void RemoveNetworkedAudioClip(string audioClip) { if (!Instance.configUseNetworking.Value) { Instance.logger.LogWarning((object)("Networking disabled! Failed to remove " + audioClip + "!")); } else if (string.IsNullOrEmpty(audioClip)) { Instance.logger.LogWarning((object)("audioClip variable of RemoveAudioClip not assigned! Failed to remove " + audioClip + "!")); } else if ((Object)(object)Instance == (Object)null || (Object)(object)GameNetworkManagerPatch.networkHandlerHost == (Object)null || (Object)(object)NetworkHandler.Instance == (Object)null) { Instance.logger.LogWarning((object)("Instance of SoundTool not found or networking has not finished initializing. Failed to remove " + audioClip + "! If you're removing things in Awake or in a scene such as the main menu it might be too early, please try some of the other built-in Unity methods and make sure your networked audio runs only after the player setups a networked connection!")); } else { NetworkHandler.Instance.RemoveAudioClipServerRpc(audioClip); } } public static void SyncNetworkedAudioClips() { if (!Instance.configUseNetworking.Value) { Instance.logger.LogWarning((object)"Networking disabled! Failed to sync audio clips!"); } else if ((Object)(object)Instance == (Object)null || (Object)(object)GameNetworkManagerPatch.networkHandlerHost == (Object)null || (Object)(object)NetworkHandler.Instance == (Object)null) { Instance.logger.LogWarning((object)"Instance of SoundTool not found or networking has not finished initializing. Failed to sync networked audio! If you're syncing things in Awake or in a scene such as the main menu it might be too early, please try some of the other built-in Unity methods and make sure your networked audio runs only after the player setups a networked connection!"); } else { NetworkHandler.Instance.SyncAudioClipsServerRpc(); } } public static void SendUnityRandomSeed(int seed) { if (!Instance.configUseNetworking.Value) { Instance.logger.LogWarning((object)"Networking disabled! Failed to send Unity random seed!"); } else if ((Object)(object)Instance == (Object)null || (Object)(object)GameNetworkManagerPatch.networkHandlerHost == (Object)null || (Object)(object)NetworkHandler.Instance == (Object)null) { Instance.logger.LogWarning((object)"Instance of SoundTool not found or networking has not finished initializing. Failed to send Unity Random seed! If you're sending the seed in Awake or in a scene such as the main menu it might be too early, please try some of the other built-in Unity methods and make sure your networked methods run only after the player setups a networked connection!"); } else { NetworkHandler.Instance.SendSeedToClientsServerRpc(seed); } } } } namespace LCSoundTool.Utilities { public static class Extensions { public static bool ContainsThisRandomAudioClip(this List<RandomAudioClip> list, RandomAudioClip thisClip) { for (int i = 0; i < list.Count; i++) { if (list[i].chance == thisClip.chance && list[i].clip.GetName() == thisClip.clip.GetName()) { return true; } } return false; } } public static class Mp3Utility { public static byte[] AudioClipToByteArray(AudioClip audioClip, out float[] samples) { samples = new float[audioClip.samples * audioClip.channels]; audioClip.GetData(samples, 0); byte[] array = new byte[samples.Length * 2]; int num = 32767; for (int i = 0; i < samples.Length; i++) { short value = (short)(samples[i] * (float)num); BitConverter.GetBytes(value).CopyTo(array, i * 2); } return array; } public static AudioClip ByteArrayToAudioClip(byte[] byteArray, string clipName) { int num = 16; int num2 = num / 8; AudioClip val = AudioClip.Create(clipName, byteArray.Length / num2, 1, 44100, false); val.SetData(ConvertByteArrayToFloatArray(byteArray), 0); return val; } private static float[] ConvertByteArrayToFloatArray(byte[] byteArray) { float[] array = new float[byteArray.Length / 2]; int num = 32767; for (int i = 0; i < array.Length; i++) { short num2 = BitConverter.ToInt16(byteArray, i * 2); array[i] = (float)num2 / (float)num; } return array; } public static AudioClip LoadFromDiskToAudioClip(string path) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Invalid comparison between Unknown and I4 AudioClip result = null; UnityWebRequest audioClip = UnityWebRequestMultimedia.GetAudioClip(path, (AudioType)13); try { audioClip.SendWebRequest(); try { while (!audioClip.isDone) { } if ((int)audioClip.result != 1) { SoundTool.Instance.logger.LogError((object)("Failed to load MP3 AudioClip from path: " + path + " Full error: " + audioClip.error)); } else { result = DownloadHandlerAudioClip.GetContent(audioClip); } } catch (Exception ex) { SoundTool.Instance.logger.LogError((object)(ex.Message + ", " + ex.StackTrace)); } } finally { ((IDisposable)audioClip)?.Dispose(); } return result; } } public static class OggUtility { public static byte[] AudioClipToByteArray(AudioClip audioClip, out float[] samples) { samples = new float[audioClip.samples * audioClip.channels]; audioClip.GetData(samples, 0); byte[] array = new byte[samples.Length * 2]; int num = 32767; for (int i = 0; i < samples.Length; i++) { short value = (short)(samples[i] * (float)num); BitConverter.GetBytes(value).CopyTo(array, i * 2); } return array; } public static AudioClip ByteArrayToAudioClip(byte[] byteArray, string clipName) { int num = 16; int num2 = num / 8; AudioClip val = AudioClip.Create(clipName, byteArray.Length / num2, 1, 44100, false); val.SetData(ConvertByteArrayToFloatArray(byteArray), 0); return val; } private static float[] ConvertByteArrayToFloatArray(byte[] byteArray) { float[] array = new float[byteArray.Length / 2]; int num = 32767; for (int i = 0; i < array.Length; i++) { short num2 = BitConverter.ToInt16(byteArray, i * 2); array[i] = (float)num2 / (float)num; } return array; } public static AudioClip LoadFromDiskToAudioClip(string path) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Invalid comparison between Unknown and I4 AudioClip result = null; UnityWebRequest audioClip = UnityWebRequestMultimedia.GetAudioClip(path, (AudioType)14); try { audioClip.SendWebRequest(); try { while (!audioClip.isDone) { } if ((int)audioClip.result != 1) { SoundTool.Instance.logger.LogError((object)("Failed to load OGGVORBIS AudioClip from path: " + path + " Full error: " + audioClip.error)); } else { result = DownloadHandlerAudioClip.GetContent(audioClip); } } catch (Exception ex) { SoundTool.Instance.logger.LogError((object)(ex.Message + ", " + ex.StackTrace)); } } finally { ((IDisposable)audioClip)?.Dispose(); } return result; } } public static class WavUtility { public static byte[] AudioClipToByteArray(AudioClip audioClip, out float[] samples) { samples = new float[audioClip.samples * audioClip.channels]; audioClip.GetData(samples, 0); byte[] array = new byte[samples.Length * 2]; int num = 32767; for (int i = 0; i < samples.Length; i++) { short value = (short)(samples[i] * (float)num); BitConverter.GetBytes(value).CopyTo(array, i * 2); } return array; } public static AudioClip ByteArrayToAudioClip(byte[] byteArray, string clipName) { int num = 16; int num2 = num / 8; AudioClip val = AudioClip.Create(clipName, byteArray.Length / num2, 1, 44100, false); val.SetData(ConvertByteArrayToFloatArray(byteArray), 0); return val; } private static float[] ConvertByteArrayToFloatArray(byte[] byteArray) { float[] array = new float[byteArray.Length / 2]; int num = 32767; for (int i = 0; i < array.Length; i++) { short num2 = BitConverter.ToInt16(byteArray, i * 2); array[i] = (float)num2 / (float)num; } return array; } public static AudioClip LoadFromDiskToAudioClip(string path) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Invalid comparison between Unknown and I4 AudioClip result = null; UnityWebRequest audioClip = UnityWebRequestMultimedia.GetAudioClip(path, (AudioType)20); try { audioClip.SendWebRequest(); try { while (!audioClip.isDone) { } if ((int)audioClip.result != 1) { SoundTool.Instance.logger.LogError((object)("Failed to load WAV AudioClip from path: " + path + " Full error: " + audioClip.error)); } else { result = DownloadHandlerAudioClip.GetContent(audioClip); } } catch (Exception ex) { SoundTool.Instance.logger.LogError((object)(ex.Message + ", " + ex.StackTrace)); } } finally { ((IDisposable)audioClip)?.Dispose(); } return result; } } } namespace LCSoundTool.Patches { [HarmonyPatch(typeof(AudioSource))] internal class AudioSourcePatch { private static Dictionary<string, AudioClip> originalClips = new Dictionary<string, AudioClip>(); [HarmonyPatch("Play", new Type[] { })] [HarmonyPrefix] public static void Play_Patch(AudioSource __instance) { RunDynamicClipReplacement(__instance); DebugPlayMethod(__instance); } [HarmonyPatch("Play", new Type[] { typeof(ulong) })] [HarmonyPrefix] public static void Play_UlongPatch(AudioSource __instance) { RunDynamicClipReplacement(__instance); DebugPlayMethod(__instance); } [HarmonyPatch("Play", new Type[] { typeof(double) })] [HarmonyPrefix] public static void Play_DoublePatch(AudioSource __instance) { RunDynamicClipReplacement(__instance); DebugPlayMethod(__instance); } [HarmonyPatch("PlayDelayed", new Type[] { typeof(float) })] [HarmonyPrefix] public static void PlayDelayed_Patch(AudioSource __instance) { RunDynamicClipReplacement(__instance); DebugPlayDelayedMethod(__instance); } [HarmonyPatch("PlayClipAtPoint", new Type[] { typeof(AudioClip), typeof(Vector3), typeof(float) })] [HarmonyPrefix] public static bool PlayClipAtPoint_Patch(AudioClip clip, Vector3 position, float volume) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject($"ClipAtPoint_{clip}"); val.transform.position = position; AudioSource val2 = val.AddComponent<AudioSource>(); val2.clip = clip; val2.spatialBlend = 1f; val2.volume = volume; val2.Play(); DebugPlayClipAtPointMethod(val2, position); Object.Destroy((Object)(object)val, clip.length * ((Time.timeScale < 0.01f) ? 0.01f : Time.timeScale)); return false; } [HarmonyPatch("PlayOneShotHelper", new Type[] { typeof(AudioSource), typeof(AudioClip), typeof(float) })] [HarmonyPrefix] public static void PlayOneShotHelper_Patch(AudioSource source, ref AudioClip clip, float volumeScale) { clip = ReplaceClipWithNew(clip, source); DebugPlayOneShotMethod(source, clip); } private static void DebugPlayMethod(AudioSource instance) { if ((Object)(object)instance == (Object)null) { return; } if (SoundTool.debugAudioSources && !SoundTool.indepthDebugging && (Object)(object)instance != (Object)null) { SoundTool.Instance.logger.LogDebug((object)$"{instance} at {((Component)instance).transform.root} is playing {((Object)instance.clip).name}"); } else if (SoundTool.indepthDebugging && (Object)(object)instance != (Object)null) { SoundTool.Instance.logger.LogDebug((object)$"{instance} is playing {((Object)instance.clip).name} at"); Transform val = ((Component)instance).transform; while ((Object)(object)val.parent != (Object)null || (Object)(object)val != (Object)(object)((Component)instance).transform.root) { SoundTool.Instance.logger.LogDebug((object)$"--- {val.parent}"); val = val.parent; } if ((Object)(object)val == (Object)(object)((Component)instance).transform.root) { SoundTool.Instance.logger.LogDebug((object)$"--- {((Component)instance).transform.root}"); } } } private static void DebugPlayDelayedMethod(AudioSource instance) { if ((Object)(object)instance == (Object)null) { return; } if (SoundTool.debugAudioSources && !SoundTool.indepthDebugging && (Object)(object)instance != (Object)null) { SoundTool.Instance.logger.LogDebug((object)$"{instance} at {((Component)instance).transform.root} is playing {((Object)instance.clip).name} with delay"); } else if (SoundTool.indepthDebugging && (Object)(object)instance != (Object)null) { SoundTool.Instance.logger.LogDebug((object)$"{instance} is playing {((Object)instance.clip).name} with delay at"); Transform val = ((Component)instance).transform; while ((Object)(object)val.parent != (Object)null || (Object)(object)val != (Object)(object)((Component)instance).transform.root) { SoundTool.Instance.logger.LogDebug((object)$"--- {val.parent}"); val = val.parent; } if ((Object)(object)val == (Object)(object)((Component)instance).transform.root) { SoundTool.Instance.logger.LogDebug((object)$"--- {((Component)instance).transform.root}"); } } } private static void DebugPlayClipAtPointMethod(AudioSource audioSource, Vector3 position) { //IL_0065: 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) if ((Object)(object)audioSource == (Object)null) { return; } if (SoundTool.debugAudioSources && !SoundTool.indepthDebugging && (Object)(object)audioSource != (Object)null) { SoundTool.Instance.logger.LogDebug((object)$"{audioSource} at {((Component)audioSource).transform.root} is playing {((Object)audioSource.clip).name} at point {position}"); } else if (SoundTool.indepthDebugging && (Object)(object)audioSource != (Object)null) { SoundTool.Instance.logger.LogDebug((object)$"{audioSource} is playing {((Object)audioSource.clip).name} located at point {position} within "); Transform val = ((Component)audioSource).transform; while ((Object)(object)val.parent != (Object)null || (Object)(object)val != (Object)(object)((Component)audioSource).transform.root) { SoundTool.Instance.logger.LogDebug((object)$"--- {val.parent}"); val = val.parent; } if ((Object)(object)val == (Object)(object)((Component)audioSource).transform.root) { SoundTool.Instance.logger.LogDebug((object)$"--- {((Component)audioSource).transform.root}"); } } } private static void DebugPlayOneShotMethod(AudioSource source, AudioClip clip) { if ((Object)(object)source == (Object)null || (Object)(object)clip == (Object)null) { return; } if (SoundTool.debugAudioSources && !SoundTool.indepthDebugging && (Object)(object)source != (Object)null) { SoundTool.Instance.logger.LogDebug((object)$"{source} at {((Component)source).transform.root} is playing one shot {((Object)clip).name}"); } else if (SoundTool.indepthDebugging && (Object)(object)source != (Object)null) { SoundTool.Instance.logger.LogDebug((object)$"{source} is playing one shot {((Object)clip).name} at"); Transform val = ((Component)source).transform; while ((Object)(object)val.parent != (Object)null || (Object)(object)val != (Object)(object)((Component)source).transform.root) { SoundTool.Instance.logger.LogDebug((object)$"--- {val.parent}"); val = val.parent; } if ((Object)(object)val == (Object)(object)((Component)source).transform.root) { SoundTool.Instance.logger.LogDebug((object)$"--- {((Component)source).transform.root}"); } } } private static void RunDynamicClipReplacement(AudioSource instance) { if ((Object)(object)instance == (Object)null || (Object)(object)instance.clip == (Object)null) { return; } string name = ((Object)((Component)instance).gameObject).name; bool flag = true; AudioClip value; string text = ((!originalClips.TryGetValue(name, out value)) ? instance.clip.GetName() : value.GetName()); string key = text; if (SoundTool.replacedClips.Keys.Count > 0) { string[] array = SoundTool.replacedClips.Keys.ToArray(); if (array.Length != 0) { for (int i = 0; i < array.Length; i++) { string[] array2 = array[i].Split("#"); if (array2.Length == 2 && array2[1].Contains(((Object)((Component)instance).gameObject).name)) { key = text + "#" + array2[1]; } } } } if (SoundTool.replacedClips.ContainsKey(key)) { if (!SoundTool.replacedClips[key].canPlay) { return; } if (!originalClips.ContainsKey(name)) { originalClips.Add(name, instance.clip); } if (!string.IsNullOrEmpty(SoundTool.replacedClips[key].source)) { flag = false; string[] array3 = SoundTool.replacedClips[key].source.Split(','); if ((Object)(object)instance != (Object)null && ((Object)((Component)instance).gameObject).name != null) { if (array3.Length > 1) { for (int j = 0; j < array3.Length; j++) { if (array3[j] == ((Object)((Component)instance).gameObject).name) { flag = true; } } } else if (array3[0] == ((Object)((Component)instance).gameObject).name) { flag = true; } } } List<RandomAudioClip> clips = SoundTool.replacedClips[key].clips; float num = 0f; foreach (RandomAudioClip item in clips) { num += item.chance; } float num2 = Random.Range(0f, num); { foreach (RandomAudioClip item2 in clips) { if (num2 <= item2.chance) { if (flag) { instance.clip = item2.clip; } else if (originalClips.ContainsKey(name)) { instance.clip = originalClips[name]; originalClips.Remove(name); } break; } num2 -= item2.chance; } return; } } if (originalClips.ContainsKey(name)) { instance.clip = originalClips[name]; originalClips.Remove(name); } } private static AudioClip ReplaceClipWithNew(AudioClip original, AudioSource source = null) { if ((Object)(object)original == (Object)null) { return original; } string name = original.GetName(); bool flag = true; string key = name; if ((Object)(object)source != (Object)null && SoundTool.replacedClips.Keys.Count > 0) { string[] array = SoundTool.replacedClips.Keys.ToArray(); if (array.Length != 0) { for (int i = 0; i < array.Length; i++) { string[] array2 = array[i].Split("#"); if (array2.Length == 2 && array2[1].Contains(((Object)((Component)source).gameObject).name)) { key = name + "#" + array2[1]; } } } } if (SoundTool.replacedClips.ContainsKey(key)) { if (!SoundTool.replacedClips[key].canPlay) { return original; } if (!originalClips.ContainsKey(key)) { originalClips.Add(key, original); } if (!string.IsNullOrEmpty(SoundTool.replacedClips[key].source)) { flag = false; string[] array3 = SoundTool.replacedClips[key].source.Split(','); if ((Object)(object)source != (Object)null && ((Object)((Component)source).gameObject).name != null) { if (array3.Length > 1) { for (int j = 0; j < array3.Length; j++) { if (array3[j] == ((Object)((Component)source).gameObject).name) { flag = true; } } } else if (array3[0] == ((Object)((Component)source).gameObject).name) { flag = true; } } } List<RandomAudioClip> clips = SoundTool.replacedClips[key].clips; float num = 0f; foreach (RandomAudioClip item in clips) { num += item.chance; } float num2 = Random.Range(0f, num); foreach (RandomAudioClip item2 in clips) { if (num2 <= item2.chance) { if (flag) { return item2.clip; } if (originalClips.ContainsKey(key)) { AudioClip result = originalClips[key]; originalClips.Remove(key); return result; } return original; } num2 -= item2.chance; } } else if (originalClips.ContainsKey(key)) { AudioClip result2 = originalClips[key]; originalClips.Remove(key); return result2; } return original; } } [HarmonyPatch(typeof(GameNetworkManager))] internal class GameNetworkManagerPatch { public static GameObject networkPrefab; public static GameObject networkHandlerHost; [HarmonyPatch("Start")] [HarmonyPrefix] public static void Start_Patch() { if (!((Object)(object)networkPrefab != (Object)null)) { SoundTool.Instance.logger.LogDebug((object)"Loading NetworkHandler prefab..."); networkPrefab = Assets.bundle.LoadAsset<GameObject>("SoundToolNetworkHandler.prefab"); if ((Object)(object)networkPrefab == (Object)null) { SoundTool.Instance.logger.LogError((object)"Failed to load NetworkHandler prefab!"); } if ((Object)(object)networkPrefab != (Object)null) { NetworkManager.Singleton.AddNetworkPrefab(networkPrefab); SoundTool.Instance.logger.LogDebug((object)"Registered NetworkHandler prefab!"); } else { SoundTool.Instance.logger.LogWarning((object)"Failed to registered NetworkHandler prefab! No networking can take place."); } } } [HarmonyPatch("StartDisconnect")] [HarmonyPostfix] private static void StartDisconnect_Patch() { try { if (NetworkManager.Singleton.IsHost || NetworkManager.Singleton.IsServer) { SoundTool.Instance.logger.LogDebug((object)"Destroying NetworkHandler prefab!"); Object.Destroy((Object)(object)networkHandlerHost); networkHandlerHost = null; } } catch { SoundTool.Instance.logger.LogError((object)"Failed to destroy NetworkHandler prefab!"); } } } [HarmonyPatch(typeof(StartOfRound))] internal class StartOfRoundPatch { [HarmonyPatch("Awake")] [HarmonyPostfix] private static void SpawnNetworkHandler() { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) try { if (NetworkManager.Singleton.IsHost || NetworkManager.Singleton.IsServer) { SoundTool.Instance.logger.LogDebug((object)"Spawning NetworkHandler prefab!"); GameNetworkManagerPatch.networkHandlerHost = Object.Instantiate<GameObject>(GameNetworkManagerPatch.networkPrefab, Vector3.zero, Quaternion.identity); GameNetworkManagerPatch.networkHandlerHost.GetComponent<NetworkObject>().Spawn(true); } } catch { SoundTool.Instance.logger.LogError((object)"Failed to spawn NetworkHandler prefab!"); } } } } namespace LCSoundTool.Networking { public class NetworkHandler : NetworkBehaviour { public static NetworkHandler Instance { get; private set; } public static Dictionary<string, AudioClip> networkedAudioClips { get; private set; } public static event Action ClientNetworkedAudioChanged; public static event Action HostNetworkedAudioChanged; public override void OnNetworkSpawn() { Debug.Log((object)"LCSoundTool - NetworkHandler created!"); NetworkHandler.ClientNetworkedAudioChanged = null; NetworkHandler.HostNetworkedAudioChanged = null; networkedAudioClips = new Dictionary<string, AudioClip>(); Instance = this; } [ClientRpc] public void ReceiveAudioClipClientRpc(string clipName, byte[] audioData) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Invalid comparison between Unknown and I4 //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Invalid comparison between Unknown and I4 //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008e: 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_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager; if (networkManager == null || !networkManager.IsListening) { return; } if ((int)base.__rpc_exec_stage != 2 && (networkManager.IsServer || networkManager.IsHost)) { ClientRpcParams val = default(ClientRpcParams); FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendClientRpc(2736638642u, val, (RpcDelivery)0); bool flag = clipName != null; ((FastBufferWriter)(ref val2)).WriteValueSafe<bool>(ref flag, default(ForPrimitives)); if (flag) { ((FastBufferWriter)(ref val2)).WriteValueSafe(clipName, false); } bool flag2 = audioData != null; ((FastBufferWriter)(ref val2)).WriteValueSafe<bool>(ref flag2, default(ForPrimitives)); if (flag2) { ((FastBufferWriter)(ref val2)).WriteValueSafe<byte>(audioData, default(ForPrimitives)); } ((NetworkBehaviour)this).__endSendClientRpc(ref val2, 2736638642u, val, (RpcDelivery)0); } if ((int)base.__rpc_exec_stage != 2 || (!networkManager.IsClient && !networkManager.IsHost)) { return; } if (!networkedAudioClips.ContainsKey(clipName)) { AudioClip val3 = null; if (SoundTool.clipTypes.ContainsKey(clipName)) { if (SoundTool.clipTypes[clipName] == SoundTool.AudioType.ogg) { val3 = OggUtility.ByteArrayToAudioClip(audioData, clipName); } else if (SoundTool.clipTypes[clipName] == SoundTool.AudioType.mp3) { val3 = Mp3Utility.ByteArrayToAudioClip(audioData, clipName); } } if ((Object)(object)val3 == (Object)null) { val3 = WavUtility.ByteArrayToAudioClip(audioData, clipName); } networkedAudioClips.Add(clipName, val3); NetworkHandler.ClientNetworkedAudioChanged?.Invoke(); } else { SoundTool.Instance.logger.LogDebug((object)("Sound " + clipName + " already exists for this client! Skipping addition of this sound for this client.")); } } [ClientRpc] public void RemoveAudioClipClientRpc(string clipName) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Invalid comparison between Unknown and I4 //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Invalid comparison between Unknown and I4 //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008e: 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) NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager; if (networkManager == null || !networkManager.IsListening) { return; } if ((int)base.__rpc_exec_stage != 2 && (networkManager.IsServer || networkManager.IsHost)) { ClientRpcParams val = default(ClientRpcParams); FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendClientRpc(1355469546u, val, (RpcDelivery)0); bool flag = clipName != null; ((FastBufferWriter)(ref val2)).WriteValueSafe<bool>(ref flag, default(ForPrimitives)); if (flag) { ((FastBufferWriter)(ref val2)).WriteValueSafe(clipName, false); } ((NetworkBehaviour)this).__endSendClientRpc(ref val2, 1355469546u, val, (RpcDelivery)0); } if ((int)base.__rpc_exec_stage == 2 && (networkManager.IsClient || networkManager.IsHost) && networkedAudioClips.ContainsKey(clipName)) { networkedAudioClips.Remove(clipName); NetworkHandler.ClientNetworkedAudioChanged?.Invoke(); } } [ClientRpc] public void SyncAudioClipsClientRpc(Strings clipNames) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Invalid comparison between Unknown and I4 //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Invalid comparison between Unknown and I4 //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager; if (networkManager == null || !networkManager.IsListening) { return; } if ((int)base.__rpc_exec_stage != 2 && (networkManager.IsServer || networkManager.IsHost)) { ClientRpcParams val = default(ClientRpcParams); FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendClientRpc(3300200130u, val, (RpcDelivery)0); ((FastBufferWriter)(ref val2)).WriteValueSafe<Strings>(ref clipNames, default(ForNetworkSerializable)); ((NetworkBehaviour)this).__endSendClientRpc(ref val2, 3300200130u, val, (RpcDelivery)0); } if ((int)base.__rpc_exec_stage != 2 || (!networkManager.IsClient && !networkManager.IsHost)) { return; } string[] myStrings = clipNames.MyStrings; for (int i = 0; i < myStrings.Length; i++) { if (!networkedAudioClips.ContainsKey(myStrings[i])) { SendExistingAudioClipServerRpc(myStrings[i]); } } } [ClientRpc] public void ReceiveSeedClientRpc(int seed) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Invalid comparison between Unknown and I4 //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Invalid comparison between Unknown and I4 //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: 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) //IL_0089: Unknown result type (might be due to invalid IL or missing references) NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager; if (networkManager != null && networkManager.IsListening) { if ((int)base.__rpc_exec_stage != 2 && (networkManager.IsServer || networkManager.IsHost)) { ClientRpcParams val = default(ClientRpcParams); FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendClientRpc(1556253924u, val, (RpcDelivery)0); BytePacker.WriteValueBitPacked(val2, seed); ((NetworkBehaviour)this).__endSendClientRpc(ref val2, 1556253924u, val, (RpcDelivery)0); } if ((int)base.__rpc_exec_stage == 2 && (networkManager.IsClient || networkManager.IsHost)) { Random.InitState(seed); SoundTool.Instance.logger.LogDebug((object)$"Client received a new Unity Random seed of {seed}!"); } } } [ServerRpc(RequireOwnership = false)] public void SendAudioClipServerRpc(string clipName, byte[] audioData) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Invalid comparison between Unknown and I4 //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Invalid comparison between Unknown and I4 //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008e: 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_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager; if (networkManager == null || !networkManager.IsListening) { return; } if ((int)base.__rpc_exec_stage != 1 && (networkManager.IsClient || networkManager.IsHost)) { ServerRpcParams val = default(ServerRpcParams); FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendServerRpc(867452943u, val, (RpcDelivery)0); bool flag = clipName != null; ((FastBufferWriter)(ref val2)).WriteValueSafe<bool>(ref flag, default(ForPrimitives)); if (flag) { ((FastBufferWriter)(ref val2)).WriteValueSafe(clipName, false); } bool flag2 = audioData != null; ((FastBufferWriter)(ref val2)).WriteValueSafe<bool>(ref flag2, default(ForPrimitives)); if (flag2) { ((FastBufferWriter)(ref val2)).WriteValueSafe<byte>(audioData, default(ForPrimitives)); } ((NetworkBehaviour)this).__endSendServerRpc(ref val2, 867452943u, val, (RpcDelivery)0); } if ((int)base.__rpc_exec_stage == 1 && (networkManager.IsServer || networkManager.IsHost)) { ReceiveAudioClipClientRpc(clipName, audioData); NetworkHandler.HostNetworkedAudioChanged?.Invoke(); } } [ServerRpc(RequireOwnership = false)] public void RemoveAudioClipServerRpc(string clipName) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Invalid comparison between Unknown and I4 //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Invalid comparison between Unknown and I4 //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008e: 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) NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager; if (networkManager == null || !networkManager.IsListening) { return; } if ((int)base.__rpc_exec_stage != 1 && (networkManager.IsClient || networkManager.IsHost)) { ServerRpcParams val = default(ServerRpcParams); FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendServerRpc(3103497155u, val, (RpcDelivery)0); bool flag = clipName != null; ((FastBufferWriter)(ref val2)).WriteValueSafe<bool>(ref flag, default(ForPrimitives)); if (flag) { ((FastBufferWriter)(ref val2)).WriteValueSafe(clipName, false); } ((Ne