Decompiled source of DeathTunes v1.0.0

DeathTunes/DeathTunes.dll

Decompiled 4 hours ago
using 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.Threading;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using LethalNetworkAPI;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Networking;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("DeathTunes")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("DeathTunes")]
[assembly: AssemblyCopyright("Copyright ©  2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("3bc8e91e-4245-4e07-9d3d-f9b30954ac9d")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.0.0")]
internal class EmptyMonoBehaviour : MonoBehaviour
{
}
namespace DeathTunes;

public static class DeathCustomizationManager
{
	[Serializable]
	[CompilerGenerated]
	private sealed class <>c
	{
		public static readonly <>c <>9 = new <>c();

		public static UnityAction <>9__10_2;

		internal void <OpenMenu>b__10_2()
		{
			PlaySelectedSound();
		}
	}

	public static Dictionary<string, AudioClip> Sounds = new Dictionary<string, AudioClip>();

	public static List<string> SoundIDs = new List<string>();

	public static string SelectedSound = "";

	private static int soundIndex = 0;

	public static string PendingSoundSelection = null;

	private static GameObject menu;

	public static int CurrentSoundIndex => soundIndex;

	private static void SendPlayerSound(PlayerControllerB player)
	{
		ulong playerSteamId = player.playerSteamId;
		DeathTunesPlugin.Log.LogInfo((object)("Sending sound '" + SelectedSound + "' for SteamID " + playerSteamId));
		DeathSoundNetworking.SendSelection(playerSteamId, SelectedSound);
	}

	public static void LoadSounds()
	{
		string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
		List<string> list = new List<string>();
		DeathTunesPlugin.Log.LogInfo((object)"Searching for death sounds...");
		string path = Path.Combine(directoryName, "Sounds");
		if (Directory.Exists(path))
		{
			list.AddRange(Directory.GetFiles(path, "*.wav", SearchOption.AllDirectories));
		}
		list.AddRange(Directory.GetFiles(directoryName, "*.wav", SearchOption.TopDirectoryOnly));
		list = list.Distinct().ToList();
		foreach (string item in list)
		{
			AudioClip val = DeathTunesPlugin.Instance.LoadWav(item);
			if ((Object)(object)val != (Object)null)
			{
				string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(item);
				if (!Sounds.ContainsKey(fileNameWithoutExtension))
				{
					Sounds.Add(fileNameWithoutExtension, val);
					SoundIDs.Add(fileNameWithoutExtension);
					DeathTunesPlugin.Log.LogInfo((object)("Loaded death sound: " + fileNameWithoutExtension));
				}
			}
		}
		if (SoundIDs.Count > 0)
		{
			string value = DeathTunesPlugin.SavedDeathSound.Value;
			if (!string.IsNullOrEmpty(value) && Sounds.ContainsKey(value))
			{
				SelectedSound = value;
			}
			else
			{
				SelectedSound = SoundIDs[0];
			}
		}
		DeathTunesPlugin.Log.LogInfo((object)("Total death sounds loaded: " + Sounds.Count));
	}

