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 EmPeak v1.2.5
BepInEx/plugins/BetterBugle/BetterBugle.dll
Decompiled a week 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; using UnityEngine.SceneManagement; [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) { if (CustomBugleClips.Count > 0) { ___bugle = CustomBugleClips.ToArray(); Log.LogInfo((object)$">>> [BetterBugle] Bugle sound list replaced ({___bugle.Length} clips)."); } } } [HarmonyPatch(typeof(BugleSFX), "Update")] public static class BuglePatch_ForceSound { [HarmonyPostfix] public static void OverridePlayedSound(BugleSFX __instance) { if (CustomBugleClips.Count == 0) { return; } AudioSource buglePlayer = __instance.buglePlayer; if (!((Object)(object)buglePlayer == (Object)null)) { int ownerActorNr = ((MonoBehaviourPun)__instance).photonView.OwnerActorNr; int soundIndexForPlayer = BugleSync.GetSoundIndexForPlayer(ownerActorNr); AudioClip val = CustomBugleClips[Mathf.Clamp(soundIndexForPlayer, 0, CustomBugleClips.Count - 1)]; if (__instance.hold && (Object)(object)buglePlayer.clip != (Object)(object)val) { buglePlayer.clip = val; buglePlayer.Play(); Log.LogInfo((object)$"[BetterBugle] Play: Actor {ownerActorNr} | Clip: {((Object)val).name}"); } if (__instance.hold && buglePlayer.isPlaying) { ManualLogSource log = Log; object arg = ownerActorNr; AudioClip clip = buglePlayer.clip; log.LogDebug((object)string.Format("[BetterBugle] Playing (actor {0}): {1}", arg, ((clip != null) ? ((Object)clip).name : null) ?? "null")); } else if (!__instance.hold && buglePlayer.isPlaying) { ManualLogSource log2 = Log; object arg2 = ownerActorNr; AudioClip clip2 = buglePlayer.clip; log2.LogDebug((object)string.Format("[BetterBugle] Stopping (actor {0}): {1}", arg2, ((clip2 != null) ? ((Object)clip2).name : null) ?? "null")); buglePlayer.Stop(); } } } } 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; private static bool isInitialized = false; private static bool isInGameScene = false; public static bool HasBugleInHand = false; private bool hasGivenBugle = false; private bool hasDuplicatedSpawner = false; private bool hasLoggedUpdateOnce = false; public const string Id = "BetterBugle"; public static string Name => "BetterBugle"; public static string Version => "0.1.0"; private void Awake() { //IL_004f: Unknown result type (might be due to invalid IL or missing references) Instance = this; Log = ((BaseUnityPlugin)this).Logger; SceneManager.sceneLoaded += OnSceneLoaded; 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"); ((MonoBehaviour)this).StartCoroutine(LoadAllAudioClips()); ((MonoBehaviour)this).StartCoroutine(WaitForSceneLoadAndInit()); } private void OnSceneLoaded(Scene scene, LoadSceneMode mode) { if (((Scene)(ref scene)).name != "Airport") { Debug.Log((object)("[BetterBugle] Scene loaded: " + ((Scene)(ref scene)).name + ", starting spawner duplication check.")); hasDuplicatedSpawner = false; ((MonoBehaviour)this).StartCoroutine(WaitAndDuplicateSpawner()); } } private IEnumerator WaitAndDuplicateSpawner() { while ((Object)(object)GameObject.Find("Bugle_Spawner") == (Object)null) { yield return null; } GameObject originalSpawner = GameObject.Find("Bugle_Spawner"); if (!((Object)(object)originalSpawner != (Object)null) || hasDuplicatedSpawner) { yield break; } Vector3 basePosition = new Vector3(19.2f, 5.1f, -364.8f); for (int i = 0; i < 3; i++) { Vector3 offset = new Vector3((float)i * 0.5f, 0f, 0f); GameObject clone = Object.Instantiate<GameObject>(originalSpawner, basePosition + offset, originalSpawner.transform.rotation); ((Object)clone).name = $"Bugle_Spawner_Clone_{i + 1}"; SingleItemSpawner spawner = clone.GetComponent<SingleItemSpawner>(); if ((Object)(object)spawner != (Object)null) { spawner.TrySpawnItems(); } } hasDuplicatedSpawner = true; Debug.Log((object)"[BetterBugle] Bugle_Spawner duplicated 3 times near custom position and forced spawn called."); } private void OnDestroy() { SceneManager.sceneLoaded -= OnSceneLoaded; } 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)) { Log.LogWarning((object)(">>> [BetterBugle] Folder not found: " + folderPath)); yield break; } string[] audioFiles = Directory.GetFiles(folderPath, "*.ogg"); if (audioFiles.Length == 0) { Log.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); Log.LogInfo((object)(">>> [BetterBugle] Loaded audio: " + ((Object)clip).name)); } else { Log.LogError((object)(">>> [BetterBugle] Failed to load audio: " + Path.GetFileName(file))); } } finally { ((IDisposable)www)?.Dispose(); } } Log.LogInfo((object)$">>> [BetterBugle] Final count of loaded clips: {CustomBugleClips.Count}"); isInitialized = true; } private IEnumerator WaitForSceneLoadAndInit() { Log.LogInfo((object)"[BetterBugle] Waiting for scene to load..."); while ((Object)(object)Character.localCharacter == (Object)null) { yield return null; } isInGameScene = true; Log.LogInfo((object)"[BetterBugle] Scene loaded, initializing BetterBugleUI and components."); GameObject uiObject = new GameObject("BetterBugleUI"); Object.DontDestroyOnLoad((Object)(object)uiObject); BetterBugleUI.Instance = uiObject.AddComponent<BetterBugleUI>(); Debug.Log((object)">>> [BetterBugle] BetterBugleUI created after scene load."); } private void Update() { //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_01ba: 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_020e: Unknown result type (might be due to invalid IL or missing references) if (!isInitialized || !isInGameScene || CustomBugleClips.Count == 0) { return; } if (!hasLoggedUpdateOnce) { Debug.Log((object)$"[BetterBugle] Update called - isInitialized={isInitialized}, isInGameScene={isInGameScene}, CustomBugleClips.Count={CustomBugleClips.Count}"); hasLoggedUpdateOnce = true; } Character localCharacter = Character.localCharacter; if ((Object)(object)localCharacter == (Object)null) { return; } 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 + ".")); } } CharacterData component = ((Component)localCharacter).GetComponent<CharacterData>(); if (!((Object)(object)component == (Object)null) && !((Object)(object)component.currentItem == (Object)null) && HasBugleInHand) { float axis = Input.GetAxis("Mouse ScrollWheel"); if (axis > 0f) { Debug.Log((object)"[BetterBugle] Mouse scroll up detected"); ChangeSound(1); } else if (axis < 0f) { Debug.Log((object)"[BetterBugle] Mouse scroll down detected"); ChangeSound(-1); } if (Input.GetKeyDown(ControllerNextKey.Value)) { Debug.Log((object)"[BetterBugle] Controller next key pressed"); ChangeSound(1); } if (Input.GetKeyDown(ControllerPreviousKey.Value)) { Debug.Log((object)"[BetterBugle] Controller previous key pressed"); ChangeSound(-1); } if (Input.GetKeyDown(KeyboardNextKey.Value)) { Debug.Log((object)"[BetterBugle] Keyboard next key pressed"); ChangeSound(1); } if (Input.GetKeyDown(KeyboardPreviousKey.Value)) { Debug.Log((object)"[BetterBugle] Keyboard previous key pressed"); ChangeSound(-1); } } } public static void SyncSound(int index) { if (!((Object)(object)Character.localCharacter == (Object)null)) { SelectedIndex = Mathf.Clamp(index, 0, CustomBugleClips.Count - 1); BugleSync component = ((Component)Character.localCharacter).GetComponent<BugleSync>(); if (component != null) { ((MonoBehaviourPun)component).photonView.RPC("RPC_SyncBugleSound", (RpcTarget)0, new object[1] { SelectedIndex }); } string name = ((Object)CustomBugleClips[SelectedIndex]).name; Debug.Log((object)(">>> [BetterBugle] Synced sound: " + name)); BetterBugleUI.Instance?.ShowSound(SelectedIndex + 1, name); } } private void ChangeSound(int direction) { int index = (SelectedIndex + direction + CustomBugleClips.Count) % CustomBugleClips.Count; SyncSound(index); } } [HarmonyPatch(typeof(CharacterItems), "Equip")] public class Patch_CharacterItems_Equip { private static void Postfix(CharacterItems __instance) { if (!((Object)(object)__instance.character != (Object)null) || !((Object)(object)__instance.character.data != (Object)null)) { return; } Item currentItem = __instance.character.data.currentItem; if ((Object)(object)currentItem != (Object)null) { BugleSFX component = ((Component)currentItem).GetComponent<BugleSFX>(); Plugin.HasBugleInHand = (Object)(object)component != (Object)null; if (Plugin.HasBugleInHand) { Debug.Log((object)"[BetterBugle] Bugle equipped."); } else { Debug.Log((object)"[BetterBugle] Bugle not equipped."); } } else { Plugin.HasBugleInHand = false; } } } 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; Plugin.Log.LogInfo((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; } 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_0108: 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; break; } } } 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) { } } }