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;
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)
{
}
}
}