	public static void OpenMenu()
	{
		//IL_002f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0039: Expected O, but got Unknown
		//IL_007e: Unknown result type (might be due to invalid IL or missing references)
		//IL_008d: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0135: 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_015e: Expected O, but got Unknown
		//IL_0174: Unknown result type (might be due to invalid IL or missing references)
		//IL_0193: Unknown result type (might be due to invalid IL or missing references)
		//IL_019d: Expected O, but got Unknown
		//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_0205: Unknown result type (might be due to invalid IL or missing references)
		//IL_0224: Unknown result type (might be due to invalid IL or missing references)
		//IL_022e: Expected O, but got Unknown
		//IL_01df: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ea: Expected O, but got Unknown
		if ((Object)(object)menu != (Object)null)
		{
			menu.SetActive(true);
			return;
		}
		menu = new GameObject("DeathTunesMenu");
		Canvas val = menu.AddComponent<Canvas>();
		val.renderMode = (RenderMode)0;
		CanvasScaler val2 = menu.AddComponent<CanvasScaler>();
		val2.uiScaleMode = (ScaleMode)1;
		menu.AddComponent<GraphicRaycaster>();
		GameObject val3 = CreatePanel(menu.transform, new Vector2(500f, 300f), new Vector2(0f, 0f));
		Image component = val3.GetComponent<Image>();
		((Graphic)component).color = new Color(0f, 0f, 0f, 0.85f);
		GameObject val4 = CreateText(val3.transform, "Choose Death Sound", 32, new Vector2(0f, 100f));
		GameObject val5 = CreateText(val3.transform, "", 24, new Vector2(0f, 20f));
		TextMeshProUGUI soundLabel = val5.GetComponent<TextMeshProUGUI>();
		UpdateSoundText(soundLabel);
		GameObject val6 = CreateButton(val3.transform, "<", new Vector2(-150f, -50f));
		((UnityEvent)val6.GetComponent<Button>().onClick).AddListener((UnityAction)delegate
		{
			PreviousSound();
			UpdateSoundText(soundLabel);
		});
		GameObject val7 = CreateButton(val3.transform, ">", new Vector2(150f, -50f));
		((UnityEvent)val7.GetComponent<Button>().onClick).AddListener((UnityAction)delegate
		{
			NextSound();
			UpdateSoundText(soundLabel);
		});
		GameObject val8 = CreateButton(val3.transform, "Preview", new Vector2(0f, -100f));
		ButtonClickedEvent onClick = val8.GetComponent<Button>().onClick;
		object obj = <>c.<>9__10_2;
		if (obj == null)
		{
			UnityAction val9 = delegate
			{
				PlaySelectedSound();
			};
			<>c.<>9__10_2 = val9;
			obj = (object)val9;
		}
		((UnityEvent)onClick).AddListener((UnityAction)obj);
		GameObject val10 = CreateButton(val3.transform, "Save & Close", new Vector2(0f, -150f));
		((UnityEvent)val10.GetComponent<Button>().onClick).AddListener(new UnityAction(SaveAndClose));
	}

	private static void SaveAndClose()
	{
		DeathTunesPlugin.Log.LogInfo((object)"===== SAVING DEATH SOUND =====");
		DeathTunesPlugin.Log.LogInfo((object)("Selected sound: " + SelectedSound));
		DeathTunesPlugin.SavedDeathSound.Value = SelectedSound;
		if ((Object)(object)GameNetworkManager.Instance == (Object)null)
		{
			DeathTunesPlugin.Log.LogWarning((object)"GameNetworkManager not initialized yet.");
			PendingSoundSelection = SelectedSound;
			menu.SetActive(false);
			return;
		}
		PlayerControllerB localPlayerController = GameNetworkManager.Instance.localPlayerController;
		if ((Object)(object)localPlayerController == (Object)null)
		{
			DeathTunesPlugin.Log.LogWarning((object)"Local player controller not available. Saving locally for later.");
			PendingSoundSelection = SelectedSound;
			menu.SetActive(false);
		}
		else
		{
			SendPlayerSound(localPlayerController);
			menu.SetActive(false);
		}
	}

	public static void CloseMenu()
	{
		if ((Object)(object)menu != (Object)null)
		{
			menu.SetActive(false);
		}
	}

	private static void UpdateSoundText(TextMeshProUGUI text)
	{
		if (SoundIDs.Count == 0)
		{
			((TMP_Text)text).text = "No sounds found";
		}
		else
		{
			((TMP_Text)text).text = SoundIDs[soundIndex];
		}
	}

	public static void NextSound()
	{
		soundIndex++;
		if (soundIndex >= SoundIDs.Count)
		{
			soundIndex = 0;
		}
		SelectedSound = SoundIDs[soundIndex];
		DeathTunesPlugin.Log.LogInfo((object)("Changed selected sound to: " + SelectedSound));
	}

