Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of Death Guanyu Song v2.1.0
DeathMusicMod.dll
Decompiled 11 hours agousing System; using System.Collections; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using UnityEngine; using UnityEngine.Networking; [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: AssemblyCopyright("Copyright © 2026")] [assembly: CompilationRelaxations(8)] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("RepoFirstMod")] [assembly: AssemblyTitle("RepoFirstMod")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("0f4ffe05-9a3f-4605-9876-fe6a1584ccad")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyVersion("1.0.0.0")] namespace DeathMusicMod; [BepInPlugin("com.lhd.deathmusic", "死亡播放关羽之歌", "2.0.0")] public class Plugin : BaseUnityPlugin { public static ConfigEntry<bool> ModEnabled; public static ConfigEntry<float> MusicVolume; public static ConfigEntry<float> MusicDuration; public static ManualLogSource ModLogger; public static AudioClip DeathClip; public static GameObject MusicPlayerObject; public static DeathMusicPlayer MusicPlayer; public static float LastDeathTime = -999f; private void Awake() { //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Expected O, but got Unknown //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Expected O, but got Unknown //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Expected O, but got Unknown //IL_0163: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Expected O, but got Unknown //IL_01e0: Unknown result type (might be due to invalid IL or missing references) //IL_01ed: Expected O, but got Unknown //IL_0252: Unknown result type (might be due to invalid IL or missing references) //IL_025f: Expected O, but got Unknown ModLogger = ((BaseUnityPlugin)this).Logger; ModEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enable Mod", true, "是否启用关羽之歌。关闭后死亡不再播放"); MusicVolume = ((BaseUnityPlugin)this).Config.Bind<float>("General", "Music Volume", 1f, new ConfigDescription("关羽之歌的音量大小(1.0 = 与游戏BGM同等音量)", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1.5f), new object[0])); MusicDuration = ((BaseUnityPlugin)this).Config.Bind<float>("General", "Music Duration", 8f, new ConfigDescription("关羽之歌的播放时长(秒)", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 16f), new object[0])); MusicPlayerObject = new GameObject("DeathMusicPlayer"); Object.DontDestroyOnLoad((Object)(object)MusicPlayerObject); MusicPlayer = MusicPlayerObject.AddComponent<DeathMusicPlayer>(); ((MonoBehaviour)this).StartCoroutine(LoadAudioClip()); ((BaseUnityPlugin)this).Logger.LogInfo((object)"=== 死亡播放关羽之歌 Mod v2.0 已加载 ==="); ((BaseUnityPlugin)this).Logger.LogInfo((object)("音量: " + MusicVolume.Value + " | 时长: " + MusicDuration.Value + "秒 | 启用: " + ModEnabled.Value)); Harmony val = new Harmony("com.lhd.deathmusic"); MethodInfo method = typeof(PlayerAvatar).GetMethod("PlayerDeath"); MethodInfo method2 = typeof(PlayerAvatar).GetMethod("PlayerDeathRPC"); MethodInfo method3 = typeof(PlayerDeathLocalPatch).GetMethod("Postfix"); MethodInfo method4 = typeof(PlayerDeathRPCPatch).GetMethod("Postfix"); if (method != null && method3 != null) { val.Patch((MethodBase)method, (HarmonyMethod)null, new HarmonyMethod(method3), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); ((BaseUnityPlugin)this).Logger.LogInfo((object)("PlayerDeath Patch 已注入: " + method.DeclaringType.Name + "." + method.Name)); } else { ((BaseUnityPlugin)this).Logger.LogError((object)"PlayerDeath Patch 注入失败!原始方法或 Postfix 为 null"); } if (method2 != null && method4 != null) { val.Patch((MethodBase)method2, (HarmonyMethod)null, new HarmonyMethod(method4), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); ((BaseUnityPlugin)this).Logger.LogInfo((object)("PlayerDeathRPC Patch 已注入: " + method2.DeclaringType.Name + "." + method2.Name)); } else { ((BaseUnityPlugin)this).Logger.LogError((object)"PlayerDeathRPC Patch 注入失败!原始方法或 Postfix 为 null"); } ((BaseUnityPlugin)this).Logger.LogInfo((object)"Harmony Patch 注入完成。监控 PlayerDeath + PlayerDeathRPC 中..."); } public static void TriggerDeathMusicSafe() { //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Expected O, but got Unknown if ((Object)(object)MusicPlayer == (Object)null) { GameObject val = GameObject.Find("DeathMusicPlayer"); if ((Object)(object)val != (Object)null) { MusicPlayer = val.GetComponent<DeathMusicPlayer>(); } if ((Object)(object)MusicPlayer == (Object)null) { ModLogger.LogWarning((object)"MusicPlayer 已被销毁,正在重建..."); MusicPlayerObject = new GameObject("DeathMusicPlayer"); Object.DontDestroyOnLoad((Object)(object)MusicPlayerObject); MusicPlayer = MusicPlayerObject.AddComponent<DeathMusicPlayer>(); ModLogger.LogInfo((object)"MusicPlayer 重建完成"); } } if ((Object)(object)MusicPlayer != (Object)null) { MusicPlayer.TriggerDeathMusic(); } else { Debug.LogError((object)"[关羽之歌] MusicPlayer 重建失败!"); } } private IEnumerator LoadAudioClip() { string dllPath = Assembly.GetExecutingAssembly().Location; string modDir = Path.GetDirectoryName(dllPath); string audioPath = Path.Combine(modDir, "关羽之歌.WAV"); if (!File.Exists(audioPath)) { audioPath = "D:\\REPO_mods\\DeathMusicMod\\关羽之歌.WAV"; } if (!File.Exists(audioPath)) { ModLogger.LogError((object)("找不到关羽之歌文件!请把 关羽之歌.WAV 放在 " + modDir)); yield break; } string url = "file:///" + audioPath.Replace('\\', '/'); ModLogger.LogInfo((object)("正在加载关羽之歌: " + audioPath)); UnityWebRequest www = UnityWebRequestMultimedia.GetAudioClip(url, (AudioType)20); try { yield return www.SendWebRequest(); if ((int)www.result == 1) { DeathClip = DownloadHandlerAudioClip.GetContent(www); ModLogger.LogInfo((object)("关羽之歌加载成功!时长: " + DeathClip.length + "秒, 采样率: " + DeathClip.frequency + "Hz")); } else { ModLogger.LogError((object)("关羽之歌加载失败: " + www.error)); } } finally { ((IDisposable)www)?.Dispose(); } } } public class DeathMusicPlayer : MonoBehaviour { private AudioSource audioSource; private bool isPlaying; private Coroutine stopCoroutine; private static FieldInfo constantMusicSourceField; private static FieldInfo constantMusicVolumeField; private static FieldInfo levelMusicSourceField; private float bgmSavedVolume = -1f; private void Awake() { audioSource = ((Component)this).gameObject.AddComponent<AudioSource>(); audioSource.playOnAwake = false; audioSource.loop = false; audioSource.spatialBlend = 0f; CacheReflectionFields(); } private static void CacheReflectionFields() { BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; try { Type typeFromHandle = typeof(ConstantMusic); constantMusicSourceField = typeFromHandle.GetField("audioSource", bindingAttr); constantMusicVolumeField = typeFromHandle.GetField("volume", bindingAttr); } catch { } try { Type typeFromHandle2 = typeof(LevelMusic); levelMusicSourceField = typeFromHandle2.GetField("audioSource", bindingAttr); } catch { } } public void TriggerDeathMusic() { if (!Plugin.ModEnabled.Value) { return; } if ((Object)(object)Plugin.DeathClip == (Object)null) { Plugin.ModLogger.LogWarning((object)"关羽之歌文件尚未加载完成,跳过"); return; } float time = Time.time; if (time - Plugin.LastDeathTime < 5f) { Plugin.ModLogger.LogInfo((object)("距上次死亡 " + (time - Plugin.LastDeathTime).ToString("F1") + " 秒 < 5 秒,继续当前播放")); Plugin.LastDeathTime = time; return; } Plugin.LastDeathTime = time; if (stopCoroutine != null) { ((MonoBehaviour)this).StopCoroutine(stopCoroutine); } ((MonoBehaviour)this).StartCoroutine(PlayAfterDelay(1f)); } private IEnumerator PlayAfterDelay(float delay) { yield return (object)new WaitForSeconds(delay); if (!((Object)(object)Plugin.DeathClip == (Object)null)) { audioSource.clip = Plugin.DeathClip; audioSource.volume = Plugin.MusicVolume.Value; audioSource.Play(); isPlaying = true; DuckBGM(0.5f); float duration = Mathf.Min(Plugin.MusicDuration.Value, Plugin.DeathClip.length); if (duration <= 0f) { duration = Plugin.DeathClip.length; } stopCoroutine = ((MonoBehaviour)this).StartCoroutine(StopAfterDuration(duration)); Plugin.ModLogger.LogInfo((object)("关羽之歌播放中... 音量:" + Plugin.MusicVolume.Value + " 时长:" + duration + "秒 | BGM已压低至0.5倍")); } } private IEnumerator StopAfterDuration(float duration) { yield return (object)new WaitForSeconds(duration); StopMusic(); } private void StopMusic() { if (audioSource.isPlaying) { audioSource.Stop(); } isPlaying = false; RestoreBGM(); Plugin.ModLogger.LogInfo((object)"关羽之歌播放结束,BGM 已恢复"); } private void DuckBGM(float multiplier) { try { if ((Object)(object)ConstantMusic.instance != (Object)null && constantMusicSourceField != null) { object? value = constantMusicSourceField.GetValue(ConstantMusic.instance); AudioSource val = (AudioSource)((value is AudioSource) ? value : null); if ((Object)(object)val != (Object)null) { bgmSavedVolume = val.volume; val.volume = bgmSavedVolume * multiplier; Plugin.ModLogger.LogInfo((object)("ConstantMusic 音量: " + bgmSavedVolume + " -> " + val.volume)); } } if ((Object)(object)LevelMusic.instance != (Object)null && levelMusicSourceField != null) { object? value2 = levelMusicSourceField.GetValue(LevelMusic.instance); AudioSource val = (AudioSource)((value2 is AudioSource) ? value2 : null); if ((Object)(object)val != (Object)null) { AudioSource obj = val; obj.volume *= multiplier; Plugin.ModLogger.LogInfo((object)"LevelMusic 音量已压低"); } } } catch (Exception ex) { Plugin.ModLogger.LogWarning((object)("压低 BGM 失败: " + ex.Message)); } } private void RestoreBGM() { try { if ((Object)(object)ConstantMusic.instance != (Object)null && constantMusicSourceField != null && bgmSavedVolume > 0f) { object? value = constantMusicSourceField.GetValue(ConstantMusic.instance); AudioSource val = (AudioSource)((value is AudioSource) ? value : null); if ((Object)(object)val != (Object)null) { val.volume = bgmSavedVolume; Plugin.ModLogger.LogInfo((object)("ConstantMusic 音量已恢复: " + bgmSavedVolume)); } } } catch { } bgmSavedVolume = -1f; } private void Update() { if (isPlaying && !audioSource.isPlaying && audioSource.time > 0f) { isPlaying = false; RestoreBGM(); } } private void OnDestroy() { RestoreBGM(); } } [HarmonyPatch(typeof(PlayerAvatar), "PlayerDeathRPC")] public static class PlayerDeathRPCPatch { [HarmonyPostfix] public static void Postfix() { Debug.Log((object)"[关羽之歌] !!! PlayerDeathRPC 被调用了!(联机死亡)"); Plugin.TriggerDeathMusicSafe(); } } [HarmonyPatch(typeof(PlayerAvatar), "PlayerDeath")] public static class PlayerDeathLocalPatch { [HarmonyPostfix] public static void Postfix() { Debug.Log((object)"[关羽之歌] !!! PlayerDeath 被调用了!(本地死亡)"); Plugin.TriggerDeathMusicSafe(); } }