The BepInEx console will not appear when launching like it does for other games on Thunderstore. This is normal (and helps prevent crashes during startup). You can turn it back on in your BepInEx.cfg file.
Decompiled source of BetterBugle v1.0.3
BepInEx/plugins/BetterBugle/BetterBugle.dll
Decompiled a day agousing 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) { } } }