	public static void PreviousSound()
	{
		soundIndex--;
		if (soundIndex < 0)
		{
			soundIndex = SoundIDs.Count - 1;
		}
		SelectedSound = SoundIDs[soundIndex];
		DeathTunesPlugin.Log.LogInfo((object)("Changed selected sound to: " + SelectedSound));
	}

	private static void PlaySelectedSound()
	{
		if (Sounds.ContainsKey(SelectedSound))
		{
			DeathTunesPlugin.PlayClip(Sounds[SelectedSound]);
		}
	}

	private static GameObject CreatePanel(Transform parent, Vector2 size, Vector2 position)
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Expected O, but got Unknown
		//IL_0021: 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)
		GameObject val = new GameObject("Panel");
		val.transform.SetParent(parent);
		RectTransform val2 = val.AddComponent<RectTransform>();
		val2.sizeDelta = size;
		val2.anchoredPosition = position;
		val.AddComponent<Image>();
		return val;
	}

	private static GameObject CreateText(Transform parent, string value, int size, Vector2 position)
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Expected O, but got Unknown
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = new GameObject("Text");
		val.transform.SetParent(parent);
		RectTransform val2 = val.AddComponent<RectTransform>();
		val2.sizeDelta = new Vector2(400f, 50f);
		val2.anchoredPosition = position;
		TextMeshProUGUI val3 = val.AddComponent<TextMeshProUGUI>();
		((TMP_Text)val3).text = value;
		((TMP_Text)val3).fontSize = size;
		((TMP_Text)val3).alignment = (TextAlignmentOptions)514;
		return val;
	}

	private static GameObject CreateButton(Transform parent, string value, Vector2 position)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0008: Expected O, but got Unknown
		//IL_0027: 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_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_005d: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = new GameObject(value);
		val.transform.SetParent(parent);
		RectTransform val2 = val.AddComponent<RectTransform>();
		val2.sizeDelta = new Vector2(120f, 40f);
		val2.anchoredPosition = position;
		Image val3 = val.AddComponent<Image>();
		((Graphic)val3).color = Color.gray;
		Button val4 = val.AddComponent<Button>();
		GameObject val5 = CreateText(val.transform, value, 18, Vector2.zero);
		return val;
	}
}
public static class DeathCustomizationMenuUtils
{
	[Serializable]
	[CompilerGenerated]
	private sealed class <>c
	{
		public static readonly <>c <>9 = new <>c();

		public static UnityAction <>9__0_0;

		public static Func<Button, GameObject> <>9__0_1;

		public static Func<GameObject, float> <>9__0_3;

		public static Func<float, float, float> <>9__0_4;

		internal void <InjectMenu>b__0_0()
		{
			DeathCustomizationManager.OpenMenu();
		}

		internal GameObject <InjectMenu>b__0_1(Button b)
		{
			return ((Component)b).gameObject;
		}

		internal float <InjectMenu>b__0_3(GameObject b)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			return b.GetComponent<RectTransform>().anchoredPosition.y;
		}

