Decompiled source of BetterBugle v1.0.3

BepInEx/plugins/BetterBugle/BetterBugle.dll

Decompiled a day ago
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 Photon.Pun;
using UnityEngine;

[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("BetterBugle")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("0.1.0.0")]
[assembly: AssemblyInformationalVersion("0.1.0")]
[assembly: AssemblyProduct("BetterBugle")]
[assembly: AssemblyTitle("BetterBugle")]
[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 BetterBugle
{
	[BepInPlugin("BetterBugle", "BetterBugle", "0.1.0")]
	public class Plugin : BaseUnityPlugin
	{
		[HarmonyPatch(typeof(BugleSFX), "Start")]
		public static class BuglePatch_Start
		{
			[HarmonyPostfix]
			public static void ReplaceBugleClips(ref AudioClip[] ___bugle)
			{
				Debug.Log((object)">>> [BetterBugle] BugleSFX.Start() patch called.");
				if (CustomBugleClips.Count > 0)
				{
					___bugle = CustomBugleClips.ToArray();
					Debug.Log((object)$">>> [BetterBugle] Bugle sound list replaced ({___bugle.Length} clips).");
				}
			}
		}

		[HarmonyPatch(typeof(BugleSFX), "Update")]
		public static class BuglePatch_ForceSound
		{
			[HarmonyPostfix]
			public static void OverridePlayedSound(object __instance)
			{
				//IL_008c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0093: Expected O, but got Unknown
				//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
				if (CustomBugleClips.Count == 0)
				{
					return;
				}
				Type type = __instance.GetType();
				FieldInfo fieldInfo = AccessTools.Field(type, "hold");
				FieldInfo fieldInfo2 = AccessTools.Field(type, "buglePlayer");
				FieldInfo fieldInfo3 = AccessTools.Field(type, "currentClip");
				if (fieldInfo == null || fieldInfo2 == null || fieldInfo3 == null)
				{
					Debug.LogError((object)">>> [BetterBugle] One or more fields not found in BugleSFX.");
					return;
				}
				bool flag = (bool)fieldInfo.GetValue(__instance);
				AudioSource val = (AudioSource)fieldInfo2.GetValue(__instance);
				if (flag && !((Object)(object)val == (Object)null))
				{
					int ownerActorNr = ((MonoBehaviourPun)__instance).photonView.OwnerActorNr;
					int soundIndexForPlayer = BugleSync.GetSoundIndexForPlayer(ownerActorNr);
					AudioClip val2 = CustomBugleClips[Mathf.Clamp(soundIndexForPlayer, 0, CustomBugleClips.Count - 1)];
					if ((Object)(object)val.clip != (Object)(object)val2)
					{
						val.clip = val2;
						val.Play();
						Debug.Log((object)$">>> [BetterBugle] Forced playback from player {ownerActorNr}: {soundIndexForPlayer + 1} - '{((Object)val2).name}'");
					}
				}
			}
		}

		internal static Plugin Instance;

		internal static List<AudioClip> CustomBugleClips = new List<AudioClip>();

		internal static int SelectedIndex = 0;

		internal static ConfigEntry<KeyCode> ControllerNextKey;

		internal static ConfigEntry<KeyCode> ControllerPreviousKey;

		internal static ConfigEntry<KeyCode> KeyboardNextKey;

		internal static ConfigEntry<KeyCode> KeyboardPreviousKey;

		public static ManualLogSource Log = null;

		public const string Id = "BetterBugle";

		public static string Name => "BetterBugle";

		public static string Version => "0.1.0";

		private void Awake()
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			Log.LogInfo((object)"[BetterBugle] Awake called.");
			Debug.Log((object)">>> [BetterBugle] Plugin is initializing...");
			new Harmony(((BaseUnityPlugin)this).Info.Metadata.GUID).PatchAll();
			Log.LogInfo((object)"[BetterBugle] Harmony patches applied.");
			ControllerNextKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Controls", "ControllerNextKey", (KeyCode)335, "Controller button to go to the next sound (default: RB)");
			ControllerPreviousKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Controls", "ControllerPreviousKey", (KeyCode)334, "Controller button to go to the previous sound (default: LB)");
			KeyboardNextKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Controls", "KeyboardNextKey", (KeyCode)280, "Keyboard key to go to the next sound");
			KeyboardPreviousKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Controls", "KeyboardPreviousKey", (KeyCode)281, "Keyboard key to go to the previous sound");
			Log.LogInfo((object)"[BetterBugle] Config bindings initialized.");
			((MonoBehaviour)this).StartCoroutine(LoadAllAudioClips());
			GameObject val = new GameObject("BetterBugleUI");
			Object.DontDestroyOnLoad((Object)(object)val);
			BetterBugleUI.Instance = val.AddComponent<BetterBugleUI>();
			Log.LogInfo((object)"[BetterBugle] BetterBugleUI created.");
			Debug.Log((object)">>> [BetterBugle] Plugin initialized!");
		}

		private IEnumerator LoadAllAudioClips()
		{
			string folderPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Sounds");
			Log.LogInfo((object)(">>> [BetterBugle] Loading sounds from folder: " + folderPath));
			if (!Directory.Exists(folderPath))
			{
				Debug.LogWarning((object)(">>> [BetterBugle] Folder not found: " + folderPath));
				yield break;
			}
			string[] audioFiles = Directory.GetFiles(folderPath, "*.ogg");
			if (audioFiles.Length == 0)
			{
				Debug.LogWarning((object)">>> [BetterBugle] No .ogg files found in the Sounds folder.");
				yield break;
			}
			string[] array = audioFiles;
			foreach (string file in array)
			{
				string url = "file://" + file;
				WWW www = new WWW(url);
				try
				{
					yield return www;
					AudioClip clip = www.GetAudioClip(false, false, (AudioType)14);
					if ((Object)(object)clip != (Object)null)
					{
						((Object)clip).name = Path.GetFileName(file);
						CustomBugleClips.Add(clip);
						Debug.Log((object)(">>> [BetterBugle] Loaded audio: " + ((Object)clip).name));
					}
					else
					{
						Debug.LogError((object)(">>> [BetterBugle] Failed to load audio: " + Path.GetFileName(file)));
					}
				}
				finally
				{
					((IDisposable)www)?.Dispose();
				}
			}
			Debug.Log((object)$">>> [BetterBugle] Total .ogg clips loaded: {CustomBugleClips.Count}");
		}

		private void Update()
		{
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: 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)
			if (CustomBugleClips.Count == 0)
			{
				return;
			}
			Character localCharacter = Character.localCharacter;
			Character[] array = Object.FindObjectsByType<Character>((FindObjectsSortMode)0);
			foreach (Character val in array)
			{
				if ((Object)(object)val != (Object)null && (Object)(object)((Component)val).GetComponent<BugleSync>() == (Object)null)
				{
					((Component)val).gameObject.AddComponent<BugleSync>();
					Debug.Log((object)("[BetterBugle] BugleSync added to character " + ((Object)val).name + "."));
				}
			}
			if ((Object)(object)localCharacter == (Object)null)
			{
				Log.LogDebug((object)"[BetterBugle] No local character found.");
				return;
			}
			CharacterData component = ((Component)localCharacter).GetComponent<CharacterData>();
			if ((Object)(object)component == (Object)null || (Object)(object)component.currentItem == (Object)null)
			{
				Log.LogDebug((object)"[BetterBugle] No CharacterData or current item.");
				return;
			}
			if (component.currentItem.GetName() != "Bugle")
			{
				Log.LogDebug((object)"[BetterBugle] Current item is not Bugle.");
				return;
			}
			float axis = Input.GetAxis("Mouse ScrollWheel");
			if (axis > 0f)
			{
				ChangeSound(1);
			}
			else if (axis < 0f)
			{
				ChangeSound(-1);
			}
			if (Input.GetKeyDown(ControllerNextKey.Value))
			{
				ChangeSound(1);
			}
			if (Input.GetKeyDown(ControllerPreviousKey.Value))
			{
				ChangeSound(-1);
			}
			if (Input.GetKeyDown(KeyboardNextKey.Value))
			{
				ChangeSound(1);
			}
			if (Input.GetKeyDown(KeyboardPreviousKey.Value))
			{
				ChangeSound(-1);
			}
		}

		private void ChangeSound(int direction)
		{
			SelectedIndex = (SelectedIndex + direction + CustomBugleClips.Count) % CustomBugleClips.Count;
			string name = ((Object)CustomBugleClips[SelectedIndex]).name;
			Debug.Log((object)$">>> [BetterBugle] Selected sound: {SelectedIndex + 1} - '{name}'");
			BetterBugleUI.Instance?.ShowSound(SelectedIndex + 1, name);
			Character localCharacter = Character.localCharacter;
			BugleSync bugleSync = ((localCharacter != null) ? ((Component)localCharacter).GetComponent<BugleSync>() : null);
			if (bugleSync != null)
			{
				((MonoBehaviourPun)bugleSync).photonView.RPC("RPC_SyncBugleSound", (RpcTarget)0, new object[1] { SelectedIndex });
			}
		}
	}
	public class BugleSync : MonoBehaviourPun
	{
		public static Dictionary<int, int> syncedIndexes = new Dictionary<int, int>();

		[PunRPC]
		public void RPC_SyncBugleSound(int index)
		{
			syncedIndexes[((MonoBehaviourPun)this).photonView.OwnerActorNr] = index;
			Debug.Log((object)$">>> [BetterBugle] RPC received for player {((MonoBehaviourPun)this).photonView.OwnerActorNr} with index {index}");
		}

		public static int GetSoundIndexForPlayer(int actorNumber)
		{
			if (syncedIndexes.TryGetValue(actorNumber, out var value))
			{
				return value;
			}
			return 0;
		}
	}
	public class BetterBugleUI : MonoBehaviour
	{
		public static BetterBugleUI Instance;

		public bool IsVisible = false;

		private float lastChangeTime = -10f;

		private string soundDisplay = "";

		private GUIStyle customStyle;

		private bool fontLoaded = false;

		private int offsetX;

		private int offsetY;

		private int fontSize;

		private ConfigEntry<int> offsetXConfig;

		private ConfigEntry<int> offsetYConfig;

		private ConfigEntry<int> fontSizeConfig;

		private void Start()
		{
			offsetXConfig = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<int>("UI", "OffsetX", 0, "Horizontal offset of the UI display");
			offsetYConfig = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<int>("UI", "OffsetY", 130, "Vertical offset of the UI display");
			fontSizeConfig = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<int>("UI", "FontSize", 42, "Font size of the UI display");
			offsetX = offsetXConfig.Value;
			offsetY = offsetYConfig.Value;
			fontSize = fontSizeConfig.Value;
			Debug.Log((object)">>> [BetterBugleUI] UI initialized with config values.");
		}

		private void Update()
		{
			if (customStyle != null)
			{
				customStyle.fontSize = fontSize;
			}
		}

		public void ShowSound(int index, string name)
		{
			soundDisplay = $"SOUND {index} : {name}";
			IsVisible = true;
			lastChangeTime = Time.time;
		}

		private void OnGUI()
		{
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Expected O, but got Unknown
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			if (!IsVisible)
			{
				return;
			}
			if (Time.time - lastChangeTime > 3f)
			{
				IsVisible = false;
				return;
			}
			if (!fontLoaded)
			{
				Font[] array = Resources.FindObjectsOfTypeAll<Font>();
				foreach (Font val in array)
				{
					if (((Object)val).name == "DarumaDropOne-Regular")
					{
						customStyle = new GUIStyle(GUI.skin.label);
						customStyle.font = val;
						customStyle.fontSize = fontSize;
						customStyle.alignment = (TextAnchor)7;
						customStyle.normal.textColor = Color.white;
						fontLoaded = true;
						Debug.Log((object)">>> [BetterBugleUI] Custom font loaded: DarumaDropOne-Regular");
						break;
					}
				}
				if (!fontLoaded)
				{
					Debug.LogWarning((object)">>> [BetterBugleUI] Font 'DarumaDropOne-Regular' not found.");
					return;
				}
			}
			GUI.Label(new Rect((float)offsetX, (float)(Screen.height - offsetY), (float)Screen.width, 50f), soundDisplay, customStyle);
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}