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.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
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: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("com.mthwj.minecraftmusic")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("0.1.0.0")]
[assembly: AssemblyInformationalVersion("0.1.0")]
[assembly: AssemblyProduct("com.mthwj.minecraftmusic")]
[assembly: AssemblyTitle("MinecraftMusicPlugin")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.1.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.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
internal sealed class NullableAttribute : Attribute
{
public readonly byte[] NullableFlags;
public NullableAttribute(byte P_0)
{
NullableFlags = new byte[1] { P_0 };
}
public NullableAttribute(byte[] P_0)
{
NullableFlags = P_0;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
internal sealed class NullableContextAttribute : Attribute
{
public readonly byte Flag;
public NullableContextAttribute(byte P_0)
{
Flag = P_0;
}
}
[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 BepInEx
{
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
[Conditional("CodeGeneration")]
internal sealed class BepInAutoPluginAttribute : Attribute
{
public BepInAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
{
}
}
}
namespace BepInEx.Preloader.Core.Patching
{
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
[Conditional("CodeGeneration")]
internal sealed class PatcherAutoPluginAttribute : Attribute
{
public PatcherAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
{
}
}
}
namespace MinecraftMusicPlugin
{
[BepInPlugin("com.mthwj.minecraftmusic", "MinecraftMusicPlugin", "0.1.0")]
public class Plugin : BaseUnityPlugin
{
[HarmonyPatch(typeof(AmbienceAudio), "FixedUpdate")]
private static class AmbienceAudio_FixedUpdate_Patch
{
[CompilerGenerated]
private sealed class <LoadAndFadeAudio>d__5 : IEnumerator<object>, IEnumerator, IDisposable
{
private int <>1__state;
private object <>2__current;
public MonoBehaviour context;
public string path;
public string region;
private AudioSource <source>5__1;
private float <targetVolume>5__2;
private bool <needsFadeOut>5__3;
private float <timer>5__4;
private float <startVolume>5__5;
private UnityWebRequest <uwr>5__6;
private AudioClip <clip>5__7;
private float <fadeInTimer>5__8;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <LoadAndFadeAudio>d__5(int <>1__state)
{
this.<>1__state = <>1__state;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
int num = <>1__state;
if (num == -3 || (uint)(num - 2) <= 1u)
{
try
{
}
finally
{
<>m__Finally1();
}
}
<source>5__1 = null;
<uwr>5__6 = null;
<clip>5__7 = null;
<>1__state = -2;
}
private bool MoveNext()
{
//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
//IL_01fa: Invalid comparison between Unknown and I4
bool result;
try
{
ManualLogSource? logger7;
switch (<>1__state)
{
default:
result = false;
goto end_IL_0000;
case 0:
{
<>1__state = -1;
<source>5__1 = ((Component)context).GetComponent<AmbienceAudio>().mainMusic;
<targetVolume>5__2 = Mathf.Max(<source>5__1.volume, 0.5f);
<needsFadeOut>5__3 = isMusicPlaying && HasRegionSpecificMusic(region, out string _);
if (<needsFadeOut>5__3)
{
ManualLogSource? logger8 = Logger;
if (logger8 != null)
{
logger8.LogDebug((object)("Fading out current track for " + region));
}
<timer>5__4 = 0f;
<startVolume>5__5 = <source>5__1.volume;
goto IL_0132;
}
goto IL_0180;
}
case 1:
<>1__state = -1;
goto IL_0132;
case 2:
{
<>1__state = -3;
if ((int)<uwr>5__6.result != 1)
{
ManualLogSource? logger = Logger;
if (logger != null)
{
logger.LogError((object)("Failed to load MP3: " + <uwr>5__6.error));
}
result = false;
break;
}
<clip>5__7 = DownloadHandlerAudioClip.GetContent(<uwr>5__6);
if ((Object)(object)<clip>5__7 == (Object)null)
{
ManualLogSource? logger2 = Logger;
if (logger2 != null)
{
logger2.LogError((object)("Failed to create AudioClip from " + path + ": Null clip"));
}
result = false;
break;
}
ManualLogSource? logger3 = Logger;
if (logger3 != null)
{
logger3.LogInfo((object)$"MP3 loaded, length: {<clip>5__7.length} seconds");
}
<source>5__1.clip = <clip>5__7;
<source>5__1.volume = 0f;
<source>5__1.Play();
ManualLogSource? logger4 = Logger;
if (logger4 != null)
{
logger4.LogDebug((object)("Fading in new track: " + Path.GetFileName(path)));
}
<fadeInTimer>5__8 = 0f;
goto IL_036a;
}
case 3:
{
<>1__state = -3;
goto IL_036a;
}
IL_036a:
if (<fadeInTimer>5__8 < 1f)
{
<fadeInTimer>5__8 += Time.deltaTime;
<source>5__1.volume = Mathf.Lerp(0f, <targetVolume>5__2, <fadeInTimer>5__8 / 1f);
<>2__current = null;
<>1__state = 3;
result = true;
}
else
{
<source>5__1.volume = <targetVolume>5__2;
isMusicPlaying = true;
ManualLogSource? logger5 = Logger;
if (logger5 != null)
{
logger5.LogInfo((object)("Playing MP3 via mainMusic: " + Path.GetFileName(path)));
}
<clip>5__7 = null;
<>m__Finally1();
<uwr>5__6 = null;
result = false;
}
goto end_IL_0000;
IL_0132:
if (!(<timer>5__4 < 1f))
{
<source>5__1.Stop();
<source>5__1.clip = null;
ManualLogSource? logger6 = Logger;
if (logger6 != null)
{
logger6.LogDebug((object)("Stopped previous track for " + region));
}
goto IL_0180;
}
<timer>5__4 += Time.deltaTime;
<source>5__1.volume = Mathf.Lerp(<startVolume>5__5, 0f, <timer>5__4 / 1f);
<>2__current = null;
<>1__state = 1;
result = true;
goto end_IL_0000;
IL_0180:
logger7 = Logger;
if (logger7 != null)
{
logger7.LogInfo((object)("Starting to load MP3 from: " + path));
}
<uwr>5__6 = UnityWebRequestMultimedia.GetAudioClip("file:///" + path, (AudioType)13);
<>1__state = -3;
<>2__current = <uwr>5__6.SendWebRequest();
<>1__state = 2;
result = true;
goto end_IL_0000;
}
<>m__Finally1();
end_IL_0000:;
}
catch
{
//try-fault
((IDisposable)this).Dispose();
throw;
}
return result;
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
private void <>m__Finally1()
{
<>1__state = -1;
if (<uwr>5__6 != null)
{
((IDisposable)<uwr>5__6).Dispose();
}
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
}
private static bool Prefix(AmbienceAudio __instance)
{
//IL_0080: Unknown result type (might be due to invalid IL or missing references)
//IL_0092: Unknown result type (might be due to invalid IL or missing references)
Transform transform = ((Component)__instance).transform;
object obj;
if (transform == null)
{
obj = null;
}
else
{
Transform root = transform.root;
obj = ((root != null) ? ((Component)root).GetComponent<CharacterData>() : null);
}
CharacterData val = (CharacterData)obj;
if ((Object)(object)val == (Object)null)
{
ManualLogSource? logger = Logger;
if (logger != null)
{
logger.LogWarning((object)"CharacterData component not found on root transform");
}
return true;
}
if (val.sinceDead > 0.5f && !val.passedOut && !val.dead && !val.fullyPassedOut)
{
float z = ((Component)__instance).transform.position.z;
float y = ((Component)__instance).transform.position.y;
isMusicPlaying = __instance.mainMusic.isPlaying && (Object)(object)__instance.mainMusic.clip != (Object)null;
ManualLogSource? logger2 = Logger;
if (logger2 != null)
{
logger2.LogDebug((object)$"Position: z={z}, y={y}, isMusicPlaying={isMusicPlaying}, mainMusicVolume={__instance.mainMusic.volume}");
}
if (z > __instance.beachStingerZ && !__instance.playedBeach)
{
ManualLogSource? logger3 = Logger;
if (logger3 != null)
{
logger3.LogInfo((object)"Entered beach region, overriding with Minecraft music");
}
TryPlayMusicForRegion((MonoBehaviour)(object)__instance, "Beach");
__instance.playedBeach = true;
return false;
}
if (z > __instance.tropicsStingerZ && !__instance.playedTropics)
{
ManualLogSource? logger4 = Logger;
if (logger4 != null)
{
logger4.LogInfo((object)"Entered tropics region, overriding with Minecraft music");
}
TryPlayMusicForRegion((MonoBehaviour)(object)__instance, "Tropics");
__instance.playedTropics = true;
return false;
}
if (z > __instance.alpineStingerZ && !__instance.playedAlpine)
{
ManualLogSource? logger5 = Logger;
if (logger5 != null)
{
logger5.LogInfo((object)"Entered alpine region, overriding with Minecraft music");
}
TryPlayMusicForRegion((MonoBehaviour)(object)__instance, "Alpine");
__instance.playedAlpine = true;
return false;
}
if (z > __instance.calderaStingerZ && !__instance.playedCaldera)
{
ManualLogSource? logger6 = Logger;
if (logger6 != null)
{
logger6.LogInfo((object)"Entered caldera region, overriding with Minecraft music");
}
TryPlayMusicForRegion((MonoBehaviour)(object)__instance, "Caldera");
__instance.playedCaldera = true;
return false;
}
if (y > __instance.kilnStingerY && !__instance.playedKiln)
{
ManualLogSource? logger7 = Logger;
if (logger7 != null)
{
logger7.LogInfo((object)"Entered kiln region, overriding with Minecraft music");
}
TryPlayMusicForRegion((MonoBehaviour)(object)__instance, "Kiln");
__instance.playedKiln = true;
return false;
}
if (z > __instance.peaksTingerZ && !__instance.playedPeak)
{
ManualLogSource? logger8 = Logger;
if (logger8 != null)
{
logger8.LogInfo((object)"Entered peak region, overriding with Minecraft music");
}
TryPlayMusicForRegion((MonoBehaviour)(object)__instance, "Peak");
__instance.playedPeak = true;
return false;
}
if (!isMusicPlaying && (Object)(object)__instance.mainMusic.clip != (Object)null)
{
string currentRegion = GetCurrentRegion(__instance);
ManualLogSource? logger9 = Logger;
if (logger9 != null)
{
logger9.LogInfo((object)("Current track ended, playing new random MP3 for " + currentRegion));
}
TryPlayMusicForRegion((MonoBehaviour)(object)__instance, currentRegion);
return false;
}
}
else
{
ManualLogSource? logger10 = Logger;
if (logger10 != null)
{
logger10.LogInfo((object)"Character conditions not met, fading out music");
}
__instance.mainMusic.volume = Mathf.Lerp(__instance.mainMusic.volume, 0f, Time.deltaTime / 1f);
}
return true;
}
private static string GetCurrentRegion(AmbienceAudio __instance)
{
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
float z = ((Component)__instance).transform.position.z;
float y = ((Component)__instance).transform.position.y;
if (y > __instance.kilnStingerY)
{
return "Kiln";
}
if (z > __instance.peaksTingerZ)
{
return "Peak";
}
if (z > __instance.calderaStingerZ)
{
return "Caldera";
}
if (z > __instance.alpineStingerZ)
{
return "Alpine";
}
if (z > __instance.tropicsStingerZ)
{
return "Tropics";
}
if (z > __instance.beachStingerZ)
{
return "Beach";
}
return "Default";
}
private static bool HasRegionSpecificMusic(string region, out string folderPath)
{
if (1 == 0)
{
}
string text = region switch
{
"Beach" => beachFolderConfig.Value.Trim(),
"Tropics" => tropicsFolderConfig.Value.Trim(),
"Alpine" => alpineFolderConfig.Value.Trim(),
"Caldera" => calderaFolderConfig.Value.Trim(),
"Kiln" => kilnFolderConfig.Value.Trim(),
"Peak" => peakFolderConfig.Value.Trim(),
_ => defaultFolderConfig.Value.Trim(),
};
if (1 == 0)
{
}
string text2 = text;
folderPath = (Path.IsPathRooted(text2) ? text2 : Path.Combine(musicFolder, text2));
if (region == "Default" || !Directory.Exists(folderPath) || Directory.GetFiles(folderPath, "*.mp3").Length == 0)
{
folderPath = Path.Combine(musicFolder, defaultFolderConfig.Value.Trim());
return false;
}
return true;
}
private static void TryPlayMusicForRegion(MonoBehaviour context, string region)
{
if (!HasRegionSpecificMusic(region, out string folderPath) && currentRegion == "Default" && isMusicPlaying)
{
ManualLogSource? logger = Logger;
if (logger != null)
{
logger.LogDebug((object)("Skipping playback for " + region + " as already playing from Default"));
}
}
else
{
PlayRandomMp3(context, region, folderPath);
currentRegion = (HasRegionSpecificMusic(region, out string _) ? region : "Default");
}
}
private static void PlayRandomMp3(MonoBehaviour context, string region, string folderPath)
{
if (!Directory.Exists(folderPath))
{
ManualLogSource? logger = Logger;
if (logger != null)
{
logger.LogError((object)("No MP3s available for " + region + " or Default at " + folderPath + "!"));
}
return;
}
string[] files = Directory.GetFiles(folderPath, "*.mp3");
if (files.Length == 0)
{
ManualLogSource? logger2 = Logger;
if (logger2 != null)
{
logger2.LogError((object)("No MP3 files found in " + folderPath + " for " + region + "!"));
}
}
else
{
Random random = new Random();
string path = files[random.Next(files.Length)];
ManualLogSource? logger3 = Logger;
if (logger3 != null)
{
logger3.LogInfo((object)("Loading MP3 for " + region + ": " + Path.GetFileName(path)));
}
context.StartCoroutine(LoadAndFadeAudio(context, path, region));
}
}
[IteratorStateMachine(typeof(<LoadAndFadeAudio>d__5))]
private static IEnumerator LoadAndFadeAudio(MonoBehaviour context, string path, string region)
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <LoadAndFadeAudio>d__5(0)
{
context = context,
path = path,
region = region
};
}
}
internal static ManualLogSource? Logger;
private static string musicFolder = string.Empty;
private static bool isMusicPlaying = false;
private static ConfigEntry<string> beachFolderConfig = null;
private static ConfigEntry<string> tropicsFolderConfig = null;
private static ConfigEntry<string> alpineFolderConfig = null;
private static ConfigEntry<string> calderaFolderConfig = null;
private static ConfigEntry<string> kilnFolderConfig = null;
private static ConfigEntry<string> peakFolderConfig = null;
private static ConfigEntry<string> defaultFolderConfig = null;
private static string currentRegion = "Default";
private const float FADE_DURATION = 1f;
public const string Id = "com.mthwj.minecraftmusic";
public static string Name => "MinecraftMusicPlugin";
public static string Version => "0.1.0";
private void Awake()
{
//IL_015b: Unknown result type (might be due to invalid IL or missing references)
//IL_0161: Expected O, but got Unknown
Logger = ((BaseUnityPlugin)this).Logger;
musicFolder = Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location) ?? throw new InvalidOperationException("Plugin location not found"), "CustomBackgroundMusic");
ManualLogSource? logger = Logger;
if (logger != null)
{
logger.LogInfo((object)("Plugin com.mthwj.minecraftmusic is loaded! Music folder: " + musicFolder));
}
beachFolderConfig = ((BaseUnityPlugin)this).Config.Bind<string>("MusicFolders", "BeachFolder", "Beach", "Folder for Beach region music (relative to CustomBackgroundMusic or absolute path).");
tropicsFolderConfig = ((BaseUnityPlugin)this).Config.Bind<string>("MusicFolders", "TropicsFolder", "Tropics", "Folder for Tropics region music (relative to CustomBackgroundMusic or absolute path).");
alpineFolderConfig = ((BaseUnityPlugin)this).Config.Bind<string>("MusicFolders", "AlpineFolder", "Alpine", "Folder for Alpine region music (relative to CustomBackgroundMusic or absolute path).");
calderaFolderConfig = ((BaseUnityPlugin)this).Config.Bind<string>("MusicFolders", "CalderaFolder", "Caldera", "Folder for Caldera region music (relative to CustomBackgroundMusic or absolute path).");
kilnFolderConfig = ((BaseUnityPlugin)this).Config.Bind<string>("MusicFolders", "KilnFolder", "Kiln", "Folder for Kiln region music (relative to CustomBackgroundMusic or absolute path).");
peakFolderConfig = ((BaseUnityPlugin)this).Config.Bind<string>("MusicFolders", "PeakFolder", "Peak", "Folder for Peak region music (relative to CustomBackgroundMusic or absolute path).");
defaultFolderConfig = ((BaseUnityPlugin)this).Config.Bind<string>("MusicFolders", "DefaultFolder", "Default", "Fallback folder if region-specific folder is missing or empty (relative to CustomBackgroundMusic or absolute path).");
Harmony val = new Harmony("com.mthwj.minecraftmusic.patch");
val.PatchAll();
ManualLogSource? logger2 = Logger;
if (logger2 != null)
{
logger2.LogInfo((object)"Harmony patches applied successfully");
}
}
}
}
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
internal sealed class IgnoresAccessChecksToAttribute : Attribute
{
public IgnoresAccessChecksToAttribute(string assemblyName)
{
}
}
}