		internal float <InjectMenu>b__0_4(float a, float b)
		{
			return Mathf.Abs(b - a);
		}
	}

	public static void InjectMenu(Transform mainButtonsTransform, GameObject quitButton)
	{
		//IL_0066: Unknown result type (might be due to invalid IL or missing references)
		//IL_0070: Expected O, but got Unknown
		//IL_008b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0090: Unknown result type (might be due to invalid IL or missing references)
		//IL_0096: Expected O, but got Unknown
		//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
		//IL_021b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0227: Unknown result type (might be due to invalid IL or missing references)
		//IL_022c: Unknown result type (might be due to invalid IL or missing references)
		DeathTunesPlugin.Log.LogInfo((object)"Injecting DeathTunes button...");
		DeathCustomizationManager.OpenMenu();
		DeathCustomizationManager.CloseMenu();
		GameObject deathButton = Object.Instantiate<GameObject>(quitButton, mainButtonsTransform);
		((Object)deathButton).name = "DeathTunesButton";
		Button component = deathButton.GetComponent<Button>();
		((UnityEventBase)component.onClick).RemoveAllListeners();
		component.onClick = new ButtonClickedEvent();
		ButtonClickedEvent onClick = component.onClick;
		object obj = <>c.<>9__0_0;
		if (obj == null)
		{
			UnityAction val = delegate
			{
				DeathCustomizationManager.OpenMenu();
			};
			<>c.<>9__0_0 = val;
			obj = (object)val;
		}
		((UnityEvent)onClick).AddListener((UnityAction)obj);
		TextMeshProUGUI componentInChildren = deathButton.GetComponentInChildren<TextMeshProUGUI>();
		if ((Object)(object)componentInChildren != (Object)null)
		{
			((TMP_Text)componentInChildren).text = "> Death Sounds";
		}
		List<GameObject> source = (from b in ((Component)mainButtonsTransform).GetComponentsInChildren<Button>()
			select ((Component)b).gameObject).ToList();
		List<float> list = (from b in source
			where (Object)(object)b != (Object)(object)deathButton
			select b.GetComponent<RectTransform>().anchoredPosition.y).ToList();
		float num = 55f;
		if (list.Count >= 2)
		{
			num = list.Zip(list.Skip(1), (float a, float b) => Mathf.Abs(b - a)).Min();
		}
		foreach (GameObject item in source.Where((GameObject g) => (Object)(object)g != (Object)(object)quitButton))
		{
			RectTransform component2 = item.GetComponent<RectTransform>();
			component2.anchoredPosition += new Vector2(0f, num);
		}
		RectTransform component3 = quitButton.GetComponent<RectTransform>();
		RectTransform component4 = deathButton.GetComponent<RectTransform>();
		component4.anchoredPosition = component3.anchoredPosition + new Vector2(0f, num);
		DeathTunesPlugin.Log.LogInfo((object)"DeathTunes button positioned successfully.");
	}
}
[HarmonyPatch(typeof(PlayerControllerB))]
public class DeathPatch
{
	[HarmonyPatch("Update")]
	[HarmonyPostfix]
	private static void CheckDeath(PlayerControllerB __instance)
	{
		if (!((Object)(object)__instance == (Object)null))
		{
			ulong playerSteamId = __instance.playerSteamId;
			bool isPlayerDead = __instance.isPlayerDead;
			bool value = false;
			DeathTunesPlugin.LastDeathState.TryGetValue(playerSteamId, out value);
			if (isPlayerDead && !value)
			{
				DeathTunesPlugin.Log.LogInfo((object)("DEATH DETECTED: Player " + playerSteamId));
				PlayerDeathSoundManager.PlayPlayerDeathSound(__instance);
			}
			DeathTunesPlugin.LastDeathState[playerSteamId] = isPlayerDead;
		}
	}
}
public class SoundSelectionData
{
	public ulong SteamID;

	public string SoundName;
}
public static class DeathSoundNetworking
{
	public static readonly Dictionary<ulong, string> PlayerSounds = new Dictionary<ulong, string>();

	public static LNetworkMessage<SoundSelectionData> SoundMessage;

	public static LNetworkMessage<string> RequestMessage;

	public static void Initialize()
	{
		SoundMessage = LNetworkMessage<SoundSelectionData>.Create("DeathSoundSelection", (Action<SoundSelectionData, ulong>)OnServerReceived, (Action<SoundSelectionData>)OnClientReceived, (Action<SoundSelectionData, ulong>)null);
		RequestMessage = LNetworkMessage<string>.Create("DeathSoundRequest", (Action<string, ulong>)OnRequestReceived, (Action<string>)null, (Action<string, ulong>)null);
		DeathTunesPlugin.Log.LogInfo((object)"Death sound networking initialized.");
	}

