Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of RepoSoundboard v1.0.2
Audio.dll
Decompiled a year agousing System; using System.Buffers.Binary; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using Audio.Wav; using Microsoft.CodeAnalysis; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("Audio")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+af3062504208f895f9297509e19f0bf4d754990a")] [assembly: AssemblyProduct("Audio")] [assembly: AssemblyTitle("Audio")] [assembly: AssemblyVersion("1.0.0.0")] [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 Audio { public readonly struct AudioFormat : IEquatable<AudioFormat> { public readonly int SampleRate; public readonly int Channels; public AudioFormat(int sampleRate, int channels) { SampleRate = sampleRate; Channels = channels; } public override bool Equals(object? obj) { if (obj is AudioFormat other) { return Equals(other); } return false; } public bool Equals(AudioFormat other) { if (SampleRate == other.SampleRate) { return Channels == other.Channels; } return false; } public override int GetHashCode() { return (SampleRate * 397) ^ Channels; } public static bool operator ==(AudioFormat left, AudioFormat right) { return left.Equals(right); } public static bool operator !=(AudioFormat left, AudioFormat right) { return !(left == right); } } public static class AudioProviderFactory { public static ISamplesProvider FromFile(FileInfo file, AudioFormat format) { ISamplesProvider samplesProvider = null; if (file.Extension.ToLower() == ".wav") { samplesProvider = FromWavFile(file); if (samplesProvider.Format != format) { samplesProvider = new ResampledAudioProvider(samplesProvider, format, disposeSource: true); } return samplesProvider; } throw new NotImplementedException($"Support for \"{file.Exists}\" missing"); } private static WaveSamplesProvider FromWavFile(FileInfo file) { return new WaveSamplesProvider(file.OpenRead(), leaveOpen: false); } } public interface ISamplesProvider : IDisposable { AudioFormat Format { get; } TimeSpan Duration { get; } int TotalSamples { get; } TimeSpan Position { get; set; } int SamplePosition { get; set; } int Read(float[] samples, int offset, int count); } public class ResampledAudioProvider : ISamplesProvider, IDisposable { private readonly float[] _srcChunk; private readonly float[] _resampledChunk; private int _resampledChunkLen; private int _resampledChunkReadIdx; private TimeSpan _pos; private int _samplePos; public ISamplesProvider Source { get; } public AudioFormat SourceFormat => Source.Format; public bool DisposeSource { get; } public AudioFormat Format { get; } public double Ratio { get; } public TimeSpan Duration => Source.Duration; public TimeSpan Position { get { return _pos; } set { SamplePosition = (int)(value.TotalSeconds * (double)(Format.SampleRate * Format.Channels)); } } public int TotalSamples { get; } public int SamplePosition { get { return _samplePos; } set { _samplePos = Math.Clamp(value, 0, TotalSamples); _pos = TimeSpan.FromSeconds((double)_samplePos / (double)(Format.SampleRate * Format.Channels)); _resampledChunkLen = 0; Source.SamplePosition = (int)Math.Floor((double)value / Ratio); } } public int Read(float[] samples, int offset, int count) { int num = 0; for (int i = 0; i < count; i++) { if (_resampledChunkReadIdx >= _resampledChunkLen && !ResampleChunk()) { break; } samples[offset++] = _resampledChunk[_resampledChunkReadIdx++]; num++; } return num; } public void Dispose() { if (DisposeSource) { Source.Dispose(); } } private bool ResampleChunk() { int num = Source.Read(_srcChunk, 0, _srcChunk.Length); if (num == 0) { _resampledChunkLen = 0; _resampledChunkReadIdx = 0; return false; } if (SourceFormat.Channels == 2 && Format.Channels == 1) { int num2 = 0; for (int i = 0; i < num; i += 2) { _srcChunk[num2++] = _srcChunk[i]; } num /= 2; } int num3 = 0; double num4; for (num4 = 0.0; num4 < (double)num; num4 += Ratio) { if (num3 >= _resampledChunk.Length) { break; } _resampledChunk[num3++] = _srcChunk[(int)Math.Floor(num4)]; } _resampledChunkLen = num3; _resampledChunkReadIdx = 0; Source.SamplePosition -= num - (int)Math.Floor(num4); return true; } public ResampledAudioProvider(ISamplesProvider source, AudioFormat format, bool disposeSource) { Source = source; Format = format; Ratio = (double)SourceFormat.SampleRate / (double)Format.SampleRate; DisposeSource = disposeSource; _srcChunk = new float[Format.SampleRate]; _resampledChunk = new float[Format.SampleRate]; TotalSamples = (int)((double)Source.TotalSamples / Ratio); } } } namespace Audio.Wav { public readonly struct WaveChunk { public readonly WaveChunkId Id; public readonly int Length; public WaveChunk(WaveChunkId id, int length) { Id = id; Length = length; } } public enum WaveChunkId { RIFF = 1179011410, FMT = 544501094, DATA = 1635017060 } public readonly struct WaveInfo { public readonly WaveFormat Format; public readonly int Channels; public readonly int SampleRate; public readonly int BitRate; public readonly int BlockAlign; public readonly int BitsPerSample; public const int SIG_WAVE = 1163280727; public WaveInfo(WaveFormat format, int channels, int sampleRate, int bitRate, int blockAlign, int bitsPerSample) { Format = format; Channels = channels; SampleRate = sampleRate; BitRate = bitRate; BlockAlign = blockAlign; BitsPerSample = bitsPerSample; } } public enum WaveFormat : short { PCM = 1 } public class WaveSamplesProvider : ISamplesProvider, IDisposable { private readonly struct MappedWaveChunk { public readonly WaveChunk Chunk; public readonly long Position; public MappedWaveChunk(WaveChunk chunk, long position) { Chunk = chunk; Position = position; } } private delegate bool WaveSampleReader(out float s); private readonly Dictionary<WaveChunkId, List<MappedWaveChunk>> _chunkMap = new Dictionary<WaveChunkId, List<MappedWaveChunk>>(); private readonly WaveSampleReader _sampleReader; private int _bytePos; private int _samplePos; private TimeSpan _timePos; private readonly int _dataChunkCount; private int _currentDataChunkSz = -1; private int _currentDataChunkByteIdx; private int _currentDataChunkIdx; private readonly byte[] _nextSamples = new byte[4]; public WaveInfo Info { get; } public Stream Stream { get; } public bool LeaveOpen { get; } public AudioFormat Format { get; } public int TotalSamples { get; } public int SamplePosition { get { return _samplePos; } set { SetSamplePos(value); } } public int BytesLength { get; } public int BytePosition { get { return _bytePos; } set { SetBytePos(value); } } public TimeSpan Duration { get; } public TimeSpan Position { get { return _timePos; } set { SetTimePos(value); } } public int Read(float[] samples, int offset, int count) { int num = 0; for (int i = 0; i < count; i++) { if (!_sampleReader(out var s)) { break; } samples[offset++] = s; num++; } _samplePos += num; _timePos = TimeSpan.FromSeconds((double)_samplePos / (double)(Format.SampleRate * Format.Channels)); return num; } public void Dispose() { if (!LeaveOpen) { Stream.Dispose(); } } private bool SampleI8(out float s) { if (!GetBytesForSample(1)) { s = 0f; return false; } s = (float)(int)_nextSamples[0] / 127f; return true; } private bool SampleI16(out float s) { if (!GetBytesForSample(2)) { s = 0f; return false; } float num = 32767f; s = (float)BinaryPrimitives.ReadInt16LittleEndian(_nextSamples) / num; return true; } private bool SampleI24(out float s) { if (!GetBytesForSample(3)) { s = 0f; return false; } float num = 8388607f; int num2 = _nextSamples[0] | (_nextSamples[1] << 8) | (_nextSamples[2] << 16); if (((uint)num2 & 0x800000u) != 0) { num2 |= -16777216; } s = (float)num2 / num; return true; } private bool SampleI32(out float s) { if (!GetBytesForSample(4)) { s = 0f; return false; } float num = 2.1474836E+09f; s = (float)BinaryPrimitives.ReadInt32LittleEndian(_nextSamples) / num; return true; } private bool GetBytesForSample(int count) { if (_currentDataChunkByteIdx >= _currentDataChunkSz && !NextDataChunk()) { return false; } if (Stream.Read(_nextSamples, 0, count) == count) { return true; } return false; } private bool NextDataChunk() { if (_currentDataChunkIdx >= _dataChunkCount) { return false; } WaveChunk waveChunk = SeekToChunk(WaveChunkId.DATA, _currentDataChunkIdx++); _currentDataChunkByteIdx = 0; _currentDataChunkSz = waveChunk.Length; return true; } private void SetSamplePos(int sample) { _samplePos = Math.Clamp(sample, 0, TotalSamples); _bytePos = _samplePos * (Info.BitsPerSample / 8); _timePos = TimeSpan.FromSeconds((double)_samplePos / (double)(Format.SampleRate * Format.Channels)); SeekToDataIdx(_bytePos); } private void SetBytePos(int idx) { _bytePos = Math.Clamp(idx, 0, BytesLength); _samplePos = _bytePos / (Info.BitsPerSample / 8); _timePos = TimeSpan.FromSeconds((double)_samplePos / (double)(Format.SampleRate * Format.Channels)); SeekToDataIdx(_bytePos); } private void SetTimePos(TimeSpan ts) { _samplePos = Math.Clamp((int)(ts.TotalSeconds * (double)(Format.SampleRate * Format.Channels)), 0, TotalSamples); _bytePos = _samplePos * (Info.BitsPerSample / 8); _timePos = TimeSpan.FromSeconds((double)_samplePos / (double)(Format.SampleRate * Format.Channels)); SeekToDataIdx(_bytePos); } private void SeekToDataIdx(int bp) { int num = 0; for (int i = 0; i < _dataChunkCount; i++) { WaveChunk waveChunk = SeekToChunk(WaveChunkId.DATA, i); if (bp - num >= waveChunk.Length) { num += waveChunk.Length; continue; } _currentDataChunkIdx = i; _currentDataChunkSz = waveChunk.Length; _currentDataChunkByteIdx = bp - num; Stream.Position += _currentDataChunkByteIdx; return; } _currentDataChunkIdx = _dataChunkCount; _currentDataChunkByteIdx = 0; _currentDataChunkSz = 0; } private byte[] ReadAll(int count, out int br) { int i = 0; byte[] array = new byte[count]; for (; i < count; i += br) { br = Stream.Read(array, i, count - i); if (br == 0) { break; } } br = i; return array; } private byte[] ReadAllOrException(int count) { int br; byte[] result = ReadAll(count, out br); if (br < count) { throw new EndOfStreamException(); } return result; } private short ReadI16() { return BinaryPrimitives.ReadInt16LittleEndian(ReadAllOrException(2)); } private int ReadI32() { return BinaryPrimitives.ReadInt32LittleEndian(ReadAllOrException(4)); } private WaveChunk ReadChunk() { return new WaveChunk((WaveChunkId)ReadI32(), ReadI32()); } private void LoadChunks() { if (ReadChunk().Id != WaveChunkId.RIFF) { throw new FormatException("Expected RIFF signature"); } if (ReadI32() != 1163280727) { throw new FormatException("Expected WAVE format"); } while (Stream.Position < Stream.Length) { WaveChunk chunk = ReadChunk(); if (!_chunkMap.TryGetValue(chunk.Id, out List<MappedWaveChunk> value)) { value = new List<MappedWaveChunk>(); _chunkMap.Add(chunk.Id, value); } else { WaveChunkId id = chunk.Id; if (id == WaveChunkId.FMT || id == WaveChunkId.RIFF) { throw new FormatException($"Repeating chunk {chunk.Id}"); } } value.Add(new MappedWaveChunk(chunk, Stream.Position - 8)); Stream.Position += chunk.Length; } } private WaveChunk SeekToChunk(WaveChunkId id, int index, bool seekToContent = true) { if (!_chunkMap.TryGetValue(id, out List<MappedWaveChunk> value)) { throw new KeyNotFoundException($"Could not find chunk {id}"); } Stream.Position = value[index].Position; if (seekToContent) { Stream.Position += 8L; } return value[index].Chunk; } private int ChunkCount(WaveChunkId id) { if (!_chunkMap.TryGetValue(id, out List<MappedWaveChunk> value)) { return 0; } return value.Count; } private WaveInfo LoadInfo() { WaveChunk waveChunk = SeekToChunk(WaveChunkId.FMT, 0); if (waveChunk.Length != 16) { throw new FormatException($"Format chunk has length of {waveChunk.Length}. Expected 16"); } short num = ReadI16(); int channels = ReadI16(); int sampleRate = ReadI32(); int bitRate = ReadI32() * 8; int blockAlign = ReadI16(); int bitsPerSample = ReadI16(); if (num != 1) { throw new NotSupportedException("Expected PCM audio format"); } return new WaveInfo((WaveFormat)num, channels, sampleRate, bitRate, blockAlign, bitsPerSample); } private void LoadDataInfo(out int bytes, out int samples) { bytes = 0; samples = 0; for (int i = 0; i < _dataChunkCount; i++) { WaveChunk waveChunk = SeekToChunk(WaveChunkId.DATA, i, seekToContent: false); bytes += waveChunk.Length; samples += waveChunk.Length / (Info.BitsPerSample / 8); } } public WaveSamplesProvider(Stream stream, bool leaveOpen) { Stream = stream; LeaveOpen = leaveOpen; LoadChunks(); Info = LoadInfo(); Format = new AudioFormat(Info.SampleRate, Info.Channels); _dataChunkCount = ChunkCount(WaveChunkId.DATA); LoadDataInfo(out var bytes, out var samples); BytesLength = bytes; TotalSamples = samples; Duration = TimeSpan.FromSeconds((double)TotalSamples / (double)(Info.SampleRate * Info.Channels)); switch (Info.BitsPerSample) { case 8: _sampleReader = SampleI8; break; case 16: _sampleReader = SampleI16; break; case 24: _sampleReader = SampleI24; break; case 32: _sampleReader = SampleI32; break; default: throw new NotSupportedException($"Unsupported bits per sample {Info.BitsPerSample}"); } } } public class WaveWriter : IDisposable { private readonly MemoryStream _ms = new MemoryStream(); public void AddSamples(float[] samples, int offset, int count) { byte[] array = new byte[2]; for (int i = 0; i < count; i++) { BinaryPrimitives.WriteInt16LittleEndian(array, (short)(samples[offset++] * 32767f)); _ms.Write(array, 0, array.Length); } } public void ToWave(Stream stream, int sampleRate) { WriteChunk(stream, new WaveChunk(WaveChunkId.RIFF, 44 + (int)_ms.Length)); WriteI32(stream, 1163280727); WriteChunk(stream, new WaveChunk(WaveChunkId.FMT, 16)); WriteI16(stream, 1, 1); WriteI32(stream, sampleRate, 96000); WriteI16(stream, 2, 16); _ms.Position = 0L; WriteChunk(stream, new WaveChunk(WaveChunkId.DATA, (int)_ms.Length)); _ms.CopyTo(stream); } public void Dispose() { _ms.Dispose(); } private void WriteI16(Stream s, params short[] value) { byte[] array = new byte[2]; foreach (short value2 in value) { BinaryPrimitives.WriteInt16LittleEndian(array, value2); s.Write(array, 0, array.Length); } } private void WriteI32(Stream s, params int[] value) { byte[] array = new byte[4]; foreach (int value2 in value) { BinaryPrimitives.WriteInt32LittleEndian(array, value2); s.Write(array, 0, array.Length); } } private void WriteChunk(Stream s, WaveChunk chk) { WriteI32(s, (int)chk.Id, chk.Length); } } }
RepoSoundboard.dll
Decompiled a year agousing System; 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 Audio; using BepInEx; using BepInEx.Logging; using MenuLib; using MenuLib.MonoBehaviors; using MenuLib.Structs; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using Photon.Voice; using Photon.Voice.Unity; using TMPro; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: IgnoresAccessChecksTo("")] [assembly: AssemblyCompany("NatanM")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+4f8309492bba3d4fb682253d577fbb5dbba8997f")] [assembly: AssemblyProduct("RepoSoundboard")] [assembly: AssemblyTitle("RepoSoundboard")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.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 RepoSoundboard { [BepInPlugin("NatanM.RepoSoundboard", "RepoSoundboard", "1.0.2")] public class RepoSoundboard : BaseUnityPlugin { private PlayerVoiceChat? _vc; internal static RepoSoundboard Instance { get; private set; } = null; internal static ManualLogSource Logger => Instance._logger; internal static AudioFormat AudioFormat { get; } = new AudioFormat(48000, 1); internal static SoundboardLoopback Loopback { get; } = new SoundboardLoopback(); private ManualLogSource _logger => ((BaseUnityPlugin)this).Logger; private void Awake() { Instance = this; SoundboardPool.Load(); ((Component)this).gameObject.transform.parent = null; ((Object)((Component)this).gameObject).hideFlags = (HideFlags)61; RepoSoundboardMenu.Init(); Logger.LogInfo((object)$"{((BaseUnityPlugin)this).Info.Metadata.GUID} v{((BaseUnityPlugin)this).Info.Metadata.Version} has loaded!"); } private void Update() { //IL_0038: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_vc == (Object)null) { _vc = Object.FindAnyObjectByType<PlayerVoiceChat>(); } else if ((Object)(object)_vc.recorder != (Object)null && (int)_vc.recorder.SourceType == 0) { Logger.LogInfo((object)"Detected native audio source. Overriding..."); InitSoundboard(); } } private void OnGUI() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Invalid comparison between Unknown and I4 //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Invalid comparison between Unknown and I4 //IL_0045: Unknown result type (might be due to invalid IL or missing references) Event current = Event.current; if ((int)current.type == 4) { if (RepoSoundboardMenu.IsCapturingHotKey) { RepoSoundboardMenu.DispatchHotKey(current.keyCode); } else if ((Object)(object)_vc != (Object)null && (int)_vc.recorder.SourceType == 2) { SoundboardPool.DispatchHotKey(current.keyCode); } } } private void InitSoundboard() { AudioSource val = ((Component)this).gameObject.AddComponent<AudioSource>(); val.clip = Loopback.Clip; val.loop = true; val.volume = 0.35f; val.Play(); Recorder recorder = _vc.recorder; recorder.RecordingEnabled = false; recorder.SourceType = (InputSourceType)2; recorder.InputFactory = () => (IAudioDesc)(object)new SoundboardMixer(_vc); Logger.LogInfo((object)"Started recording."); recorder.RestartRecording(); } } public static class RepoSoundboardMenu { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static BuilderDelegate <>9__0_0; public static ShouldCloseMenuDelegate <>9__1_2; public static ShouldCloseMenuDelegate <>9__4_8; internal void <Init>b__0_0(Transform p) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) MenuAPI.CreateREPOButton("Soundboard", (Action)SpawnSoundboardMenu, p, new Vector2(120f, 90f)); } internal bool <SpawnSoundboardMenu>b__1_2() { return true; } internal bool <CreateEntryLayout>b__4_8() { SoundboardPool.Save(); return true; } } private static SoundboardObject? capturingHotKeyObj; private static REPOButton? capturingHotKeyBtn; private static readonly List<REPOElement> entryLayoutElements = new List<REPOElement>(); public static bool IsCapturingHotKey { get; set; } public static void Init() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown object obj = <>c.<>9__0_0; if (obj == null) { BuilderDelegate val = delegate(Transform p) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) MenuAPI.CreateREPOButton("Soundboard", (Action)SpawnSoundboardMenu, p, new Vector2(120f, 90f)); }; <>c.<>9__0_0 = val; obj = (object)val; } MenuAPI.AddElementToSettingsMenu((BuilderDelegate)obj); } private static void SpawnSoundboardMenu() { //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Expected O, but got Unknown //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Expected O, but got Unknown //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Expected O, but got Unknown //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Expected O, but got Unknown SoundboardPool.Save(); if (IsCapturingHotKey) { RepoSoundboard.Logger.LogWarning((object)"IsCapturingHotKey didn't properly reset."); IsCapturingHotKey = false; } REPOPopupPage popup = MenuAPI.CreateREPOPopupPage("Soundboard", (PresetSide)0, false, true, 0f); popup.scrollView.scrollSpeed = 3f; REPOPopupPage obj = popup; Padding maskPadding = popup.maskPadding; maskPadding.top = 35f; obj.maskPadding = maskPadding; REPOPopupPage obj2 = popup; ShouldCloseMenuDelegate onEscapePressed = obj2.onEscapePressed; object obj3 = <>c.<>9__1_2; if (obj3 == null) { ShouldCloseMenuDelegate val = () => true; <>c.<>9__1_2 = val; obj3 = (object)val; } obj2.onEscapePressed = (ShouldCloseMenuDelegate)Delegate.Combine((Delegate?)(object)onEscapePressed, (Delegate?)obj3); CreateCfgLayout(popup); popup.AddElement((BuilderDelegate)delegate(Transform p) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) MenuAPI.CreateREPOButton("Back", (Action)delegate { popup.ClosePage(true); }, p, new Vector2(66f, 10f)); }); popup.AddElement((BuilderDelegate)delegate(Transform p) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) MenuAPI.CreateREPOButton("Add", (Action)delegate { SoundboardObject entry = SoundboardPool.Add(new SoundboardObject { Name = "New Sound" }); popup.ClosePage(true); OpenMenuForEntry(entry); }, p, new Vector2(150f, 10f)); }); popup.OpenPage(false); } private static void CreateCfgLayout(REPOPopupPage popup) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Expected O, but got Unknown REPOPopupPage popup2 = popup; for (int i = 0; i < SoundboardPool.Count; i++) { SoundboardObject entry = SoundboardPool.Get(i); popup2.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform p) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) REPOButton val = MenuAPI.CreateREPOButton(entry.Name, (Action)delegate { popup2.ClosePage(false); OpenMenuForEntry(entry); }, p, default(Vector2)); return ((REPOElement)val).rectTransform; }, 0f, 0f); } } private static void OpenMenuForEntry(SoundboardObject entry) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Expected O, but got Unknown //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Expected O, but got Unknown //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Expected O, but got Unknown REPOPopupPage popup = MenuAPI.CreateREPOPopupPage("Entry Settings", (PresetSide)0, false, true, 0f); popup.scrollView.scrollSpeed = 3f; REPOPopupPage obj = popup; Padding maskPadding = popup.maskPadding; maskPadding.top = 35f; obj.maskPadding = maskPadding; REPOPopupPage obj2 = popup; obj2.onEscapePressed = (ShouldCloseMenuDelegate)Delegate.Combine((Delegate?)(object)obj2.onEscapePressed, (Delegate?)(ShouldCloseMenuDelegate)delegate { if (IsCapturingHotKey) { return false; } SpawnSoundboardMenu(); popup.ClosePage(true); return false; }); CreateEntryLayout(popup, entry); popup.AddElement((BuilderDelegate)delegate(Transform p) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) REPOButton item = MenuAPI.CreateREPOButton("Back", (Action)delegate { popup.ClosePage(true); SpawnSoundboardMenu(); }, p, new Vector2(66f, 10f)); entryLayoutElements.Add((REPOElement)(object)item); }); popup.OpenPage(false); } private static void CreateEntryLayout(REPOPopupPage popup, SoundboardObject entry) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Expected O, but got Unknown //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Expected O, but got Unknown //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Expected O, but got Unknown //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Expected O, but got Unknown //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Expected O, but got Unknown //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Expected O, but got Unknown SoundboardObject entry2 = entry; REPOPopupPage popup2 = popup; entryLayoutElements.Clear(); entry2.Stop(); popup2.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform p) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) REPOInputField val4 = MenuAPI.CreateREPOInputField("Name", (Action<string>)delegate(string s) { entry2.Name = s; }, p, default(Vector2), false, "", ""); val4.inputStringSystem.SetValue(entry2.Name, false); entryLayoutElements.Add((REPOElement)(object)val4); return ((REPOElement)val4).rectTransform; }, 0f, 0f); popup2.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform p) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) REPOInputField val3 = MenuAPI.CreateREPOInputField("Path", (Action<string>)delegate(string s) { entry2.Path = s; }, p, default(Vector2), false, "", ""); val3.inputStringSystem.SetValue(entry2.Path, false); entryLayoutElements.Add((REPOElement)(object)val3); return ((REPOElement)val3).rectTransform; }, 0f, 0f); popup2.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform p) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) KeyCode hotKey = entry2.HotKey; REPOButton button = MenuAPI.CreateREPOButton("HotKey: " + ((object)(KeyCode)(ref hotKey)).ToString(), (Action)null, p, default(Vector2)); button.onClick = delegate { ((TMP_Text)button.labelTMP).text = "HotKey: ..."; capturingHotKeyObj = entry2; capturingHotKeyBtn = button; IsCapturingHotKey = true; RepoSoundboard.Logger.LogDebug((object)$"IsCapturingHotKey: {IsCapturingHotKey}"); foreach (REPOElement entryLayoutElement in entryLayoutElements) { ((Behaviour)entryLayoutElement).enabled = false; } }; entryLayoutElements.Add((REPOElement)(object)button); return ((REPOElement)button).rectTransform; }, 0f, 0f); popup2.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform p) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) REPOButton val2 = MenuAPI.CreateREPOButton("Delete", (Action)delegate { popup2.ClosePage(false); SoundboardPool.Remove(entry2); SpawnSoundboardMenu(); }, p, default(Vector2)); RectTransform rectTransform = ((REPOElement)val2).rectTransform; ((Transform)rectTransform).position = ((Transform)rectTransform).position + new Vector3(0f, 10f); ((Graphic)val2.labelTMP).color = new Color(0.8f, 0.25f, 0.25f, 1f); entryLayoutElements.Add((REPOElement)(object)val2); return ((REPOElement)val2).rectTransform; }, 0f, 0f); REPOPopupPage obj = popup2; ShouldCloseMenuDelegate onEscapePressed = obj.onEscapePressed; object obj2 = <>c.<>9__4_8; if (obj2 == null) { ShouldCloseMenuDelegate val = delegate { SoundboardPool.Save(); return true; }; <>c.<>9__4_8 = val; obj2 = (object)val; } obj.onEscapePressed = (ShouldCloseMenuDelegate)Delegate.Combine((Delegate?)(object)onEscapePressed, (Delegate?)obj2); } public static void DispatchHotKey(KeyCode keyCode) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Invalid comparison between Unknown and I4 //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Invalid comparison between Unknown and I4 //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) if ((int)keyCode == 27) { RepoSoundboard.Logger.LogDebug((object)$"Ignore set new key code: {keyCode}"); RestoreAfterHotKey(); return; } if ((int)keyCode == 8) { keyCode = (KeyCode)0; } RepoSoundboard.Logger.LogDebug((object)$"Set new HotKey: {keyCode}"); if (capturingHotKeyObj == null) { RestoreAfterHotKey(); return; } RepoSoundboard.Logger.LogDebug((object)(capturingHotKeyObj.UpdateHotKey(keyCode) ? "Success." : "Failed.")); RestoreAfterHotKey(); } private static void RestoreAfterHotKey() { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) IsCapturingHotKey = false; foreach (REPOElement entryLayoutElement in entryLayoutElements) { ((Behaviour)entryLayoutElement).enabled = true; } TextMeshProUGUI labelTMP = capturingHotKeyBtn.labelTMP; KeyCode hotKey = capturingHotKeyObj.HotKey; ((TMP_Text)labelTMP).text = "HotKey: " + ((object)(KeyCode)(ref hotKey)).ToString(); } } public static class SoundboardAudioProvider { private static readonly List<SoundboardObject> _active = new List<SoundboardObject>(); public static void Push(SoundboardObject obj) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) lock (_active) { ISamplesProvider? provider = obj.Provider; ResampledAudioProvider val = (ResampledAudioProvider)(object)((provider is ResampledAudioProvider) ? provider : null); if (val != null) { RepoSoundboard.Logger.LogDebug((object)$"Resampling from {val.SourceFormat.SampleRate} to {val.Format.SampleRate}"); } _active.Add(obj); } } public static void Remove(SoundboardObject obj) { lock (_active) { _active.Remove(obj); } } public static void Mix(float[] samples, float[] soundboardLoopback) { float[] array = new float[samples.Length]; lock (_active) { for (int num = _active.Count - 1; num >= 0; num--) { SoundboardObject soundboardObject = _active[num]; if (soundboardObject.Finished) { soundboardObject.Stop(); } int num2 = soundboardObject.Read(array, 0, array.Length); if (num2 == 0) { soundboardObject.Stop(); } for (int i = 0; i < num2; i++) { samples[i] += array[i]; soundboardLoopback[i] += array[i]; } } } } } public class SoundboardLoopback { private int _readIdx; private int _writeIdx; private int _samplesAvailable; private readonly float[] _samples; private readonly object _lock = new object(); public AudioClip Clip { get; } public SoundboardLoopback() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Expected O, but got Unknown //IL_0068: Expected O, but got Unknown _samples = new float[RepoSoundboard.AudioFormat.SampleRate / 2]; Clip = AudioClip.Create("SoundboardLoopback", _samples.Length, RepoSoundboard.AudioFormat.Channels, RepoSoundboard.AudioFormat.SampleRate, true, new PCMReaderCallback(OnRead), new PCMSetPositionCallback(OnSetPosition)); } public void Push(float[] buffer) { lock (_lock) { foreach (float num in buffer) { _samples[_writeIdx] = num; _writeIdx = (_writeIdx + 1) % _samples.Length; if (_samplesAvailable < _samples.Length) { _samplesAvailable++; } else { _readIdx = (_readIdx + 1) % _samples.Length; } } } } private void OnRead(float[] samples) { lock (_lock) { Array.Clear(samples, 0, samples.Length); int num = Math.Min(samples.Length, _samplesAvailable); for (int i = 0; i < num; i++) { samples[i] = _samples[_readIdx]; _readIdx = (_readIdx + 1) % _samples.Length; } _samplesAvailable -= num; } } private void OnSetPosition(int position) { } } public class SoundboardMixer : IAudioReader<float>, IDataReader<float>, IDisposable, IAudioDesc { private int _lastMicPos; public PlayerVoiceChat VoiceChat { get; } public DeviceInfo MicrophoneDevice { get; set; } public AudioClip? MicrophoneClip { get; private set; } public int SamplingRate => RepoSoundboard.AudioFormat.SampleRate; public int Channels => RepoSoundboard.AudioFormat.Channels; public string? Error { get; private set; } public SoundboardMixer(PlayerVoiceChat voiceChat) { VoiceChat = voiceChat; base..ctor(); } private void EnsureAudioDevice() { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) DeviceInfo microphoneDevice = VoiceChat.recorder.MicrophoneDevice; string iDString = ((DeviceInfo)(ref microphoneDevice)).IDString; microphoneDevice = MicrophoneDevice; if (iDString != ((DeviceInfo)(ref microphoneDevice)).IDString) { _lastMicPos = 0; MicrophoneDevice = VoiceChat.recorder.MicrophoneDevice; microphoneDevice = MicrophoneDevice; MicrophoneClip = Microphone.Start(((DeviceInfo)(ref microphoneDevice)).Name, true, 1, SamplingRate); RepoSoundboard.Logger.LogInfo((object)"Microphone clip updated."); } } public bool Read(float[] buffer) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) EnsureAudioDevice(); if (!((Object)(object)MicrophoneClip == (Object)null)) { DeviceInfo microphoneDevice = MicrophoneDevice; if (Microphone.IsRecording(((DeviceInfo)(ref microphoneDevice)).Name)) { microphoneDevice = MicrophoneDevice; int position = Microphone.GetPosition(((DeviceInfo)(ref microphoneDevice)).Name); int num = position - _lastMicPos; if (num < 0) { num += MicrophoneClip.samples; } if (num < buffer.Length) { return false; } Array.Clear(buffer, 0, buffer.Length); MicrophoneClip.GetData(buffer, _lastMicPos); float[] array = new float[buffer.Length]; SoundboardAudioProvider.Mix(buffer, array); RepoSoundboard.Loopback.Push(array); _lastMicPos = (_lastMicPos + buffer.Length) % MicrophoneClip.samples; return true; } } return false; } public void Dispose() { //IL_0001: 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_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) DeviceInfo microphoneDevice = MicrophoneDevice; if (Microphone.IsRecording(((DeviceInfo)(ref microphoneDevice)).Name)) { microphoneDevice = MicrophoneDevice; Microphone.End(((DeviceInfo)(ref microphoneDevice)).Name); } AudioClip? microphoneClip = MicrophoneClip; if (microphoneClip != null) { microphoneClip.UnloadAudioData(); } } } public class SoundboardObject { [JsonIgnore] private readonly object _lock = new object(); private KeyCode _hk; public string Name { get; set; } = string.Empty; public string Path { get; set; } = string.Empty; public KeyCode HotKey { get { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return _hk; } set { //IL_0001: Unknown result type (might be due to invalid IL or missing references) UpdateHotKey(value); } } [JsonIgnore] public bool Finished { get { if (Provider != null) { return Provider.SamplePosition >= Provider.TotalSamples; } return true; } } [JsonIgnore] public ISamplesProvider? Provider { get; private set; } public void Play() { //IL_00a4: Unknown result type (might be due to invalid IL or missing references) try { lock (_lock) { if (Provider != null) { RepoSoundboard.Logger.LogDebug((object)("Sound " + Name + " restarted.")); Restart(); return; } RepoSoundboard.Logger.LogInfo((object)("Trying to play " + Name + " from file " + Path + "...")); FileInfo fileInfo = new FileInfo(Path); if (!fileInfo.Exists) { throw new FileNotFoundException(Path); } Provider = AudioProviderFactory.FromFile(fileInfo, RepoSoundboard.AudioFormat); SoundboardAudioProvider.Push(this); } } catch (Exception arg) { RepoSoundboard.Logger.LogWarning((object)$"Could not play \"{Name}\": {arg}"); } } public void Stop() { lock (_lock) { SoundboardAudioProvider.Remove(this); ((IDisposable)Provider)?.Dispose(); Provider = null; RepoSoundboard.Logger.LogDebug((object)("Sound " + Name + " stopped.")); } } public void Restart() { lock (_lock) { Provider.Position = TimeSpan.Zero; } } public int Read(float[] buffer, int offset, int samples) { lock (_lock) { if (Provider == null) { return 0; } return Provider.Read(buffer, offset, samples); } } public bool UpdateHotKey(KeyCode newHk) { //IL_0021: 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) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) if (SoundboardPool.HasObject(this)) { if (!SoundboardPool.IsHotKeyAvailableFor(newHk, this)) { return false; } SoundboardPool.UpdateHk(this, HotKey, newHk); } _hk = newHk; return true; } } public static class SoundboardPool { private static readonly List<SoundboardObject> _objects = new List<SoundboardObject>(); private static readonly Dictionary<KeyCode, SoundboardObject> _keyMap = new Dictionary<KeyCode, SoundboardObject>(); public static int Count => _objects.Count; public static SoundboardObject Add(SoundboardObject obj) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0040: 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_004d: Unknown result type (might be due to invalid IL or missing references) if (!IsHotKeyAvailable(obj.HotKey)) { RepoSoundboard.Logger.LogWarning((object)$"Found object with repeating HotKey: {obj.HotKey}"); obj.UpdateHotKey((KeyCode)0); } _objects.Add(obj); if ((int)obj.HotKey != 0) { _keyMap.Add(obj.HotKey, obj); } return obj; } public static void Remove(SoundboardObject obj) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) _objects.Remove(obj); _keyMap.Remove(obj.HotKey, out SoundboardObject _); } public static bool HasObject(SoundboardObject obj) { return _objects.Contains(obj); } public static void Save() { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Expected O, but got Unknown try { FileInfo settingsFile = GetSettingsFile(); RepoSoundboard.Logger.LogDebug((object)("Saving settings to \"" + settingsFile.FullName + "\"...")); File.WriteAllText(settingsFile.FullName, JsonConvert.SerializeObject((object)_objects, new JsonSerializerSettings { Converters = { (JsonConverter)(object)new HotKeyConverter() }, Formatting = (Formatting)1 })); RepoSoundboard.Logger.LogDebug((object)"Settings saved."); } catch (Exception arg) { RepoSoundboard.Logger.LogError((object)$"Failed to write settings: {arg}"); } } public static void Load() { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Expected O, but got Unknown try { RepoSoundboard.Logger.LogDebug((object)"Loading settings..."); _objects.Clear(); _keyMap.Clear(); FileInfo settingsFile = GetSettingsFile(); string text = File.ReadAllText(settingsFile.FullName); List<SoundboardObject> list = JsonConvert.DeserializeObject<List<SoundboardObject>>(text, new JsonSerializerSettings { Converters = { (JsonConverter)(object)new HotKeyConverter() } }); if (list != null) { foreach (SoundboardObject item in list) { Add(item); } } RepoSoundboard.Logger.LogDebug((object)"Settings loaded."); } catch (Exception arg) { RepoSoundboard.Logger.LogError((object)$"Failed to read settings: {arg}"); } } public static SoundboardObject Get(int idx) { return _objects[idx]; } public static void DispatchHotKey(KeyCode key) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) if (_keyMap.TryGetValue(key, out SoundboardObject value)) { value.Play(); } } public static bool IsHotKeyAvailable(KeyCode key) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) if ((int)key != 0) { return !_keyMap.ContainsKey(key); } return true; } public static bool IsHotKeyAvailableFor(KeyCode key, SoundboardObject obj) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) if ((int)key == 0 || !_keyMap.TryGetValue(key, out SoundboardObject value)) { return true; } return obj == value; } internal static void UpdateHk(SoundboardObject obj, KeyCode old, KeyCode newValue) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) _keyMap.Remove(old); _keyMap.Add(newValue, obj); } internal static FileInfo GetSettingsFile() { try { Process currentProcess = Process.GetCurrentProcess(); FileInfo fileInfo = new FileInfo(currentProcess.MainModule.FileName); return new FileInfo(Path.Combine(fileInfo.Directory.FullName, "soundboard_settings.json")); } catch (Exception arg) { RepoSoundboard.Logger.LogError((object)$"Failed to get settings file path. Defaulting to current working directory. Reason: {arg}"); return new FileInfo("soundboard_settings.json"); } } } internal class HotKeyConverter : JsonConverter { public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) if (!(value is KeyCode val)) { writer.WriteNull(); } else { writer.WriteValue(((object)(KeyCode)(ref val)).ToString()); } } public override object ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) if (!(reader.Value is string value) || !Enum.TryParse<KeyCode>(value, out KeyCode result)) { return (object)(KeyCode)0; } return result; } public override bool CanConvert(Type objectType) { return objectType == typeof(KeyCode); } } }