using System;
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 System.Xml;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using NOMusicReplacer.Patch;
using UnityEngine;
using UnityEngine.Networking;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("NOMusicReplacer")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("NOMusicReplacer")]
[assembly: AssemblyCopyright("Copyright © 2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("290b0796-69ec-4736-9a4b-951bee0793ca")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace NOMusicReplacer
{
[BepInPlugin("Truffle.NOMusicReplacer", "Nuclear Option Music Replacer", "0.30.2.1")]
public class MusicReplacerBase : BaseUnityPlugin
{
private const string modGUID = "Truffle.NOMusicReplacer";
private const string modName = "Nuclear Option Music Replacer";
private const string modVersion = "0.30.2.1";
private readonly Harmony harmony = new Harmony("Truffle.NOMusicReplacer");
internal static Dictionary<string, bool> BundleDict = new Dictionary<string, bool>();
internal static Dictionary<string, List<AudioClip>> AudioDict = new Dictionary<string, List<AudioClip>>();
internal static List<string> PackNames = new List<string>
{
"cricket", "compass", "chicane", "revoker", "tarantula", "ifrit", "medusa", "darkreach", "vortex", "ibis",
"brawler", "win", "loss", "kill", "tactical", "strategic", "title", "pala", "bdf"
};
internal static List<string> PlanePacks = new List<string>
{
"cricket", "compass", "chicane", "revoker", "tarantula", "ifrit", "medusa", "darkreach", "vortex", "ibis",
"brawler"
};
internal static List<string> EventPacks = new List<string> { "win", "loss", "kill", "tactical", "strategic", "title", "pala", "bdf" };
internal static Dictionary<string, string> ConversionDict = new Dictionary<string, string>();
internal static MusicReplacerBase Instance;
internal static ManualLogSource mls;
internal static Random rng = new Random();
internal static bool LoopSetting = false;
internal static string FolderPath;
private XmlDocument settings = new XmlDocument();
private void Awake()
{
if ((Object)(object)Instance == (Object)null)
{
Instance = this;
}
mls = Logger.CreateLogSource("Truffle.NOMusicReplacer");
harmony.PatchAll(typeof(MusicReplacerBase));
harmony.PatchAll(typeof(MusicPatch));
mls.LogInfo((object)"Music Replacer Started");
FolderPath = ((BaseUnityPlugin)Instance).Info.Location;
FolderPath = FolderPath.TrimEnd("NOMusicReplacer.dll".ToCharArray());
settings.Load(FolderPath + "settings.xml");
XmlNode xmlNode = settings.DocumentElement.SelectSingleNode("/Settings");
if (xmlNode != null)
{
string innerText = xmlNode.SelectSingleNode("LoopMusic").InnerText;
bool.TryParse(innerText, out var result);
LoopSetting = result;
}
else
{
mls.LogError((object)"settings.xml corrupted");
}
ConversionDict.Add("Ignition (UnityEngine.AudioClip)", "title");
ConversionDict.Add("9. PALA (UnityEngine.AudioClip)", "pala");
ConversionDict.Add("2. BDF (UnityEngine.AudioClip)", "bdf");
ConversionDict.Add("CI-22 Cricket (UnityEngine.AudioClip)", "cricket");
ConversionDict.Add("Compass_song1 (UnityEngine.AudioClip)", "compass");
ConversionDict.Add("SAH46_Chicane (UnityEngine.AudioClip)", "chicane");
ConversionDict.Add("Furball (UnityEngine.AudioClip)", "revoker");
ConversionDict.Add("18. VL-49 Tarantula (UnityEngine.AudioClip)", "tarantula");
ConversionDict.Add("KR-67_Ifrit_2 (UnityEngine.AudioClip)", "ifrit");
ConversionDict.Add("EW-25_Medusa (UnityEngine.AudioClip)", "medusa");
ConversionDict.Add("SFB81_Darkreach (UnityEngine.AudioClip)", "darkreach");
ConversionDict.Add("FS-20 Vortex (UnityEngine.AudioClip)", "vortex");
ConversionDict.Add("UH-90 Ibis (UnityEngine.AudioClip)", "ibis");
ConversionDict.Add("CAS1 master (UnityEngine.AudioClip)", "brawler");
ConversionDict.Add("Stratosphere_-_fadeout_ending (UnityEngine.AudioClip)", "win");
ConversionDict.Add("Mission_Failed_extended (1) (UnityEngine.AudioClip)", "loss");
ConversionDict.Add("12. Nuclear Escalation (UnityEngine.AudioClip)", "tactical");
ConversionDict.Add("Ignus Balls (UnityEngine.AudioClip)", "tactical");
ConversionDict.Add("3. Port Maris (UnityEngine.AudioClip)", "strategic");
ConversionDict.Add("10. Agrapol (UnityEngine.AudioClip)", "strategic");
ConversionDict.Add("BDF Island Theme 3 (UnityEngine.AudioClip)", "strategic");
ConversionDict.Add("PALA Island theme 2 (UnityEngine.AudioClip)", "strategic");
ConversionDict.Add("Kill_song (UnityEngine.AudioClip)", "kill");
PreloadAudio(FolderPath);
}
internal static AudioClip GetReplacement(string input)
{
List<AudioClip> list = AudioDict[input];
int index = rng.Next(list.Count);
return list[index];
}
private void PreloadAudio(string path)
{
mls.LogInfo((object)("BASEPATH: " + path));
char directorySeparatorChar = Path.DirectorySeparatorChar;
string text = path + "Aircraft" + directorySeparatorChar;
directorySeparatorChar = Path.DirectorySeparatorChar;
string text2 = path + "Events" + directorySeparatorChar;
for (int i = 0; i < PlanePacks.Count; i++)
{
string[] files = Directory.GetFiles(text + PlanePacks[i]);
if (files.Length == 0)
{
mls.LogInfo((object)(PlanePacks[i] + " music not found."));
BundleDict.Add(PlanePacks[i], value: false);
continue;
}
List<AudioClip> list = new List<AudioClip>();
string[] array = files;
foreach (string path2 in array)
{
AudioClip val = LoadSong(path2);
if ((Object)(object)val != (Object)null)
{
list.Add(val);
}
}
if (list.Count == 0)
{
mls.LogInfo((object)(PlanePacks[i] + " music not found."));
BundleDict.Add(PlanePacks[i], value: false);
}
else
{
BundleDict.Add(PlanePacks[i], value: true);
AudioDict.Add(PlanePacks[i], list);
mls.LogInfo((object)(PlanePacks[i] + " asset bundle loaded"));
}
}
for (int k = 0; k < EventPacks.Count; k++)
{
string[] files2 = Directory.GetFiles(text2 + EventPacks[k]);
if (files2.Length == 0)
{
mls.LogInfo((object)(EventPacks[k] + " music not found."));
BundleDict.Add(EventPacks[k], value: false);
continue;
}
List<AudioClip> list2 = new List<AudioClip>();
string[] array2 = files2;
foreach (string path3 in array2)
{
AudioClip val2 = LoadSong(path3);
if ((Object)(object)val2 != (Object)null)
{
list2.Add(val2);
}
}
if (list2.Count == 0)
{
mls.LogInfo((object)(EventPacks[k] + " music not found."));
BundleDict.Add(EventPacks[k], value: false);
}
else
{
BundleDict.Add(EventPacks[k], value: true);
AudioDict.Add(EventPacks[k], list2);
mls.LogInfo((object)(EventPacks[k] + " asset bundle loaded"));
}
}
}
private AudioClip LoadSong(string path)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
//IL_000a: Invalid comparison between Unknown and I4
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_0075: Unknown result type (might be due to invalid IL or missing references)
//IL_007b: Invalid comparison between Unknown and I4
AudioType audioType = GetAudioType(path);
if ((int)audioType == 0)
{
return null;
}
UnityWebRequest audioClip = UnityWebRequestMultimedia.GetAudioClip(path, audioType);
audioClip.SendWebRequest();
while (!audioClip.isDone)
{
}
if (audioClip.error != null)
{
mls.LogError((object)audioClip.error);
return null;
}
AudioClip content = DownloadHandlerAudioClip.GetContent(audioClip);
if (Object.op_Implicit((Object)(object)content) && (int)content.loadState == 2)
{
((Object)content).name = path.TrimStart(FolderPath.ToCharArray());
return content;
}
mls.LogError((object)("Failed to load clip:" + path));
return null;
}
private static AudioType GetAudioType(string path)
{
//IL_001e: Unknown result type (might be due to invalid IL or missing references)
//IL_0032: Unknown result type (might be due to invalid IL or missing references)
//IL_0065: Unknown result type (might be due to invalid IL or missing references)
//IL_0062: Unknown result type (might be due to invalid IL or missing references)
//IL_0048: Unknown result type (might be due to invalid IL or missing references)
switch (Path.GetExtension(path).ToLower())
{
case ".wav":
return (AudioType)20;
case ".ogg":
return (AudioType)14;
case ".mp3":
return (AudioType)13;
default:
mls.LogError((object)("Unsupported extension: " + path));
return (AudioType)0;
}
}
}
}
namespace NOMusicReplacer.Patch
{
[HarmonyPatch(typeof(MusicManager))]
internal class MusicPatch
{
[HarmonyPatch("PlayMusic")]
[HarmonyPrefix]
private static void SwapTheme(ref AudioClip audioClip, ref bool repeat)
{
repeat = MusicReplacerBase.LoopSetting;
string text = ((object)audioClip).ToString();
AudioClip newSong = GetNewSong(text);
if ((Object)(object)newSong != (Object)null)
{
audioClip = newSong;
MusicReplacerBase.mls.LogInfo((object)("Replaced: " + text + " with: " + ((object)newSong).ToString()));
}
else
{
MusicReplacerBase.mls.LogError((object)(text + " resulted in a failed pull from an asset bundle"));
}
}
[HarmonyPatch("CrossFadeMusic")]
[HarmonyPrefix]
private static void SwapCrossTheme(ref AudioClip audioClip, ref bool repeat)
{
repeat = MusicReplacerBase.LoopSetting;
string text = ((object)audioClip).ToString();
AudioClip newSong = GetNewSong(text);
if ((Object)(object)newSong != (Object)null)
{
audioClip = newSong;
MusicReplacerBase.mls.LogInfo((object)("Replaced: " + text + " with: " + ((object)newSong).ToString()));
}
}
private static AudioClip GetNewSong(string song_title)
{
if (!MusicReplacerBase.ConversionDict.ContainsKey(song_title))
{
MusicReplacerBase.mls.LogError((object)(song_title + " resulted in a failed pull."));
return null;
}
string text = MusicReplacerBase.ConversionDict[song_title];
if (!MusicReplacerBase.BundleDict[text])
{
MusicReplacerBase.mls.LogInfo((object)("Asset Bundle not found, playing " + song_title));
return null;
}
return MusicReplacerBase.GetReplacement(text);
}
}
}