	public static void SendSelection(ulong steamID, string sound)
	{
		SoundSelectionData soundSelectionData = new SoundSelectionData
		{
			SteamID = steamID,
			SoundName = sound
		};
		PlayerSounds[steamID] = sound;
		DeathTunesPlugin.Log.LogInfo((object)$"Sending sound selection: {steamID} -> {sound}");
		SoundMessage.SendServer(soundSelectionData);
	}

	private static void OnServerReceived(SoundSelectionData data, ulong sender)
	{
		PlayerSounds[data.SteamID] = data.SoundName;
		DeathTunesPlugin.Log.LogInfo((object)$"Host stored sound: {data.SteamID} -> {data.SoundName}");
		SoundMessage.SendClients(data);
	}

	private static void OnClientReceived(SoundSelectionData data)
	{
		PlayerSounds[data.SteamID] = data.SoundName;
		DeathTunesPlugin.Log.LogInfo((object)$"Client stored sound: {data.SteamID} -> {data.SoundName}");
	}

	public static void RequestAllSounds()
	{
		DeathTunesPlugin.Log.LogInfo((object)"Requesting all death sounds...");
		RequestMessage.SendServer("");
	}

	private static void OnRequestReceived(string unused, ulong sender)
	{
		DeathTunesPlugin.Log.LogInfo((object)$"Sending all sounds to client {sender}");
		Dictionary<ulong, string> dictionary = new Dictionary<ulong, string>(PlayerSounds);
		foreach (KeyValuePair<ulong, string> item in dictionary)
		{
			SoundSelectionData soundSelectionData = new SoundSelectionData
			{
				SteamID = item.Key,
				SoundName = item.Value
			};
			SoundMessage.SendClient(soundSelectionData, sender);
		}
		DeathTunesPlugin.Log.LogInfo((object)$"Finished sending {dictionary.Count} sounds to client {sender}");
	}

	public static void PrintDatabase()
	{
		DeathTunesPlugin.Log.LogInfo((object)"===== DEATH SOUND DATABASE =====");
		foreach (KeyValuePair<ulong, string> playerSound in PlayerSounds)
		{
			DeathTunesPlugin.Log.LogInfo((object)$"{playerSound.Key} -> {playerSound.Value}");
		}
	}
}
[BepInPlugin("ryang.deathtunes", "DeathTunes", "0.1.0")]
public class DeathTunesPlugin : BaseUnityPlugin
{
	public static DeathTunesPlugin Instance;

	public static ManualLogSource Log;

	public static AudioSource AudioSource;

	public static ConfigEntry<string> SavedDeathSound;

	public static Dictionary<ulong, bool> LastDeathState = new Dictionary<ulong, bool>();

