The BepInEx console will not appear when launching like it does for other games on Thunderstore (you can turn it back on in your BepInEx.cfg file). If your PEAK crashes on startup, add -dx12 to your launch parameters.
Decompiled source of Virtuoso v0.3.1
plugins/com.github.mondash.Virtuoso.dll
Decompiled 19 hours agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; 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 Virtuoso.Audio; using Virtuoso.Behaviour; using Virtuoso.Config; using Virtuoso.Data; using Virtuoso.Event; using Virtuoso.Input; using Virtuoso.Runtime; using Virtuoso.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("com.github.mondash.Virtuoso")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.3.1.0")] [assembly: AssemblyInformationalVersion("0.3.1+3c45e2ed3eef365c1b2beae79cb6154ed4f13559")] [assembly: AssemblyProduct("com.github.mondash.Virtuoso")] [assembly: AssemblyTitle("Virtuoso")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.3.1.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 Virtuoso { [BepInPlugin("com.github.mondash.Virtuoso", "Virtuoso", "0.3.1")] public class Plugin : BaseUnityPlugin { private Harmony? _harmony; public const string Id = "com.github.mondash.Virtuoso"; internal static ManualLogSource Log { get; private set; } public static string Name => "Virtuoso"; public static string Version => "0.3.1"; private void Awake() { //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Expected O, but got Unknown //IL_0060: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; Log.LogInfo((object)"Plugin waking..."); Log.LogDebug((object)"Loading configuration..."); BugleConfig.Bind(((BaseUnityPlugin)this).Config); Log.LogDebug((object)"Applying harmony patches..."); Harmony val = new Harmony(((BaseUnityPlugin)this).Info.Metadata.GUID); Harmony val2 = val; _harmony = val; val2.PatchAll(); Log.LogDebug((object)"Adding runtime components..."); ((Component)this).gameObject.AddComponent<BugleUILoader>(); Log.LogInfo((object)"Plugin awake!"); } private void OnDestroy() { Log.LogInfo((object)"Plugin destroying..."); Log.LogDebug((object)"Disconnecting custom bugle behaviour..."); BugleBehaviour.DisconnectAll(); Log.LogDebug((object)"Removing harmony patches..."); Harmony? harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } Log.LogInfo((object)"Plugin destroyed!"); } } } namespace Virtuoso.UI { internal class BugleNote { private static readonly string[] NoteNames = new string[12] { "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B" }; public static string FromSemitone(float semitone) { int num = Mathf.RoundToInt(semitone) + 69; num = Mathf.Clamp(num, 0, 127); int num2 = num / 12 - 1; int num3 = num % 12; return $"{NoteNames[num3]}{num2}"; } } internal class BugleUI : MonoBehaviour { private static BugleUI? _instance; private static bool _visible = true; private static KeyCode ToggleUIKey => BugleConfig.ToggleUIKey.Value; private static bool IsPaused => GUIManager.instance.pauseMenu.activeSelf; public static void Initialize(GameObject gameObject) { if (!Object.op_Implicit((Object)(object)_instance)) { _instance = gameObject.AddComponent<BugleUI>(); Plugin.Log.LogInfo((object)"BugleUI initialized"); } } public static void DestroyInstance() { if (Object.op_Implicit((Object)(object)_instance)) { Object.Destroy((Object)(object)_instance); _instance = null; Plugin.Log.LogInfo((object)"BugleUI destroyed"); } } private void Update() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) if (Input.GetKeyDown(ToggleUIKey)) { _visible = !_visible; } } private void OnGUI() { if (!_visible || IsPaused) { return; } Character localCharacter = Character.localCharacter; if (!Object.op_Implicit((Object)(object)localCharacter)) { return; } Item currentItem = localCharacter.data.currentItem; BugleSFX val = default(BugleSFX); if (!Object.op_Implicit((Object)(object)currentItem) || !((Component)currentItem).TryGetComponent<BugleSFX>(ref val)) { return; } Camera main = Camera.main; if (!Object.op_Implicit((Object)(object)main)) { return; } float maxAngle = BuglePartial.MaxAngle; int partials = BuglePartial.Partials; int num = partials - 1; float y = localCharacter.data.lookValues.y; float fieldOfView = main.fieldOfView; float num2 = fieldOfView * 0.5f * (MathF.PI / 180f); float num3 = Screen.height; float num4 = Screen.width; for (int i = 1; i <= num; i++) { float num5 = (float)i / (float)partials; float num6 = Mathf.Lerp(0f - maxAngle, maxAngle, num5); float num7 = num6 - y; float num8 = num7 * (MathF.PI / 180f); if (!(Mathf.Abs(num8) > num2)) { float num9 = 0.5f - Mathf.Tan(num8) / Mathf.Tan(num2); float y2 = num9 * num3; float x = (num4 - 20f) * 0.5f; DrawLine(x, y2, 20f); } } } private static void DrawLine(float x, float y, float width) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) Color color = GUI.color; GUI.color = Color.white; GUI.DrawTexture(new Rect(x, y, width, 5f), (Texture)(object)Texture2D.whiteTexture); GUI.color = color; } } } namespace Virtuoso.Runtime { internal class BugleUILoader : MonoBehaviour { [CompilerGenerated] private sealed class <LoadUI>d__3 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public BugleUILoader <>4__this; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <LoadUI>d__3(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Expected O, but got Unknown int num = <>1__state; BugleUILoader bugleUILoader = <>4__this; switch (num) { default: return false; case 0: <>1__state = -1; Plugin.Log.LogInfo((object)"Bugle UI loader routine started"); <>2__current = (object)new WaitUntil((Func<bool>)bugleUILoader.ReadyOrDisabled); <>1__state = 1; return true; case 1: <>1__state = -1; if (((Behaviour)bugleUILoader).isActiveAndEnabled) { BugleUI.Initialize(((Component)bugleUILoader).gameObject); } Plugin.Log.LogInfo((object)"Bugle UI loader routine finished"); return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private void OnEnable() { ((MonoBehaviour)this).StartCoroutine(LoadUI()); } private void OnDisable() { BugleUI.DestroyInstance(); } private bool ReadyOrDisabled() { if (!Object.op_Implicit((Object)(object)Character.localCharacter)) { return !((Behaviour)this).isActiveAndEnabled; } return true; } [IteratorStateMachine(typeof(<LoadUI>d__3))] private IEnumerator LoadUI() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <LoadUI>d__3(0) { <>4__this = this }; } } } namespace Virtuoso.Patching { [HarmonyPatch(typeof(BugleSFX))] internal static class BugleSFX_Patch { private static void SetTooting(BugleSFX instance) { ((object)instance).GetType().GetField("t", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(instance, true); } [HarmonyPatch("RPC_StartToot")] [HarmonyPostfix] private static void RPC_StartToot_Postfix(BugleSFX __instance, int clip, float pitch) { SetTooting(__instance); BugleBehaviour.Connect(__instance); BugleHub.RaiseTootStarted(__instance); } [HarmonyPatch("RPC_EndToot")] [HarmonyPostfix] private static void RPC_EndToot_Postfix(BugleSFX __instance) { BugleHub.RaiseTootStopped(__instance); } } } namespace Virtuoso.Input { public static class BugleBend { private static float? _initialAngle; private static float MaxAngle => BugleConfig.MaxBendAngle.Value; private static float MaxSemitones => BugleConfig.MaxBendSemitones.Value; private static float CurrentAngle { get { if (!Object.op_Implicit((Object)(object)Character.localCharacter)) { return 0f; } return Character.localCharacter.data.lookValues.x; } } public static float Semitones() { if (!_initialAngle.HasValue) { return 0f; } float num = Mathf.DeltaAngle(_initialAngle.Value, CurrentAngle); float num2 = Mathf.Clamp(num / MaxAngle, -1f, 1f); return num2 * MaxSemitones; } public static void Reset() { _initialAngle = null; } public static void SetInitialAngle() { _initialAngle = CurrentAngle; } } internal static class BuglePartial { private const float SmoothStrength = 300f; private static readonly float[] RealisticHarmonics = new float[7] { 12f, 19.02f, 24f, 27.86f, 31.02f, 33.69f, 36f }; private static readonly float[] IdealHarmonics = new float[7] { 12f, 19f, 24f, 28f, 31f, 34f, 36f }; private static float? _smoothAngle; private static float SmoothSpeed => 300f * BugleConfig.HarmonicSmoothMult.Value; public static float MaxAngle => BugleConfig.MaxPartialAngle.Value; private static bool Ideal => BugleConfig.UseIdealHarmonics.Value; private static float[] Harmonics { get { if (!Ideal) { return RealisticHarmonics; } return IdealHarmonics; } } public static int Partials => Harmonics.Length; private static float CurrentAngle { get { if (!Object.op_Implicit((Object)(object)Character.localCharacter)) { return 0f; } return Character.localCharacter.data.lookValues.y; } } public static float Semitones() { float num = _smoothAngle ?? CurrentAngle; float num2 = Mathf.InverseLerp(0f - MaxAngle, MaxAngle, num); int num3 = Mathf.FloorToInt(num2 * (float)Partials); int num4 = Mathf.Clamp(num3, 0, Partials - 1); return Harmonics[num4]; } public static void Reset() { _smoothAngle = null; } public static void Smooth(float delta) { _smoothAngle = (_smoothAngle.HasValue ? Mathf.MoveTowards(_smoothAngle.Value, CurrentAngle, delta * SmoothSpeed) : CurrentAngle); } } internal static class TrumpetValves { private static readonly Dictionary<int, float> RealisticOffsets = new Dictionary<int, float> { [0] = -0f, [2] = -1f, [1] = -2f, [4] = -2.95f, [3] = -3f, [6] = -4f, [5] = -5.35f, [7] = -6.75f }; private static readonly Dictionary<int, float> IdealOffsets = new Dictionary<int, float> { [0] = -0f, [2] = -1f, [1] = -2f, [4] = -3f, [3] = -3f, [6] = -4f, [5] = -5f, [7] = -6f }; private static bool Ideal => BugleConfig.UseIdealValves.Value; private static KeyCode Valve1Key => BugleConfig.Valve1Key.Value; private static KeyCode Valve2Key => BugleConfig.Valve2Key.Value; private static KeyCode Valve3Key => BugleConfig.Valve3Key.Value; private static Dictionary<int, float> Offsets { get { if (!Ideal) { return RealisticOffsets; } return IdealOffsets; } } public static float Semitones() { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) int num = 0; if (Input.GetKey(Valve1Key)) { num |= 1; } if (Input.GetKey(Valve2Key)) { num |= 2; } if (Input.GetKey(Valve3Key)) { num |= 4; } return Offsets.GetValueOrDefault(num, 0f); } } } namespace Virtuoso.Event { internal sealed class BugleHub { private readonly HashSet<IBugleListener> _listeners = new HashSet<IBugleListener>(); private static readonly ConditionalWeakTable<BugleSFX, BugleHub> Registry = new ConditionalWeakTable<BugleSFX, BugleHub>(); private event Action? TootStarted; private event Action? TootStopped; private event Action<BuglePitchFrame>? Frame; public Action Subscribe(IBugleListener listener) { IBugleListener listener2 = listener; if (!_listeners.Add(listener2)) { return delegate { }; } TootStarted += listener2.HandleTootStarted; TootStopped += listener2.HandleTootStopped; Frame += listener2.HandleFrame; return delegate { Unsubscribe(listener2); }; } private void Unsubscribe(IBugleListener listener) { if (_listeners.Remove(listener)) { TootStarted -= listener.HandleTootStarted; TootStopped -= listener.HandleTootStopped; Frame -= listener.HandleFrame; } } private void RaiseTootStarted() { this.TootStarted?.Invoke(); } private void RaiseTootStopped() { this.TootStopped?.Invoke(); } public void RaiseFrame(BuglePitchFrame frame) { this.Frame?.Invoke(frame); } public static BugleHub Get(BugleSFX sfx) { return Registry.GetValue(sfx, (BugleSFX _) => new BugleHub()); } public static void RaiseTootStarted(BugleSFX sfx) { Get(sfx).RaiseTootStarted(); } public static void RaiseTootStopped(BugleSFX sfx) { Get(sfx).RaiseTootStopped(); } } internal interface IBugleListener { void HandleTootStarted(); void HandleTootStopped(); void HandleFrame(BuglePitchFrame frame); } } namespace Virtuoso.Data { internal readonly struct BuglePitchFrame { public readonly float Valves; public readonly float Partial; public readonly float Bend; public object Data => new object[3] { Valves, Partial, Bend }; public float Semitone => Valves + Partial + Bend; public float Pitch => Mathf.Pow(2f, Semitone / 12f); public BuglePitchFrame(float valves, float partial, float bend) { Valves = valves; Partial = partial; Bend = bend; } public BuglePitchFrame() : this(TrumpetValves.Semitones(), BuglePartial.Semitones(), BugleBend.Semitones()) { } public BuglePitchFrame(object[] data) : this((float)data[0], (float)data[1], (float)data[2]) { } public bool Approximately(BuglePitchFrame other, float bendThreshold = 0.05f) { if (Mathf.Approximately(Valves, other.Valves) && Mathf.Approximately(Partial, other.Partial)) { return Mathf.Abs(Bend - other.Bend) < bendThreshold; } return false; } public float Smooth(float current, float delta, float speed = 100f) { return Mathf.MoveTowards(current, Pitch, delta * speed); } } } namespace Virtuoso.Config { internal static class BugleConfig { public static ConfigEntry<float> MaxBendAngle; public static ConfigEntry<float> MaxBendSemitones; public static ConfigEntry<bool> UseIdealHarmonics; public static ConfigEntry<float> MaxPartialAngle; public static ConfigEntry<float> HarmonicSmoothMult; public static ConfigEntry<float> PitchSmoothMult; public static ConfigEntry<float> SyncInterval; public static ConfigEntry<KeyCode> ToggleUIKey; public static ConfigEntry<bool> UseIdealValves; public static ConfigEntry<KeyCode> Valve1Key; public static ConfigEntry<KeyCode> Valve2Key; public static ConfigEntry<KeyCode> Valve3Key; public static void Bind(ConfigFile config) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Expected O, but got Unknown //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Expected O, but got Unknown //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Expected O, but got Unknown //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Expected O, but got Unknown //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Expected O, but got Unknown //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Expected O, but got Unknown MaxBendAngle = config.Bind<float>("Bend", "MaxBendAngle", 80f, new ConfigDescription("Maximum left/right view angle (in degrees) allowed to bend pitch", (AcceptableValueBase)(object)new AcceptableValueRange<float>(10f, 170f), Array.Empty<object>())); MaxBendSemitones = config.Bind<float>("Bend", "MaxBendSemitones", 2f, new ConfigDescription("Maximum pitch bending amount in semitones", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 12f), Array.Empty<object>())); UseIdealHarmonics = config.Bind<bool>("Harmonics", "UseIdealHarmonics", true, "If true, uses mathematically ideal harmonics"); MaxPartialAngle = config.Bind<float>("Harmonics", "MaxPartialAngle", 80f, new ConfigDescription("Vertical angle span (in degrees) allocated to partial selection", (AcceptableValueBase)(object)new AcceptableValueRange<float>(10f, 90f), Array.Empty<object>())); HarmonicSmoothMult = config.Bind<float>("Smoothing", "HarmonicSmoothMult", 1f, new ConfigDescription("How quickly harmonic partials react, higher values reacting quicker", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.125f, 8f), Array.Empty<object>())); PitchSmoothMult = config.Bind<float>("Smoothing", "PitchSmoothMult", 1f, new ConfigDescription("How quickly pitch changes are smoothed, higher values smoothing quicker", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.125f, 8f), Array.Empty<object>())); SyncInterval = config.Bind<float>("Sync", "SyncInterval", 0.1f, new ConfigDescription("Time (in seconds) between bugle sync frames", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.01f, 1f), Array.Empty<object>())); ToggleUIKey = config.Bind<KeyCode>("UI", "ToggleUIKey", (KeyCode)117, "Keyboard shortcut to toggle the bugle UI visibility"); UseIdealValves = config.Bind<bool>("Valves", "UseIdealValves", true, "If true, uses mathematically ideal tuning offsets for valve combinations"); Valve1Key = config.Bind<KeyCode>("Valves", "Valve1Key", (KeyCode)122, "Keyboard key for Valve 1"); Valve2Key = config.Bind<KeyCode>("Valves", "Valve2Key", (KeyCode)120, "Keyboard key for Valve 2"); Valve3Key = config.Bind<KeyCode>("Valves", "Valve3Key", (KeyCode)99, "Keyboard key for Valve 3"); } } } namespace Virtuoso.Behaviour { [DefaultExecutionOrder(2)] internal class BugleAudio : BugleBehaviour { [CompilerGenerated] private sealed class <StopRoutine>d__11 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public BugleAudio <>4__this; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <StopRoutine>d__11(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Expected O, but got Unknown int num = <>1__state; BugleAudio bugleAudio = <>4__this; switch (num) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitWhile((Func<bool>)bugleAudio.SourceActive); <>1__state = 1; return true; case 1: <>1__state = -1; if (Object.op_Implicit((Object)(object)bugleAudio.Source) && bugleAudio.Source.isPlaying) { bugleAudio.Source.Stop(); } bugleAudio._stopRoutine = null; return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private const float VolumeEpsilon = 0.001f; private const float SmoothStrength = 100f; private bool _newToot; private BuglePitchFrame _frame; private Coroutine? _stopRoutine; private static float SmoothSpeed => 100f * BugleConfig.PitchSmoothMult.Value; private AudioSource Source => base.Sfx.buglePlayer; protected override bool ShouldUpdate { get { if (!base.ShouldUpdate) { return Source.isPlaying; } return true; } } protected override void OnTootStarted() { Source.clip = BugleClip.Pinched(); Source.loop = true; _newToot = true; } private bool SourceActive() { if (((Behaviour)this).isActiveAndEnabled) { AudioSource source = Source; if (source != null && source.isPlaying) { return source.volume > 0.001f; } return false; } return false; } [IteratorStateMachine(typeof(<StopRoutine>d__11))] private IEnumerator StopRoutine() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <StopRoutine>d__11(0) { <>4__this = this }; } protected override void OnTootStopped() { if (_stopRoutine == null) { _stopRoutine = ((MonoBehaviour)this).StartCoroutine(StopRoutine()); } } protected override void OnFrame(BuglePitchFrame frame) { _frame = frame; } private bool Pause() { if (Time.timeScale != 0f) { return false; } if (Source.isPlaying) { Source.Stop(); } return true; } protected override void OnUpdate() { if (!Pause()) { Source.pitch = (_newToot ? _frame.Pitch : _frame.Smooth(Source.pitch, Time.deltaTime, SmoothSpeed)); if (!Source.isPlaying) { Source.Play(); } _newToot = false; } } } [RequireComponent(typeof(BugleSFX))] internal abstract class BugleBehaviour : MonoBehaviour, IBugleListener { private Action? _unsubscribe; private bool _implementsOnTootStarted; private bool _implementsOnTootStopped; private bool _implementsOnFrame; private bool _implementsOnUpdate; protected string Name { get; private set; } protected BugleSFX Sfx { get; private set; } protected BugleHub Hub { get; private set; } protected bool IsMine => ((MonoBehaviourPun)Sfx).photonView.IsMine; protected int ViewID => ((MonoBehaviourPun)Sfx).photonView.ViewID; protected virtual bool ShouldHandleTootStarted => true; protected virtual bool ShouldHandleTootStopped => true; protected virtual bool ShouldHandleFrame => true; protected virtual bool ShouldUpdate { get { if (Sfx.hold) { return Time.timeScale > 0f; } return false; } } private static T Connect<T>(BugleSFX sfx) where T : BugleBehaviour { T result = default(T); if (!((Component)sfx).TryGetComponent<T>(ref result)) { return ((Component)sfx).gameObject.AddComponent<T>(); } return result; } public static void Connect(BugleSFX sfx) { Connect<BugleInput>(sfx); Connect<BugleAudio>(sfx); Connect<BugleSync>(sfx); Connect<BugleDrop>(sfx); } protected static void Disconnect(BugleSFX sfx) { ((Component)sfx).GetComponents<BugleBehaviour>().ToList().ForEach((Action<BugleBehaviour>)Object.Destroy); } public static void DisconnectAll() { Object.FindObjectsByType<BugleBehaviour>((FindObjectsSortMode)0).ToList().ForEach((Action<BugleBehaviour>)Object.Destroy); } private static bool ImplementsHandler(Type type, string name) { MethodInfo method = type.GetMethod(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (method != null) { return method.DeclaringType != typeof(BugleBehaviour); } return false; } private void Awake() { Type type = ((object)this).GetType(); _implementsOnTootStarted = ImplementsHandler(type, "OnTootStarted"); _implementsOnTootStopped = ImplementsHandler(type, "OnTootStopped"); _implementsOnFrame = ImplementsHandler(type, "OnFrame"); _implementsOnUpdate = ImplementsHandler(type, "OnUpdate"); Name = type.Name; Sfx = ((Component)this).GetComponent<BugleSFX>(); Hub = BugleHub.Get(Sfx); } protected virtual void OnEnable() { if (_unsubscribe == null) { _unsubscribe = Hub.Subscribe(this); } Plugin.Log.LogInfo((object)$"Enabled {Name} for view {ViewID}"); } protected virtual void OnDisable() { _unsubscribe?.Invoke(); _unsubscribe = null; Plugin.Log.LogInfo((object)$"Disabled {Name} for view {ViewID}"); } protected virtual void OnTootStarted() { } protected virtual void OnTootStopped() { } protected virtual void OnFrame(BuglePitchFrame f) { } protected virtual void OnUpdate() { } void IBugleListener.HandleTootStarted() { if (_implementsOnTootStarted && ShouldHandleTootStarted) { Plugin.Log.LogDebug((object)$"{Name} handling toot start for view {ViewID}"); OnTootStarted(); } } void IBugleListener.HandleTootStopped() { if (_implementsOnTootStopped && ShouldHandleTootStopped) { Plugin.Log.LogDebug((object)$"{Name} handling toot stop for view {ViewID}"); OnTootStopped(); } } void IBugleListener.HandleFrame(BuglePitchFrame frame) { if (_implementsOnFrame && ShouldHandleFrame) { Plugin.Log.LogDebug((object)$"{Name} handling frame for view {ViewID}"); OnFrame(frame); } } private void Update() { if (_implementsOnUpdate && ShouldUpdate) { Plugin.Log.LogDebug((object)$"{Name} handling update for view {ViewID}"); OnUpdate(); } } } [DefaultExecutionOrder(4)] internal class BugleDrop : BugleBehaviour { protected override void OnEnable() { Item item = base.Sfx.item; item.OnStateChange = (Action<ItemState>)Delegate.Combine(item.OnStateChange, new Action<ItemState>(DisconnectOnDrop)); base.OnEnable(); } protected override void OnDisable() { Item item = base.Sfx.item; item.OnStateChange = (Action<ItemState>)Delegate.Remove(item.OnStateChange, new Action<ItemState>(DisconnectOnDrop)); base.OnDisable(); } private void DisconnectOnDrop(ItemState state) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Invalid comparison between Unknown and I4 if ((int)state != 1) { BugleBehaviour.Disconnect(base.Sfx); } } } [DefaultExecutionOrder(1)] internal class BugleInput : BugleBehaviour { protected override bool ShouldHandleTootStarted { get { if (base.ShouldHandleTootStarted) { return base.IsMine; } return false; } } protected override bool ShouldHandleTootStopped { get { if (base.ShouldHandleTootStopped) { return base.IsMine; } return false; } } protected override bool ShouldUpdate { get { if (base.ShouldUpdate) { return base.IsMine; } return false; } } protected override void OnTootStarted() { BugleBend.SetInitialAngle(); base.Hub.RaiseFrame(new BuglePitchFrame()); } protected override void OnTootStopped() { BugleBend.Reset(); BuglePartial.Reset(); } protected override void OnUpdate() { BuglePartial.Smooth(Time.deltaTime); base.Hub.RaiseFrame(new BuglePitchFrame()); } } [DefaultExecutionOrder(3)] internal class BugleSync : BugleBehaviour { private float _since; private BuglePitchFrame _lastLocal; private BuglePitchFrame _lastSent; private static float SyncInterval => BugleConfig.SyncInterval.Value; protected override bool ShouldHandleFrame { get { if (base.ShouldHandleFrame) { return base.IsMine; } return false; } } protected override bool ShouldUpdate { get { if (base.ShouldUpdate) { return base.IsMine; } return false; } } protected override void OnFrame(BuglePitchFrame frame) { _lastLocal = frame; } protected override void OnUpdate() { _since += Time.deltaTime; if (!(_since < SyncInterval) || !_lastSent.Approximately(_lastLocal)) { SyncBuglePitchFrame(_lastLocal); } } private void SyncBuglePitchFrame(BuglePitchFrame frame) { ((MonoBehaviourPun)base.Sfx).photonView.RPC("RPC_SyncBuglePitchFrame", (RpcTarget)1, new object[1] { frame.Data }); Plugin.Log.LogDebug((object)$"Sent frame sync from view {base.ViewID}"); _lastSent = frame; _since = 0f; } [PunRPC] private void RPC_SyncBuglePitchFrame(object[] data, PhotonMessageInfo info) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) Plugin.Log.LogDebug((object)$"Received frame sync from actor {info.Sender.ActorNumber}"); base.Hub.RaiseFrame(new BuglePitchFrame(data)); } } } namespace Virtuoso.Audio { internal static class BugleClip { private const float Frequency = 58.27f; private static AudioClip? _clip; public static AudioClip Brass() { if (Object.op_Implicit((Object)(object)_clip)) { return _clip; } Plugin.Log.LogInfo((object)"Generating bugle brass clip"); float[] array = new float[7568]; for (int i = 0; i < 7568; i++) { float num = 366.12122f * (float)i / 44100f; float num2 = (Mathf.Sin(num) + 0.7f * Mathf.Sin(2f * num) + 0.5f * Mathf.Sin(3f * num) + 0.4f * Mathf.Sin(4f * num) + 0.3f * Mathf.Sin(5f * num) + 0.2f * Mathf.Sin(6f * num) + 0.15f * Mathf.Sin(7f * num) + 0.1f * Mathf.Sin(8f * num)) * 0.2f; float num3 = 0.02f * (Random.value - 0.5f); array[i] = num2 + num3; } _clip = AudioClip.Create("BugleBrassClip", 7568, 1, 44100, false); _clip.SetData(array, 0); return _clip; } public static AudioClip Brassier() { if (Object.op_Implicit((Object)(object)_clip)) { return _clip; } Plugin.Log.LogInfo((object)"Generating brassier clip"); float[] array = new float[7568]; for (int i = 0; i < 7568; i++) { float num = 366.12122f * (float)i / 44100f; float num2 = 1f * Mathf.Sin(num) + 0.8f * Mathf.Sin(2f * num) + 1.2f * Mathf.Sin(3f * num) + 0.6f * Mathf.Sin(4f * num) + 0.4f * Mathf.Sin(5f * num) + 0.8f * Mathf.Sin(6f * num) + 0.2f * Mathf.Sin(7f * num) + 0.1f * Mathf.Sin(8f * num); num2 *= 0.15f; float num3 = 0.01f * (Random.value - 0.5f); array[i] = num2 + num3; } _clip = AudioClip.Create("BugleBrassierClip", 7568, 1, 44100, false); _clip.SetData(array, 0); return _clip; } public static AudioClip Sawtooth() { if (Object.op_Implicit((Object)(object)_clip)) { return _clip; } Plugin.Log.LogInfo((object)"Generating sawtooth clip"); float[] array = new float[7568]; for (int i = 0; i < 7568; i++) { float num = 366.12122f * (float)i / 44100f; float num2 = 366.85345f * (float)i / 44100f; float num3 = 0f; for (int j = 1; j <= 20; j++) { float num4 = 1f / (float)j * Mathf.Exp(-0.05f * (float)j); if (j >= 5 && j <= 7) { num4 *= 1.5f; } float num5 = (float)i / 7568f; float num6 = 1f + 0.05f * Mathf.Sin(MathF.PI * 2f * (float)j * num5); num3 += num4 * num6 * (Mathf.Sin((float)j * num) + 0.3f * Mathf.Sin((float)j * num2)); } num3 *= 0.2f; float num7 = 0.01f * (Random.value - 0.5f); array[i] = num3 + num7; } _clip = AudioClip.Create("BugleSawtoothClip", 7568, 1, 44100, false); _clip.SetData(array, 0); return _clip; } public static AudioClip Pinched() { if (Object.op_Implicit((Object)(object)_clip)) { return _clip; } Plugin.Log.LogInfo((object)"Generating fixed pinched brass clip"); float[] array = new float[7568]; for (int i = 0; i < 7568; i++) { float num = (float)i / 44100f; float num2 = 366.12122f * num; float num3 = 0f; for (int j = 1; j <= 20; j++) { float num4 = num2 * (float)j; float num5 = Mathf.Sin(num4); float num6 = Mathf.Sign(num5) * Mathf.Pow(Mathf.Abs(num5), 1.1f); float num7 = 1f / (float)j * Mathf.Exp(-0.045f * (float)j); if (j >= 5 && j <= 7) { num7 *= 1.5f; } num3 += num7 * num6; } num3 += 0.15f * Mathf.Pow(num3, 3f); float num8 = 0.005f * (Random.value - 0.5f); array[i] = num3 * 0.3f + num8; } _clip = AudioClip.Create("BuglePinchedClip", 7568, 1, 44100, false); _clip.SetData(array, 0); return _clip; } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }