Decompiled source of DeathTunes v1.1.2

DeathTunes/DeathTunes.dll

Decompiled 3 weeks 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.EventSystems;
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
{
	private class ButtonHoverHandler : MonoBehaviour, IPointerEnterHandler, IEventSystemHandler, IPointerExitHandler
	{
		public Image Background;

		public TextMeshProUGUI Text;

		public bool IsArrow;

		public Color NormalBackgroundColor;

		public Color HoverBackgroundColor;

		public Color NormalTextColor;

		public Color HoverTextColor;

		public void OnPointerEnter(PointerEventData eventData)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			if (!IsArrow)
			{
				if ((Object)(object)Background != (Object)null)
				{
					((Graphic)Background).color = HoverBackgroundColor;
				}
				if ((Object)(object)Text != (Object)null)
				{
					((Graphic)Text).color = HoverTextColor;
				}
			}
		}

		public void OnPointerExit(PointerEventData eventData)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)Background != (Object)null)
			{
				((Graphic)Background).color = NormalBackgroundColor;
			}
			if ((Object)(object)Text != (Object)null)
			{
				((Graphic)Text).color = NormalTextColor;
			}
		}
	}

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

		public static UnityAction <>9__28_0;

		public static UnityAction <>9__28_1;

		internal void <CreateMenu>b__28_0()
		{
			PreviousSound();
			UpdateMenuDisplay();
		}

		internal void <CreateMenu>b__28_1()
		{
			NextSound();
			UpdateMenuDisplay();
		}
	}

	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;

	private static TextMeshProUGUI soundNameText;

	private static TextMeshProUGUI soundCounterText;

	private static Button previousButton;

	private static Button nextButton;

	private static Button previewButton;

	private static Button saveButton;

	private static Button closeButton;

	private static bool menuCreated = false;

	private static TMP_FontAsset gameFont;

	private static readonly Color BackgroundColor = Color32.op_Implicit(new Color32((byte)0, (byte)0, (byte)0, (byte)235));

	private static readonly Color PanelColor = Color32.op_Implicit(new Color32((byte)0, (byte)0, (byte)0, byte.MaxValue));

	private static readonly Color RedColor = Color32.op_Implicit(new Color32((byte)247, (byte)0, (byte)7, byte.MaxValue));

	private static readonly Color SecondaryRedColor = Color32.op_Implicit(new Color32((byte)240, (byte)0, (byte)7, (byte)250));

	private static readonly Color BlackColor = Color32.op_Implicit(new Color32((byte)0, (byte)0, (byte)0, byte.MaxValue));

	private static readonly Color WhiteColor = Color32.op_Implicit(new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue));

	private static readonly Color DisabledColor = Color32.op_Implicit(new Color32((byte)45, (byte)45, (byte)45, (byte)180));

	public static int CurrentSoundIndex => soundIndex;

	private static void LoadGameFont()
	{
		if ((Object)(object)gameFont != (Object)null)
		{
			return;
		}
		TMP_FontAsset[] array = Resources.FindObjectsOfTypeAll<TMP_FontAsset>();
		TMP_FontAsset[] array2 = array;
		foreach (TMP_FontAsset val in array2)
		{
			if (!((Object)(object)val == (Object)null) && ((Object)val).name.Equals("3270-Regular", StringComparison.OrdinalIgnoreCase))
			{
				gameFont = val;
				break;
			}
		}
		if ((Object)(object)gameFont == (Object)null)
		{
			TMP_FontAsset[] array3 = array;
			foreach (TMP_FontAsset val2 in array3)
			{
				if (!((Object)(object)val2 == (Object)null) && ((Object)val2).name.IndexOf("3270", StringComparison.OrdinalIgnoreCase) >= 0)
				{
					gameFont = val2;
					break;
				}
			}
		}
		if ((Object)(object)gameFont != (Object)null)
		{
			DeathTunesPlugin.Log.LogInfo((object)("DeathTunes using game font: " + ((Object)gameFont).name));
		}
		else
		{
			DeathTunesPlugin.Log.LogWarning((object)"3270-Regular font could not be found. Using default TMP font.");
		}
	}

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

	public static void LoadSounds()
	{
		LoadGameFont();
		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;
				soundIndex = SoundIDs.IndexOf(value);
				if (soundIndex < 0)
				{
					soundIndex = 0;
				}
			}
			else
			{
				SelectedSound = SoundIDs[0];
				soundIndex = 0;
			}
		}
		DeathTunesPlugin.Log.LogInfo((object)("Total death sounds loaded: " + Sounds.Count));
	}

	public static void OpenMenu()
	{
		if ((Object)(object)menu != (Object)null)
		{
			menu.SetActive(true);
			UpdateMenuDisplay();
		}
		else
		{
			CreateMenu();
			menu.SetActive(true);
			UpdateMenuDisplay();
		}
	}

	private static void CreateMenu()
	{
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		//IL_002c: Expected O, but got Unknown
		//IL_0069: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
		//IL_0108: Unknown result type (might be due to invalid IL or missing references)
		//IL_010d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0112: Unknown result type (might be due to invalid IL or missing references)
		//IL_0120: Unknown result type (might be due to invalid IL or missing references)
		//IL_0148: Unknown result type (might be due to invalid IL or missing references)
		//IL_014d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0190: Unknown result type (might be due to invalid IL or missing references)
		//IL_0195: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
		//IL_0213: Unknown result type (might be due to invalid IL or missing references)
		//IL_0222: 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_0235: Unknown result type (might be due to invalid IL or missing references)
		//IL_0253: Unknown result type (might be due to invalid IL or missing references)
		//IL_0258: Unknown result type (might be due to invalid IL or missing references)
		//IL_02aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_030d: Unknown result type (might be due to invalid IL or missing references)
		//IL_031c: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e6: Unknown result type (might be due to invalid IL or missing references)
		//IL_02eb: Unknown result type (might be due to invalid IL or missing references)
		//IL_02f1: Expected O, but got Unknown
		//IL_0372: Unknown result type (might be due to invalid IL or missing references)
		//IL_0377: Unknown result type (might be due to invalid IL or missing references)
		//IL_03b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_03c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_03e0: Unknown result type (might be due to invalid IL or missing references)
		//IL_03ea: Expected O, but got Unknown
		//IL_03fc: Unknown result type (might be due to invalid IL or missing references)
		//IL_041d: Unknown result type (might be due to invalid IL or missing references)
		//IL_042c: Unknown result type (might be due to invalid IL or missing references)
		//IL_044c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0456: Expected O, but got Unknown
		//IL_046d: Unknown result type (might be due to invalid IL or missing references)
		//IL_047c: Unknown result type (might be due to invalid IL or missing references)
		//IL_049c: Unknown result type (might be due to invalid IL or missing references)
		//IL_04a6: Expected O, but got Unknown
		//IL_0349: Unknown result type (might be due to invalid IL or missing references)
		//IL_034e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0354: Expected O, but got Unknown
		if (menuCreated)
		{
			return;
		}
		menuCreated = true;
		LoadGameFont();
		menu = new GameObject("DeathTunesMenu");
		Canvas val = menu.AddComponent<Canvas>();
		val.renderMode = (RenderMode)0;
		val.sortingOrder = 5000;
		CanvasScaler val2 = menu.AddComponent<CanvasScaler>();
		val2.uiScaleMode = (ScaleMode)1;
		val2.referenceResolution = new Vector2(1920f, 1080f);
		val2.screenMatchMode = (ScreenMatchMode)0;
		val2.matchWidthOrHeight = 0.5f;
		menu.AddComponent<GraphicRaycaster>();
		Object.DontDestroyOnLoad((Object)(object)menu);
		GameObject val3 = CreatePanel(menu.transform, Vector2.zero, Vector2.zero, BackgroundColor);
		RectTransform component = val3.GetComponent<RectTransform>();
		component.anchorMin = Vector2.zero;
		component.anchorMax = Vector2.one;
		component.offsetMin = Vector2.zero;
		component.offsetMax = Vector2.zero;
		GameObject val4 = CreatePanel(menu.transform, new Vector2(760f, 570f), Vector2.zero, PanelColor);
		AddBorder(val4, RedColor, 2f);
		GameObject val5 = CreateText(val4.transform, "DEATHTUNES", 44, new Vector2(0f, 215f), RedColor);
		TextMeshProUGUI component2 = val5.GetComponent<TextMeshProUGUI>();
		((TMP_Text)component2).fontStyle = (FontStyles)1;
		((TMP_Text)component2).characterSpacing = 3f;
		GameObject val6 = CreateText(val4.transform, "DEATH SOUND CUSTOMIZATION", 20, new Vector2(0f, 175f), RedColor);
		((TMP_Text)val6.GetComponent<TextMeshProUGUI>()).fontStyle = (FontStyles)1;
		CreateDivider(val4.transform, new Vector2(0f, 145f));
		GameObject val7 = CreateText(val4.transform, "SELECT SOUND", 21, new Vector2(0f, 112f), RedColor);
		((TMP_Text)val7.GetComponent<TextMeshProUGUI>()).fontStyle = (FontStyles)1;
		GameObject val8 = CreatePanel(val4.transform, new Vector2(500f, 100f), new Vector2(0f, 48f), BlackColor);
		AddBorder(val8, RedColor, 1f);
		GameObject val9 = CreateText(val8.transform, "", 30, Vector2.zero, RedColor);
		soundNameText = val9.GetComponent<TextMeshProUGUI>();
		((TMP_Text)soundNameText).fontStyle = (FontStyles)1;
		((TMP_Text)soundNameText).enableWordWrapping = false;
		((TMP_Text)soundNameText).overflowMode = (TextOverflowModes)1;
		previousButton = CreateStyledButton(val4.transform, "‹", new Vector2(-315f, 48f), new Vector2(70f, 70f));
		ButtonClickedEvent onClick = previousButton.onClick;
		object obj = <>c.<>9__28_0;
		if (obj == null)
		{
			UnityAction val10 = delegate
			{
				PreviousSound();
				UpdateMenuDisplay();
			};
			<>c.<>9__28_0 = val10;
			obj = (object)val10;
		}
		((UnityEvent)onClick).AddListener((UnityAction)obj);
		nextButton = CreateStyledButton(val4.transform, "›", new Vector2(315f, 48f), new Vector2(70f, 70f));
		ButtonClickedEvent onClick2 = nextButton.onClick;
		object obj2 = <>c.<>9__28_1;
		if (obj2 == null)
		{
			UnityAction val11 = delegate
			{
				NextSound();
				UpdateMenuDisplay();
			};
			<>c.<>9__28_1 = val11;
			obj2 = (object)val11;
		}
		((UnityEvent)onClick2).AddListener((UnityAction)obj2);
		GameObject val12 = CreateText(val4.transform, "", 17, new Vector2(0f, -18f), SecondaryRedColor);
		soundCounterText = val12.GetComponent<TextMeshProUGUI>();
		((TMP_Text)soundCounterText).fontStyle = (FontStyles)1;
		previewButton = CreateStyledButton(val4.transform, ">  PREVIEW SOUND", new Vector2(0f, -72f), new Vector2(300f, 48f));
		((UnityEvent)previewButton.onClick).AddListener(new UnityAction(PlaySelectedSound));
		CreateDivider(val4.transform, new Vector2(0f, -115f));
		saveButton = CreateStyledButton(val4.transform, ">  SAVE", new Vector2(-125f, -165f), new Vector2(190f, 50f));
		((UnityEvent)saveButton.onClick).AddListener(new UnityAction(SaveSelection));
		closeButton = CreateStyledButton(val4.transform, ">  CLOSE", new Vector2(125f, -165f), new Vector2(190f, 50f));
		((UnityEvent)closeButton.onClick).AddListener(new UnityAction(CloseMenu));
		menu.SetActive(false);
	}

	private static void UpdateMenuDisplay()
	{
		if ((Object)(object)soundNameText == (Object)null)
		{
			return;
		}
		if (SoundIDs.Count == 0)
		{
			((TMP_Text)soundNameText).text = "NO SOUNDS FOUND";
			if ((Object)(object)soundCounterText != (Object)null)
			{
				((TMP_Text)soundCounterText).text = "0 / 0";
			}
			SetButtonInteractable(previousButton, interactable: false);
			SetButtonInteractable(nextButton, interactable: false);
			SetButtonInteractable(previewButton, interactable: false);
			SetButtonInteractable(saveButton, interactable: false);
			return;
		}
		if (soundIndex < 0)
		{
			soundIndex = 0;
		}
		if (soundIndex >= SoundIDs.Count)
		{
			soundIndex = 0;
		}
		SelectedSound = SoundIDs[soundIndex];
		((TMP_Text)soundNameText).text = FormatSoundName(SelectedSound);
		if ((Object)(object)soundCounterText != (Object)null)
		{
			((TMP_Text)soundCounterText).text = "SOUND " + (soundIndex + 1) + " / " + SoundIDs.Count;
		}
		SetButtonInteractable(previousButton, SoundIDs.Count > 1);
		SetButtonInteractable(nextButton, SoundIDs.Count > 1);
		SetButtonInteractable(previewButton, interactable: true);
		SetButtonInteractable(saveButton, interactable: true);
	}

	private static void SaveSelection()
	{
		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;
			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;
		}
		else
		{
			SendPlayerSound(localPlayerController);
		}
	}

	public static void CloseMenu()
	{
		DeathTunesPlugin.Log.LogInfo((object)"Closing DeathTunes customization menu.");
		if ((Object)(object)menu != (Object)null)
		{
			menu.SetActive(false);
		}
	}

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

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

	private static void PlaySelectedSound()
	{
		DeathTunesPlugin.Log.LogInfo((object)("Previewing death sound: " + SelectedSound));
		if (Sounds.ContainsKey(SelectedSound))
		{
			DeathTunesPlugin.PlayClip(Sounds[SelectedSound]);
		}
		else
		{
			DeathTunesPlugin.Log.LogWarning((object)("Cannot preview sound. Sound not found: " + SelectedSound));
		}
	}

	private static GameObject CreatePanel(Transform parent, Vector2 size, Vector2 position, Color color)
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Expected O, but got Unknown
		//IL_002c: 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_0058: Unknown result type (might be due to invalid IL or missing references)
		//IL_0064: Unknown result type (might be due to invalid IL or missing references)
		//IL_006c: Unknown result type (might be due to invalid IL or missing references)
		//IL_007b: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = new GameObject("Panel");
		val.transform.SetParent(parent, false);
		RectTransform val2 = val.AddComponent<RectTransform>();
		val2.anchorMin = new Vector2(0.5f, 0.5f);
		val2.anchorMax = new Vector2(0.5f, 0.5f);
		val2.pivot = new Vector2(0.5f, 0.5f);
		val2.sizeDelta = size;
		val2.anchoredPosition = position;
		Image val3 = val.AddComponent<Image>();
		((Graphic)val3).color = color;
		return val;
	}

	private static GameObject CreateText(Transform parent, string value, int size, Vector2 position, Color color)
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Expected O, but got Unknown
		//IL_002c: 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_0058: Unknown result type (might be due to invalid IL or missing references)
		//IL_006e: Unknown result type (might be due to invalid IL or missing references)
		//IL_007a: Unknown result type (might be due to invalid IL or missing references)
		//IL_009a: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = new GameObject("Text");
		val.transform.SetParent(parent, false);
		RectTransform val2 = val.AddComponent<RectTransform>();
		val2.anchorMin = new Vector2(0.5f, 0.5f);
		val2.anchorMax = new Vector2(0.5f, 0.5f);
		val2.pivot = new Vector2(0.5f, 0.5f);
		val2.sizeDelta = new Vector2(600f, 50f);
		val2.anchoredPosition = position;
		TextMeshProUGUI val3 = val.AddComponent<TextMeshProUGUI>();
		((TMP_Text)val3).text = value;
		((TMP_Text)val3).fontSize = size;
		((Graphic)val3).color = color;
		((TMP_Text)val3).alignment = (TextAlignmentOptions)514;
		((TMP_Text)val3).enableWordWrapping = true;
		((Graphic)val3).raycastTarget = false;
		if ((Object)(object)gameFont != (Object)null)
		{
			((TMP_Text)val3).font = gameFont;
		}
		return val;
	}

	private static Button CreateStyledButton(Transform parent, string value, Vector2 position, Vector2 size)
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Expected O, but got Unknown
		//IL_002c: 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_0058: Unknown result type (might be due to invalid IL or missing references)
		//IL_0064: Unknown result type (might be due to invalid IL or missing references)
		//IL_006c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0078: Unknown result type (might be due to invalid IL or missing references)
		//IL_007e: Expected O, but got Unknown
		//IL_0099: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f2: Expected O, but got Unknown
		//IL_0111: Unknown result type (might be due to invalid IL or missing references)
		//IL_011e: 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_014c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0162: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
		//IL_0217: Unknown result type (might be due to invalid IL or missing references)
		//IL_021c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0223: Unknown result type (might be due to invalid IL or missing references)
		//IL_0228: Unknown result type (might be due to invalid IL or missing references)
		//IL_023a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0233: Unknown result type (might be due to invalid IL or missing references)
		//IL_023f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0251: Unknown result type (might be due to invalid IL or missing references)
		//IL_024a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0256: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = new GameObject("Button");
		val.transform.SetParent(parent, false);
		RectTransform val2 = val.AddComponent<RectTransform>();
		val2.anchorMin = new Vector2(0.5f, 0.5f);
		val2.anchorMax = new Vector2(0.5f, 0.5f);
		val2.pivot = new Vector2(0.5f, 0.5f);
		val2.sizeDelta = size;
		val2.anchoredPosition = position;
		GameObject val3 = new GameObject("Border");
		val3.transform.SetParent(val.transform, false);
		RectTransform val4 = val3.AddComponent<RectTransform>();
		val4.anchorMin = Vector2.zero;
		val4.anchorMax = Vector2.one;
		val4.offsetMin = Vector2.zero;
		val4.offsetMax = Vector2.zero;
		Image val5 = val3.AddComponent<Image>();
		((Graphic)val5).color = RedColor;
		((Graphic)val5).raycastTarget = false;
		GameObject val6 = new GameObject("Background");
		val6.transform.SetParent(val.transform, false);
		RectTransform val7 = val6.AddComponent<RectTransform>();
		val7.anchorMin = Vector2.zero;
		val7.anchorMax = Vector2.one;
		val7.offsetMin = new Vector2(2f, 2f);
		val7.offsetMax = new Vector2(-2f, -2f);
		Image val8 = val6.AddComponent<Image>();
		((Graphic)val8).color = BlackColor;
		Button val9 = val.AddComponent<Button>();
		((Selectable)val9).transition = (Transition)0;
		((Selectable)val9).targetGraphic = (Graphic)(object)val8;
		bool flag = value == "‹" || value == "›";
		Color color = (flag ? WhiteColor : RedColor);
		GameObject val10 = CreateText(val6.transform, value, flag ? 38 : 18, Vector2.zero, color);
		TextMeshProUGUI component = val10.GetComponent<TextMeshProUGUI>();
		((TMP_Text)component).fontStyle = (FontStyles)1;
		((Graphic)component).raycastTarget = false;
		ButtonHoverHandler buttonHoverHandler = val.AddComponent<ButtonHoverHandler>();
		buttonHoverHandler.Background = val8;
		buttonHoverHandler.Text = component;
		buttonHoverHandler.IsArrow = flag;
		buttonHoverHandler.NormalBackgroundColor = BlackColor;
		buttonHoverHandler.HoverBackgroundColor = RedColor;
		buttonHoverHandler.NormalTextColor = (flag ? WhiteColor : RedColor);
		buttonHoverHandler.HoverTextColor = (flag ? WhiteColor : BlackColor);
		return val9;
	}

	private static void AddBorder(GameObject target, Color color, float thickness)
	{
		//IL_0009: Unknown result type (might be due to invalid IL or missing references)
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		Outline val = target.AddComponent<Outline>();
		((Shadow)val).effectColor = color;
		((Shadow)val).effectDistance = new Vector2(thickness, thickness);
		((Shadow)val).useGraphicAlpha = true;
	}

	private static void CreateDivider(Transform parent, Vector2 position)
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Expected O, but got Unknown
		//IL_002c: 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_0058: Unknown result type (might be due to invalid IL or missing references)
		//IL_006e: Unknown result type (might be due to invalid IL or missing references)
		//IL_007a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0095: Unknown result type (might be due to invalid IL or missing references)
		//IL_009a: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = new GameObject("Divider");
		val.transform.SetParent(parent, false);
		RectTransform val2 = val.AddComponent<RectTransform>();
		val2.anchorMin = new Vector2(0.5f, 0.5f);
		val2.anchorMax = new Vector2(0.5f, 0.5f);
		val2.pivot = new Vector2(0.5f, 0.5f);
		val2.sizeDelta = new Vector2(600f, 1f);
		val2.anchoredPosition = position;
		Image val3 = val.AddComponent<Image>();
		((Graphic)val3).color = Color32.op_Implicit(new Color32((byte)247, (byte)0, (byte)7, (byte)180));
	}

	private static void SetButtonInteractable(Button button, bool interactable)
	{
		if (!((Object)(object)button == (Object)null))
		{
			((Selectable)button).interactable = interactable;
		}
	}

	private static string FormatSoundName(string id)
	{
		if (string.IsNullOrEmpty(id))
		{
			return "UNKNOWN SOUND";
		}
		string text = id.Replace("_", " ").Replace("-", " ");
		string[] array = text.Split(new char[1] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
		for (int i = 0; i < array.Length; i++)
		{
			if (array[i].Length != 0)
			{
				array[i] = char.ToUpper(array[i][0]) + ((array[i].Length > 1) ? array[i].Substring(1).ToLower() : "");
			}
		}
		return string.Join(" ", array).ToUpper();
	}
}
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);
	}
}