	private void Awake()
	{
		//IL_007b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0081: Expected O, but got Unknown
		Instance = this;
		Log = ((BaseUnityPlugin)this).Logger;
		SavedDeathSound = ((BaseUnityPlugin)this).Config.Bind<string>("DeathTunes", "SelectedDeathSound", "", "The selected death sound for this player.");
		Log.LogInfo((object)"DeathTunes starting...");
		Log.LogInfo((object)("DLL location: " + Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)));
		DeathCustomizationManager.LoadSounds();
		DeathSoundNetworking.Initialize();
		Harmony val = new Harmony("ryang.deathtunes");
		val.PatchAll();
		((MonoBehaviour)this).StartCoroutine(CreateAudioSource());
		Log.LogInfo((object)"DeathTunes loaded!");
	}

	private void Update()
	{
		if (DeathCustomizationManager.PendingSoundSelection == null)
		{
			return;
		}
		Log.LogInfo((object)("DeathTunes pending sound: " + DeathCustomizationManager.PendingSoundSelection));
		if ((Object)(object)StartOfRound.Instance == (Object)null)
		{
			Log.LogInfo((object)"Waiting for StartOfRound...");
			return;
		}
		Log.LogInfo((object)"StartOfRound exists");
		PlayerControllerB localPlayerController = StartOfRound.Instance.localPlayerController;
		if ((Object)(object)localPlayerController == (Object)null)
		{
			Log.LogInfo((object)"Waiting for local player...");
			return;
		}
		Log.LogInfo((object)"Local player found!");
		ulong playerSteamId = localPlayerController.playerSteamId;
		DeathSoundNetworking.SendSelection(playerSteamId, DeathCustomizationManager.PendingSoundSelection);
		Log.LogInfo((object)("Sent sound " + DeathCustomizationManager.PendingSoundSelection + " for SteamID " + playerSteamId));
		DeathCustomizationManager.PendingSoundSelection = null;
	}

	private IEnumerator CreateAudioSource()
	{
		yield return (object)new WaitForSeconds(3f);
		CreateAudioObject();
		Log.LogInfo((object)"DeathTunes AudioSource created");
	}

	public static void CreateAudioObject()
	{
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		//IL_001d: Expected O, but got Unknown
		if (!((Object)(object)AudioSource != (Object)null))
		{
			GameObject val = new GameObject("DeathTunesAudio");
			Object.DontDestroyOnLoad((Object)(object)val);
			AudioSource = val.AddComponent<AudioSource>();
			AudioSource.playOnAwake = false;
			AudioSource.loop = false;
			AudioSource.spatialBlend = 0f;
			AudioSource.volume = 1f;
			AudioSource.ignoreListenerVolume = true;
			AudioSource.priority = 0;
		}
	}

	public static AudioClip LoadWavPublic(string path)
	{
		return Instance.LoadWav(path);
	}

	public AudioClip LoadWav(string path)
	{
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_003c: Invalid comparison between Unknown and I4
		try
		{
			UnityWebRequest audioClip = UnityWebRequestMultimedia.GetAudioClip("file:///" + path, (AudioType)20);
			UnityWebRequestAsyncOperation val = audioClip.SendWebRequest();
			while (!((AsyncOperation)val).isDone)
			{
				Thread.Sleep(10);
			}
			if ((int)audioClip.result != 1)
			{
				Log.LogError((object)audioClip.error);
				return null;
			}
			AudioClip content = DownloadHandlerAudioClip.GetContent(audioClip);
			((Object)content).name = Path.GetFileNameWithoutExtension(path);
			return content;
		}
		catch (Exception ex)
		{
			Log.LogError((object)ex.Message);
			return null;
		}
	}

	public static void PlayClip(AudioClip clip)
	{
		if ((Object)(object)clip == (Object)null)
		{
			Log.LogError((object)"Tried to play NULL clip");
			return;
		}
		if ((Object)(object)AudioSource == (Object)null)
		{
			CreateAudioObject();
		}
		AudioSource.Stop();
		AudioSource.clip = clip;
		AudioSource.volume = 1f;
		AudioSource.Play();
		Log.LogInfo((object)("Playing death sound: " + ((Object)clip).name));
	}
}
[HarmonyPatch(typeof(MenuManager))]
public class MainMenuPatch
{
	[HarmonyPatch("Start")]
	[HarmonyPostfix]
	public static void Start(MenuManager __instance)
	{
		if (!__instance.isInitScene)
		{
			DeathTunesPlugin.Log.LogInfo((object)"DeathTunes injecting menu...");
			((MonoBehaviour)__instance).StartCoroutine(DelayedInjection());
		}
	}

	private static IEnumerator DelayedInjection()
	{
		yield return (object)new WaitForSeconds(1f);
		InjectMenu();
	}

	private static void InjectMenu()
	{
		GameObject val = GameObject.Find("MenuContainer");
		if ((Object)(object)val == (Object)null)
		{
			return;
		}
		Transform val2 = val.transform.Find("MainButtons");
		if (!((Object)(object)val2 == (Object)null))
		{
			Transform val3 = val2.Find("QuitButton");
			if ((Object)(object)val3 == (Object)null)
			{
				DeathTunesPlugin.Log.LogError((object)"QuitButton missing!");
			}
			else
			{
				DeathCustomizationMenuUtils.InjectMenu(val2, ((Component)val3).gameObject);
			}
		}
	}
}
[HarmonyPatch(typeof(StartOfRound))]
public class PlayerConnectionPatch
{
	private static bool hasSynced;

