using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using HarmonyLib;
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: AssemblyTitle("UKSoundTool")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("UKSoundTool")]
[assembly: AssemblyCopyright("Copyright © 2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("ae817c5f-a4a9-458f-a608-9f621ebc9e08")]
[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")]
public static class FolderBootstrap
{
public static bool Ensure(string parent, string folder, out string path, string readme = null)
{
path = null;
bool result = false;
try
{
string text = Path.Combine(parent, folder);
if (!Directory.Exists(text))
{
Directory.CreateDirectory(text);
result = true;
}
path = text;
}
catch (Exception)
{
try
{
path = Path.Combine(Paths.PluginPath, folder);
}
catch
{
path = folder;
}
try
{
Directory.CreateDirectory(path);
}
catch
{
}
}
if (!string.IsNullOrEmpty(readme))
{
try
{
string path2 = Path.Combine(path, "README.txt");
if (!File.Exists(path2))
{
File.WriteAllText(path2, readme);
}
}
catch
{
}
}
return result;
}
}
namespace UniversalAudioReplacer;
public static class AudioHooks
{
[HarmonyPatch(/*Could not decode attribute arguments.*/)]
public class AudioSource_SetClip_Patch
{
[HarmonyPrefix]
public static void Prefix(ref AudioClip value)
{
if (AudioReplacerPlugin.TryGetReplacement(value, out var replacementClip))
{
value = replacementClip;
}
}
}
[HarmonyPatch(typeof(AudioSource), "Play", new Type[] { })]
public class AudioSource_Play_Patch
{
[HarmonyPrefix]
public static void Prefix(AudioSource __instance)
{
if ((Object)(object)__instance != (Object)null && AudioReplacerPlugin.TryGetReplacement(__instance.clip, out var replacementClip) && (Object)(object)__instance.clip != (Object)(object)replacementClip)
{
__instance.clip = replacementClip;
}
}
}
[HarmonyPatch(typeof(AudioSource), "Play", new Type[] { typeof(ulong) })]
public class AudioSource_PlayDelay_Patch
{
[HarmonyPrefix]
public static void Prefix(AudioSource __instance)
{
if ((Object)(object)__instance != (Object)null && AudioReplacerPlugin.TryGetReplacement(__instance.clip, out var replacementClip) && (Object)(object)__instance.clip != (Object)(object)replacementClip)
{
__instance.clip = replacementClip;
}
}
}
[HarmonyPatch(typeof(AudioSource), "PlayDelayed")]
public class AudioSource_PlayDelayed_Patch
{
[HarmonyPrefix]
public static void Prefix(AudioSource __instance)
{
if ((Object)(object)__instance != (Object)null && AudioReplacerPlugin.TryGetReplacement(__instance.clip, out var replacementClip) && (Object)(object)__instance.clip != (Object)(object)replacementClip)
{
__instance.clip = replacementClip;
}
}
}
[HarmonyPatch(typeof(AudioSource), "PlayScheduled")]
public class AudioSource_PlayScheduled_Patch
{
[HarmonyPrefix]
public static void Prefix(AudioSource __instance)
{
if ((Object)(object)__instance != (Object)null && AudioReplacerPlugin.TryGetReplacement(__instance.clip, out var replacementClip) && (Object)(object)__instance.clip != (Object)(object)replacementClip)
{
__instance.clip = replacementClip;
}
}
}
[HarmonyPatch(typeof(AudioSource), "PlayOneShot", new Type[]
{
typeof(AudioClip),
typeof(float)
})]
public class AudioSource_PlayOneShot_Patch
{
[HarmonyPrefix]
public static void Prefix(ref AudioClip clip)
{
if (AudioReplacerPlugin.TryGetReplacement(clip, out var replacementClip))
{
clip = replacementClip;
}
}
}
[HarmonyPatch(typeof(AudioSource), "PlayClipAtPoint", new Type[]
{
typeof(AudioClip),
typeof(Vector3),
typeof(float)
})]
public class AudioSource_PlayClipAtPoint_Patch
{
[HarmonyPrefix]
public static void Prefix(ref AudioClip clip)
{
if (AudioReplacerPlugin.TryGetReplacement(clip, out var replacementClip))
{
clip = replacementClip;
}
}
}
}
[BepInPlugin("com.thehalfbunny.universalaudioreplacer", "Universal Audio Replacer", "2.0.0")]
public class AudioReplacerPlugin : BaseUnityPlugin
{
public static Dictionary<string, AudioClip> loadedCustomClips = new Dictionary<string, AudioClip>(StringComparer.OrdinalIgnoreCase);
public static Dictionary<int, AudioClip> clipCache = new Dictionary<int, AudioClip>();
private static List<UnityWebRequest> activeStreams = new List<UnityWebRequest>();
private readonly Harmony harmony = new Harmony("com.thehalfbunny.universalaudioreplacer");
private const long StreamingThresholdBytes = 10485760L;
private void Awake()
{
((MonoBehaviour)this).StartCoroutine(LoadAudioFiles());
harmony.PatchAll();
SceneManager.sceneLoaded += OnSceneLoaded;
((BaseUnityPlugin)this).Logger.LogInfo((object)"UAReplacer loaded!");
}
private IEnumerator LoadAudioFiles()
{
FolderBootstrap.Ensure(Paths.ConfigPath, "AudioMod", out var defaultFolder, "Drop ur shii in here to make it work ig (ONLY .WAV OR .OGG!!)");
string[] audioFolders = Directory.GetDirectories(Paths.ConfigPath, "AudioMod", SearchOption.AllDirectories);
if (audioFolders.Length == 0)
{
audioFolders = new string[1] { defaultFolder };
}
string[] supportedExtensions = new string[2] { "*.wav", "*.ogg" };
string[] array = audioFolders;
foreach (string folder in array)
{
((BaseUnityPlugin)this).Logger.LogInfo((object)("Scanning for audio in: " + folder));
string[] array2 = supportedExtensions;
foreach (string ext in array2)
{
string[] files = Directory.GetFiles(folder, ext, SearchOption.AllDirectories);
foreach (string file in files)
{
string name = Path.GetFileNameWithoutExtension(file);
AudioType audioType = (AudioType)((ext == "*.wav") ? 20 : 14);
string safeUri = new Uri(file).AbsoluteUri;
long fileSize = new FileInfo(file).Length;
bool shouldStream = fileSize >= 10485760;
UnityWebRequest uwr = UnityWebRequestMultimedia.GetAudioClip(safeUri, audioType);
((DownloadHandlerAudioClip)uwr.downloadHandler).streamAudio = shouldStream;
yield return uwr.SendWebRequest();
if ((int)uwr.result == 1)
{
AudioClip clip = DownloadHandlerAudioClip.GetContent(uwr);
((Object)clip).name = name;
((Object)clip).hideFlags = (HideFlags)32;
if (shouldStream)
{
activeStreams.Add(uwr);
((BaseUnityPlugin)this).Logger.LogInfo((object)("Streaming large file: " + name));
}
else
{
clip.LoadAudioData();
uwr.Dispose();
((BaseUnityPlugin)this).Logger.LogInfo((object)("Loaded into RAM: " + name));
}
loadedCustomClips[name] = clip;
}
else
{
((BaseUnityPlugin)this).Logger.LogError((object)("Failed to load " + name + ". Error: " + uwr.error));
uwr.Dispose();
}
}
}
}
}
private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
{
AudioSource[] array = Resources.FindObjectsOfTypeAll<AudioSource>();
AudioSource[] array2 = array;
foreach (AudioSource val in array2)
{
if ((Object)(object)val.clip != (Object)null && TryGetReplacement(val.clip, out var replacementClip) && (Object)(object)val.clip != (Object)(object)replacementClip)
{
bool isPlaying = val.isPlaying;
bool playOnAwake = val.playOnAwake;
val.clip = replacementClip;
if (((Component)val).gameObject.activeInHierarchy && ((Behaviour)val).enabled && (isPlaying || playOnAwake))
{
val.Play();
}
}
}
}
public static bool TryGetReplacement(AudioClip originalClip, out AudioClip replacementClip)
{
replacementClip = null;
if ((Object)(object)originalClip == (Object)null)
{
return false;
}
int instanceID = ((Object)originalClip).GetInstanceID();
if (clipCache.TryGetValue(instanceID, out var value) && (Object)(object)value != (Object)null)
{
replacementClip = value;
return true;
}
if (loadedCustomClips.TryGetValue(((Object)originalClip).name, out var value2))
{
clipCache[instanceID] = value2;
replacementClip = value2;
return true;
}
return false;
}
}