	[HarmonyPatch("Start")]
	[HarmonyPostfix]
	public static void OnGameStart(StartOfRound __instance)
	{
		if (!hasSynced)
		{
			hasSynced = true;
			DeathTunesPlugin.Log.LogInfo((object)"DeathTunes player connection sync started.");
			((MonoBehaviour)__instance).StartCoroutine(DelayedSync());
		}
	}

	private static IEnumerator DelayedSync()
	{
		yield return (object)new WaitForSeconds(3f);
		PlayerControllerB player = StartOfRound.Instance.localPlayerController;
		if ((Object)(object)player == (Object)null)
		{
			DeathTunesPlugin.Log.LogWarning((object)"Cannot sync death sound. Local player missing.");
			yield break;
		}
		ulong steamID = player.playerSteamId;
		DeathTunesPlugin.Log.LogInfo((object)$"Local player found. SteamID: {steamID}");
		if (!string.IsNullOrEmpty(DeathTunesPlugin.SavedDeathSound.Value))
		{
			DeathSoundNetworking.SendSelection(steamID, DeathTunesPlugin.SavedDeathSound.Value);
			DeathTunesPlugin.Log.LogInfo((object)"Sent saved death sound.");
		}
		else
		{
			DeathTunesPlugin.Log.LogInfo((object)"No saved death sound found.");
		}
		DeathSoundNetworking.RequestAllSounds();
		DeathTunesPlugin.Log.LogInfo((object)"Requested all player death sounds.");
	}

	[HarmonyPatch("OnDestroy")]
	[HarmonyPostfix]
	public static void OnDestroy()
	{
		hasSynced = false;
		DeathTunesPlugin.Log.LogInfo((object)"DeathTunes player sync reset.");
	}
}
public static class PlayerDeathSoundManager
{
	public static void PlayPlayerDeathSound(PlayerControllerB player)
	{
		if ((Object)(object)player == (Object)null)
		{
			return;
		}
		ulong playerSteamId = player.playerSteamId;
		DeathTunesPlugin.Log.LogInfo((object)$"Looking up death sound for SteamID: {playerSteamId}");
		AudioClip val = null;
		if (DeathSoundNetworking.PlayerSounds.TryGetValue(playerSteamId, out var value))
		{
			DeathTunesPlugin.Log.LogInfo((object)$"Found sound entry: {playerSteamId} -> {value}");
			if (DeathCustomizationManager.Sounds.ContainsKey(value))
			{
				val = DeathCustomizationManager.Sounds[value];
			}
			else
			{
				DeathTunesPlugin.Log.LogWarning((object)("Sound file does not exist: " + value));
			}
		}
		else
		{
			DeathTunesPlugin.Log.LogWarning((object)$"No sound registered for SteamID: {playerSteamId}");
		}
		if ((Object)(object)val == (Object)null && (Object)(object)player == (Object)(object)StartOfRound.Instance.localPlayerController)
		{
			string value2 = DeathTunesPlugin.SavedDeathSound.Value;
			if (!string.IsNullOrEmpty(value2) && DeathCustomizationManager.Sounds.ContainsKey(value2))
			{
				DeathTunesPlugin.Log.LogInfo((object)("Using local saved fallback sound: " + value2));
				val = DeathCustomizationManager.Sounds[value2];
			}
		}
		if ((Object)(object)val == (Object)null)
		{
			DeathTunesPlugin.Log.LogWarning((object)$"Could not find death sound for {playerSteamId}");
			return;
		}
		DeathTunesPlugin.Log.LogInfo((object)$"Playing death sound for {playerSteamId}: {((Object)val).name}");
		DeathTunesPlugin.PlayClip(val);
	}
}