Decompiled source of ResourcefulHands v0.9.60

NAudio-Unity.dll

Decompiled 3 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using Microsoft.Win32;
using NAudio.CoreAudioApi;
using NAudio.CoreAudioApi.Interfaces;
using NAudio.Dmo;
using NAudio.Dsp;
using NAudio.FileFormats.Wav;
using NAudio.MediaFoundation;
using NAudio.Utils;
using NAudio.Wave;
using NAudio.Wave.Asio;
using NAudio.Wave.Compression;
using NAudio.Wave.SampleProviders;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("NAudio-Unity")]
[assembly: AssemblyDescription("NAudio .NET Audio Library (Unity 3.5 Subset)")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Wulf Marius")]
[assembly: AssemblyProduct("NAudio (Unity 3.5 Subset)")]
[assembly: AssemblyCopyright("© 2018 Wulf Marius")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("678589a3-c646-4464-8afa-5ea83bff44a7")]
[assembly: AssemblyFileVersion("2.0.0")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("2.0.0.0")]
[module: UnverifiableCode]
namespace NAudio
{
	public enum Manufacturers
	{
		Microsoft = 1,
		Creative = 2,
		Mediavision = 3,
		Fujitsu = 4,
		Artisoft = 20,
		TurtleBeach = 21,
		Ibm = 22,
		Vocaltec = 23,
		Roland = 24,
		DspSolutions = 25,
		Nec = 26,
		Ati = 27,
		Wanglabs = 28,
		Tandy = 29,
		Voyetra = 30,
		Antex = 31,
		IclPS = 32,
		Intel = 33,
		Gravis = 34,
		Val = 35,
		Interactive = 36,
		Yamaha = 37,
		Everex = 38,
		Echo = 39,
		Sierra = 40,
		Cat = 41,
		Apps = 42,
		DspGroup = 43,
		Melabs = 44,
		ComputerFriends = 45,
		Ess = 46,
		Audiofile = 47,
		Motorola = 48,
		Canopus = 49,
		Epson = 50,
		Truevision = 51,
		Aztech = 52,
		Videologic = 53,
		Scalacs = 54,
		Korg = 55,
		Apt = 56,
		Ics = 57,
		Iteratedsys = 58,
		Metheus = 59,
		Logitech = 60,
		Winnov = 61,
		Ncr = 62,
		Exan = 63,
		Ast = 64,
		Willowpond = 65,
		Sonicfoundry = 66,
		Vitec = 67,
		Moscom = 68,
		Siliconsoft = 69,
		Supermac = 73,
		Audiopt = 74,
		Speechcomp = 76,
		Ahead = 77,
		Dolby = 78,
		Oki = 79,
		Auravision = 80,
		Olivetti = 81,
		Iomagic = 82,
		Matsushita = 83,
		Controlres = 84,
		Xebec = 85,
		Newmedia = 86,
		Nms = 87,
		Lyrrus = 88,
		Compusic = 89,
		Opti = 90,
		Adlacc = 91,
		Compaq = 92,
		Dialogic = 93,
		Insoft = 94,
		Mptus = 95,
		Weitek = 96,
		LernoutAndHauspie = 97,
		Qciar = 98,
		Apple = 99,
		Digital = 100,
		Motu = 101,
		Workbit = 102,
		Ositech = 103,
		Miro = 104,
		Cirruslogic = 105,
		Isolution = 106,
		Horizons = 107,
		Concepts = 108,
		Vtg = 109,
		Radius = 110,
		Rockwell = 111,
		Xyz = 112,
		Opcode = 113,
		Voxware = 114,
		NorthernTelecom = 115,
		Apicom = 116,
		Grande = 117,
		Addx = 118,
		Wildcat = 119,
		Rhetorex = 120,
		Brooktree = 121,
		Ensoniq = 125,
		Fast = 126,
		Nvidia = 127,
		Oksori = 128,
		Diacoustics = 129,
		Gulbransen = 130,
		KayElemetrics = 131,
		Crystal = 132,
		SplashStudios = 133,
		Quarterdeck = 134,
		Tdk = 135,
		DigitalAudioLabs = 136,
		Seersys = 137,
		Picturetel = 138,
		AttMicroelectronics = 139,
		Osprey = 140,
		Mediatrix = 141,
		Soundesigns = 142,
		Aldigital = 143,
		SpectrumSignalProcessing = 144,
		Ecs = 145,
		Amd = 146,
		Coredynamics = 147,
		Canam = 148,
		Softsound = 149,
		Norris = 150,
		Ddd = 151,
		Euphonics = 152,
		Precept = 153,
		CrystalNet = 154,
		Chromatic = 155,
		Voiceinfo = 156,
		Viennasys = 157,
		Connectix = 158,
		Gadgetlabs = 159,
		Frontier = 160,
		Viona = 161,
		Casio = 162,
		Diamondmm = 163,
		S3 = 164,
		FraunhoferIis = 172
	}
	public class MmException : Exception
	{
		private MmResult result;

		private string function;

		public MmResult Result => result;

		public MmException(MmResult result, string function)
			: base(ErrorMessage(result, function))
		{
			this.result = result;
			this.function = function;
		}

		private static string ErrorMessage(MmResult result, string function)
		{
			return $"{result} calling {function}";
		}

		public static void Try(MmResult result, string function)
		{
			if (result != 0)
			{
				throw new MmException(result, function);
			}
		}
	}
	public enum MmResult
	{
		NoError = 0,
		UnspecifiedError = 1,
		BadDeviceId = 2,
		NotEnabled = 3,
		AlreadyAllocated = 4,
		InvalidHandle = 5,
		NoDriver = 6,
		MemoryAllocationError = 7,
		NotSupported = 8,
		BadErrorNumber = 9,
		InvalidFlag = 10,
		InvalidParameter = 11,
		HandleBusy = 12,
		InvalidAlias = 13,
		BadRegistryDatabase = 14,
		RegistryKeyNotFound = 15,
		RegistryReadError = 16,
		RegistryWriteError = 17,
		RegistryDeleteError = 18,
		RegistryValueNotFound = 19,
		NoDriverCallback = 20,
		MoreData = 21,
		WaveBadFormat = 32,
		WaveStillPlaying = 33,
		WaveHeaderUnprepared = 34,
		WaveSync = 35,
		AcmNotPossible = 512,
		AcmBusy = 513,
		AcmHeaderUnprepared = 514,
		AcmCancelled = 515,
		MixerInvalidLine = 1024,
		MixerInvalidControl = 1025,
		MixerInvalidValue = 1026
	}
}
namespace NAudio.Mixer
{
	public class BooleanMixerControl : MixerControl
	{
		private MixerInterop.MIXERCONTROLDETAILS_BOOLEAN boolDetails;

		public bool Value
		{
			get
			{
				GetControlDetails();
				return boolDetails.fValue == 1;
			}
			set
			{
				boolDetails.fValue = (value ? 1 : 0);
				mixerControlDetails.paDetails = Marshal.AllocHGlobal(Marshal.SizeOf((object)boolDetails));
				Marshal.StructureToPtr((object)boolDetails, mixerControlDetails.paDetails, fDeleteOld: false);
				MmException.Try(MixerInterop.mixerSetControlDetails(mixerHandle, ref mixerControlDetails, MixerFlags.Mixer | mixerHandleType), "mixerSetControlDetails");
				Marshal.FreeHGlobal(mixerControlDetails.paDetails);
			}
		}

		internal BooleanMixerControl(MixerInterop.MIXERCONTROL mixerControl, IntPtr mixerHandle, MixerFlags mixerHandleType, int nChannels)
		{
			base.mixerControl = mixerControl;
			base.mixerHandle = mixerHandle;
			base.mixerHandleType = mixerHandleType;
			base.nChannels = nChannels;
			mixerControlDetails = default(MixerInterop.MIXERCONTROLDETAILS);
			GetControlDetails();
		}

		protected override void GetDetails(IntPtr pDetails)
		{
			boolDetails = (MixerInterop.MIXERCONTROLDETAILS_BOOLEAN)Marshal.PtrToStructure(pDetails, typeof(MixerInterop.MIXERCONTROLDETAILS_BOOLEAN));
		}
	}
	public class CustomMixerControl : MixerControl
	{
		internal CustomMixerControl(MixerInterop.MIXERCONTROL mixerControl, IntPtr mixerHandle, MixerFlags mixerHandleType, int nChannels)
		{
			base.mixerControl = mixerControl;
			base.mixerHandle = mixerHandle;
			base.mixerHandleType = mixerHandleType;
			base.nChannels = nChannels;
			mixerControlDetails = default(MixerInterop.MIXERCONTROLDETAILS);
			GetControlDetails();
		}

		protected override void GetDetails(IntPtr pDetails)
		{
		}
	}
	public class ListTextMixerControl : MixerControl
	{
		internal ListTextMixerControl(MixerInterop.MIXERCONTROL mixerControl, IntPtr mixerHandle, MixerFlags mixerHandleType, int nChannels)
		{
			base.mixerControl = mixerControl;
			base.mixerHandle = mixerHandle;
			base.mixerHandleType = mixerHandleType;
			base.nChannels = nChannels;
			mixerControlDetails = default(MixerInterop.MIXERCONTROLDETAILS);
			GetControlDetails();
		}

		protected override void GetDetails(IntPtr pDetails)
		{
		}
	}
	public class Mixer
	{
		private MixerInterop.MIXERCAPS caps;

		private IntPtr mixerHandle;

		private MixerFlags mixerHandleType;

		public static int NumberOfDevices => MixerInterop.mixerGetNumDevs();

		public int DestinationCount => (int)caps.cDestinations;

		public string Name => caps.szPname;

		public Manufacturers Manufacturer => (Manufacturers)caps.wMid;

		public int ProductID => caps.wPid;

		public IEnumerable<MixerLine> Destinations
		{
			get
			{
				for (int destination = 0; destination < DestinationCount; destination++)
				{
					yield return GetDestination(destination);
				}
			}
		}

		public static IEnumerable<Mixer> Mixers
		{
			get
			{
				for (int device = 0; device < NumberOfDevices; device++)
				{
					yield return new Mixer(device);
				}
			}
		}

		public Mixer(int mixerIndex)
		{
			if (mixerIndex < 0 || mixerIndex >= NumberOfDevices)
			{
				throw new ArgumentOutOfRangeException("mixerID");
			}
			caps = default(MixerInterop.MIXERCAPS);
			MmException.Try(MixerInterop.mixerGetDevCaps((IntPtr)mixerIndex, ref caps, Marshal.SizeOf((object)caps)), "mixerGetDevCaps");
			mixerHandle = (IntPtr)mixerIndex;
			mixerHandleType = MixerFlags.Mixer;
		}

		public MixerLine GetDestination(int destinationIndex)
		{
			if (destinationIndex < 0 || destinationIndex >= DestinationCount)
			{
				throw new ArgumentOutOfRangeException("destinationIndex");
			}
			return new MixerLine(mixerHandle, destinationIndex, mixerHandleType);
		}
	}
	public abstract class MixerControl
	{
		internal MixerInterop.MIXERCONTROL mixerControl;

		internal MixerInterop.MIXERCONTROLDETAILS mixerControlDetails;

		protected IntPtr mixerHandle;

		protected int nChannels;

		protected MixerFlags mixerHandleType;

		public string Name => mixerControl.szName;

		public MixerControlType ControlType => mixerControl.dwControlType;

		public bool IsBoolean => IsControlBoolean(mixerControl.dwControlType);

		public bool IsListText => IsControlListText(mixerControl.dwControlType);

		public bool IsSigned => IsControlSigned(mixerControl.dwControlType);

		public bool IsUnsigned => IsControlUnsigned(mixerControl.dwControlType);

		public bool IsCustom => IsControlCustom(mixerControl.dwControlType);

		public static IList<MixerControl> GetMixerControls(IntPtr mixerHandle, MixerLine mixerLine, MixerFlags mixerHandleType)
		{
			List<MixerControl> list = new List<MixerControl>();
			if (mixerLine.ControlsCount > 0)
			{
				int num = Marshal.SizeOf(typeof(MixerInterop.MIXERCONTROL));
				MixerInterop.MIXERLINECONTROLS mixerLineControls = default(MixerInterop.MIXERLINECONTROLS);
				IntPtr intPtr = Marshal.AllocHGlobal(num * mixerLine.ControlsCount);
				mixerLineControls.cbStruct = Marshal.SizeOf((object)mixerLineControls);
				mixerLineControls.dwLineID = mixerLine.LineId;
				mixerLineControls.cControls = mixerLine.ControlsCount;
				mixerLineControls.pamxctrl = intPtr;
				mixerLineControls.cbmxctrl = Marshal.SizeOf(typeof(MixerInterop.MIXERCONTROL));
				try
				{
					MmResult mmResult = MixerInterop.mixerGetLineControls(mixerHandle, ref mixerLineControls, MixerFlags.Mixer | mixerHandleType);
					if (mmResult != 0)
					{
						throw new MmException(mmResult, "mixerGetLineControls");
					}
					for (int i = 0; i < mixerLineControls.cControls; i++)
					{
						MixerInterop.MIXERCONTROL mIXERCONTROL = (MixerInterop.MIXERCONTROL)Marshal.PtrToStructure((IntPtr)(intPtr.ToInt64() + num * i), typeof(MixerInterop.MIXERCONTROL));
						MixerControl item = GetMixerControl(mixerHandle, mixerLine.LineId, mIXERCONTROL.dwControlID, mixerLine.Channels, mixerHandleType);
						list.Add(item);
					}
				}
				finally
				{
					Marshal.FreeHGlobal(intPtr);
				}
			}
			return list;
		}

		public static MixerControl GetMixerControl(IntPtr mixerHandle, int nLineID, int controlId, int nChannels, MixerFlags mixerFlags)
		{
			MixerInterop.MIXERLINECONTROLS mixerLineControls = default(MixerInterop.MIXERLINECONTROLS);
			MixerInterop.MIXERCONTROL mIXERCONTROL = default(MixerInterop.MIXERCONTROL);
			IntPtr intPtr = Marshal.AllocCoTaskMem(Marshal.SizeOf((object)mIXERCONTROL));
			mixerLineControls.cbStruct = Marshal.SizeOf((object)mixerLineControls);
			mixerLineControls.cControls = 1;
			mixerLineControls.dwControlID = controlId;
			mixerLineControls.cbmxctrl = Marshal.SizeOf((object)mIXERCONTROL);
			mixerLineControls.pamxctrl = intPtr;
			mixerLineControls.dwLineID = nLineID;
			MmResult mmResult = MixerInterop.mixerGetLineControls(mixerHandle, ref mixerLineControls, MixerFlags.ListText | mixerFlags);
			if (mmResult != 0)
			{
				Marshal.FreeCoTaskMem(intPtr);
				throw new MmException(mmResult, "mixerGetLineControls");
			}
			mIXERCONTROL = (MixerInterop.MIXERCONTROL)Marshal.PtrToStructure(mixerLineControls.pamxctrl, typeof(MixerInterop.MIXERCONTROL));
			Marshal.FreeCoTaskMem(intPtr);
			if (IsControlBoolean(mIXERCONTROL.dwControlType))
			{
				return new BooleanMixerControl(mIXERCONTROL, mixerHandle, mixerFlags, nChannels);
			}
			if (IsControlSigned(mIXERCONTROL.dwControlType))
			{
				return new SignedMixerControl(mIXERCONTROL, mixerHandle, mixerFlags, nChannels);
			}
			if (IsControlUnsigned(mIXERCONTROL.dwControlType))
			{
				return new UnsignedMixerControl(mIXERCONTROL, mixerHandle, mixerFlags, nChannels);
			}
			if (IsControlListText(mIXERCONTROL.dwControlType))
			{
				return new ListTextMixerControl(mIXERCONTROL, mixerHandle, mixerFlags, nChannels);
			}
			if (IsControlCustom(mIXERCONTROL.dwControlType))
			{
				return new CustomMixerControl(mIXERCONTROL, mixerHandle, mixerFlags, nChannels);
			}
			throw new InvalidOperationException($"Unknown mixer control type {mIXERCONTROL.dwControlType}");
		}

		protected void GetControlDetails()
		{
			mixerControlDetails.cbStruct = Marshal.SizeOf((object)mixerControlDetails);
			mixerControlDetails.dwControlID = mixerControl.dwControlID;
			if (IsCustom)
			{
				mixerControlDetails.cChannels = 0;
			}
			else if ((mixerControl.fdwControl & (true ? 1u : 0u)) != 0)
			{
				mixerControlDetails.cChannels = 1;
			}
			else
			{
				mixerControlDetails.cChannels = nChannels;
			}
			if ((mixerControl.fdwControl & 2u) != 0)
			{
				mixerControlDetails.hwndOwner = (IntPtr)mixerControl.cMultipleItems;
			}
			else if (IsCustom)
			{
				mixerControlDetails.hwndOwner = IntPtr.Zero;
			}
			else
			{
				mixerControlDetails.hwndOwner = IntPtr.Zero;
			}
			if (IsBoolean)
			{
				mixerControlDetails.cbDetails = Marshal.SizeOf((object)default(MixerInterop.MIXERCONTROLDETAILS_BOOLEAN));
			}
			else if (IsListText)
			{
				mixerControlDetails.cbDetails = Marshal.SizeOf((object)default(MixerInterop.MIXERCONTROLDETAILS_LISTTEXT));
			}
			else if (IsSigned)
			{
				mixerControlDetails.cbDetails = Marshal.SizeOf((object)default(MixerInterop.MIXERCONTROLDETAILS_SIGNED));
			}
			else if (IsUnsigned)
			{
				mixerControlDetails.cbDetails = Marshal.SizeOf((object)default(MixerInterop.MIXERCONTROLDETAILS_UNSIGNED));
			}
			else
			{
				mixerControlDetails.cbDetails = mixerControl.Metrics.customData;
			}
			int num = mixerControlDetails.cbDetails * mixerControlDetails.cChannels;
			if ((mixerControl.fdwControl & 2u) != 0)
			{
				num *= (int)mixerControl.cMultipleItems;
			}
			IntPtr intPtr = Marshal.AllocCoTaskMem(num);
			mixerControlDetails.paDetails = intPtr;
			MmResult mmResult = MixerInterop.mixerGetControlDetails(mixerHandle, ref mixerControlDetails, MixerFlags.Mixer | mixerHandleType);
			if (mmResult == MmResult.NoError)
			{
				GetDetails(mixerControlDetails.paDetails);
			}
			Marshal.FreeCoTaskMem(intPtr);
			if (mmResult != 0)
			{
				throw new MmException(mmResult, "mixerGetControlDetails");
			}
		}

		protected abstract void GetDetails(IntPtr pDetails);

		private static bool IsControlBoolean(MixerControlType controlType)
		{
			switch (controlType)
			{
			case MixerControlType.BooleanMeter:
			case MixerControlType.Boolean:
			case MixerControlType.OnOff:
			case MixerControlType.Mute:
			case MixerControlType.Mono:
			case MixerControlType.Loudness:
			case MixerControlType.StereoEnhance:
			case MixerControlType.Button:
			case MixerControlType.SingleSelect:
			case MixerControlType.Mux:
			case MixerControlType.MultipleSelect:
			case MixerControlType.Mixer:
				return true;
			default:
				return false;
			}
		}

		private static bool IsControlListText(MixerControlType controlType)
		{
			if (controlType == MixerControlType.Equalizer || (uint)(controlType - 1879113728) <= 1u || (uint)(controlType - 1895890944) <= 1u)
			{
				return true;
			}
			return false;
		}

		private static bool IsControlSigned(MixerControlType controlType)
		{
			switch (controlType)
			{
			case MixerControlType.SignedMeter:
			case MixerControlType.PeakMeter:
			case MixerControlType.Signed:
			case MixerControlType.Decibels:
			case MixerControlType.Slider:
			case MixerControlType.Pan:
			case MixerControlType.QSoundPan:
				return true;
			default:
				return false;
			}
		}

		private static bool IsControlUnsigned(MixerControlType controlType)
		{
			switch (controlType)
			{
			case MixerControlType.UnsignedMeter:
			case MixerControlType.Unsigned:
			case MixerControlType.Percent:
			case MixerControlType.Fader:
			case MixerControlType.Volume:
			case MixerControlType.Bass:
			case MixerControlType.Treble:
			case MixerControlType.Equalizer:
			case MixerControlType.MicroTime:
			case MixerControlType.MilliTime:
				return true;
			default:
				return false;
			}
		}

		private static bool IsControlCustom(MixerControlType controlType)
		{
			return controlType == MixerControlType.Custom;
		}

		public override string ToString()
		{
			return $"{Name} {ControlType}";
		}
	}
	[Flags]
	internal enum MixerControlClass
	{
		Custom = 0,
		Meter = 0x10000000,
		Switch = 0x20000000,
		Number = 0x30000000,
		Slider = 0x40000000,
		Fader = 0x50000000,
		Time = 0x60000000,
		List = 0x70000000,
		Mask = 0x70000000
	}
	[Flags]
	internal enum MixerControlSubclass
	{
		SwitchBoolean = 0,
		SwitchButton = 0x1000000,
		MeterPolled = 0,
		TimeMicrosecs = 0,
		TimeMillisecs = 0x1000000,
		ListSingle = 0,
		ListMultiple = 0x1000000,
		Mask = 0xF000000
	}
	[Flags]
	internal enum MixerControlUnits
	{
		Custom = 0,
		Boolean = 0x10000,
		Signed = 0x20000,
		Unsigned = 0x30000,
		Decibels = 0x40000,
		Percent = 0x50000,
		Mask = 0xFF0000
	}
	public enum MixerControlType
	{
		Custom = 0,
		BooleanMeter = 268500992,
		SignedMeter = 268566528,
		PeakMeter = 268566529,
		UnsignedMeter = 268632064,
		Boolean = 536936448,
		OnOff = 536936449,
		Mute = 536936450,
		Mono = 536936451,
		Loudness = 536936452,
		StereoEnhance = 536936453,
		Button = 553713664,
		Decibels = 805568512,
		Signed = 805437440,
		Unsigned = 805502976,
		Percent = 805634048,
		Slider = 1073872896,
		Pan = 1073872897,
		QSoundPan = 1073872898,
		Fader = 1342373888,
		Volume = 1342373889,
		Bass = 1342373890,
		Treble = 1342373891,
		Equalizer = 1342373892,
		SingleSelect = 1879113728,
		Mux = 1879113729,
		MultipleSelect = 1895890944,
		Mixer = 1895890945,
		MicroTime = 1610809344,
		MilliTime = 1627586560
	}
	public class MixerLine
	{
		private MixerInterop.MIXERLINE mixerLine;

		private IntPtr mixerHandle;

		private MixerFlags mixerHandleType;

		public string Name => mixerLine.szName;

		public string ShortName => mixerLine.szShortName;

		public int LineId => mixerLine.dwLineID;

		public MixerLineComponentType ComponentType => mixerLine.dwComponentType;

		public string TypeDescription => mixerLine.dwComponentType switch
		{
			MixerLineComponentType.DestinationUndefined => "Undefined Destination", 
			MixerLineComponentType.DestinationDigital => "Digital Destination", 
			MixerLineComponentType.DestinationLine => "Line Level Destination", 
			MixerLineComponentType.DestinationMonitor => "Monitor Destination", 
			MixerLineComponentType.DestinationSpeakers => "Speakers Destination", 
			MixerLineComponentType.DestinationHeadphones => "Headphones Destination", 
			MixerLineComponentType.DestinationTelephone => "Telephone Destination", 
			MixerLineComponentType.DestinationWaveIn => "Wave Input Destination", 
			MixerLineComponentType.DestinationVoiceIn => "Voice Recognition Destination", 
			MixerLineComponentType.SourceUndefined => "Undefined Source", 
			MixerLineComponentType.SourceDigital => "Digital Source", 
			MixerLineComponentType.SourceLine => "Line Level Source", 
			MixerLineComponentType.SourceMicrophone => "Microphone Source", 
			MixerLineComponentType.SourceSynthesizer => "Synthesizer Source", 
			MixerLineComponentType.SourceCompactDisc => "Compact Disk Source", 
			MixerLineComponentType.SourceTelephone => "Telephone Source", 
			MixerLineComponentType.SourcePcSpeaker => "PC Speaker Source", 
			MixerLineComponentType.SourceWaveOut => "Wave Out Source", 
			MixerLineComponentType.SourceAuxiliary => "Auxiliary Source", 
			MixerLineComponentType.SourceAnalog => "Analog Source", 
			_ => "Invalid Component Type", 
		};

		public int Channels => mixerLine.cChannels;

		public int SourceCount => mixerLine.cConnections;

		public int ControlsCount => mixerLine.cControls;

		public bool IsActive => (mixerLine.fdwLine & MixerInterop.MIXERLINE_LINEF.MIXERLINE_LINEF_ACTIVE) != 0;

		public bool IsDisconnected => (mixerLine.fdwLine & MixerInterop.MIXERLINE_LINEF.MIXERLINE_LINEF_DISCONNECTED) != 0;

		public bool IsSource => (mixerLine.fdwLine & MixerInterop.MIXERLINE_LINEF.MIXERLINE_LINEF_SOURCE) != 0;

		public IEnumerable<MixerControl> Controls => MixerControl.GetMixerControls(mixerHandle, this, mixerHandleType);

		public IEnumerable<MixerLine> Sources
		{
			get
			{
				for (int source = 0; source < SourceCount; source++)
				{
					yield return GetSource(source);
				}
			}
		}

		public string TargetName => mixerLine.szPname;

		public MixerLine(IntPtr mixerHandle, int destinationIndex, MixerFlags mixerHandleType)
		{
			this.mixerHandle = mixerHandle;
			this.mixerHandleType = mixerHandleType;
			mixerLine = default(MixerInterop.MIXERLINE);
			mixerLine.cbStruct = Marshal.SizeOf((object)mixerLine);
			mixerLine.dwDestination = destinationIndex;
			MmException.Try(MixerInterop.mixerGetLineInfo(mixerHandle, ref mixerLine, mixerHandleType | MixerFlags.Mixer), "mixerGetLineInfo");
		}

		public MixerLine(IntPtr mixerHandle, int destinationIndex, int sourceIndex, MixerFlags mixerHandleType)
		{
			this.mixerHandle = mixerHandle;
			this.mixerHandleType = mixerHandleType;
			mixerLine = default(MixerInterop.MIXERLINE);
			mixerLine.cbStruct = Marshal.SizeOf((object)mixerLine);
			mixerLine.dwDestination = destinationIndex;
			mixerLine.dwSource = sourceIndex;
			MmException.Try(MixerInterop.mixerGetLineInfo(mixerHandle, ref mixerLine, mixerHandleType | MixerFlags.ListText), "mixerGetLineInfo");
		}

		public static int GetMixerIdForWaveIn(int waveInDevice)
		{
			int mixerID = -1;
			MmException.Try(MixerInterop.mixerGetID((IntPtr)waveInDevice, out mixerID, MixerFlags.WaveIn), "mixerGetID");
			return mixerID;
		}

		public MixerLine GetSource(int sourceIndex)
		{
			if (sourceIndex < 0 || sourceIndex >= SourceCount)
			{
				throw new ArgumentOutOfRangeException("sourceIndex");
			}
			return new MixerLine(mixerHandle, mixerLine.dwDestination, sourceIndex, mixerHandleType);
		}

		public override string ToString()
		{
			return $"{Name} {TypeDescription} ({ControlsCount} controls, ID={mixerLine.dwLineID})";
		}
	}
	[Flags]
	public enum MixerFlags
	{
		Handle = int.MinValue,
		Mixer = 0,
		MixerHandle = int.MinValue,
		WaveOut = 0x10000000,
		WaveOutHandle = -1879048192,
		WaveIn = 0x20000000,
		WaveInHandle = -1610612736,
		MidiOut = 0x30000000,
		MidiOutHandle = -1342177280,
		MidiIn = 0x40000000,
		MidiInHandle = -1073741824,
		Aux = 0x50000000,
		Value = 0,
		ListText = 1,
		QueryMask = 0xF,
		All = 0,
		OneById = 1,
		OneByType = 2,
		GetLineInfoOfDestination = 0,
		GetLineInfoOfSource = 1,
		GetLineInfoOfLineId = 2,
		GetLineInfoOfComponentType = 3,
		GetLineInfoOfTargetType = 4,
		GetLineInfoOfQueryMask = 0xF
	}
	internal class MixerInterop
	{
		[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto, Pack = 1)]
		public struct MIXERCONTROLDETAILS
		{
			public int cbStruct;

			public int dwControlID;

			public int cChannels;

			public IntPtr hwndOwner;

			public int cbDetails;

			public IntPtr paDetails;
		}

		[StructLayout(LayoutKind.Sequential, Pack = 1)]
		public struct MIXERCAPS
		{
			public ushort wMid;

			public ushort wPid;

			public uint vDriverVersion;

			[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
			public string szPname;

			public uint fdwSupport;

			public uint cDestinations;
		}

		[StructLayout(LayoutKind.Sequential, Pack = 1)]
		public struct MIXERLINECONTROLS
		{
			public int cbStruct;

			public int dwLineID;

			public int dwControlID;

			public int cControls;

			public int cbmxctrl;

			public IntPtr pamxctrl;
		}

		[Flags]
		public enum MIXERLINE_LINEF
		{
			MIXERLINE_LINEF_ACTIVE = 1,
			MIXERLINE_LINEF_DISCONNECTED = 0x8000,
			MIXERLINE_LINEF_SOURCE = int.MinValue
		}

		[StructLayout(LayoutKind.Sequential, Pack = 1)]
		public struct MIXERLINE
		{
			public int cbStruct;

			public int dwDestination;

			public int dwSource;

			public int dwLineID;

			public MIXERLINE_LINEF fdwLine;

			public IntPtr dwUser;

			public MixerLineComponentType dwComponentType;

			public int cChannels;

			public int cConnections;

			public int cControls;

			[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
			public string szShortName;

			[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
			public string szName;

			public uint dwType;

			public uint dwDeviceID;

			public ushort wMid;

			public ushort wPid;

			public uint vDriverVersion;

			[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
			public string szPname;
		}

		[StructLayout(LayoutKind.Sequential, Pack = 1)]
		public struct Bounds
		{
			public int minimum;

			public int maximum;

			public int reserved2;

			public int reserved3;

			public int reserved4;

			public int reserved5;
		}

		[StructLayout(LayoutKind.Sequential, Pack = 1)]
		public struct Metrics
		{
			public int step;

			public int customData;

			public int reserved2;

			public int reserved3;

			public int reserved4;

			public int reserved5;
		}

		[StructLayout(LayoutKind.Sequential, Pack = 1)]
		public struct MIXERCONTROL
		{
			public uint cbStruct;

			public int dwControlID;

			public MixerControlType dwControlType;

			public uint fdwControl;

			public uint cMultipleItems;

			[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
			public string szShortName;

			[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
			public string szName;

			public Bounds Bounds;

			public Metrics Metrics;
		}

		public struct MIXERCONTROLDETAILS_BOOLEAN
		{
			public int fValue;
		}

		public struct MIXERCONTROLDETAILS_SIGNED
		{
			public int lValue;
		}

		[StructLayout(LayoutKind.Sequential, Pack = 1)]
		public struct MIXERCONTROLDETAILS_LISTTEXT
		{
			public uint dwParam1;

			public uint dwParam2;

			[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
			public string szName;
		}

		public struct MIXERCONTROLDETAILS_UNSIGNED
		{
			public uint dwValue;
		}

		public const uint MIXERCONTROL_CONTROLF_UNIFORM = 1u;

		public const uint MIXERCONTROL_CONTROLF_MULTIPLE = 2u;

		public const uint MIXERCONTROL_CONTROLF_DISABLED = 2147483648u;

		public const int MAXPNAMELEN = 32;

		public const int MIXER_SHORT_NAME_CHARS = 16;

		public const int MIXER_LONG_NAME_CHARS = 64;

		[DllImport("winmm.dll", CharSet = CharSet.Ansi)]
		public static extern int mixerGetNumDevs();

		[DllImport("winmm.dll", CharSet = CharSet.Ansi)]
		public static extern MmResult mixerOpen(out IntPtr hMixer, int uMxId, IntPtr dwCallback, IntPtr dwInstance, MixerFlags dwOpenFlags);

		[DllImport("winmm.dll", CharSet = CharSet.Ansi)]
		public static extern MmResult mixerClose(IntPtr hMixer);

		[DllImport("winmm.dll", CharSet = CharSet.Ansi)]
		public static extern MmResult mixerGetControlDetails(IntPtr hMixer, ref MIXERCONTROLDETAILS mixerControlDetails, MixerFlags dwDetailsFlags);

		[DllImport("winmm.dll", CharSet = CharSet.Ansi)]
		public static extern MmResult mixerGetDevCaps(IntPtr nMixerID, ref MIXERCAPS mixerCaps, int mixerCapsSize);

		[DllImport("winmm.dll", CharSet = CharSet.Ansi)]
		public static extern MmResult mixerGetID(IntPtr hMixer, out int mixerID, MixerFlags dwMixerIDFlags);

		[DllImport("winmm.dll", CharSet = CharSet.Ansi)]
		public static extern MmResult mixerGetLineControls(IntPtr hMixer, ref MIXERLINECONTROLS mixerLineControls, MixerFlags dwControlFlags);

		[DllImport("winmm.dll", CharSet = CharSet.Ansi)]
		public static extern MmResult mixerGetLineInfo(IntPtr hMixer, ref MIXERLINE mixerLine, MixerFlags dwInfoFlags);

		[DllImport("winmm.dll", CharSet = CharSet.Ansi)]
		public static extern MmResult mixerMessage(IntPtr hMixer, uint nMessage, IntPtr dwParam1, IntPtr dwParam2);

		[DllImport("winmm.dll", CharSet = CharSet.Ansi)]
		public static extern MmResult mixerSetControlDetails(IntPtr hMixer, ref MIXERCONTROLDETAILS mixerControlDetails, MixerFlags dwDetailsFlags);
	}
	public enum MixerLineComponentType
	{
		DestinationUndefined = 0,
		DestinationDigital = 1,
		DestinationLine = 2,
		DestinationMonitor = 3,
		DestinationSpeakers = 4,
		DestinationHeadphones = 5,
		DestinationTelephone = 6,
		DestinationWaveIn = 7,
		DestinationVoiceIn = 8,
		SourceUndefined = 4096,
		SourceDigital = 4097,
		SourceLine = 4098,
		SourceMicrophone = 4099,
		SourceSynthesizer = 4100,
		SourceCompactDisc = 4101,
		SourceTelephone = 4102,
		SourcePcSpeaker = 4103,
		SourceWaveOut = 4104,
		SourceAuxiliary = 4105,
		SourceAnalog = 4106
	}
	public class SignedMixerControl : MixerControl
	{
		private MixerInterop.MIXERCONTROLDETAILS_SIGNED signedDetails;

		public int Value
		{
			get
			{
				GetControlDetails();
				return signedDetails.lValue;
			}
			set
			{
				signedDetails.lValue = value;
				mixerControlDetails.paDetails = Marshal.AllocHGlobal(Marshal.SizeOf((object)signedDetails));
				Marshal.StructureToPtr((object)signedDetails, mixerControlDetails.paDetails, fDeleteOld: false);
				MmException.Try(MixerInterop.mixerSetControlDetails(mixerHandle, ref mixerControlDetails, MixerFlags.Mixer | mixerHandleType), "mixerSetControlDetails");
				Marshal.FreeHGlobal(mixerControlDetails.paDetails);
			}
		}

		public int MinValue => mixerControl.Bounds.minimum;

		public int MaxValue => mixerControl.Bounds.maximum;

		public double Percent
		{
			get
			{
				return 100.0 * (double)(Value - MinValue) / (double)(MaxValue - MinValue);
			}
			set
			{
				Value = (int)((double)MinValue + value / 100.0 * (double)(MaxValue - MinValue));
			}
		}

		internal SignedMixerControl(MixerInterop.MIXERCONTROL mixerControl, IntPtr mixerHandle, MixerFlags mixerHandleType, int nChannels)
		{
			base.mixerControl = mixerControl;
			base.mixerHandle = mixerHandle;
			base.mixerHandleType = mixerHandleType;
			base.nChannels = nChannels;
			mixerControlDetails = default(MixerInterop.MIXERCONTROLDETAILS);
			GetControlDetails();
		}

		protected override void GetDetails(IntPtr pDetails)
		{
			signedDetails = (MixerInterop.MIXERCONTROLDETAILS_SIGNED)Marshal.PtrToStructure(mixerControlDetails.paDetails, typeof(MixerInterop.MIXERCONTROLDETAILS_SIGNED));
		}

		public override string ToString()
		{
			return $"{base.ToString()} {Percent}%";
		}
	}
	public class UnsignedMixerControl : MixerControl
	{
		private MixerInterop.MIXERCONTROLDETAILS_UNSIGNED[] unsignedDetails;

		public uint Value
		{
			get
			{
				GetControlDetails();
				return unsignedDetails[0].dwValue;
			}
			set
			{
				int num = Marshal.SizeOf((object)unsignedDetails[0]);
				mixerControlDetails.paDetails = Marshal.AllocHGlobal(num * nChannels);
				for (int i = 0; i < nChannels; i++)
				{
					unsignedDetails[i].dwValue = value;
					long num2 = mixerControlDetails.paDetails.ToInt64() + num * i;
					Marshal.StructureToPtr((object)unsignedDetails[i], (IntPtr)num2, fDeleteOld: false);
				}
				MmException.Try(MixerInterop.mixerSetControlDetails(mixerHandle, ref mixerControlDetails, MixerFlags.Mixer | mixerHandleType), "mixerSetControlDetails");
				Marshal.FreeHGlobal(mixerControlDetails.paDetails);
			}
		}

		public uint MinValue => (uint)mixerControl.Bounds.minimum;

		public uint MaxValue => (uint)mixerControl.Bounds.maximum;

		public double Percent
		{
			get
			{
				return 100.0 * (double)(Value - MinValue) / (double)(MaxValue - MinValue);
			}
			set
			{
				Value = (uint)((double)MinValue + value / 100.0 * (double)(MaxValue - MinValue));
			}
		}

		internal UnsignedMixerControl(MixerInterop.MIXERCONTROL mixerControl, IntPtr mixerHandle, MixerFlags mixerHandleType, int nChannels)
		{
			base.mixerControl = mixerControl;
			base.mixerHandle = mixerHandle;
			base.mixerHandleType = mixerHandleType;
			base.nChannels = nChannels;
			mixerControlDetails = default(MixerInterop.MIXERCONTROLDETAILS);
			GetControlDetails();
		}

		protected override void GetDetails(IntPtr pDetails)
		{
			unsignedDetails = new MixerInterop.MIXERCONTROLDETAILS_UNSIGNED[nChannels];
			for (int i = 0; i < nChannels; i++)
			{
				unsignedDetails[i] = (MixerInterop.MIXERCONTROLDETAILS_UNSIGNED)Marshal.PtrToStructure(mixerControlDetails.paDetails, typeof(MixerInterop.MIXERCONTROLDETAILS_UNSIGNED));
			}
		}

		public override string ToString()
		{
			return $"{base.ToString()} {Percent}%";
		}
	}
}
namespace NAudio.SoundFont
{
	public class Generator
	{
		private GeneratorEnum generatorType;

		private ushort rawAmount;

		private Instrument instrument;

		private SampleHeader sampleHeader;

		public GeneratorEnum GeneratorType
		{
			get
			{
				return generatorType;
			}
			set
			{
				generatorType = value;
			}
		}

		public ushort UInt16Amount
		{
			get
			{
				return rawAmount;
			}
			set
			{
				rawAmount = value;
			}
		}

		public short Int16Amount
		{
			get
			{
				return (short)rawAmount;
			}
			set
			{
				rawAmount = (ushort)value;
			}
		}

		public byte LowByteAmount
		{
			get
			{
				return (byte)(rawAmount & 0xFFu);
			}
			set
			{
				rawAmount &= 65280;
				rawAmount += value;
			}
		}

		public byte HighByteAmount
		{
			get
			{
				return (byte)((rawAmount & 0xFF00) >> 8);
			}
			set
			{
				rawAmount &= 255;
				rawAmount += (ushort)(value << 8);
			}
		}

		public Instrument Instrument
		{
			get
			{
				return instrument;
			}
			set
			{
				instrument = value;
			}
		}

		public SampleHeader SampleHeader
		{
			get
			{
				return sampleHeader;
			}
			set
			{
				sampleHeader = value;
			}
		}

		public override string ToString()
		{
			if (generatorType == GeneratorEnum.Instrument)
			{
				return $"Generator Instrument {instrument.Name}";
			}
			if (generatorType == GeneratorEnum.SampleID)
			{
				return $"Generator SampleID {sampleHeader}";
			}
			return $"Generator {generatorType} {rawAmount}";
		}
	}
	internal class GeneratorBuilder : StructureBuilder<Generator>
	{
		public override int Length => 4;

		public Generator[] Generators => data.ToArray();

		public override Generator Read(BinaryReader br)
		{
			Generator generator = new Generator();
			generator.GeneratorType = (GeneratorEnum)br.ReadUInt16();
			generator.UInt16Amount = br.ReadUInt16();
			data.Add(generator);
			return generator;
		}

		public override void Write(BinaryWriter bw, Generator o)
		{
		}

		public void Load(Instrument[] instruments)
		{
			Generator[] generators = Generators;
			foreach (Generator generator in generators)
			{
				if (generator.GeneratorType == GeneratorEnum.Instrument)
				{
					generator.Instrument = instruments[generator.UInt16Amount];
				}
			}
		}

		public void Load(SampleHeader[] sampleHeaders)
		{
			Generator[] generators = Generators;
			foreach (Generator generator in generators)
			{
				if (generator.GeneratorType == GeneratorEnum.SampleID)
				{
					generator.SampleHeader = sampleHeaders[generator.UInt16Amount];
				}
			}
		}
	}
	public enum GeneratorEnum
	{
		StartAddressOffset,
		EndAddressOffset,
		StartLoopAddressOffset,
		EndLoopAddressOffset,
		StartAddressCoarseOffset,
		ModulationLFOToPitch,
		VibratoLFOToPitch,
		ModulationEnvelopeToPitch,
		InitialFilterCutoffFrequency,
		InitialFilterQ,
		ModulationLFOToFilterCutoffFrequency,
		ModulationEnvelopeToFilterCutoffFrequency,
		EndAddressCoarseOffset,
		ModulationLFOToVolume,
		Unused1,
		ChorusEffectsSend,
		ReverbEffectsSend,
		Pan,
		Unused2,
		Unused3,
		Unused4,
		DelayModulationLFO,
		FrequencyModulationLFO,
		DelayVibratoLFO,
		FrequencyVibratoLFO,
		DelayModulationEnvelope,
		AttackModulationEnvelope,
		HoldModulationEnvelope,
		DecayModulationEnvelope,
		SustainModulationEnvelope,
		ReleaseModulationEnvelope,
		KeyNumberToModulationEnvelopeHold,
		KeyNumberToModulationEnvelopeDecay,
		DelayVolumeEnvelope,
		AttackVolumeEnvelope,
		HoldVolumeEnvelope,
		DecayVolumeEnvelope,
		SustainVolumeEnvelope,
		ReleaseVolumeEnvelope,
		KeyNumberToVolumeEnvelopeHold,
		KeyNumberToVolumeEnvelopeDecay,
		Instrument,
		Reserved1,
		KeyRange,
		VelocityRange,
		StartLoopAddressCoarseOffset,
		KeyNumber,
		Velocity,
		InitialAttenuation,
		Reserved2,
		EndLoopAddressCoarseOffset,
		CoarseTune,
		FineTune,
		SampleID,
		SampleModes,
		Reserved3,
		ScaleTuning,
		ExclusiveClass,
		OverridingRootKey,
		Unused5,
		UnusedEnd
	}
	public class InfoChunk
	{
		public SFVersion SoundFontVersion { get; }

		public string WaveTableSoundEngine { get; set; }

		public string BankName { get; set; }

		public string DataROM { get; set; }

		public string CreationDate { get; set; }

		public string Author { get; set; }

		public string TargetProduct { get; set; }

		public string Copyright { get; set; }

		public string Comments { get; set; }

		public string Tools { get; set; }

		public SFVersion ROMVersion { get; set; }

		internal InfoChunk(RiffChunk chunk)
		{
			bool flag = false;
			bool flag2 = false;
			if (chunk.ReadChunkID() != "INFO")
			{
				throw new NAudio.Utils.InvalidDataException("Not an INFO chunk");
			}
			RiffChunk nextSubChunk;
			while ((nextSubChunk = chunk.GetNextSubChunk()) != null)
			{
				switch (nextSubChunk.ChunkID)
				{
				case "ifil":
					flag = true;
					SoundFontVersion = nextSubChunk.GetDataAsStructure(new SFVersionBuilder());
					break;
				case "isng":
					WaveTableSoundEngine = nextSubChunk.GetDataAsString();
					break;
				case "INAM":
					flag2 = true;
					BankName = nextSubChunk.GetDataAsString();
					break;
				case "irom":
					DataROM = nextSubChunk.GetDataAsString();
					break;
				case "iver":
					ROMVersion = nextSubChunk.GetDataAsStructure(new SFVersionBuilder());
					break;
				case "ICRD":
					CreationDate = nextSubChunk.GetDataAsString();
					break;
				case "IENG":
					Author = nextSubChunk.GetDataAsString();
					break;
				case "IPRD":
					TargetProduct = nextSubChunk.GetDataAsString();
					break;
				case "ICOP":
					Copyright = nextSubChunk.GetDataAsString();
					break;
				case "ICMT":
					Comments = nextSubChunk.GetDataAsString();
					break;
				case "ISFT":
					Tools = nextSubChunk.GetDataAsString();
					break;
				default:
					throw new NAudio.Utils.InvalidDataException($"Unknown chunk type {nextSubChunk.ChunkID}");
				}
			}
			if (!flag)
			{
				throw new NAudio.Utils.InvalidDataException("Missing SoundFont version information");
			}
			if (!flag2)
			{
				throw new NAudio.Utils.InvalidDataException("Missing SoundFont name information");
			}
		}

		public override string ToString()
		{
			return string.Format("Bank Name: {0}\r\nAuthor: {1}\r\nCopyright: {2}\r\nCreation Date: {3}\r\nTools: {4}\r\nComments: {5}\r\nSound Engine: {6}\r\nSoundFont Version: {7}\r\nTarget Product: {8}\r\nData ROM: {9}\r\nROM Version: {10}", BankName, Author, Copyright, CreationDate, Tools, "TODO-fix comments", WaveTableSoundEngine, SoundFontVersion, TargetProduct, DataROM, ROMVersion);
		}
	}
	public class Instrument
	{
		private string name;

		internal ushort startInstrumentZoneIndex;

		internal ushort endInstrumentZoneIndex;

		private Zone[] zones;

		public string Name
		{
			get
			{
				return name;
			}
			set
			{
				name = value;
			}
		}

		public Zone[] Zones
		{
			get
			{
				return zones;
			}
			set
			{
				zones = value;
			}
		}

		public override string ToString()
		{
			return name;
		}
	}
	internal class InstrumentBuilder : StructureBuilder<Instrument>
	{
		private Instrument lastInstrument;

		public override int Length => 22;

		public Instrument[] Instruments => data.ToArray();

		public override Instrument Read(BinaryReader br)
		{
			Instrument instrument = new Instrument();
			string text = Encoding.UTF8.GetString(br.ReadBytes(20), 0, 20);
			if (text.IndexOf('\0') >= 0)
			{
				text = text.Substring(0, text.IndexOf('\0'));
			}
			instrument.Name = text;
			instrument.startInstrumentZoneIndex = br.ReadUInt16();
			if (lastInstrument != null)
			{
				lastInstrument.endInstrumentZoneIndex = (ushort)(instrument.startInstrumentZoneIndex - 1);
			}
			data.Add(instrument);
			lastInstrument = instrument;
			return instrument;
		}

		public override void Write(BinaryWriter bw, Instrument instrument)
		{
		}

		public void LoadZones(Zone[] zones)
		{
			for (int i = 0; i < data.Count - 1; i++)
			{
				Instrument instrument = data[i];
				instrument.Zones = new Zone[instrument.endInstrumentZoneIndex - instrument.startInstrumentZoneIndex + 1];
				Array.Copy(zones, instrument.startInstrumentZoneIndex, instrument.Zones, 0, instrument.Zones.Length);
			}
			data.RemoveAt(data.Count - 1);
		}
	}
	public enum TransformEnum
	{
		Linear
	}
	public class Modulator
	{
		private ModulatorType sourceModulationData;

		private GeneratorEnum destinationGenerator;

		private short amount;

		private ModulatorType sourceModulationAmount;

		private TransformEnum sourceTransform;

		public ModulatorType SourceModulationData
		{
			get
			{
				return sourceModulationData;
			}
			set
			{
				sourceModulationData = value;
			}
		}

		public GeneratorEnum DestinationGenerator
		{
			get
			{
				return destinationGenerator;
			}
			set
			{
				destinationGenerator = value;
			}
		}

		public short Amount
		{
			get
			{
				return amount;
			}
			set
			{
				amount = value;
			}
		}

		public ModulatorType SourceModulationAmount
		{
			get
			{
				return sourceModulationAmount;
			}
			set
			{
				sourceModulationAmount = value;
			}
		}

		public TransformEnum SourceTransform
		{
			get
			{
				return sourceTransform;
			}
			set
			{
				sourceTransform = value;
			}
		}

		public override string ToString()
		{
			return $"Modulator {sourceModulationData} {destinationGenerator} {amount} {sourceModulationAmount} {sourceTransform}";
		}
	}
	internal class ModulatorBuilder : StructureBuilder<Modulator>
	{
		public override int Length => 10;

		public Modulator[] Modulators => data.ToArray();

		public override Modulator Read(BinaryReader br)
		{
			Modulator modulator = new Modulator();
			modulator.SourceModulationData = new ModulatorType(br.ReadUInt16());
			modulator.DestinationGenerator = (GeneratorEnum)br.ReadUInt16();
			modulator.Amount = br.ReadInt16();
			modulator.SourceModulationAmount = new ModulatorType(br.ReadUInt16());
			modulator.SourceTransform = (TransformEnum)br.ReadUInt16();
			data.Add(modulator);
			return modulator;
		}

		public override void Write(BinaryWriter bw, Modulator o)
		{
		}
	}
	public enum ControllerSourceEnum
	{
		NoController = 0,
		NoteOnVelocity = 2,
		NoteOnKeyNumber = 3,
		PolyPressure = 10,
		ChannelPressure = 13,
		PitchWheel = 14,
		PitchWheelSensitivity = 16
	}
	public enum SourceTypeEnum
	{
		Linear,
		Concave,
		Convex,
		Switch
	}
	public class ModulatorType
	{
		private bool polarity;

		private bool direction;

		private bool midiContinuousController;

		private ControllerSourceEnum controllerSource;

		private SourceTypeEnum sourceType;

		private ushort midiContinuousControllerNumber;

		internal ModulatorType(ushort raw)
		{
			polarity = (raw & 0x200) == 512;
			direction = (raw & 0x100) == 256;
			midiContinuousController = (raw & 0x80) == 128;
			sourceType = (SourceTypeEnum)((raw & 0xFC00) >> 10);
			controllerSource = (ControllerSourceEnum)(raw & 0x7F);
			midiContinuousControllerNumber = (ushort)(raw & 0x7Fu);
		}

		public override string ToString()
		{
			if (midiContinuousController)
			{
				return $"{sourceType} CC{midiContinuousControllerNumber}";
			}
			return $"{sourceType} {controllerSource}";
		}
	}
	public class Preset
	{
		private string name;

		private ushort patchNumber;

		private ushort bank;

		internal ushort startPresetZoneIndex;

		internal ushort endPresetZoneIndex;

		internal uint library;

		internal uint genre;

		internal uint morphology;

		private Zone[] zones;

		public string Name
		{
			get
			{
				return name;
			}
			set
			{
				name = value;
			}
		}

		public ushort PatchNumber
		{
			get
			{
				return patchNumber;
			}
			set
			{
				patchNumber = value;
			}
		}

		public ushort Bank
		{
			get
			{
				return bank;
			}
			set
			{
				bank = value;
			}
		}

		public Zone[] Zones
		{
			get
			{
				return zones;
			}
			set
			{
				zones = value;
			}
		}

		public override string ToString()
		{
			return $"{bank}-{patchNumber} {name}";
		}
	}
	internal class PresetBuilder : StructureBuilder<Preset>
	{
		private Preset lastPreset;

		public override int Length => 38;

		public Preset[] Presets => data.ToArray();

		public override Preset Read(BinaryReader br)
		{
			Preset preset = new Preset();
			string text = Encoding.UTF8.GetString(br.ReadBytes(20), 0, 20);
			if (text.IndexOf('\0') >= 0)
			{
				text = text.Substring(0, text.IndexOf('\0'));
			}
			preset.Name = text;
			preset.PatchNumber = br.ReadUInt16();
			preset.Bank = br.ReadUInt16();
			preset.startPresetZoneIndex = br.ReadUInt16();
			preset.library = br.ReadUInt32();
			preset.genre = br.ReadUInt32();
			preset.morphology = br.ReadUInt32();
			if (lastPreset != null)
			{
				lastPreset.endPresetZoneIndex = (ushort)(preset.startPresetZoneIndex - 1);
			}
			data.Add(preset);
			lastPreset = preset;
			return preset;
		}

		public override void Write(BinaryWriter bw, Preset preset)
		{
		}

		public void LoadZones(Zone[] presetZones)
		{
			for (int i = 0; i < data.Count - 1; i++)
			{
				Preset preset = data[i];
				preset.Zones = new Zone[preset.endPresetZoneIndex - preset.startPresetZoneIndex + 1];
				Array.Copy(presetZones, preset.startPresetZoneIndex, preset.Zones, 0, preset.Zones.Length);
			}
			data.RemoveAt(data.Count - 1);
		}
	}
	public class PresetsChunk
	{
		private PresetBuilder presetHeaders = new PresetBuilder();

		private ZoneBuilder presetZones = new ZoneBuilder();

		private ModulatorBuilder presetZoneModulators = new ModulatorBuilder();

		private GeneratorBuilder presetZoneGenerators = new GeneratorBuilder();

		private InstrumentBuilder instruments = new InstrumentBuilder();

		private ZoneBuilder instrumentZones = new ZoneBuilder();

		private ModulatorBuilder instrumentZoneModulators = new ModulatorBuilder();

		private GeneratorBuilder instrumentZoneGenerators = new GeneratorBuilder();

		private SampleHeaderBuilder sampleHeaders = new SampleHeaderBuilder();

		public Preset[] Presets => presetHeaders.Presets;

		public Instrument[] Instruments => instruments.Instruments;

		public SampleHeader[] SampleHeaders => sampleHeaders.SampleHeaders;

		internal PresetsChunk(RiffChunk chunk)
		{
			string text = chunk.ReadChunkID();
			if (text != "pdta")
			{
				throw new NAudio.Utils.InvalidDataException($"Not a presets data chunk ({text})");
			}
			RiffChunk nextSubChunk;
			while ((nextSubChunk = chunk.GetNextSubChunk()) != null)
			{
				switch (nextSubChunk.ChunkID)
				{
				case "PHDR":
				case "phdr":
					nextSubChunk.GetDataAsStructureArray(presetHeaders);
					break;
				case "PBAG":
				case "pbag":
					nextSubChunk.GetDataAsStructureArray(presetZones);
					break;
				case "PMOD":
				case "pmod":
					nextSubChunk.GetDataAsStructureArray(presetZoneModulators);
					break;
				case "PGEN":
				case "pgen":
					nextSubChunk.GetDataAsStructureArray(presetZoneGenerators);
					break;
				case "INST":
				case "inst":
					nextSubChunk.GetDataAsStructureArray(instruments);
					break;
				case "IBAG":
				case "ibag":
					nextSubChunk.GetDataAsStructureArray(instrumentZones);
					break;
				case "IMOD":
				case "imod":
					nextSubChunk.GetDataAsStructureArray(instrumentZoneModulators);
					break;
				case "IGEN":
				case "igen":
					nextSubChunk.GetDataAsStructureArray(instrumentZoneGenerators);
					break;
				case "SHDR":
				case "shdr":
					nextSubChunk.GetDataAsStructureArray(sampleHeaders);
					break;
				default:
					throw new NAudio.Utils.InvalidDataException($"Unknown chunk type {nextSubChunk.ChunkID}");
				}
			}
			instrumentZoneGenerators.Load(sampleHeaders.SampleHeaders);
			instrumentZones.Load(instrumentZoneModulators.Modulators, instrumentZoneGenerators.Generators);
			instruments.LoadZones(instrumentZones.Zones);
			presetZoneGenerators.Load(instruments.Instruments);
			presetZones.Load(presetZoneModulators.Modulators, presetZoneGenerators.Generators);
			presetHeaders.LoadZones(presetZones.Zones);
			sampleHeaders.RemoveEOS();
		}

		public override string ToString()
		{
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append("Preset Headers:\r\n");
			Preset[] presets = presetHeaders.Presets;
			foreach (Preset arg in presets)
			{
				stringBuilder.AppendFormat("{0}\r\n", arg);
			}
			stringBuilder.Append("Instruments:\r\n");
			Instrument[] array = instruments.Instruments;
			foreach (Instrument arg2 in array)
			{
				stringBuilder.AppendFormat("{0}\r\n", arg2);
			}
			return stringBuilder.ToString();
		}
	}
	internal class RiffChunk
	{
		private string chunkID;

		private uint chunkSize;

		private long dataOffset;

		private BinaryReader riffFile;

		public string ChunkID
		{
			get
			{
				return chunkID;
			}
			set
			{
				if (value == null)
				{
					throw new ArgumentNullException("ChunkID may not be null");
				}
				if (value.Length != 4)
				{
					throw new ArgumentException("ChunkID must be four characters");
				}
				chunkID = value;
			}
		}

		public uint ChunkSize => chunkSize;

		public long DataOffset => dataOffset;

		public static RiffChunk GetTopLevelChunk(BinaryReader file)
		{
			RiffChunk riffChunk = new RiffChunk(file);
			riffChunk.ReadChunk();
			return riffChunk;
		}

		private RiffChunk(BinaryReader file)
		{
			riffFile = file;
			chunkID = "????";
			chunkSize = 0u;
			dataOffset = 0L;
		}

		public string ReadChunkID()
		{
			byte[] array = riffFile.ReadBytes(4);
			if (array.Length != 4)
			{
				throw new NAudio.Utils.InvalidDataException("Couldn't read Chunk ID");
			}
			return ByteEncoding.Instance.GetString(array, 0, array.Length);
		}

		private void ReadChunk()
		{
			chunkID = ReadChunkID();
			chunkSize = riffFile.ReadUInt32();
			dataOffset = riffFile.BaseStream.Position;
		}

		public RiffChunk GetNextSubChunk()
		{
			if (riffFile.BaseStream.Position + 8 < dataOffset + chunkSize)
			{
				RiffChunk riffChunk = new RiffChunk(riffFile);
				riffChunk.ReadChunk();
				return riffChunk;
			}
			return null;
		}

		public byte[] GetData()
		{
			riffFile.BaseStream.Position = dataOffset;
			byte[] array = riffFile.ReadBytes((int)chunkSize);
			if (array.Length != chunkSize)
			{
				throw new NAudio.Utils.InvalidDataException($"Couldn't read chunk's data Chunk: {this}, read {array.Length} bytes");
			}
			return array;
		}

		public string GetDataAsString()
		{
			byte[] data = GetData();
			if (data == null)
			{
				return null;
			}
			return ByteEncoding.Instance.GetString(data, 0, data.Length);
		}

		public T GetDataAsStructure<T>(StructureBuilder<T> s)
		{
			riffFile.BaseStream.Position = dataOffset;
			if (s.Length != chunkSize)
			{
				throw new NAudio.Utils.InvalidDataException($"Chunk size is: {chunkSize} so can't read structure of: {s.Length}");
			}
			return s.Read(riffFile);
		}

		public T[] GetDataAsStructureArray<T>(StructureBuilder<T> s)
		{
			riffFile.BaseStream.Position = dataOffset;
			if (chunkSize % s.Length != 0L)
			{
				throw new NAudio.Utils.InvalidDataException($"Chunk size is: {chunkSize} not a multiple of structure size: {s.Length}");
			}
			int num = (int)(chunkSize / s.Length);
			T[] array = new T[num];
			for (int i = 0; i < num; i++)
			{
				array[i] = s.Read(riffFile);
			}
			return array;
		}

		public override string ToString()
		{
			return $"RiffChunk ID: {ChunkID} Size: {ChunkSize} Data Offset: {DataOffset}";
		}
	}
	public class SampleHeader
	{
		public string SampleName;

		public uint Start;

		public uint End;

		public uint StartLoop;

		public uint EndLoop;

		public uint SampleRate;

		public byte OriginalPitch;

		public sbyte PitchCorrection;

		public ushort SampleLink;

		public SFSampleLink SFSampleLink;

		public override string ToString()
		{
			return SampleName;
		}
	}
	internal class SampleHeaderBuilder : StructureBuilder<SampleHeader>
	{
		public override int Length => 46;

		public SampleHeader[] SampleHeaders => data.ToArray();

		public override SampleHeader Read(BinaryReader br)
		{
			SampleHeader sampleHeader = new SampleHeader();
			byte[] array = br.ReadBytes(20);
			sampleHeader.SampleName = ByteEncoding.Instance.GetString(array, 0, array.Length);
			sampleHeader.Start = br.ReadUInt32();
			sampleHeader.End = br.ReadUInt32();
			sampleHeader.StartLoop = br.ReadUInt32();
			sampleHeader.EndLoop = br.ReadUInt32();
			sampleHeader.SampleRate = br.ReadUInt32();
			sampleHeader.OriginalPitch = br.ReadByte();
			sampleHeader.PitchCorrection = br.ReadSByte();
			sampleHeader.SampleLink = br.ReadUInt16();
			sampleHeader.SFSampleLink = (SFSampleLink)br.ReadUInt16();
			data.Add(sampleHeader);
			return sampleHeader;
		}

		public override void Write(BinaryWriter bw, SampleHeader sampleHeader)
		{
		}

		internal void RemoveEOS()
		{
			data.RemoveAt(data.Count - 1);
		}
	}
	public enum SampleMode
	{
		NoLoop,
		LoopContinuously,
		ReservedNoLoop,
		LoopAndContinue
	}
	public enum SFSampleLink : ushort
	{
		MonoSample = 1,
		RightSample = 2,
		LeftSample = 4,
		LinkedSample = 8,
		RomMonoSample = 32769,
		RomRightSample = 32770,
		RomLeftSample = 32772,
		RomLinkedSample = 32776
	}
	public class SFVersion
	{
		private short major;

		private short minor;

		public short Major
		{
			get
			{
				return major;
			}
			set
			{
				major = value;
			}
		}

		public short Minor
		{
			get
			{
				return minor;
			}
			set
			{
				minor = value;
			}
		}
	}
	internal class SFVersionBuilder : StructureBuilder<SFVersion>
	{
		public override int Length => 4;

		public override SFVersion Read(BinaryReader br)
		{
			SFVersion sFVersion = new SFVersion();
			sFVersion.Major = br.ReadInt16();
			sFVersion.Minor = br.ReadInt16();
			data.Add(sFVersion);
			return sFVersion;
		}

		public override void Write(BinaryWriter bw, SFVersion v)
		{
			bw.Write(v.Major);
			bw.Write(v.Minor);
		}
	}
	internal abstract class StructureBuilder<T>
	{
		protected List<T> data;

		public abstract int Length { get; }

		public T[] Data => data.ToArray();

		public StructureBuilder()
		{
			Reset();
		}

		public abstract T Read(BinaryReader br);

		public abstract void Write(BinaryWriter bw, T o);

		public void Reset()
		{
			data = new List<T>();
		}
	}
	public class Zone
	{
		internal ushort generatorIndex;

		internal ushort modulatorIndex;

		internal ushort generatorCount;

		internal ushort modulatorCount;

		private Modulator[] modulators;

		private Generator[] generators;

		public Modulator[] Modulators
		{
			get
			{
				return modulators;
			}
			set
			{
				modulators = value;
			}
		}

		public Generator[] Generators
		{
			get
			{
				return generators;
			}
			set
			{
				generators = value;
			}
		}

		public override string ToString()
		{
			return $"Zone {generatorCount} Gens:{generatorIndex} {modulatorCount} Mods:{modulatorIndex}";
		}
	}
	internal class ZoneBuilder : StructureBuilder<Zone>
	{
		private Zone lastZone;

		public Zone[] Zones => data.ToArray();

		public override int Length => 4;

		public override Zone Read(BinaryReader br)
		{
			Zone zone = new Zone();
			zone.generatorIndex = br.ReadUInt16();
			zone.modulatorIndex = br.ReadUInt16();
			if (lastZone != null)
			{
				lastZone.generatorCount = (ushort)(zone.generatorIndex - lastZone.generatorIndex);
				lastZone.modulatorCount = (ushort)(zone.modulatorIndex - lastZone.modulatorIndex);
			}
			data.Add(zone);
			lastZone = zone;
			return zone;
		}

		public override void Write(BinaryWriter bw, Zone zone)
		{
		}

		public void Load(Modulator[] modulators, Generator[] generators)
		{
			for (int i = 0; i < data.Count - 1; i++)
			{
				Zone zone = data[i];
				zone.Generators = new Generator[zone.generatorCount];
				Array.Copy(generators, zone.generatorIndex, zone.Generators, 0, zone.generatorCount);
				zone.Modulators = new Modulator[zone.modulatorCount];
				Array.Copy(modulators, zone.modulatorIndex, zone.Modulators, 0, zone.modulatorCount);
			}
			data.RemoveAt(data.Count - 1);
		}
	}
}
namespace NAudio.Dmo
{
	internal class AudioMediaSubtypes
	{
		public static readonly Guid MEDIASUBTYPE_PCM = new Guid("00000001-0000-0010-8000-00AA00389B71");

		public static readonly Guid MEDIASUBTYPE_PCMAudioObsolete = new Guid("e436eb8a-524f-11ce-9f53-0020af0ba770");

		public static readonly Guid MEDIASUBTYPE_MPEG1Packet = new Guid("e436eb80-524f-11ce-9f53-0020af0ba770");

		public static readonly Guid MEDIASUBTYPE_MPEG1Payload = new Guid("e436eb81-524f-11ce-9f53-0020af0ba770");

		public static readonly Guid MEDIASUBTYPE_MPEG2_AUDIO = new Guid("e06d802b-db46-11cf-b4d1-00805f6cbbea");

		public static readonly Guid MEDIASUBTYPE_DVD_LPCM_AUDIO = new Guid("e06d8032-db46-11cf-b4d1-00805f6cbbea");

		public static readonly Guid MEDIASUBTYPE_DRM_Audio = new Guid("00000009-0000-0010-8000-00aa00389b71");

		public static readonly Guid MEDIASUBTYPE_IEEE_FLOAT = new Guid("00000003-0000-0010-8000-00aa00389b71");

		public static readonly Guid MEDIASUBTYPE_DOLBY_AC3 = new Guid("e06d802c-db46-11cf-b4d1-00805f6cbbea");

		public static readonly Guid MEDIASUBTYPE_DOLBY_AC3_SPDIF = new Guid("00000092-0000-0010-8000-00aa00389b71");

		public static readonly Guid MEDIASUBTYPE_RAW_SPORT = new Guid("00000240-0000-0010-8000-00aa00389b71");

		public static readonly Guid MEDIASUBTYPE_SPDIF_TAG_241h = new Guid("00000241-0000-0010-8000-00aa00389b71");

		public static readonly Guid WMMEDIASUBTYPE_MP3 = new Guid("00000055-0000-0010-8000-00AA00389B71");

		public static readonly Guid MEDIASUBTYPE_WAVE = new Guid("e436eb8b-524f-11ce-9f53-0020af0ba770");

		public static readonly Guid MEDIASUBTYPE_AU = new Guid("e436eb8c-524f-11ce-9f53-0020af0ba770");

		public static readonly Guid MEDIASUBTYPE_AIFF = new Guid("e436eb8d-524f-11ce-9f53-0020af0ba770");

		public static readonly Guid[] AudioSubTypes = new Guid[13]
		{
			MEDIASUBTYPE_PCM, MEDIASUBTYPE_PCMAudioObsolete, MEDIASUBTYPE_MPEG1Packet, MEDIASUBTYPE_MPEG1Payload, MEDIASUBTYPE_MPEG2_AUDIO, MEDIASUBTYPE_DVD_LPCM_AUDIO, MEDIASUBTYPE_DRM_Audio, MEDIASUBTYPE_IEEE_FLOAT, MEDIASUBTYPE_DOLBY_AC3, MEDIASUBTYPE_DOLBY_AC3_SPDIF,
			MEDIASUBTYPE_RAW_SPORT, MEDIASUBTYPE_SPDIF_TAG_241h, WMMEDIASUBTYPE_MP3
		};

		public static readonly string[] AudioSubTypeNames = new string[13]
		{
			"PCM", "PCM Obsolete", "MPEG1Packet", "MPEG1Payload", "MPEG2_AUDIO", "DVD_LPCM_AUDIO", "DRM_Audio", "IEEE_FLOAT", "DOLBY_AC3", "DOLBY_AC3_SPDIF",
			"RAW_SPORT", "SPDIF_TAG_241h", "MP3"
		};

		public static string GetAudioSubtypeName(Guid subType)
		{
			for (int i = 0; i < AudioSubTypes.Length; i++)
			{
				if (subType == AudioSubTypes[i])
				{
					return AudioSubTypeNames[i];
				}
			}
			return subType.ToString();
		}
	}
	public class DmoDescriptor
	{
		public string Name { get; private set; }

		public Guid Clsid { get; private set; }

		public DmoDescriptor(string name, Guid clsid)
		{
			Name = name;
			Clsid = clsid;
		}
	}
	public class DmoEnumerator
	{
		public static IEnumerable<DmoDescriptor> GetAudioEffectNames()
		{
			return GetDmos(DmoGuids.DMOCATEGORY_AUDIO_EFFECT);
		}

		public static IEnumerable<DmoDescriptor> GetAudioEncoderNames()
		{
			return GetDmos(DmoGuids.DMOCATEGORY_AUDIO_ENCODER);
		}

		public static IEnumerable<DmoDescriptor> GetAudioDecoderNames()
		{
			return GetDmos(DmoGuids.DMOCATEGORY_AUDIO_DECODER);
		}

		private static IEnumerable<DmoDescriptor> GetDmos(Guid category)
		{
			Marshal.ThrowExceptionForHR(DmoInterop.DMOEnum(ref category, DmoEnumFlags.None, 0, null, 0, null, out var enumDmo));
			int itemsFetched;
			do
			{
				enumDmo.Next(1, out var clsid, out var name, out itemsFetched);
				if (itemsFetched == 1)
				{
					string name2 = Marshal.PtrToStringUni(name);
					Marshal.FreeCoTaskMem(name);
					yield return new DmoDescriptor(name2, clsid);
				}
			}
			while (itemsFetched > 0);
		}
	}
	[Flags]
	internal enum DmoEnumFlags
	{
		None = 0,
		DMO_ENUMF_INCLUDE_KEYED = 1
	}
	internal static class DmoGuids
	{
		public static readonly Guid DMOCATEGORY_AUDIO_DECODER = new Guid("57f2db8b-e6bb-4513-9d43-dcd2a6593125");

		public static readonly Guid DMOCATEGORY_AUDIO_ENCODER = new Guid("33D9A761-90C8-11d0-BD43-00A0C911CE86");

		public static readonly Guid DMOCATEGORY_VIDEO_DECODER = new Guid("4a69b442-28be-4991-969c-b500adf5d8a8");

		public static readonly Guid DMOCATEGORY_VIDEO_ENCODER = new Guid("33D9A760-90C8-11d0-BD43-00A0C911CE86");

		public static readonly Guid DMOCATEGORY_AUDIO_EFFECT = new Guid("f3602b3f-0592-48df-a4cd-674721e7ebeb");

		public static readonly Guid DMOCATEGORY_VIDEO_EFFECT = new Guid("d990ee14-776c-4723-be46-3da2f56f10b9");

		public static readonly Guid DMOCATEGORY_AUDIO_CAPTURE_EFFECT = new Guid("f665aaba-3e09-4920-aa5f-219811148f09");
	}
	internal static class DmoMediaTypeGuids
	{
		public static readonly Guid FORMAT_None = new Guid("0F6417D6-C318-11D0-A43F-00A0C9223196");

		public static readonly Guid FORMAT_VideoInfo = new Guid("05589f80-c356-11ce-bf01-00aa0055595a");

		public static readonly Guid FORMAT_VideoInfo2 = new Guid("F72A76A0-EB0A-11d0-ACE4-0000C0CC16BA");

		public static readonly Guid FORMAT_WaveFormatEx = new Guid("05589f81-c356-11ce-bf01-00aa0055595a");

		public static readonly Guid FORMAT_MPEGVideo = new Guid("05589f82-c356-11ce-bf01-00aa0055595a");

		public static readonly Guid FORMAT_MPEGStreams = new Guid("05589f83-c356-11ce-bf01-00aa0055595a");

		public static readonly Guid FORMAT_DvInfo = new Guid("05589f84-c356-11ce-bf01-00aa0055595a");

		public static readonly Guid FORMAT_525WSS = new Guid("C7ECF04D-4582-4869-9ABB-BFB523B62EDF");
	}
	internal enum DmoHResults
	{
		DMO_E_INVALIDSTREAMINDEX = -2147220991,
		DMO_E_INVALIDTYPE,
		DMO_E_TYPE_NOT_SET,
		DMO_E_NOTACCEPTING,
		DMO_E_TYPE_NOT_ACCEPTED,
		DMO_E_NO_MORE_ITEMS
	}
	internal static class DmoInterop
	{
		[DllImport("msdmo.dll")]
		public static extern int DMOEnum([In] ref Guid guidCategory, DmoEnumFlags flags, int inTypes, [In] DmoPartialMediaType[] inTypesArray, int outTypes, [In] DmoPartialMediaType[] outTypesArray, out IEnumDmo enumDmo);

		[DllImport("msdmo.dll")]
		public static extern int MoFreeMediaType([In] ref DmoMediaType mediaType);

		[DllImport("msdmo.dll")]
		public static extern int MoInitMediaType([In][Out] ref DmoMediaType mediaType, int formatBlockBytes);

		[DllImport("msdmo.dll")]
		public static extern int DMOGetName([In] ref Guid clsidDMO, [Out] StringBuilder name);
	}
	internal struct DmoPartialMediaType
	{
		private Guid type;

		private Guid subtype;

		public Guid Type
		{
			get
			{
				return type;
			}
			internal set
			{
				type = value;
			}
		}

		public Guid Subtype
		{
			get
			{
				return subtype;
			}
			internal set
			{
				subtype = value;
			}
		}
	}
	[ComImport]
	[SuppressUnmanagedCodeSecurity]
	[Guid("6d6cbb60-a223-44aa-842f-a2f06750be6d")]
	[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
	internal interface IMediaParamInfo
	{
		[PreserveSig]
		int GetParamCount(out int paramCount);

		[PreserveSig]
		int GetParamInfo(int paramIndex, ref MediaParamInfo paramInfo);

		[PreserveSig]
		int GetParamText(int paramIndex, out IntPtr paramText);

		[PreserveSig]
		int GetNumTimeFormats(out int numTimeFormats);

		[PreserveSig]
		int GetSupportedTimeFormat(int formatIndex, out Guid guidTimeFormat);

		[PreserveSig]
		int GetCurrentTimeFormat(out Guid guidTimeFormat, out int mediaTimeData);
	}
	[Guid("E7E9984F-F09F-4da4-903F-6E2E0EFE56B5")]
	[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
	internal interface IWMResamplerProps
	{
		int SetHalfFilterLength(int outputQuality);

		int SetUserChannelMtx([In] float[] channelConversionMatrix);
	}
	public class MediaBuffer : IMediaBuffer, IDisposable
	{
		private IntPtr buffer;

		private int length;

		private readonly int maxLength;

		public int Length
		{
			get
			{
				return length;
			}
			set
			{
				if (length > maxLength)
				{
					throw new ArgumentException("Cannot be greater than maximum buffer size");
				}
				length = value;
			}
		}

		public MediaBuffer(int maxLength)
		{
			buffer = Marshal.AllocCoTaskMem(maxLength);
			this.maxLength = maxLength;
		}

		public void Dispose()
		{
			if (buffer != IntPtr.Zero)
			{
				Marshal.FreeCoTaskMem(buffer);
				buffer = IntPtr.Zero;
				GC.SuppressFinalize(this);
			}
		}

		~MediaBuffer()
		{
			Dispose();
		}

		int IMediaBuffer.SetLength(int length)
		{
			if (length > maxLength)
			{
				return -2147483645;
			}
			this.length = length;
			return 0;
		}

		int IMediaBuffer.GetMaxLength(out int maxLength)
		{
			maxLength = this.maxLength;
			return 0;
		}

		int IMediaBuffer.GetBufferAndLength(IntPtr bufferPointerPointer, IntPtr validDataLengthPointer)
		{
			if (bufferPointerPointer != IntPtr.Zero)
			{
				Marshal.WriteIntPtr(bufferPointerPointer, buffer);
			}
			if (validDataLengthPointer != IntPtr.Zero)
			{
				Marshal.WriteInt32(validDataLengthPointer, length);
			}
			return 0;
		}

		public void LoadData(byte[] data, int bytes)
		{
			Length = bytes;
			Marshal.Copy(data, 0, buffer, bytes);
		}

		public void RetrieveData(byte[] data, int offset)
		{
			Marshal.Copy(buffer, data, offset, Length);
		}
	}
	public class MediaObject : IDisposable
	{
		private IMediaObject mediaObject;

		private readonly int inputStreams;

		private readonly int outputStreams;

		public int InputStreamCount => inputStreams;

		public int OutputStreamCount => outputStreams;

		internal MediaObject(IMediaObject mediaObject)
		{
			this.mediaObject = mediaObject;
			mediaObject.GetStreamCount(out inputStreams, out outputStreams);
		}

		public DmoMediaType? GetInputType(int inputStream, int inputTypeIndex)
		{
			try
			{
				if (mediaObject.GetInputType(inputStream, inputTypeIndex, out var mediaType) == 0)
				{
					DmoInterop.MoFreeMediaType(ref mediaType);
					return mediaType;
				}
			}
			catch (COMException exception)
			{
				if (exception.GetHResult() != -2147220986)
				{
					throw;
				}
			}
			return null;
		}

		public DmoMediaType? GetOutputType(int outputStream, int outputTypeIndex)
		{
			try
			{
				if (mediaObject.GetOutputType(outputStream, outputTypeIndex, out var mediaType) == 0)
				{
					DmoInterop.MoFreeMediaType(ref mediaType);
					return mediaType;
				}
			}
			catch (COMException exception)
			{
				if (exception.GetHResult() != -2147220986)
				{
					throw;
				}
			}
			return null;
		}

		public DmoMediaType GetOutputCurrentType(int outputStreamIndex)
		{
			DmoMediaType mediaType;
			int outputCurrentType = mediaObject.GetOutputCurrentType(outputStreamIndex, out mediaType);
			switch (outputCurrentType)
			{
			case 0:
				DmoInterop.MoFreeMediaType(ref mediaType);
				return mediaType;
			case -2147220989:
				throw new InvalidOperationException("Media type was not set.");
			default:
				throw Marshal.GetExceptionForHR(outputCurrentType);
			}
		}

		public IEnumerable<DmoMediaType> GetInputTypes(int inputStreamIndex)
		{
			int typeIndex = 0;
			while (true)
			{
				DmoMediaType? inputType;
				DmoMediaType? mediaType = (inputType = GetInputType(inputStreamIndex, typeIndex));
				inputType = inputType;
				if (inputType.HasValue)
				{
					yield return mediaType.Value;
					typeIndex++;
					continue;
				}
				break;
			}
		}

		public IEnumerable<DmoMediaType> GetOutputTypes(int outputStreamIndex)
		{
			int typeIndex = 0;
			while (true)
			{
				DmoMediaType? outputType;
				DmoMediaType? mediaType = (outputType = GetOutputType(outputStreamIndex, typeIndex));
				outputType = outputType;
				if (outputType.HasValue)
				{
					yield return mediaType.Value;
					typeIndex++;
					continue;
				}
				break;
			}
		}

		public bool SupportsInputType(int inputStreamIndex, DmoMediaType mediaType)
		{
			return SetInputType(inputStreamIndex, mediaType, DmoSetTypeFlags.DMO_SET_TYPEF_TEST_ONLY);
		}

		private bool SetInputType(int inputStreamIndex, DmoMediaType mediaType, DmoSetTypeFlags flags)
		{
			switch (mediaObject.SetInputType(inputStreamIndex, ref mediaType, flags))
			{
			case -2147220991:
				throw new ArgumentException("Invalid stream index");
			default:
				_ = -2147220987;
				return false;
			case 0:
				return true;
			}
		}

		public void SetInputType(int inputStreamIndex, DmoMediaType mediaType)
		{
			if (!SetInputType(inputStreamIndex, mediaType, DmoSetTypeFlags.None))
			{
				throw new ArgumentException("Media Type not supported");
			}
		}

		public void SetInputWaveFormat(int inputStreamIndex, WaveFormat waveFormat)
		{
			DmoMediaType mediaType = CreateDmoMediaTypeForWaveFormat(waveFormat);
			bool num = SetInputType(inputStreamIndex, mediaType, DmoSetTypeFlags.None);
			DmoInterop.MoFreeMediaType(ref mediaType);
			if (!num)
			{
				throw new ArgumentException("Media Type not supported");
			}
		}

		public bool SupportsInputWaveFormat(int inputStreamIndex, WaveFormat waveFormat)
		{
			DmoMediaType mediaType = CreateDmoMediaTypeForWaveFormat(waveFormat);
			bool result = SetInputType(inputStreamIndex, mediaType, DmoSetTypeFlags.DMO_SET_TYPEF_TEST_ONLY);
			DmoInterop.MoFreeMediaType(ref mediaType);
			return result;
		}

		private DmoMediaType CreateDmoMediaTypeForWaveFormat(WaveFormat waveFormat)
		{
			DmoMediaType mediaType = default(DmoMediaType);
			int formatBlockBytes = Marshal.SizeOf((object)waveFormat);
			DmoInterop.MoInitMediaType(ref mediaType, formatBlockBytes);
			mediaType.SetWaveFormat(waveFormat);
			return mediaType;
		}

		public bool SupportsOutputType(int outputStreamIndex, DmoMediaType mediaType)
		{
			return SetOutputType(outputStreamIndex, mediaType, DmoSetTypeFlags.DMO_SET_TYPEF_TEST_ONLY);
		}

		public bool SupportsOutputWaveFormat(int outputStreamIndex, WaveFormat waveFormat)
		{
			DmoMediaType mediaType = CreateDmoMediaTypeForWaveFormat(waveFormat);
			bool result = SetOutputType(outputStreamIndex, mediaType, DmoSetTypeFlags.DMO_SET_TYPEF_TEST_ONLY);
			DmoInterop.MoFreeMediaType(ref mediaType);
			return result;
		}

		private bool SetOutputType(int outputStreamIndex, DmoMediaType mediaType, DmoSetTypeFlags flags)
		{
			int num = mediaObject.SetOutputType(outputStreamIndex, ref mediaType, flags);
			return num switch
			{
				-2147220987 => false, 
				0 => true, 
				_ => throw Marshal.GetExceptionForHR(num), 
			};
		}

		public void SetOutputType(int outputStreamIndex, DmoMediaType mediaType)
		{
			if (!SetOutputType(outputStreamIndex, mediaType, DmoSetTypeFlags.None))
			{
				throw new ArgumentException("Media Type not supported");
			}
		}

		public void SetOutputWaveFormat(int outputStreamIndex, WaveFormat waveFormat)
		{
			DmoMediaType mediaType = CreateDmoMediaTypeForWaveFormat(waveFormat);
			bool num = SetOutputType(outputStreamIndex, mediaType, DmoSetTypeFlags.None);
			DmoInterop.MoFreeMediaType(ref mediaType);
			if (!num)
			{
				throw new ArgumentException("Media Type not supported");
			}
		}

		public MediaObjectSizeInfo GetInputSizeInfo(int inputStreamIndex)
		{
			Marshal.ThrowExceptionForHR(mediaObject.GetInputSizeInfo(inputStreamIndex, out var size, out var maxLookahead, out var alignment));
			return new MediaObjectSizeInfo(size, maxLookahead, alignment);
		}

		public MediaObjectSizeInfo GetOutputSizeInfo(int outputStreamIndex)
		{
			Marshal.ThrowExceptionForHR(mediaObject.GetOutputSizeInfo(outputStreamIndex, out var size, out var alignment));
			return new MediaObjectSizeInfo(size, 0, alignment);
		}

		public void ProcessInput(int inputStreamIndex, IMediaBuffer mediaBuffer, DmoInputDataBufferFlags flags, long timestamp, long duration)
		{
			Marshal.ThrowExceptionForHR(mediaObject.ProcessInput(inputStreamIndex, mediaBuffer, flags, timestamp, duration));
		}

		public void ProcessOutput(DmoProcessOutputFlags flags, int outputBufferCount, DmoOutputDataBuffer[] outputBuffers)
		{
			Marshal.ThrowExceptionForHR(mediaObject.ProcessOutput(flags, outputBufferCount, outputBuffers, out var _));
		}

		public void AllocateStreamingResources()
		{
			Marshal.ThrowExceptionForHR(mediaObject.AllocateStreamingResources());
		}

		public void FreeStreamingResources()
		{
			Marshal.ThrowExceptionForHR(mediaObject.FreeStreamingResources());
		}

		public long GetInputMaxLatency(int inputStreamIndex)
		{
			Marshal.ThrowExceptionForHR(mediaObject.GetInputMaxLatency(inputStreamIndex, out var referenceTimeMaxLatency));
			return referenceTimeMaxLatency;
		}

		public void Flush()
		{
			Marshal.ThrowExceptionForHR(mediaObject.Flush());
		}

		public void Discontinuity(int inputStreamIndex)
		{
			Marshal.ThrowExceptionForHR(mediaObject.Discontinuity(inputStreamIndex));
		}

		public bool IsAcceptingData(int inputStreamIndex)
		{
			Marshal.ThrowExceptionForHR(mediaObject.GetInputStatus(inputStreamIndex, out var flags));
			return (flags & DmoInputStatusFlags.DMO_INPUT_STATUSF_ACCEPT_DATA) == DmoInputStatusFlags.DMO_INPUT_STATUSF_ACCEPT_DATA;
		}

		public void Dispose()
		{
			if (mediaObject != null)
			{
				Marshal.ReleaseComObject(mediaObject);
				mediaObject = null;
			}
		}
	}
	public class MediaObjectSizeInfo
	{
		public int Size { get; private set; }

		public int MaxLookahead { get; }

		public int Alignment { get; }

		public MediaObjectSizeInfo(int size, int maxLookahead, int alignment)
		{
			Size = size;
			MaxLookahead = maxLookahead;
			Alignment = alignment;
		}

		public override string ToString()
		{
			return $"Size: {Size}, Alignment {Alignment}, MaxLookahead {MaxLookahead}";
		}
	}
	internal struct MediaParamInfo
	{
		public MediaParamType mpType;

		public MediaParamCurveType mopCaps;

		public float mpdMinValue;

		public float mpdMaxValue;

		public float mpdNeutralValue;

		[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
		public string szUnitText;

		[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
		public string szLabel;
	}
	internal enum MediaParamType
	{
		Int,
		Float,
		Bool,
		Enum,
		Max
	}
	[Flags]
	internal enum MediaParamCurveType
	{
		MP_CURVE_JUMP = 1,
		MP_CURVE_LINEAR = 2,
		MP_CURVE_SQUARE = 4,
		MP_CURVE_INVSQUARE = 8,
		MP_CURVE_SINE = 0x10
	}
	internal static class MediaTypes
	{
		public static readonly Guid MEDIATYPE_AnalogAudio = new Guid("0482DEE1-7817-11cf-8a03-00aa006ecb65");

		public static readonly Guid MEDIATYPE_AnalogVideo = new Guid("0482DDE1-7817-11cf-8A03-00AA006ECB65");

		public static readonly Guid MEDIATYPE_Audio = new Guid("73647561-0000-0010-8000-00AA00389B71");

		public static readonly Guid MEDIATYPE_AUXLine21Data = new Guid("670AEA80-3A82-11d0-B79B-00AA003767A7");

		public static readonly Guid MEDIATYPE_File = new Guid("656c6966-0000-0010-8000-00AA00389B71");

		public static readonly Guid MEDIATYPE_Interleaved = new Guid("73766169-0000-0010-8000-00AA00389B71");

		public static readonly Guid MEDIATYPE_Midi = new Guid("7364696D-0000-0010-8000-00AA00389B71");

		public static readonly Guid MEDIATYPE_ScriptCommand = new Guid("73636d64-0000-0010-8000-00AA00389B71");

		public static readonly Guid MEDIATYPE_Stream = new Guid("e436eb83-524f-11ce-9f53-0020af0ba770");

		public static readonly Guid MEDIATYPE_Text = new Guid("73747874-0000-0010-8000-00AA00389B71");

		public static readonly Guid MEDIATYPE_Timecode = new Guid("0482DEE3-7817-11cf-8a03-00aa006ecb65");

		public static readonly Guid MEDIATYPE_Video = new Guid("73646976-0000-0010-8000-00AA00389B71");

		public static readonly Guid[] MajorTypes = new Guid[12]
		{
			MEDIATYPE_AnalogAudio, MEDIATYPE_AnalogVideo, MEDIATYPE_Audio, MEDIATYPE_AUXLine21Data, MEDIATYPE_File, MEDIATYPE_Interleaved, MEDIATYPE_Midi, MEDIATYPE_ScriptCommand, MEDIATYPE_Stream, MEDIATYPE_Text,
			MEDIATYPE_Timecode, MEDIATYPE_Video
		};

		public static readonly string[] MajorTypeNames = new string[12]
		{
			"Analog Audio", "Analog Video", "Audio", "AUXLine21Data", "File", "Interleaved", "Midi", "ScriptCommand", "Stream", "Text",
			"Timecode", "Video"
		};

		public static string GetMediaTypeName(Guid majorType)
		{
			for (int i = 0; i < MajorTypes.Length; i++)
			{
				if (majorType == MajorTypes[i])
				{
					return MajorTypeNames[i];
				}
			}
			throw new ArgumentException("Major Type not found");
		}
	}
	[ComImport]
	[Guid("bbeea841-0a63-4f52-a7ab-a9b3a84ed38a")]
	internal class WindowsMediaMp3DecoderComObject
	{
	}
	public class WindowsMediaMp3Decoder : IDisposable
	{
		private MediaObject mediaObject;

		private IPropertyStore propertyStoreInterface;

		private WindowsMediaMp3DecoderComObject mediaComObject;

		public MediaObject MediaObject => mediaObject;

		public WindowsMediaMp3Decoder()
		{
			mediaComObject = new WindowsMediaMp3DecoderComObject();
			mediaObject = new MediaObject((IMediaObject)mediaComObject);
			propertyStoreInterface = (IPropertyStore)mediaComObject;
		}

		public void Dispose()
		{
			if (propertyStoreInterface != null)
			{
				Marshal.ReleaseComObject(propertyStoreInterface);
				propertyStoreInterface = null;
			}
			if (mediaObject != null)
			{
				mediaObject.Dispose();
				mediaObject = null;
			}
			if (mediaComObject != null)
			{
				Marshal.ReleaseComObject(mediaComObject);
				mediaComObject = null;
			}
		}
	}
	[Flags]
	public enum DmoInputDataBufferFlags
	{
		None = 0,
		SyncPoint = 1,
		Time = 2,
		TimeLength = 4
	}
	[Flags]
	internal enum DmoInputStatusFlags
	{
		None = 0,
		DMO_INPUT_STATUSF_ACCEPT_DATA = 1
	}
	public struct DmoMediaType
	{
		private Guid majortype;

		private Guid subtype;

		private bool bFixedSizeSamples;

		private bool bTemporalCompression;

		private int lSampleSize;

		private Guid formattype;

		private IntPtr pUnk;

		private int cbFormat;

		private IntPtr pbFormat;

		public Guid MajorType => majortype;

		public string MajorTypeName => MediaTypes.GetMediaTypeName(majortype);

		public Guid SubType => subtype;

		public string SubTypeName
		{
			get
			{
				if (majortype == MediaTypes.MEDIATYPE_Audio)
				{
					return AudioMediaSubtypes.GetAudioSubtypeName(subtype);
				}
				return subtype.ToString();
			}
		}

		public bool FixedSizeSamples => bFixedSizeSamples;

		public int SampleSize => lSampleSize;

		public Guid FormatType => formattype;

		public string FormatTypeName
		{
			get
			{
				if (formattype == DmoMediaTypeGuids.FORMAT_None)
				{
					return "None";
				}
				if (formattype == Guid.Empty)
				{
					return "Null";
				}
				if (formattype == DmoMediaTypeGuids.FORMAT_WaveFormatEx)
				{
					return "WaveFormatEx";
				}
				return FormatType.ToString();
			}
		}

		public WaveFormat GetWaveFormat()
		{
			if (formattype == DmoMediaTypeGuids.FORMAT_WaveFormatEx)
			{
				return WaveFormat.MarshalFromPtr(pbFormat);
			}
			throw new InvalidOperationException("Not a WaveFormat type");
		}

		public void SetWaveFormat(WaveFormat waveFormat)
		{
			majortype = MediaTypes.MEDIATYPE_Audio;
			if (waveFormat is WaveFormatExtensible waveFormatExtensible)
			{
				subtype = waveFormatExtensible.SubFormat;
			}
			else
			{
				switch (waveFormat.Encoding)
				{
				case WaveFormatEncoding.Pcm:
					subtype = AudioMediaSubtypes.MEDIASUBTYPE_PCM;
					break;
				case WaveFormatEncoding.IeeeFloat:
					subtype = AudioMediaSubtypes.MEDIASUBTYPE_IEEE_FLOAT;
					break;
				case WaveFormatEncoding.MpegLayer3:
					subtype = AudioMediaSubtypes.WMMEDIASUBTYPE_MP3;
					break;
				default:
					throw new ArgumentException($"Not a supported encoding {waveFormat.Encoding}");
				}
			}
			bFixedSizeSamples = SubType == AudioMediaSubtypes.MEDIASUBTYPE_PCM || SubType == AudioMediaSubtypes.MEDIASUBTYPE_IEEE_FLOAT;
			formattype = DmoMediaTypeGuids.FORMAT_WaveFormatEx;
			if (cbFormat < Marshal.SizeOf((object)waveFormat))
			{
				throw new InvalidOperationException("Not enough memory assigned for a WaveFormat structure");
			}
			Marshal.StructureToPtr((object)waveFormat, pbFormat, fDeleteOld: false);
		}
	}
	[StructLayout(LayoutKind.Sequential, Pack = 8)]
	public struct DmoOutputDataBuffer : IDisposable
	{
		[MarshalAs(UnmanagedType.Interface)]
		private IMediaBuffer pBuffer;

		private DmoOutputDataBufferFlags dwStatus;

		private long rtTimestamp;

		private long referenceTimeDuration;

		public IMediaBuffer MediaBuffer
		{
			get
			{
				return pBuffer;
			}
			internal set
			{
				pBuffer = value;
			}
		}

		public int Length => ((MediaBuffer)pBuffer).Length;

		public DmoOutputDataBufferFlags StatusFlags
		{
			get
			{
				return dwStatus;
			}
			internal set
			{
				dwStatus = value;
			}
		}

		public long Timestamp
		{
			get
			{
				return rtTimestamp;
			}
			internal set
			{
				rtTimestamp = value;
			}
		}

		public long Duration
		{
			get
			{
				return referenceTimeDuration;
			}
			internal set
			{
				referenceTimeDuration = value;
			}
		}

		public bool MoreDataAvailable => (StatusFlags & DmoOutputDataBufferFlags.Incomplete) == DmoOutputDataBufferFlags.Incomplete;

		public DmoOutputDataBuffer(int maxBufferSize)
		{
			pBuffer = new MediaBuffer(maxBufferSize);
			dwStatus = DmoOutputDataBufferFlags.None;
			rtTimestamp = 0L;
			referenceTimeDuration = 0L;
		}

		public void Dispose()
		{
			if (pBuffer != null)
			{
				((MediaBuffer)pBuffer).Dispose();
				pBuffer = null;
				GC.SuppressFinalize(this);
			}
		}

		public void RetrieveData(byte[] data, int offset)
		{
			((MediaBuffer)pBuffer).RetrieveData(data, offset);
		}
	}
	[Flags]
	public enum DmoOutputDataBufferFlags
	{
		None = 0,
		SyncPoint = 1,
		Time = 2,
		TimeLength = 4,
		Incomplete = 0x1000000
	}
	[Flags]
	public enum DmoProcessOutputFlags
	{
		None = 0,
		DiscardWhenNoBuffer = 1
	}
	[Flags]
	internal enum DmoSetTypeFlags
	{
		None = 0,
		DMO_SET_TYPEF_TEST_ONLY = 1,
		DMO_SET_TYPEF_CLEAR = 2
	}
	[Guid("2c3cd98a-2bfa-4a53-9c27-5249ba64ba0f")]
	[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
	internal interface IEnumDmo
	{
		int Next(int itemsToFetch, out Guid clsid, out IntPtr name, out int itemsFetched);

		int Skip(int itemsToSkip);

		int Reset();

		int Clone(out IEnumDmo enumPointer);
	}
	[ComImport]
	[SuppressUnmanagedCodeSecurity]
	[Guid("59eff8b9-938c-4a26-82f2-95cb84cdc837")]
	[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
	public interface IMediaBuffer
	{
		[PreserveSig]
		int SetLength(int length);

		[PreserveSig]
		int GetMaxLength(out int maxLength);

		[PreserveSig]
		int GetBufferAndLength(IntPtr bufferPointerPointer, IntPtr validDataLengthPointer);
	}
	[ComImport]
	[SuppressUnmanagedCodeSecurity]
	[Guid("d8ad0f58-5494-4102-97c5-ec798e59bcf4")]
	[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
	internal interface IMediaObject
	{
		[PreserveSig]
		int GetStreamCount(out int inputStreams, out int outputStreams);

		[PreserveSig]
		int GetInputStreamInfo(int inputStreamIndex, out InputStreamInfoFlags flags);

		[PreserveSig]
		int GetOutputStreamInfo(int outputStreamIndex, out OutputStreamInfoFlags flags);

		[PreserveSig]
		int GetInputType(int inputStreamIndex, int typeIndex, out DmoMediaType mediaType);

		[PreserveSig]
		int GetOutputType(int outputStreamIndex, int typeIndex, out DmoMediaType mediaType);

		[PreserveSig]
		int SetInputType(int inputStreamIndex, [In] ref DmoMediaType mediaType, DmoSetTypeFlags flags);

		[PreserveSig]
		int SetOutputType(int outputStreamIndex, [In] ref DmoMediaType mediaType, DmoSetTypeFlags flags);

		[PreserveSig]
		int GetInputCurrentType(int inputStreamIndex, out DmoMediaType mediaType);

		[PreserveSig]
		int GetOutputCurrentType(int outputStreamIndex, out DmoMediaType mediaType);

		[PreserveSig]
		int GetInputSizeInfo(int inputStreamIndex, out int size, out int maxLookahead, out int alignment);

		[PreserveSig]
		int GetOutputSizeInfo(int outputStreamIndex, out int size, out int alignment);

		[PreserveSig]
		int GetInputMaxLatency(int inputStreamIndex, out long referenceTimeMaxLatency);

		[PreserveSig]
		int SetInputMaxLatency(int inputStreamIndex, long referenceTimeMaxLatency);

		[PreserveSig]
		int Flush();

		[PreserveSig]
		int Discontinuity(int inputStreamIndex);

		[PreserveSig]
		int AllocateStreamingResources();

		[PreserveSig]
		int FreeStreamingResources();

		[PreserveSig]
		int GetInputStatus(int inputStreamIndex, out DmoInputStatusFlags flags);

		[PreserveSig]
		int ProcessInput(int inputStreamIndex, [In] IMediaBuffer mediaBuffer, DmoInputDataBufferFlags flags, long referenceTimeTimestamp, long referenceTimeDuration);

		[PreserveSig]
		int ProcessOutput(DmoProcessOutputFlags flags, int outputBufferCount, [In][Out][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] DmoOutputDataBuffer[] outputBuffers, out int statusReserved);

		[PreserveSig]
		int Lock(bool acquireLock);
	}
	[Flags]
	internal enum InputStreamInfoFlags
	{
		None = 0,
		DMO_INPUT_STREAMF_WHOLE_SAMPLES = 1,
		DMO_INPUT_STREAMF_SINGLE_SAMPLE_PER_BUFFER = 2,
		DMO_INPUT_STREAMF_FIXED_SAMPLE_SIZE = 4,
		DMO_INPUT_STREAMF_HOLDS_BUFFERS = 8
	}
	[Flags]
	internal enum OutputStreamInfoFlags
	{
		DMO_OUTPUT_STREAMF_WHOLE_SAMPLES = 1,
		DMO_OUTPUT_STREAMF_SINGLE_SAMPLE_PER_BUFFER = 2,
		DMO_OUTPUT_STREAMF_FIXED_SAMPLE_SIZE = 4,
		DMO_OUTPUT_STREAMF_DISCARDABLE = 8,
		DMO_OUTPUT_STREAMF_OPTIONAL = 0x10
	}
	[ComImport]
	[Guid("f447b69e-1884-4a7e-8055-346f74d6edb3")]
	internal class ResamplerMediaComObject
	{
	}
	public class DmoResampler : IDisposable
	{
		private MediaObject mediaObject;

		private IPropertyStore propertyStoreInterface;

		private IWMResamplerProps resamplerPropsInterface;

		private ResamplerMediaComObject mediaComObject;

		public MediaObject MediaObject => mediaObject;

		public DmoResampler()
		{
			mediaComObject = new ResamplerMediaComObject();
			mediaObject = new MediaObject((IMediaObject)mediaComObject);
			propertyStoreInterface = (IPropertyStore)mediaComObject;
			resamplerPropsInterface = (IWMResamplerProps)mediaComObject;
		}

		public void Dispose()
		{
			if (propertyStoreInterface != null)
			{
				Marshal.ReleaseComObject(propertyStoreInterface);
				propertyStoreInterface = null;
			}
			if (resamplerPropsInterface != null)
			{
				Marshal.ReleaseComObject(resamplerPropsInterface);
				resamplerPropsInterface = null;
			}
			if (mediaObject != null)
			{
				mediaObject.Dispose();
				mediaObject = null;
			}
			if (mediaComObject != null)
			{
				Marshal.ReleaseComObject(mediaComObject);
				mediaComObject = null;
			}
		}
	}
}
namespace NAudio.Wave
{
	public static class WaveExtensionMethods
	{
		public static ISampleProvider ToSampleProvider(this IWaveProvider waveProvider)
		{
			return SampleProviderConverters.ConvertWaveProviderIntoSampleProvider(waveProvider);
		}

		public static void Init(this IWavePlayer wavePlayer, ISampleProvider sampleProvider, bool convertTo16Bit = false)
		{
			IWaveProvider waveProvider2;
			if (!convertTo16Bit)
			{
				IWaveProvider waveProvider = new SampleToWaveProvider(sampleProvider);
				waveProvider2 = waveProvider;
			}
			else
			{
				IWaveProvider waveProvider = new SampleToWaveProvider16(sampleProvider);
				waveProvider2 = waveProvider;
			}
			IWaveProvider waveProvider3 = waveProvider2;
			wavePlayer.Init(waveProvider3);
		}

		public static WaveFormat AsStandardWaveFormat(this WaveFormat waveFormat)
		{
			if (!(waveFormat is WaveFormatExtensible waveFormatExtensible))
			{
				return waveFormat;
			}
			return waveFormatExtensible.ToStandardWaveFormat();
		}

		public static IWaveProvider ToWaveProvider(this ISampleProvider sampleProvider)
		{
			return new SampleToWaveProvider(sampleProvider);
		}

		public static IWaveProvider ToWaveProvider16(this ISampleProvider sampleProvider)
		{
			return new SampleToWaveProvider16(sampleProvider);
		}

		public static ISampleProvider FollowedBy(this ISampleProvider sampleProvider, ISampleProvider next)
		{
			return new ConcatenatingSampleProvider(new ISampleProvider[2] { sampleProvider, next });
		}

		public static ISampleProvider FollowedBy(this ISampleProvider sampleProvider, TimeSpan silenceDuration, ISampleProvider next)
		{
			OffsetSampleProvider offsetSampleProvider = new OffsetSampleProvider(sampleProvider)
			{
				LeadOut = silenceDuration
			};
			return new ConcatenatingSampleProvider(new ISampleProvider[2] { offsetSampleProvider, next });
		}

		public static ISampleProvider Skip(this ISampleProvider sampleProvider, TimeSpan skipDuration)
		{
			return new OffsetSampleProvider(sampleProvider)
			{
				SkipOver = skipDuration
			};
		}

		public static ISampleProvider Take(this ISampleProvider sampleProvider, TimeSpan takeDuration)
		{
			return new OffsetSampleProvider(sampleProvider)
			{
				Take = takeDuration
			};
		}

		public static ISampleProvider ToMono(this ISampleProvider sourceProvider, float leftVol = 0.5f, float rightVol = 0.5f)
		{
			if (sourceProvider.WaveFormat.Channels == 1)
			{
				return sourceProvider;
			}
			return new StereoToMonoSampleProvider(sourceProvider)
			{
				LeftVolume = leftVol,
				RightVolume = rightVol
			};
		}

		public static ISampleProvider ToStereo(this ISampleProvider sourceProvider, float leftVol = 1f, float rightVol = 1f)
		{
			if (sourceProvider.WaveFormat.Channels == 2)
			{
				return sourceProvider;
			}
			return new MonoToStereoSampleProvider(sourceProvider)
			{
				LeftVolume = leftVol,
				RightVolume = rightVol
			};
		}
	}
	public enum ChannelMode
	{
		Stereo,
		JointStereo,
		DualChannel,
		Mono
	}
	public class Id3v2Tag
	{
		private long tagStartPosition;

		private long tagEndPosition;

		private byte[] rawData;

		public byte[] RawData => rawData;

		public static Id3v2Tag ReadTag(Stream input)
		{
			try
			{
				return new Id3v2Tag(input);
			}
			catch (FormatException)
			{
				return null;
			}
		}

		public static Id3v2Tag Create(IEnumerable<KeyValuePair<string, string>> tags)
		{
			return ReadTag(CreateId3v2TagStream(tags));
		}

		private static byte[] FrameSizeToBytes(int n)
		{
			byte[] bytes = BitConverter.GetBytes(n);
			Array.Reverse((Array)bytes);
			return bytes;
		}

		private static byte[] CreateId3v2Frame(string key, string value)
		{
			if (string.IsNullOrEmpty(key))
			{
				throw new ArgumentNullException("key");
			}
			if (string.IsNullOrEmpty(value))
			{
				throw new ArgumentNullException("value");
			}
			if (key.Length != 4)
			{
				throw new ArgumentOutOfRangeException("key", "key " + key + " must be 4 characters long");
			}
			byte[] array = new byte[2] { 255, 254 };
			byte[] array2 = new byte[3];
			byte[] array3 = new byte[2];
			byte[] array4 = ((!(key == "COMM")) ? ByteArrayExtensions.Concat(new byte[1] { 1 }, array, Encoding.Unicode.GetBytes(value)) : ByteArrayExtensions.Concat(new byte[1] { 1 }, array2, array3, array, Encoding.Unicode.GetBytes(value)));
			return ByteArrayExtensions.Concat(Encoding.UTF8.GetBytes(key), FrameSizeToBytes(array4.Length), new byte[2], array4);
		}

		private static byte[] GetId3TagHeaderSize(int size)
		{
			byte[] array = new byte[4];
			for (int num = array.Length - 1; num >= 0; num--)
			{
				array[num] = (byte)(size % 128);
				size /= 128;
			}
			return array;
		}

		private static byte[] CreateId3v2TagHeader(IEnumerable<byte[]> frames)
		{
			int num = 0;
			foreach (byte[] frame in frames)
			{
				num += frame.Length;
			}
			return ByteArrayExtensions.Concat(Encoding.UTF8.GetBytes("ID3"), new byte[2] { 3, 0 }, new byte[1], GetId3TagHeaderSize(num));
		}

		private static Stream CreateId3v2TagStream(IEnumerable<KeyValuePair<string, string>> tags)
		{
			List<byte[]> list = new List<byte[]>();
			foreach (KeyValuePair<string, string> tag in tags)
			{
				list.Add(CreateId3v2Frame(tag.Key, tag.Value));
			}
			byte[] array = CreateId3v2TagHeader(list);
			MemoryStream memoryStream = new MemoryStream();
			memoryStream.Write(array, 0, array.Length);
			foreach (byte[] item in list)
			{
				memoryStream.Write(item, 0, item.Length);
			}
			memoryStream.Position = 0L;
			return memoryStream;
		}

		private Id3v2Tag(Stream input)
		{
			tagStartPosition = input.Position;
			BinaryReader binaryReader = new BinaryReader(input);
			byte[] array = binaryReader.ReadBytes(10);
			if (array.Length >= 3 && array[0] == 73 && array[1] == 68 && array[2] == 51)
			{
				if ((array[5] & 0x40) == 64)
				{
					byte[] array2 = binaryReader.ReadBytes(4);
					_ = array2[0] * 2097152 + array2[1] * 16384 + array2[2] * 128;
					_ = array2[3];
				}
				int num = array[6] * 2097152;
				num += array[7] * 16384;
				num += array[8] * 128;
				num += array[9];
				binaryReader.ReadBytes(num);
				if ((array[5] & 0x10) == 16)
				{
					binaryReader.ReadBytes(10);
				}
				tagEndPosition = input.Position;
				input.Position = tagStartPosition;
				rawData = binaryReader.ReadBytes((int)(tagEndPosition - tagStartPosition));
				return;
			}
			input.Position = tagStartPosition;
			throw new FormatException("Not an ID3v2 tag");
		}
	}
	public interface IMp3FrameDecompressor : IDisposable
	{
		WaveFormat OutputFormat { get; }

		int DecompressFrame(Mp3Frame frame, byte[] dest, int destOffset);

		void Reset();
	}
	public class Mp3Frame
	{
		private static readonly int[,,] bitRates = new int[2, 3, 15]
		{
			{
				{
					0, 32, 64, 96, 128, 160, 192, 224, 256, 288,
					320, 352, 384, 416, 448
				},
				{
					0, 32, 48, 56, 64, 80, 96, 112, 128, 160,
					192, 224, 256, 320, 384
				},
				{
					0, 32, 40, 48, 56, 64, 80, 96, 112, 128,
					160, 192, 224, 256, 320
				}
			},
			{
				{
					0, 32, 48, 56, 64, 80, 96, 112, 128, 144,
					160, 176, 192, 224, 256
				},
				{
					0, 8, 16, 24, 32, 40, 48, 56, 64, 80,
					96, 112, 128, 144, 160
				},
				{
					0, 8, 16, 24, 32, 40, 48, 56, 64, 80,
					96, 112, 128, 144, 160
				}
			}
		};

		private static readonly int[,] samplesPerFrame = new int[2, 3]
		{
			{ 384, 1152, 1152 },
			{ 384, 1152, 576 }
		};

		private static readonly int[] sampleRatesVersion1 = new int[3] { 44100, 48000, 32000 };

		private static readonly int[] sampleRatesVersion2 = new int[3] { 22050, 24000, 16000 };

		private static readonly int[] sampleRatesVersion25 = new int[3] { 11025, 12000, 8000 };

		private const int MaxFrameLength = 16384;

		public int SampleRate { get; private set; }

		public int FrameLength { get; private set; }

		public int BitRate { get; private set; }

		public byte[] RawData { get; private set; }

		public MpegVersion MpegVersion { get; private set; }

		public MpegLayer MpegLayer { get; private set; }

		public ChannelMode ChannelMode { get; private set; }

		public int SampleCount { get; private set; }

		public int ChannelExtension { get; private set; }

		public int BitRateIndex { get; private set; }

		public bool Copyright { get; private set; }

		public bool CrcPresent { get; private set; }

		public long FileOffset { get; private set; }

		public static Mp3Frame LoadFromStream(Stream input)
		{
			return LoadFromStream(input, readData: true);
		}

		public static Mp3Frame LoadFromStream(Stream input, bool readData)
		{
			Mp3Frame mp3Frame = new Mp3Frame();
			mp3Frame.FileOffset = input.Position;
			byte[] array = new byte[4];
			if (input.Read(array, 0, array.Length) < array.Length)
			{
				return null;
			}
			while (!IsValidHeader(array, mp3Frame))
			{
				array[0] = array[1];
				array[1] = array[2];
				array[2] = array[3];
				if (input.Read(array, 3, 1) < 1)
				{
					return null;
				}
				mp3Frame.FileOffset++;
			}
			int num = mp3Frame.FrameLength - 4;
			if (readData)
			{
				mp3Frame.RawData = new byte[mp3Frame.FrameLength];
				Array.Copy(array, mp3Frame.RawData, 4);
				if (input.Read(mp3Frame.RawData, 4, num) < num)
				{
					throw new EndOfStreamException("Unexpected end of stream before frame complete");
				}
			}
			else
			{
				input.Position += num;
			}
			return mp3Frame;
		}

		private Mp3Frame()
		{
		}

		private static bool IsValidHeader(byte[] headerBytes, Mp3Frame frame)
		{
			if (headerBytes[0] == byte.MaxValue && (headerBytes[1] & 0xE0) == 224)
			{
				frame.MpegVersion = (MpegVersion)((headerBytes[1] & 0x18) >> 3);
				if (frame.MpegVersion == MpegVersion.Reserved)
				{
					return false;
				}
				frame.MpegLayer = (MpegLayer)((headerBytes[1] & 6) >> 1);
				if (frame.MpegLayer == MpegLayer.Reserved)
				{
					return false;
				}
				int num = ((frame.MpegLayer != MpegLayer.Layer1) ? ((frame.MpegLayer == MpegLayer.Layer2) ? 1 : 2) : 0);
				frame.CrcPresent = (headerBytes[1] & 1) == 0;
				frame.BitRateIndex = (headerBytes[2] & 0xF0) >> 4;
				if (frame.BitRateIndex == 15)
				{
					return false;
				}
				int num2 = ((frame.MpegVersion != MpegVersion.Version1) ? 1 : 0);
				frame.BitRate = bitRates[num2, num, frame.BitRateIndex] * 1000;
				if (frame.BitRate == 0)
				{
					return false;
				}
				int num3 = (headerBytes[2] & 0xC) >> 2;
				if (num3 == 3)
				{
					return false;
				}
				if (frame.MpegVersion == MpegVersion.Version1)
				{
					frame.SampleRate = sampleRatesVersion1[num3];
				}
				else if (frame.MpegVersion == MpegVersion.Version2)
				{
					frame.SampleRate = sampleRatesVersion2[num3];
				}
				else
				{
					frame.SampleRate = sampleRatesVersion25[num3];
				}
				bool flag = (headerBytes[2] & 2) == 2;
				_ = headerBytes[2];
				frame.ChannelMode = (ChannelMode)((headerBytes[3] & 0xC0) >> 6);
				frame.ChannelExtension = (headerBytes[3] & 0x30) >> 4;
				if (frame.ChannelExtension != 0 && frame.ChannelMode != ChannelMode.JointStereo)
				{
					return false;
				}
				frame.Copyright = (headerBytes[3] & 8) == 8;
				_ = headerBytes[3];
				_ = headerBytes[3];
				int num4 = (flag ? 1 : 0);
				frame.SampleCount = samplesPerFrame[num2, num];
				int num5 = frame.SampleCount / 8;
				if (frame.MpegLayer == MpegLayer.Layer1)
				{
					frame.FrameLength = (num5 * frame.BitRate / frame.SampleRate + num4) * 4;
				}
				else
				{
					frame.FrameLength = num5 * frame.BitRate / frame.SampleRate + num4;
				}
				if (frame.FrameLength > 16384)
				{
					return false;
				}
				return true;
			}
			return false;
		}
	}
	public class AcmMp3FrameDecompressor : IMp3FrameDecompressor, IDisposable
	{
		private readonly AcmStream conversionStream;

		private readonly WaveFormat pcmFormat;

		private bool disposed;

		public WaveFormat OutputFormat => pcmFormat;

		public AcmMp3FrameDecompressor(WaveFormat sourceFormat)
		{
			pcmFormat = AcmStream.SuggestPcmFormat(sourceFormat);
			try
			{
				conversionStream = new AcmStream(sourceFormat, pcmFormat);
			}
			catch (Exception)
			{
				disposed = true;
				GC.SuppressFinalize(this);
				throw;
			}
		}

		public int DecompressFrame(Mp3Frame frame, byte[] dest, int destOffset)
		{
			if (frame == null)
			{
				throw new ArgumentNullException("frame", "You must provide a non-null Mp3Frame to decompress");
			}
			Array.Copy(frame.RawData, conversionStream.SourceBuffer, frame.FrameLength);
			int sourceBytesConverted = 0;
			int num = conversionStream.Convert(frame.FrameLength, out sourceBytesConverted);
			if (sourceBytesConverted != frame.FrameLength)
			{
				throw new InvalidOperationException($"Couldn't convert the whole MP3 frame (converted {sourceBytesConverted}/{frame.FrameLength})");
			}
			Array.Copy(conversionStream.DestBuffer, 0, dest, destOffset, num);
			return num;
		}

		public void Reset()
		{
			conversionStream.Reposition();
		}

		public void Dispose()
		{
			if (!disposed)
			{
				disposed = true;
				if (conversionStream != null)
				{
					conversionStream.Dispose();
				}
				GC.SuppressFinalize(this);
			}
		}

		~AcmMp3FrameDecompressor()
		{
			Dispose();
		}
	}
	public enum MpegLayer
	{
		Reserved,
		Layer3,
		Layer2,
		Layer1
	}
	public enum MpegVersion
	{
		Version25,
		Reserved,
		Version2,
		Version1
	}
	public class XingHeader
	{
		[Flags]
		private enum XingHeaderOptions
		{
			Frames = 1,
			Bytes = 2,
			Toc = 4,
			VbrScale = 8
		}

		private static int[] sr_table = new int[4] { 44100, 48000, 32000, 99999 };

		private int vbrScale = -1;

		private int startOffset;

		private int endOffset;

		private int tocOffset = -1;

		private int framesOffset = -1;

		private int bytesOffset = -1;

		private Mp3Frame frame;

		public int Frames
		{
			get
			{
				if (framesOffset == -1)
				{
					return -1;
				}
				return ReadBigEndian(frame.RawData, framesOffset);
			}
			set
			{
				if (framesOffset == -1)
				{
					throw new InvalidOperationException("Frames flag is not set");
				}
				WriteBigEndian(frame.RawData, framesOffset, value);
			}
		}

		public int Bytes
		{
			get
			{
				if (bytesOffset == -1)
				{
					return -1;
				}
				return ReadBigEndian(frame.RawData, bytesOffset);
			}
			set
			{
				if (framesOffset == -1)
				{
					throw new InvalidOperationException("Bytes flag is not set");
				}
				WriteBigEndian(frame.RawData, bytesOffset, value);
			}
		}

		public int VbrScale => vbrScale;

		public Mp3Frame Mp3Frame => frame;

		private static int ReadBigEndian(byte[] buffer, int offset)
		{
			return (((((buffer[offset] << 8) | buffer[offset + 1]) << 8) | buffer[offset + 2]) << 8) | buffer[offset + 3];
		}

		private void WriteBigEndian(byte[] buffer, int offset, int value)
		{
			byte[] bytes = BitConverter.GetBytes(value);
			for (int i = 0; i < 4; i++)
			{
				buffer[offset + 3 - i] = bytes[i];
			}
		}

		public static XingHeader LoadXingHeader(Mp3Frame frame)
		{
			XingHeader xingHeader = new XingHeader();
			xingHeader.frame = frame;
			int num = 0;
			if (frame.MpegVersion == MpegVersion.Version1)
			{
				num = ((frame.ChannelMode == ChannelMode.Mono) ? 21 : 36);
			}
			else
			{
				if (frame.MpegVersion != MpegVersion.Version2)
				{
					return null;
				}
				num = ((frame.ChannelMode == ChannelMode.Mono) ? 13 : 21);
			}
			if (frame.RawData[num] == 88 && frame.RawData[num + 1] == 105 && frame.RawData[num + 2

ResourcefulHands.dll

Decompiled 3 weeks ago
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using NAudio.Wave;
using Newtonsoft.Json;
using ResourcefulHands.Patches;
using Steamworks;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.SceneManagement;
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: AssemblyCompany("ResourcefulHands")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+b770ebe2ed528182a684f486d8217e8a774fa5e6")]
[assembly: AssemblyProduct("ResourcefulHands")]
[assembly: AssemblyTitle("ResourcefulHands")]
[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 ResourcefulHands
{
	public static class MiscUtils
	{
		private static int StartIndex;

		public static string CleanString(string str)
		{
			char[] invalidFileNameChars = Path.GetInvalidFileNameChars();
			foreach (char c in invalidFileNameChars)
			{
				str = str.Replace(c.ToString(), "");
			}
			StringBuilder stringBuilder = new StringBuilder();
			string text = str;
			foreach (char c2 in text)
			{
				if (c2 <= '\u007f')
				{
					stringBuilder.Append(c2);
				}
			}
			return stringBuilder.ToString();
		}

		public static void WriteString(this Stream stream, string value)
		{
			foreach (char c in value)
			{
				stream.WriteByte((byte)c);
			}
		}

		public static void WriteInteger(this Stream stream, uint value)
		{
			stream.WriteByte((byte)(value & 0xFFu));
			stream.WriteByte((byte)((value >> 8) & 0xFFu));
			stream.WriteByte((byte)((value >> 16) & 0xFFu));
			stream.WriteByte((byte)((value >> 24) & 0xFFu));
		}

		public static void WriteShort(this Stream stream, ushort value)
		{
			stream.WriteByte((byte)(value & 0xFFu));
			stream.WriteByte((byte)((uint)(value >> 8) & 0xFFu));
		}

		public static RenderTexture ConvertToARGB32(this RenderTexture self)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			if ((int)self.format == 0)
			{
				return self;
			}
			RenderTexture temporary = RenderTexture.GetTemporary(((Texture)self).width, ((Texture)self).height, 0, (RenderTextureFormat)0);
			Graphics.Blit((Texture)(object)self, temporary);
			return temporary;
		}

		public static float[] LoadAudioFile(string filePath, out int sampleRate, out int channels)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			AudioFileReader val = new AudioFileReader(filePath);
			try
			{
				sampleRate = ((WaveStream)val).WaveFormat.SampleRate;
				channels = ((WaveStream)val).WaveFormat.Channels;
				int num = (int)(((Stream)(object)val).Length / 4);
				float[] array = new float[num];
				int num2 = val.Read(array, 0, num);
				return array[..num2];
			}
			finally
			{
				((IDisposable)val)?.Dispose();
			}
		}

		public static AudioClip CreateAudioClip(float[] samples, int sampleRate, int channels, string name = "GeneratedClip")
		{
			int num = samples.Length / channels;
			AudioClip obj = AudioClip.Create(name, num, channels, sampleRate, true);
			obj.SetData(samples, 0);
			return obj;
		}

		public static AudioClip LoadAudioClipFromFile(string path)
		{
			int sampleRate;
			int channels;
			return CreateAudioClip(LoadAudioFile(path, out sampleRate, out channels), sampleRate, channels);
		}

		public static string GetSHA256Checksum(string filePath)
		{
			using FileStream inputStream = File.OpenRead(filePath);
			using SHA256 sHA = SHA256.Create();
			byte[] array = sHA.ComputeHash(inputStream);
			StringBuilder stringBuilder = new StringBuilder();
			byte[] array2 = array;
			foreach (byte b in array2)
			{
				stringBuilder.Append(b.ToString("x2"));
			}
			return stringBuilder.ToString();
		}

		public static byte[] ToWav(this AudioClip clip)
		{
			float[] array = new float[clip.samples * clip.channels];
			clip.GetData(array, 0);
			byte[] array2 = new byte[array.Length * 2];
			for (int i = 0; i < array.Length; i++)
			{
				byte[] bytes = BitConverter.GetBytes((short)(array[i] * 32767f));
				array2[i * 2] = bytes[0];
				array2[i * 2 + 1] = bytes[1];
			}
			byte[] array3 = new byte[44 + array2.Length];
			byte[] array4 = new byte[40]
			{
				82, 73, 70, 70, 0, 0, 0, 0, 87, 65,
				86, 69, 102, 109, 116, 32, 16, 0, 0, 0,
				1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
				0, 0, 4, 0, 16, 0, 100, 97, 116, 97
			};
			Buffer.BlockCopy(array4, 0, array3, 0, array4.Length);
			Buffer.BlockCopy(BitConverter.GetBytes(36 + array2.Length), 0, array3, 4, 4);
			Buffer.BlockCopy(BitConverter.GetBytes(clip.channels), 0, array3, 22, 2);
			Buffer.BlockCopy(BitConverter.GetBytes(clip.frequency), 0, array3, 24, 4);
			Buffer.BlockCopy(BitConverter.GetBytes(clip.frequency * clip.channels * 2), 0, array3, 28, 4);
			Buffer.BlockCopy(BitConverter.GetBytes(clip.channels * 2), 0, array3, 32, 2);
			Buffer.BlockCopy(BitConverter.GetBytes(array2.Length), 0, array3, 40, 4);
			Buffer.BlockCopy(array2, 0, array3, 44, array2.Length);
			return array3;
		}

		public static void Start()
		{
			StartIndex = 0;
		}

		public static void End()
		{
			StartIndex = 0;
		}

		public static string MeshToString(this MeshFilter mf, Transform t)
		{
			//IL_0001: 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_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: 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_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			_ = t.localScale;
			_ = t.localPosition;
			Quaternion localRotation = t.localRotation;
			int num = 0;
			Mesh sharedMesh = mf.sharedMesh;
			if (!Object.op_Implicit((Object)(object)sharedMesh))
			{
				return "####Error####";
			}
			Material[] sharedMaterials = ((Component)mf).GetComponent<Renderer>().sharedMaterials;
			StringBuilder stringBuilder = new StringBuilder();
			Vector3[] vertices = sharedMesh.vertices;
			foreach (Vector3 val in vertices)
			{
				Vector3 val2 = t.TransformPoint(val);
				num++;
				stringBuilder.Append($"v {val2.x} {val2.y} {0f - val2.z}\n");
			}
			stringBuilder.Append("\n");
			vertices = sharedMesh.normals;
			foreach (Vector3 val3 in vertices)
			{
				Vector3 val4 = localRotation * val3;
				stringBuilder.Append($"vn {0f - val4.x} {0f - val4.y} {val4.z}\n");
			}
			stringBuilder.Append("\n");
			Vector2[] uv = sharedMesh.uv;
			for (int i = 0; i < uv.Length; i++)
			{
				Vector3 val5 = Vector2.op_Implicit(uv[i]);
				stringBuilder.Append($"vt {val5.x} {val5.y}\n");
			}
			for (int j = 0; j < sharedMesh.subMeshCount; j++)
			{
				stringBuilder.Append("\n");
				stringBuilder.Append("usemtl ").Append(((Object)sharedMaterials[j]).name).Append("\n");
				stringBuilder.Append("usemap ").Append(((Object)sharedMaterials[j]).name).Append("\n");
				int[] triangles = sharedMesh.GetTriangles(j);
				for (int k = 0; k < triangles.Length; k += 3)
				{
					stringBuilder.Append(string.Format("f {0}/{0}/{0} {1}/{1}/{1} {2}/{2}/{2}\n", triangles[k] + 1 + StartIndex, triangles[k + 1] + 1 + StartIndex, triangles[k + 2] + 1 + StartIndex));
				}
			}
			StartIndex += num;
			return stringBuilder.ToString();
		}
	}
	[BepInPlugin("triggeredidiot.wkd.resourcefulhands", "Resourceful Hands", "0.9.6")]
	public class Plugin : BaseUnityPlugin
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static UnityAction <0>__ReloadPacks;
		}

		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static Func<UI_TabGroup, bool> <>9__27_0;

			public static UnityAction <>9__27_1;

			public static Action <>9__28_1;

			internal bool <LoadCustomSettings>b__27_0(UI_TabGroup tabGroup)
			{
				return ((Object)tabGroup).name.ToLower() == "tab selection hor";
			}

			internal void <LoadCustomSettings>b__27_1()
			{
				Application.OpenURL("file://" + ConfigFolder.Replace("\\", "/"));
			}

			internal void <Awake>b__28_1()
			{
				SpriteRenderer[] array = Object.FindObjectsByType<SpriteRenderer>((FindObjectsSortMode)0);
				foreach (SpriteRenderer obj in array)
				{
					obj.sprite = obj.sprite;
				}
			}
		}

		[CompilerGenerated]
		private sealed class <>c__DisplayClass27_0
		{
			public UI_TabGroup tabGroup;

			internal void <LoadCustomSettings>b__2()
			{
				tabGroup.SelectTab("packs");
			}
		}

		[CompilerGenerated]
		private sealed class <LoadCustomSettings>d__27 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public UI_SettingsMenu settingsMenu;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <LoadCustomSettings>d__27(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_001d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0027: Expected O, but got Unknown
				//IL_0137: Unknown result type (might be due to invalid IL or missing references)
				//IL_013c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0142: Expected O, but got Unknown
				//IL_0176: Unknown result type (might be due to invalid IL or missing references)
				//IL_017b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0181: Expected O, but got Unknown
				//IL_02e7: Unknown result type (might be due to invalid IL or missing references)
				//IL_02ec: Unknown result type (might be due to invalid IL or missing references)
				//IL_02f3: Unknown result type (might be due to invalid IL or missing references)
				//IL_02fe: Unknown result type (might be due to invalid IL or missing references)
				//IL_0308: Expected O, but got Unknown
				//IL_0315: Unknown result type (might be due to invalid IL or missing references)
				//IL_031f: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = (object)new WaitForSecondsRealtime(1f);
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					RHLog.Info("Loading custom settings menu...", 123, "C:\\Dev\\VSProjects\\ResourcefulHands\\Plugin.cs");
					if ((Object)(object)Assets == (Object)null)
					{
						RHLog.Warning("No assets?", 126, "C:\\Dev\\VSProjects\\ResourcefulHands\\Plugin.cs");
						return false;
					}
					try
					{
						<>c__DisplayClass27_0 CS$<>8__locals0 = new <>c__DisplayClass27_0();
						UI_TabGroup[] componentsInChildren = ((Component)settingsMenu).GetComponentsInChildren<UI_TabGroup>();
						CS$<>8__locals0.tabGroup = ((IEnumerable<UI_TabGroup>)componentsInChildren).FirstOrDefault((Func<UI_TabGroup, bool>)((UI_TabGroup tabGroup) => ((Object)tabGroup).name.ToLower() == "tab selection hor"));
						if ((Object)(object)CS$<>8__locals0.tabGroup != (Object)null)
						{
							GameObject obj = Object.Instantiate<GameObject>(Assets.LoadAsset<GameObject>("Packs"), ((Component)CS$<>8__locals0.tabGroup).transform, false);
							Button componentInChildren = obj.GetComponentInChildren<Button>();
							TextMeshProUGUI componentInChildren2 = obj.GetComponentInChildren<TextMeshProUGUI>();
							GameObject val = Object.Instantiate<GameObject>(Assets.LoadAsset<GameObject>("Pack Settings"), ((Component)CS$<>8__locals0.tabGroup).transform.parent, false);
							ButtonClickedEvent onClick = ((Component)val.transform.Find("Reload")).GetComponentInChildren<Button>().onClick;
							object obj2 = <>O.<0>__ReloadPacks;
							if (obj2 == null)
							{
								UnityAction val2 = ResourcePacksManager.ReloadPacks;
								<>O.<0>__ReloadPacks = val2;
								obj2 = (object)val2;
							}
							((UnityEvent)onClick).AddListener((UnityAction)obj2);
							ButtonClickedEvent onClick2 = ((Component)val.transform.Find("OpenFolder")).GetComponentInChildren<Button>().onClick;
							object obj3 = <>c.<>9__27_1;
							if (obj3 == null)
							{
								UnityAction val3 = delegate
								{
									Application.OpenURL("file://" + ConfigFolder.Replace("\\", "/"));
								};
								<>c.<>9__27_1 = val3;
								obj3 = (object)val3;
							}
							((UnityEvent)onClick2).AddListener((UnityAction)obj3);
							val.AddComponent<UI_RHPacksList>();
							val.SetActive(false);
							for (int i = 0; i < ((Component)CS$<>8__locals0.tabGroup).transform.childCount; i++)
							{
								Transform child = ((Component)CS$<>8__locals0.tabGroup).transform.GetChild(i);
								string text = ((Object)child).name.ToLower();
								if (text.StartsWith("lb") || text.StartsWith("rb"))
								{
									((Component)child).gameObject.SetActive(false);
								}
							}
							Tab val4 = CS$<>8__locals0.tabGroup.tabs.FirstOrDefault();
							if (val4 != null)
							{
								((TMP_Text)componentInChildren2).font = ((TMP_Text)((Component)val4.button).GetComponentInChildren<TextMeshProUGUI>()).font;
								for (int j = 0; j < val4.tabObject.transform.childCount; j++)
								{
									Transform child2 = val4.tabObject.transform.GetChild(j);
									if (((Object)child2).name.ToLower().Contains("title") && Object.op_Implicit((Object)(object)((Component)child2).GetComponentInChildren<TextMeshProUGUI>()))
									{
										TextMeshProUGUI componentInChildren3 = Object.Instantiate<GameObject>(((Component)child2).gameObject, val.transform, true).GetComponentInChildren<TextMeshProUGUI>();
										((TMP_Text)componentInChildren3).text = "PACKS";
										TextMeshProUGUI[] componentsInChildren2 = val.GetComponentsInChildren<TextMeshProUGUI>(true);
										for (int k = 0; k < componentsInChildren2.Length; k++)
										{
											((TMP_Text)componentsInChildren2[k]).font = ((TMP_Text)componentInChildren3).font;
										}
									}
								}
							}
							Tab item = new Tab
							{
								button = componentInChildren,
								name = "packs",
								tabObject = val
							};
							((UnityEvent)componentInChildren.onClick).AddListener((UnityAction)delegate
							{
								CS$<>8__locals0.tabGroup.SelectTab("packs");
							});
							CS$<>8__locals0.tabGroup.tabs.Add(item);
						}
					}
					catch (Exception ex)
					{
						RHLog.Error("Failed to load custom settings menu:\n" + ex.ToString(), 197, "C:\\Dev\\VSProjects\\ResourcefulHands\\Plugin.cs");
					}
					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();
			}
		}

		public const string GUID = "triggeredidiot.wkd.resourcefulhands";

		public const string ModifiedStr = " [modified asset]";

		private static AssetBundle? _assets;

		public static Texture2D? CorruptionTexture;

		public static Texture2D? Icon;

		public static Texture2D? IconGray;

		public static AssetBundle? Assets
		{
			get
			{
				if ((Object)(object)_assets != (Object)null)
				{
					return _assets;
				}
				Assembly executingAssembly = Assembly.GetExecutingAssembly();
				string name = "ResourcefulHands.rh_assets.bundle";
				using Stream stream = executingAssembly.GetManifestResourceStream(name);
				if (stream != null)
				{
					_assets = AssetBundle.LoadFromStream(stream);
				}
				AssetBundle? assets = _assets;
				CorruptionTexture = ((assets != null) ? assets.LoadAsset<Texture2D>("Corruption1") : null);
				AssetBundle? assets2 = _assets;
				Icon = ((assets2 != null) ? assets2.LoadAsset<Texture2D>("icon") : null);
				AssetBundle? assets3 = _assets;
				IconGray = ((assets3 != null) ? assets3.LoadAsset<Texture2D>("gray_icon") : null);
				return _assets;
			}
			private set
			{
				_assets = value;
			}
		}

		public static Plugin Instance { get; private set; }

		internal static ManualLogSource Log { get; private set; }

		public static string ConfigFolder => Path.Combine(Paths.ConfigPath, "RHPacks");

		public static bool IsDemo
		{
			get
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				try
				{
					if (SteamClient.AppId.Value == 3218540)
					{
						return true;
					}
				}
				catch (Exception data)
				{
					RHLog.Error(data, 68, "C:\\Dev\\VSProjects\\ResourcefulHands\\Plugin.cs");
				}
				return false;
			}
		}

		public Harmony? Harmony { get; private set; }

		internal static void RefreshTextures()
		{
			SpriteRendererPatches._customSpriteCache.Clear();
			List<Material> allMaterials = Resources.FindObjectsOfTypeAll<Material>().ToList();
			Renderer[] array = Object.FindObjectsOfType<Renderer>(true);
			foreach (Renderer val in array)
			{
				allMaterials.AddRange(val.sharedMaterials.Where((Material mat) => !allMaterials.Contains(mat)));
			}
			int num = Shader.PropertyToID("_MainTex");
			int num2 = Shader.PropertyToID("_CORRUPTTEXTURE");
			Texture2D textureFromPacks = ResourcePacksManager.GetTextureFromPacks("_CORRUPTTEXTURE");
			foreach (Material item in allMaterials)
			{
				if ((Object)(object)item != (Object)null)
				{
					if (item.HasTexture(num))
					{
						item.mainTexture = item.mainTexture;
					}
					try
					{
						item.SetTexture(num2, (Texture)(object)textureFromPacks);
					}
					catch (Exception data)
					{
						RHLog.Error(data, 100, "C:\\Dev\\VSProjects\\ResourcefulHands\\Plugin.cs");
					}
				}
			}
			SpriteRenderer[] array2 = Object.FindObjectsOfType<SpriteRenderer>(true);
			foreach (SpriteRenderer obj in array2)
			{
				obj.sprite = obj.sprite;
			}
		}

		internal static void RefreshSounds()
		{
			foreach (AudioSource item in Resources.FindObjectsOfTypeAll<AudioSource>().ToList())
			{
				item.clip = item.clip;
			}
			AudioSource[] array = Object.FindObjectsOfType<AudioSource>(true);
			foreach (AudioSource obj in array)
			{
				obj.clip = obj.clip;
			}
		}

		[IteratorStateMachine(typeof(<LoadCustomSettings>d__27))]
		private IEnumerator LoadCustomSettings(UI_SettingsMenu settingsMenu)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <LoadCustomSettings>d__27(0)
			{
				settingsMenu = settingsMenu
			};
		}

		public void Awake()
		{
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			Instance = this;
			RHLog.Info("Setting up config", 205, "C:\\Dev\\VSProjects\\ResourcefulHands\\Plugin.cs");
			if (!Directory.Exists(ConfigFolder))
			{
				Directory.CreateDirectory(ConfigFolder);
			}
			RHConfig.BindConfigs();
			Harmony = new Harmony("triggeredidiot.wkd.resourcefulhands");
			Harmony.PatchAll();
			bool hasLoadedIntro = false;
			SceneManager.sceneLoaded += delegate(Scene scene, LoadSceneMode mode)
			{
				//IL_0007: 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 (!((Scene)(ref scene)).name.ToLower().Contains("intro") && !hasLoadedIntro)
				{
					hasLoadedIntro = true;
					AssetBundle? assets = Assets;
					if (assets != null)
					{
						assets.LoadAllAssets();
					}
					CoroutineDispatcher.AddToUpdate(delegate
					{
						SpriteRenderer[] array = Object.FindObjectsByType<SpriteRenderer>((FindObjectsSortMode)0);
						foreach (SpriteRenderer obj in array)
						{
							obj.sprite = obj.sprite;
						}
					});
					DebugTools.Create();
				}
				if (hasLoadedIntro)
				{
					if (ResourcePacksManager.HasPacksChanged)
					{
						ResourcePacksManager.ReloadPacks_Internal();
					}
					RHCommands.RefreshCommands();
					UI_SettingsMenu val = ((IEnumerable<UI_SettingsMenu>)Object.FindObjectsOfType<UI_SettingsMenu>(true)).FirstOrDefault((Func<UI_SettingsMenu, bool>)((UI_SettingsMenu m) => ((Component)m).gameObject.scene == scene));
					if (Object.op_Implicit((Object)(object)val) && (Object)(object)Assets != (Object)null)
					{
						CoroutineDispatcher.Dispatch(LoadCustomSettings(val));
					}
					RefreshTextures();
					RefreshSounds();
				}
			};
		}
	}
	public static class RHCommands
	{
		public const string DumpCommand = "dumptopack";

		public const string ReloadCommand = "reloadpacks";

		public const string MoveCommand = "reorderpack";

		public const string ListCommand = "listpacks";

		public const string EnableCommand = "enablepack";

		public const string DisableCommand = "disablepack";

		public const string ToggleDebug = "rhtoggledebug";

		public static void RefreshCommands()
		{
			CommandConsole instance = CommandConsole.instance;
			if (Object.op_Implicit((Object)(object)instance))
			{
				CommandConsole.RemoveCommand("dumptopack");
				CommandConsole.RemoveCommand("reloadpacks");
				CommandConsole.RemoveCommand("reorderpack");
				CommandConsole.RemoveCommand("listpacks");
				CommandConsole.RemoveCommand("enablepack");
				CommandConsole.RemoveCommand("disablepack");
				CommandConsole.RemoveCommand("rhtoggledebug");
				instance.RegisterCommand("dumptopack", (Action<string[]>)DumpAllToPack, false);
				instance.RegisterCommand("reloadpacks", (Action<string[]>)ReloadPacks, false);
				instance.RegisterCommand("reorderpack", (Action<string[]>)MovePacks, false);
				instance.RegisterCommand("listpacks", (Action<string[]>)ListPacks, false);
				instance.RegisterCommand("enablepack", (Action<string[]>)EnablePack, false);
				instance.RegisterCommand("disablepack", (Action<string[]>)DisablePack, false);
				instance.RegisterCommand("rhtoggledebug", (Action<string[]>)delegate
				{
					DebugTools.isOn = !DebugTools.isOn;
				}, false);
			}
		}

		internal static void MovePack(TexturePack pack, bool isUp)
		{
			TexturePack pack2 = pack;
			int num = ResourcePacksManager.LoadedPacks.FindIndex((TexturePack p) => p == pack2);
			int num2 = 0;
			num2 = (isUp ? Math.Clamp(num - 1, 0, ResourcePacksManager.LoadedPacks.Count - 1) : Math.Clamp(num + 1, 0, ResourcePacksManager.LoadedPacks.Count - 1));
			try
			{
				TexturePack texturePack = ResourcePacksManager.LoadedPacks[num2];
				TexturePack texturePack2 = ResourcePacksManager.LoadedPacks[num];
				texturePack.GetHashCode();
				texturePack2.GetHashCode();
			}
			catch (ArgumentOutOfRangeException)
			{
				RHLog.Warning("Failed to move packs!", 62, "C:\\Dev\\VSProjects\\ResourcefulHands\\Types\\Commands.cs");
				return;
			}
			TexturePack value = ResourcePacksManager.LoadedPacks[num2];
			ResourcePacksManager.LoadedPacks[num2] = pack2;
			ResourcePacksManager.LoadedPacks[num] = value;
		}

		private static void MovePacks(string[] args)
		{
			if (args.Length != 2)
			{
				RHLog.Player.Error("Invalid number of arguments!");
				RHLog.Player.Info("Usage: reorderpack [pack guid/pack index] [up/down]\nResource packs at the bottom of the loaded list will override textures at the top, use this command to move a texture pack up or down the list.");
				return;
			}
			TexturePack texturePack = null;
			if (int.TryParse(args[0], out var result))
			{
				try
				{
					texturePack = ResourcePacksManager.LoadedPacks[result];
				}
				catch
				{
				}
				if (texturePack == null)
				{
					RHLog.Player.Error($"Invalid first argument!\nThe resource pack at index {result} doesn't exist!");
					RHLog.Player.Info("Usage: reorderpack [pack guid/pack index] [up/down]\nResource packs at the bottom of the loaded list will override textures at the top, use this command to move a texture pack up or down the list.");
					return;
				}
			}
			else
			{
				string packName = args[0].ToLower();
				texturePack = ResourcePacksManager.LoadedPacks.FirstOrDefault((TexturePack p) => p.guid == packName);
				if (texturePack == null)
				{
					RHLog.Player.Error("Invalid first argument!\nThe resource pack with guid '" + packName + "' doesn't exist!");
					RHLog.Player.Info("Usage: reorderpack [pack guid/pack index] [up/down]\nResource packs at the bottom of the loaded list will override textures at the top, use this command to move a texture pack up or down the list.");
					return;
				}
			}
			string text = args[1].ToLower();
			bool flag;
			switch (text)
			{
			case "up":
			case "down":
			case "u":
			case "d":
				flag = true;
				break;
			default:
				flag = false;
				break;
			}
			if (!flag)
			{
				RHLog.Player.Error("Invalid second argument!\nExpected: up or down");
				RHLog.Player.Info("Usage: reorderpack [pack guid/pack index] [up/down]\nResource packs at the bottom of the loaded list will override textures at the top, use this command to move a texture pack up or down the list.");
				return;
			}
			flag = ((text == "up" || text == "u") ? true : false);
			bool flag2 = flag;
			MovePack(texturePack, flag2);
			RHLog.Player.Info("Reloading packs...");
			ResourcePacksManager.ReloadPacks_Internal();
			RHLog.Player.Info(string.Format("Moved {0} {1}{2}{3} {4} successfully!", texturePack.name, '{', texturePack.guid, '}', flag2 ? "up" : "down"));
		}

		private static void ListPacks(string[] args)
		{
			for (int i = 0; i < ResourcePacksManager.LoadedPacks.Count; i++)
			{
				TexturePack texturePack = ResourcePacksManager.LoadedPacks[i];
				RHLog.Player.Info(((!texturePack.IsActive) ? "[DISABLED] " : $"[{i}] ") + texturePack.name + " by " + texturePack.author + "\n-- description:\n" + texturePack.desc + "\n-- guid: '" + texturePack.guid + "'\n____");
			}
		}

		private static void ReloadPacks(string[] args)
		{
			ResourcePacksManager.ReloadPacks_Internal();
			RHLog.Player.Info("Resource packs reloaded successfully!");
		}

		private static TexturePack? GetPackFromArgs(string[] args, Action<string> logErr)
		{
			TexturePack texturePack = null;
			if (int.TryParse(args[0], out var result))
			{
				try
				{
					texturePack = ResourcePacksManager.LoadedPacks[result];
				}
				catch
				{
				}
				if (texturePack == null)
				{
					logErr($"Invalid first argument!\nThe resource pack at index {result} doesn't exist!");
					return null;
				}
			}
			else
			{
				string packName = args[0].ToLower();
				texturePack = ResourcePacksManager.LoadedPacks.FirstOrDefault((TexturePack p) => p.guid.ToLower() == packName);
				if (texturePack == null)
				{
					logErr("Invalid first argument!\nThe resource pack with guid '" + packName + "' doesn't exist!");
					return null;
				}
			}
			return texturePack;
		}

		private static void DisablePack(string[] args)
		{
			TexturePack packFromArgs = GetPackFromArgs(args, RHLog.Player.Error);
			if (packFromArgs == null)
			{
				RHLog.Player.Info("Usage: disablepack [pack guid/pack index]\nDisables a resource pack.");
				return;
			}
			packFromArgs.IsActive = false;
			RHLog.Player.Info("Reloading packs...");
			ResourcePacksManager.ReloadPacks_Internal();
			RHLog.Player.Info($"Disabled {packFromArgs.name} {'{'}{packFromArgs.guid}{'}'} successfully!");
		}

		private static void EnablePack(string[] args)
		{
			TexturePack packFromArgs = GetPackFromArgs(args, RHLog.Player.Error);
			if (packFromArgs == null)
			{
				RHLog.Player.Info("Usage: enablepack [pack guid/pack index]\nEnables a resource pack.");
				return;
			}
			packFromArgs.IsActive = true;
			RHLog.Player.Info("Reloading packs...");
			ResourcePacksManager.ReloadPacks_Internal();
			RHLog.Player.Info($"Enabled {packFromArgs.name} {'{'}{packFromArgs.guid}{'}'} successfully!");
		}

		private static void DumpAllToPack(string[] args)
		{
			if (args.Any((string arg) => arg.ToLower() == "help"))
			{
				RHLog.Player.Info("Use this command to generate a resource pack that contains every in-game asset. Good to find assets to replace but beware that there will probably be unused assets!");
				return;
			}
			if (!args.Any((string arg) => arg.ToLower() == "confirm"))
			{
				RHLog.Player.Error("Warning: This takes up alot of storage space due to uncompressed audio!\nTHIS WILL ALSO END YOUR RUN AND LOAD YOU BACK TO THE MAIN MENU!!\nARE YOU SURE? (type 'dumptopack confirm')");
				return;
			}
			RHLog.Player.Info("Dumping all resources to a template texture pack [this will take some time]...");
			List<Texture2D> textures = new List<Texture2D>();
			List<Texture2D> spriteTextures = new List<Texture2D>();
			List<AudioClip> sounds = new List<AudioClip>();
			Texture2D[] source = Resources.FindObjectsOfTypeAll<Texture2D>();
			textures.AddRange(source.Where((Texture2D tex) => !textures.Contains(tex)));
			AudioClip[] source2 = Resources.FindObjectsOfTypeAll<AudioClip>();
			sounds.AddRange(source2.Where((AudioClip sound) => !sounds.Contains(sound)));
			Sprite[] source3 = Resources.FindObjectsOfTypeAll<Sprite>();
			spriteTextures.AddRange(from sprite in source3
				where Object.op_Implicit((Object)(object)sprite.texture) && !spriteTextures.Contains(sprite.texture)
				select sprite.texture);
			RHLog.Player.Info("Loading Playground [to extract assets]");
			SceneManager.LoadScene("Playground");
			source = Resources.FindObjectsOfTypeAll<Texture2D>();
			textures.AddRange(source.Where((Texture2D tex) => !textures.Contains(tex)));
			source2 = Resources.FindObjectsOfTypeAll<AudioClip>();
			sounds.AddRange(source2.Where((AudioClip sound) => !sounds.Contains(sound)));
			source3 = Resources.FindObjectsOfTypeAll<Sprite>();
			spriteTextures.AddRange(from sprite in source3
				where Object.op_Implicit((Object)(object)sprite.texture) && !spriteTextures.Contains(sprite.texture)
				select sprite.texture);
			RHLog.Player.Info("Loading Training-Level [to extract assets]");
			SceneManager.LoadScene("Training-Level");
			source = Resources.FindObjectsOfTypeAll<Texture2D>();
			textures.AddRange(source.Where((Texture2D tex) => !textures.Contains(tex)));
			source2 = Resources.FindObjectsOfTypeAll<AudioClip>();
			sounds.AddRange(source2.Where((AudioClip sound) => !sounds.Contains(sound)));
			source3 = Resources.FindObjectsOfTypeAll<Sprite>();
			spriteTextures.AddRange(from sprite in source3
				where Object.op_Implicit((Object)(object)sprite.texture) && !spriteTextures.Contains(sprite.texture)
				select sprite.texture);
			RHLog.Player.Info("Loading Main-Menu [to extract assets and finish]");
			SceneManager.LoadScene("Main-Menu");
			source = Resources.FindObjectsOfTypeAll<Texture2D>();
			textures.AddRange(source.Where((Texture2D tex) => !textures.Contains(tex)));
			source2 = Resources.FindObjectsOfTypeAll<AudioClip>();
			sounds.AddRange(source2.Where((AudioClip sound) => !sounds.Contains(sound)));
			source3 = Resources.FindObjectsOfTypeAll<Sprite>();
			spriteTextures.AddRange(from sprite in source3
				where Object.op_Implicit((Object)(object)sprite.texture) && !spriteTextures.Contains(sprite.texture)
				select sprite.texture);
			RHLog.Player.Info("Packing assets...");
			int count = textures.Count;
			int count2 = spriteTextures.Count;
			int count3 = sounds.Count;
			string text = Path.Combine(Plugin.ConfigFolder, $"extracted-assets-{count + count3 + count2}-{DateTimeOffset.UtcNow.ToUnixTimeSeconds()}");
			if (!Directory.Exists(text))
			{
				Directory.CreateDirectory(text);
			}
			string texturesPath = Path.Combine(text, "Textures");
			string path = Path.Combine(texturesPath, "Sprites");
			string text2 = Path.Combine(text, "Sounds");
			if (!Directory.Exists(texturesPath))
			{
				Directory.CreateDirectory(texturesPath);
			}
			if (!Directory.Exists(path))
			{
				Directory.CreateDirectory(path);
			}
			if (!Directory.Exists(text2))
			{
				Directory.CreateDirectory(text2);
			}
			StringBuilder stringBuilder = new StringBuilder();
			StringBuilder stringBuilder2 = new StringBuilder();
			StringBuilder stringBuilder3 = new StringBuilder();
			stringBuilder.AppendLine("-- ingame textures list --");
			stringBuilder2.AppendLine("-- ingame sprite textures list --");
			stringBuilder3.AppendLine("-- ingame sounds list --");
			int num = 0;
			int num2 = 0;
			int num3 = 0;
			for (int i = 0; i < count; i++)
			{
				Texture2D val = textures[i];
				RHLog.Player.Info($"Saving textures ({i}/{count})");
				stringBuilder.Append(((Object)val).name);
				bool flag = false;
				try
				{
					flag = ExportTexture(val);
				}
				catch (Exception ex)
				{
					RHLog.Player.Error(((Object)val).name + " failed because " + ex.Message);
				}
				if (flag)
				{
					num++;
				}
				stringBuilder.AppendLine(flag ? "" : " [failed to extract]");
			}
			for (int j = 0; j < count2; j++)
			{
				Texture2D val2 = spriteTextures[j];
				RHLog.Player.Info($"Saving textures ({j}/{count2})");
				stringBuilder2.Append(((Object)val2).name);
				bool flag2 = false;
				try
				{
					flag2 = ExportTexture(val2);
				}
				catch (Exception ex2)
				{
					RHLog.Player.Error(((Object)val2).name + " failed because " + ex2.Message);
				}
				if (flag2)
				{
					num3++;
				}
				stringBuilder2.AppendLine(flag2 ? "" : " [failed to extract]");
			}
			for (int k = 0; k < count3; k++)
			{
				AudioClip val3 = sounds[k];
				RHLog.Player.Info($"Saving sounds ({k}/{count3})");
				stringBuilder3.Append(((Object)val3).name);
				bool flag3 = false;
				try
				{
					string path2 = Path.Combine(text2, ((Object)val3).name + ".wav");
					float[] array = new float[val3.samples * val3.channels];
					if (!val3.GetData(array, 0))
					{
						RHLog.Player.Error("Failed to access " + ((Object)val3).name + "'s audio data!");
						stringBuilder3.AppendLine(" [failed to extract]");
						continue;
					}
					using (FileStream stream = new FileStream(path2, FileMode.CreateNew, FileAccess.Write))
					{
						ushort num4 = 16;
						string value = "RIFF";
						string value2 = "WAVE";
						string value3 = "fmt ";
						uint value4 = 16u;
						ushort value5 = 1;
						ushort num5 = (ushort)val3.channels;
						uint frequency = (uint)val3.frequency;
						uint value6 = (uint)(frequency * val3.channels * num4 / 8);
						ushort value7 = (ushort)(num5 * num4 / 8);
						string value8 = "data";
						uint num6 = (uint)(array.Length * val3.channels * num4 / 8);
						uint value9 = 36 + num6;
						stream.WriteString(value);
						stream.WriteInteger(value9);
						stream.WriteString(value2);
						stream.WriteString(value3);
						stream.WriteInteger(value4);
						stream.WriteShort(value5);
						stream.WriteShort(num5);
						stream.WriteInteger(frequency);
						stream.WriteInteger(value6);
						stream.WriteShort(value7);
						stream.WriteShort(num4);
						stream.WriteString(value8);
						stream.WriteInteger(num6);
						float[] array2 = array;
						foreach (float num7 in array2)
						{
							short num8 = 0;
							if (num7 > 0f)
							{
								float num9 = num7 * 32767f;
								if (num9 > 32767f)
								{
									num9 = 32767f;
								}
								num8 = (short)num9;
							}
							if (num7 < 0f)
							{
								float num10 = num7 * 32768f;
								if (num10 < -32768f)
								{
									num10 = -32768f;
								}
								num8 = (short)num10;
							}
							stream.WriteShort((ushort)num8);
						}
						num2++;
						flag3 = true;
					}
					goto IL_07d9;
				}
				catch (Exception ex3)
				{
					RHLog.Player.Info(((Object)val3).name + " failed because " + ex3.Message);
					goto IL_07d9;
				}
				IL_07d9:
				stringBuilder3.AppendLine(flag3 ? "" : " [failed to extract]");
			}
			RHLog.Player.Info("Writing data files");
			File.WriteAllText(Path.Combine(text, "info.json"), "{\r\n    \"name\":\"generated-game-assets\",\r\n    \"desc\":\"Every game asset\",\r\n    \r\n    \"author\":\"Dark Machine Games\",\r\n    \"steamid\":0,\r\n    \r\n    \"guid\":\"generated-game-assets\",\r\n    \r\n    \"hidden-from-list\":true,\r\n    \"only-in-full-game\":false,\r\n    \r\n    \"textures-folder\":\"Textures\",\r\n    \"sounds-folder\":\"Sounds\",\r\n    \"icon-file\":\"pack.png\",\r\n    \r\n    \"format-version\":2\r\n}                                                           ");
			File.WriteAllText(Path.Combine(text, "textures_list.txt"), stringBuilder.ToString());
			File.WriteAllText(Path.Combine(text, "sprite_textures_list.txt"), stringBuilder2.ToString());
			File.WriteAllText(Path.Combine(text, "audio_list.txt"), stringBuilder3.ToString());
			RHLog.Player.Info($"Successfully saved {num} of {count} textures!");
			RHLog.Player.Info($"Successfully saved {num3} of {count2} sprite textures!");
			RHLog.Player.Info($"Successfully saved {num2} of {count3} sounds!");
			RHLog.Player.Info("Packed all assets to '" + text + "'");
			bool ExportTexture(Texture2D texture)
			{
				//IL_0031: Unknown result type (might be due to invalid IL or missing references)
				//IL_0037: Expected O, but got Unknown
				//IL_0064: 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_006f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0088: Unknown result type (might be due to invalid IL or missing references)
				//IL_0094: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a5: Expected O, but got Unknown
				bool result = false;
				try
				{
					if (!((Texture)texture).isReadable)
					{
						RHLog.Player.Info(((Object)texture).name + " isn't readable, saving the slow way...");
						RenderTexture val4 = new RenderTexture(((Texture)texture).width, ((Texture)texture).height, 24);
						RenderTexture active = RenderTexture.active;
						try
						{
							RenderTexture.active = val4;
							Graphics.Blit((Texture)(object)texture, val4);
							RenderTexture val6 = (RenderTexture.active = val4.ConvertToARGB32());
							Texture2D val7 = new Texture2D(((Texture)texture).width, ((Texture)texture).height, texture.format, false);
							val7.ReadPixels(new Rect(0f, 0f, (float)((Texture)texture).width, (float)((Texture)texture).height), 0, 0);
							val7.Apply();
							val6.Release();
							byte[] bytes = ImageConversion.EncodeToPNG(val7);
							File.WriteAllBytes(Path.Combine(texturesPath, ((Object)texture).name + ".png"), bytes);
							result = true;
						}
						catch
						{
						}
						RenderTexture.active = active;
						val4.Release();
					}
					else
					{
						byte[] bytes2 = ImageConversion.EncodeToPNG(texture);
						File.WriteAllBytes(Path.Combine(texturesPath, ((Object)texture).name + ".png"), bytes2);
						result = true;
					}
				}
				catch (Exception ex4)
				{
					RHLog.Player.Error(((Object)texture).name + " failed because " + ex4.Message);
				}
				return result;
			}
		}
	}
	public static class RHConfig
	{
		internal static ConfigEntry<bool>? LoadFullAudio;

		internal static ConfigEntry<bool>? AlwaysDebug;

		internal static ConfigEntry<bool>? LazyManip;

		internal static void BindConfigs()
		{
			LoadFullAudio = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<bool>("General", "Load entire audio file", false, "When enabled every audio file is always fully loaded, this can reduce stutters but will slow down loading.");
			AlwaysDebug = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<bool>("General", "Always debug mode", false, "When enabled pack debug mode is always enabled unless toggled via the command (rhtoggledebug).");
			LazyManip = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<bool>("General", "Lazy Loading", true, "When enabled every pack doesn't get reloaded when reordering or enabling/disabling packs in the settings menu.");
		}
	}
	public class CoroutineDispatcher : MonoBehaviour
	{
		private static CoroutineDispatcher? _instance;

		private static Dictionary<string, Action> updateActions = new Dictionary<string, Action>();

		public static void Dispatch(IEnumerator routine)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_instance == (Object)null)
			{
				_instance = new GameObject("CoroutineDispatcher").AddComponent<CoroutineDispatcher>();
				Object.DontDestroyOnLoad((Object)(object)_instance);
			}
			((MonoBehaviour)_instance).StartCoroutine(routine);
		}

		public static string AddToUpdate(Action action)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_instance == (Object)null)
			{
				_instance = new GameObject("CoroutineDispatcher").AddComponent<CoroutineDispatcher>();
				Object.DontDestroyOnLoad((Object)(object)_instance);
			}
			string text = Guid.NewGuid().ToString();
			updateActions.Add(text, action);
			return text;
		}

		public static void RemoveFromUpdate(string guid)
		{
			if (updateActions.ContainsKey(guid))
			{
				updateActions.Remove(guid);
			}
		}

		public void LateUpdate()
		{
			foreach (Action value in updateActions.Values)
			{
				value();
			}
		}
	}
	public class DebugTools : MonoBehaviour
	{
		[CompilerGenerated]
		private sealed class <_queueSound>d__7 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public bool force;

			public AudioClip clip;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <_queueSound>d__7(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0049: Unknown result type (might be due to invalid IL or missing references)
				//IL_0053: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					if (!force && _playingClips.Contains(clip))
					{
						return false;
					}
					_playingClips.Add(clip);
					<>2__current = (object)new WaitForSeconds(1f);
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					if (Object.op_Implicit((Object)(object)clip))
					{
						_playingClips.Remove(clip);
					}
					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();
			}
		}

		public static DebugTools? Instance;

		public static bool isOn = false;

		private static List<AudioClip> _playingClips = new List<AudioClip>();

		private GUIStyle _style = GUIStyle.none;

		private bool _enableNextFrame;

		internal static void Create()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			Instance = new GameObject("DebugTools").AddComponent<DebugTools>();
			Object.DontDestroyOnLoad((Object)(object)Instance);
		}

		public static void QueueSound(AudioClip clip, bool force = false)
		{
			CoroutineDispatcher.Dispatch(_queueSound(clip, force));
		}

		[IteratorStateMachine(typeof(<_queueSound>d__7))]
		private static IEnumerator _queueSound(AudioClip clip, bool force)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <_queueSound>d__7(0)
			{
				clip = clip,
				force = force
			};
		}

		public void Awake()
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: 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_0034: 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_003a: 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: Expected O, but got Unknown
			//IL_004f: Expected O, but got Unknown
			Instance = this;
			ConfigEntry<bool>? alwaysDebug = RHConfig.AlwaysDebug;
			if (alwaysDebug != null && alwaysDebug.Value)
			{
				isOn = true;
			}
			_style = new GUIStyle
			{
				fontSize = 32,
				fontStyle = (FontStyle)1,
				normal = new GUIStyleState
				{
					textColor = Color.white
				}
			};
			SceneManager.sceneUnloaded += delegate
			{
				_enableNextFrame |= isOn;
				isOn = false;
			};
			SceneManager.sceneLoaded += delegate(Scene arg0, LoadSceneMode mode)
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				if ((int)mode == 0)
				{
					_playingClips.Clear();
					_enableNextFrame |= isOn;
					isOn = false;
				}
			};
		}

		public void OnGUI()
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: 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)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			if (!isOn)
			{
				return;
			}
			Color contentColor = GUI.contentColor;
			GUI.contentColor = Color.white;
			GUILayout.Label("Recent sounds:", _style, Array.Empty<GUILayoutOption>());
			foreach (AudioClip playingClip in _playingClips)
			{
				GUILayout.Label(((Object)playingClip).name, _style, Array.Empty<GUILayoutOption>());
			}
			GUI.contentColor = contentColor;
		}

		public void LateUpdate()
		{
			if (_enableNextFrame)
			{
				isOn = true;
				_enableNextFrame = false;
			}
		}
	}
	[HarmonyPatch(typeof(AudioSource))]
	[HarmonyPriority(200)]
	public static class DEBUG_AudioSourcePatches
	{
		[HarmonyPatch("set_clip")]
		[HarmonyPostfix]
		private static void Setter_Postfix(AudioSource __instance, ref AudioClip value)
		{
			if (DebugTools.isOn && !((Object)(object)value == (Object)null) && (__instance.isPlaying || (__instance.playOnAwake && Time.timeSinceLevelLoad <= 0.25f)))
			{
				DebugTools.QueueSound(value);
			}
		}

		[HarmonyPatch("get_clip")]
		[HarmonyPostfix]
		private static void Getter_Postfix(AudioSource __instance, ref AudioClip __result)
		{
			if (DebugTools.isOn && !((Object)(object)__result == (Object)null) && (__instance.isPlaying || (__instance.playOnAwake && Time.timeSinceLevelLoad <= 0.25f)))
			{
				DebugTools.QueueSound(__result);
			}
		}

		[HarmonyPatch("Play", new Type[] { typeof(double) })]
		[HarmonyPostfix]
		private static void Play_Prefix(AudioSource __instance, double delay)
		{
			if (DebugTools.isOn && !((Object)(object)__instance.clip == (Object)null))
			{
				DebugTools.QueueSound(__instance.clip);
			}
		}

		[HarmonyPatch("PlayHelper", new Type[]
		{
			typeof(AudioSource),
			typeof(ulong)
		})]
		[HarmonyPostfix]
		private static void PlayHelper_Prefix(AudioSource source, ulong delay)
		{
			if (DebugTools.isOn && !((Object)(object)source.clip == (Object)null))
			{
				DebugTools.QueueSound(source.clip);
			}
		}
	}
	public static class RHLog
	{
		public static class Player
		{
			public static void Message(string message, bool printToConsole = true)
			{
				CommandConsole.Log("[Resourceful Hands] " + message, printToConsole);
			}

			public static void Info(string message, bool printToConsole = true)
			{
				Message(message, printToConsole);
			}

			public static void Warning(string message, bool printToConsole = true)
			{
				CommandConsole.Log("[Resourceful Hands] [WARNING] " + message, printToConsole);
			}

			public static void Error(string message)
			{
				CommandConsole.LogError("[Resourceful Hands] " + message);
			}
		}

		private const string Prefix = "[Resourceful Hands] ";

		[Conditional("DEBUG")]
		public static void Debug(object data, [CallerLineNumber] int lineNumber = 0, [CallerFilePath] string file = "")
		{
			Plugin.Log.LogInfo((object)$"[{Path.GetFileName(file)}:{lineNumber}] {data}");
		}

		public static void Info(object data, [CallerLineNumber] int lineNumber = 0, [CallerFilePath] string file = "")
		{
			Plugin.Log.LogInfo((object)$"[{Path.GetFileName(file)}:{lineNumber}] {data}");
		}

		public static void Message(object data, [CallerLineNumber] int lineNumber = 0, [CallerFilePath] string file = "")
		{
			Plugin.Log.LogMessage((object)$"[{Path.GetFileName(file)}:{lineNumber}] {data}");
		}

		public static void Warning(object data, [CallerLineNumber] int lineNumber = 0, [CallerFilePath] string file = "")
		{
			Plugin.Log.LogWarning((object)$"[{Path.GetFileName(file)}:{lineNumber}] {data}");
		}

		public static void Error(object data, [CallerLineNumber] int lineNumber = 0, [CallerFilePath] string file = "")
		{
			Plugin.Log.LogError((object)$"[{Path.GetFileName(file)}:{lineNumber}] {data}");
		}
	}
	public static class ResourcePacksManager
	{
		public static bool HasPacksChanged = true;

		public const string PackPrefsName = "__ResourcefulHands_Mod_PackOrder";

		public const string DisabledPacksPrefsName = "__ResourcefulHands_Mod_DisabledPacks";

		public static List<TexturePack> LoadedPacks { get; internal set; } = new List<TexturePack>();


		public static TexturePack[] ActivePacks => LoadedPacks.Where((TexturePack pack) => pack.IsActive).ToArray();

		public static Texture2D? GetTextureFromPacks(string textureName)
		{
			Texture2D val = null;
			TexturePack[] activePacks = ActivePacks;
			for (int i = 0; i < activePacks.Length; i++)
			{
				Texture2D texture = activePacks[i].GetTexture(textureName);
				if ((Object)(object)texture != (Object)null)
				{
					val = texture;
				}
			}
			if (Object.op_Implicit((Object)(object)val))
			{
				return val;
			}
			if (textureName == "DeathFloor_02" || textureName == "_CORRUPTTEXTURE")
			{
				return Plugin.CorruptionTexture;
			}
			return null;
		}

		public static AudioClip? GetSoundFromPacks(string soundName)
		{
			AudioClip result = null;
			TexturePack[] activePacks = ActivePacks;
			for (int i = 0; i < activePacks.Length; i++)
			{
				AudioClip sound = activePacks[i].GetSound(soundName);
				if ((Object)(object)sound != (Object)null)
				{
					result = sound;
				}
			}
			return result;
		}

		internal static void SaveDisabledPacks()
		{
			List<string> list = new List<string>();
			foreach (TexturePack loadedPack in LoadedPacks)
			{
				if (!loadedPack.IsActive)
				{
					list.Add(loadedPack.guid);
				}
			}
			string text = JsonConvert.SerializeObject((object)list.ToArray());
			PlayerPrefs.SetString("__ResourcefulHands_Mod_DisabledPacks", text);
		}

		internal static void LoadDisabledPacks()
		{
			string @string = PlayerPrefs.GetString("__ResourcefulHands_Mod_DisabledPacks", "");
			if (string.IsNullOrWhiteSpace(@string))
			{
				return;
			}
			string[] array = JsonConvert.DeserializeObject<string[]>(@string);
			if (array == null || array.Length == 0)
			{
				return;
			}
			string[] array2 = array;
			foreach (string disabledPackGuid in array2)
			{
				foreach (TexturePack item in LoadedPacks.Where((TexturePack pack) => pack.guid == disabledPackGuid))
				{
					item.IsActive = false;
				}
			}
		}

		internal static void SavePackOrder()
		{
			string[] array = new string[LoadedPacks.Count];
			for (int i = 0; i < LoadedPacks.Count; i++)
			{
				TexturePack texturePack = LoadedPacks[i];
				array[i] = texturePack.guid;
			}
			string text = JsonConvert.SerializeObject((object)array);
			PlayerPrefs.SetString("__ResourcefulHands_Mod_PackOrder", text);
		}

		internal static void LoadPackOrder()
		{
			string @string = PlayerPrefs.GetString("__ResourcefulHands_Mod_PackOrder", "");
			if (string.IsNullOrWhiteSpace(@string))
			{
				return;
			}
			string[] array = JsonConvert.DeserializeObject<string[]>(@string);
			if (array == null)
			{
				return;
			}
			TexturePack[] array2 = LoadedPacks.ToArray();
			TexturePack[] array3 = new TexturePack[array.Length];
			for (int i = 0; i < array3.Length; i++)
			{
				array3[i] = null;
			}
			for (int j = 0; j < array.Length; j++)
			{
				string guid = array[j];
				TexturePack texturePack = array2.FirstOrDefault((TexturePack p) => p.guid == guid);
				if (texturePack != null)
				{
					array3[j] = texturePack;
				}
			}
			List<TexturePack> list = new List<TexturePack>();
			TexturePack[] array4 = array3;
			foreach (TexturePack texturePack2 in array4)
			{
				if (texturePack2 != null)
				{
					list.Add(texturePack2);
				}
			}
			array4 = array2;
			foreach (TexturePack item in array4)
			{
				if (!list.Contains(item))
				{
					list.Add(item);
				}
			}
			LoadedPacks = list;
			SavePackOrder();
		}

		public static void ReloadPacks()
		{
			ReloadPacks_Internal();
		}

		internal static void ReloadPacks_Internal()
		{
			HasPacksChanged = false;
			if (LoadedPacks.Count != 0)
			{
				SavePackOrder();
				SaveDisabledPacks();
			}
			LoadedPacks.Clear();
			RHLog.Info("Expanding zips...", 137, "C:\\Dev\\VSProjects\\ResourcefulHands\\Types\\ResourcePacksManager.cs");
			string[] files = Directory.GetFiles(Plugin.ConfigFolder, "*.zip", SearchOption.TopDirectoryOnly);
			foreach (string text in files)
			{
				try
				{
					RHLog.Info("Expanding texture pack zip: " + text, 143, "C:\\Dev\\VSProjects\\ResourcefulHands\\Types\\ResourcePacksManager.cs");
					bool flag = true;
					using (ZipArchive zipArchive = ZipFile.OpenRead(text))
					{
						flag = zipArchive.GetEntry("info.json") != null;
					}
					if (flag)
					{
						DirectoryInfo directoryInfo = Directory.CreateDirectory(Path.Combine(Plugin.ConfigFolder, Path.GetFileNameWithoutExtension(text)));
						ZipFile.ExtractToDirectory(text, directoryInfo.FullName);
					}
					else
					{
						ZipFile.ExtractToDirectory(text, Plugin.ConfigFolder);
					}
					File.Delete(text);
					RHLog.Info("Expanded!", 157, "C:\\Dev\\VSProjects\\ResourcefulHands\\Types\\ResourcePacksManager.cs");
				}
				catch (Exception data)
				{
					RHLog.Info("Failed to expand!", 161, "C:\\Dev\\VSProjects\\ResourcefulHands\\Types\\ResourcePacksManager.cs");
					RHLog.Error(data, 162, "C:\\Dev\\VSProjects\\ResourcefulHands\\Types\\ResourcePacksManager.cs");
				}
			}
			RHLog.Info("Loading texture packs...", 165, "C:\\Dev\\VSProjects\\ResourcefulHands\\Types\\ResourcePacksManager.cs");
			List<string> list = new List<string>();
			list.AddRange(Directory.GetDirectories(Plugin.ConfigFolder, "*", SearchOption.TopDirectoryOnly));
			list.AddRange(Directory.GetDirectories(Paths.PluginPath, "*", SearchOption.TopDirectoryOnly));
			foreach (string item in list)
			{
				if (!File.Exists(Path.Combine(item, "info.json")))
				{
					continue;
				}
				try
				{
					RHLog.Info("Loading texture pack: " + item, 178, "C:\\Dev\\VSProjects\\ResourcefulHands\\Types\\ResourcePacksManager.cs");
					TexturePack texturePack = TexturePack.Load(item);
					if (texturePack == null)
					{
						RHLog.Warning("Failed to load pack at " + item + "!", 182, "C:\\Dev\\VSProjects\\ResourcefulHands\\Types\\ResourcePacksManager.cs");
						continue;
					}
					LoadedPacks.Add(texturePack);
					RHLog.Info("Loaded!", 187, "C:\\Dev\\VSProjects\\ResourcefulHands\\Types\\ResourcePacksManager.cs");
				}
				catch (Exception data2)
				{
					RHLog.Info("Failed to load!", 191, "C:\\Dev\\VSProjects\\ResourcefulHands\\Types\\ResourcePacksManager.cs");
					RHLog.Error(data2, 192, "C:\\Dev\\VSProjects\\ResourcefulHands\\Types\\ResourcePacksManager.cs");
				}
			}
			RHLog.Info("Re-ordering to user order...", 196, "C:\\Dev\\VSProjects\\ResourcefulHands\\Types\\ResourcePacksManager.cs");
			LoadPackOrder();
			RHLog.Info("Disabling packs that should be disabled...", 198, "C:\\Dev\\VSProjects\\ResourcefulHands\\Types\\ResourcePacksManager.cs");
			LoadDisabledPacks();
			RHLog.Info($"Loaded {LoadedPacks.Count}/{list.Count} texture packs", 201, "C:\\Dev\\VSProjects\\ResourcefulHands\\Types\\ResourcePacksManager.cs");
			Plugin.RefreshTextures();
			Plugin.RefreshSounds();
			if ((Object)(object)UI_RHPacksList.Instance != (Object)null)
			{
				UI_RHPacksList.Instance?.BuildList();
			}
		}
	}
	public class StreamedAudioClip
	{
		private int _position;

		private int _sampleRate;

		private int _channels;

		private float[] _samples = Array.Empty<float>();

		public AudioClip clip { get; private set; }

		public string path { get; private set; }

		public StreamedAudioClip(string fileName)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Expected O, but got Unknown
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Expected O, but got Unknown
			//IL_0099: Expected O, but got Unknown
			path = fileName;
			int num = 0;
			AudioFileReader val = new AudioFileReader(path);
			try
			{
				_sampleRate = ((WaveStream)val).WaveFormat.SampleRate;
				_channels = ((WaveStream)val).WaveFormat.Channels;
				num = (int)(((Stream)(object)val).Length / 4);
			}
			finally
			{
				((IDisposable)val)?.Dispose();
			}
			int num2 = num / _channels;
			clip = AudioClip.Create("MemoryStreamedAudioClip", num2, _channels, _sampleRate, true, new PCMReaderCallback(OnAudioRead), new PCMSetPositionCallback(OnAudioSetPosition));
			ConfigEntry<bool>? loadFullAudio = RHConfig.LoadFullAudio;
			if (loadFullAudio != null && loadFullAudio.Value)
			{
				LoadFile();
			}
		}

		public void LoadFile()
		{
			int sampleRate;
			int channels;
			float[] samples = MiscUtils.LoadAudioFile(path, out sampleRate, out channels);
			_sampleRate = sampleRate;
			_channels = channels;
			_samples = samples;
		}

		private void OnAudioRead(float[] data)
		{
			if (_samples.Length == 0)
			{
				LoadFile();
			}
			int num = data.Length;
			int num2 = _samples.Length - _position;
			int num3 = Mathf.Min(num, num2);
			Array.Copy(_samples, _position, data, 0, num3);
			for (int i = num3; i < num; i++)
			{
				data[i] = 0f;
			}
			_position += num3;
		}

		private void OnAudioSetPosition(int newPosition)
		{
			_position = newPosition;
		}
	}
	[Serializable]
	public class TexturePack
	{
		public string name = string.Empty;

		public string desc = string.Empty;

		public string author = string.Empty;

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public ulong steamid;

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public string guid = string.Empty;

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public bool hiddenFromList;

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public bool onlyInFullGame;

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public string relativeTexturesPath = "Textures";

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public string relativeSoundsPath = "Sounds";

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public string relativeIconPath = "pack.png";

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public int texturePackVersion = 2;

		[NonSerialized]
		[JsonIgnore]
		public const int CurrentFormatVersion = 2;

		[NonSerialized]
		[JsonIgnore]
		public bool IsActive = true;

		[NonSerialized]
		[JsonIgnore]
		public Dictionary<string, Texture2D> Textures = new Dictionary<string, Texture2D>();

		[NonSerialized]
		[JsonIgnore]
		public Dictionary<string, AudioClip> Sounds = new Dictionary<string, AudioClip>();

		[NonSerialized]
		[JsonIgnore]
		protected List<StreamedAudioClip> RawSounds = new List<StreamedAudioClip>();

		[NonSerialized]
		[JsonIgnore]
		public const string DefaultJson = "{\r\n    \"name\":\"generated-game-assets\",\r\n    \"desc\":\"Every game asset\",\r\n    \r\n    \"author\":\"Dark Machine Games\",\r\n    \"steamid\":0,\r\n    \r\n    \"guid\":\"generated-game-assets\",\r\n    \r\n    \"hidden-from-list\":true,\r\n    \"only-in-full-game\":false,\r\n    \r\n    \"textures-folder\":\"Textures\",\r\n    \"sounds-folder\":\"Sounds\",\r\n    \"icon-file\":\"pack.png\",\r\n    \r\n    \"format-version\":2\r\n}                                                           ";

		[JsonIgnore]
		public Texture2D Icon { get; private set; }

		public Texture2D? GetTexture(string textureName)
		{
			Textures.TryGetValue(textureName, out Texture2D value);
			return value;
		}

		public AudioClip? GetSound(string soundName)
		{
			Sounds.TryGetValue(soundName, out AudioClip value);
			return value;
		}

		public static TexturePack? Load(string path, bool force = false)
		{
			//IL_0390: Unknown result type (might be due to invalid IL or missing references)
			//IL_0397: Expected O, but got Unknown
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Expected O, but got Unknown
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			string text = Path.Combine(path, "info.json");
			if (!File.Exists(text))
			{
				RHLog.Warning(path + " doesn't have an info.json!", 133, "C:\\Dev\\VSProjects\\ResourcefulHands\\Types\\TexturePack.cs");
				return null;
			}
			TexturePack texturePack = JsonConvert.DeserializeObject<TexturePack>(File.ReadAllText(text));
			if (texturePack == null)
			{
				RHLog.Warning(text + " isn't a valid TexturePack json!", 139, "C:\\Dev\\VSProjects\\ResourcefulHands\\Types\\TexturePack.cs");
				RHLog.Info("Example: {\r\n    \"name\":\"generated-game-assets\",\r\n    \"desc\":\"Every game asset\",\r\n    \r\n    \"author\":\"Dark Machine Games\",\r\n    \"steamid\":0,\r\n    \r\n    \"guid\":\"generated-game-assets\",\r\n    \r\n    \"hidden-from-list\":true,\r\n    \"only-in-full-game\":false,\r\n    \r\n    \"textures-folder\":\"Textures\",\r\n    \"sounds-folder\":\"Sounds\",\r\n    \"icon-file\":\"pack.png\",\r\n    \r\n    \"format-version\":2\r\n}                                                           ", 140, "C:\\Dev\\VSProjects\\ResourcefulHands\\Types\\TexturePack.cs");
				return null;
			}
			if (!force)
			{
				if (texturePack.hiddenFromList)
				{
					RHLog.Info("Not loading texture pack at " + path + " because it is hidden.", 147, "C:\\Dev\\VSProjects\\ResourcefulHands\\Types\\TexturePack.cs");
					return null;
				}
				if (texturePack.onlyInFullGame && Plugin.IsDemo)
				{
					RHLog.Info("Skipping incompatible texture pack (it says it only works for the fullgame): " + path, 152, "C:\\Dev\\VSProjects\\ResourcefulHands\\Types\\TexturePack.cs");
					return null;
				}
			}
			if (texturePack.texturePackVersion != 2)
			{
				RHLog.Warning($"Texture pack at {path} is format version {texturePack.texturePackVersion} which isn't {2} (the current version), it may not function correctly.", 158, "C:\\Dev\\VSProjects\\ResourcefulHands\\Types\\TexturePack.cs");
			}
			string text2 = Path.Combine(path, texturePack.relativeIconPath);
			if (!File.Exists(text2))
			{
				RHLog.Warning(path + " doesn't have an pack.png! (icon path: '" + texturePack.relativeIconPath + "')", 163, "C:\\Dev\\VSProjects\\ResourcefulHands\\Types\\TexturePack.cs");
				texturePack.Icon = (Texture2D)(((object)Plugin.IconGray) ?? ((object)new Texture2D(2, 2)));
			}
			else
			{
				byte[] array = File.ReadAllBytes(text2);
				Texture2D val = new Texture2D(2, 2);
				if (!ImageConversion.LoadImage(val, array, false))
				{
					RHLog.Warning(text2 + " isn't a valid texture!", 172, "C:\\Dev\\VSProjects\\ResourcefulHands\\Types\\TexturePack.cs");
					try
					{
						Object.Destroy((Object)(object)val);
					}
					catch
					{
					}
				}
				else
				{
					((Object)val).name = Path.GetFileNameWithoutExtension(text2);
					((Texture)val).filterMode = (FilterMode)0;
					val.Apply();
					texturePack.Icon = val;
				}
			}
			string text3 = texturePack.guid;
			if (string.IsNullOrWhiteSpace(texturePack.guid))
			{
				texturePack.guid = texturePack.author.ToLower() + "." + texturePack.name.ToLower();
			}
			texturePack.guid = MiscUtils.CleanString(texturePack.guid.Replace(' ', '_'));
			if (texturePack.guid != text3)
			{
				string contents = JsonConvert.SerializeObject((object)texturePack);
				File.WriteAllText(text, contents);
				RHLog.Warning("Corrected " + texturePack.name + "'s guid: " + text3 + " -> " + texturePack.guid, 193, "C:\\Dev\\VSProjects\\ResourcefulHands\\Types\\TexturePack.cs");
			}
			RHLog.Info("Texture pack at " + path + " is valid, loading assets...", 196, "C:\\Dev\\VSProjects\\ResourcefulHands\\Types\\TexturePack.cs");
			string path2 = Path.Combine(path, texturePack.relativeTexturesPath);
			string path3 = Path.Combine(path, texturePack.relativeSoundsPath);
			string[] array2 = Array.Empty<string>();
			string[] array3 = Array.Empty<string>();
			if (Directory.Exists(path2))
			{
				array2 = Directory.GetFiles(path2, "*.*", SearchOption.AllDirectories);
			}
			if (Directory.Exists(path3))
			{
				array3 = Directory.GetFiles(path3, "*.*", SearchOption.AllDirectories);
			}
			int num = array2.Length;
			int num2 = array3.Length;
			int num3 = 0;
			string[] array4 = array2;
			foreach (string text4 in array4)
			{
				RHLog.Info($"Loading textures ({num3++}/{num})", 214, "C:\\Dev\\VSProjects\\ResourcefulHands\\Types\\TexturePack.cs");
				string text5 = Path.GetExtension(text4).ToLower();
				if (!text5.Contains("png") && !text5.Contains("jpg"))
				{
					RHLog.Warning(text5 + " isn't supported! Only png and jpg files are supported! [at: " + text4 + "]", 218, "C:\\Dev\\VSProjects\\ResourcefulHands\\Types\\TexturePack.cs");
					continue;
				}
				byte[] array5 = File.ReadAllBytes(text4);
				Texture2D val2 = new Texture2D(2, 2);
				if (!ImageConversion.LoadImage(val2, array5, false))
				{
					RHLog.Warning(text4 + " isn't a valid texture!", 225, "C:\\Dev\\VSProjects\\ResourcefulHands\\Types\\TexturePack.cs");
					try
					{
						Object.Destroy((Object)(object)val2);
					}
					catch
					{
					}
					continue;
				}
				((Object)val2).name = Path.GetFileNameWithoutExtension(text4);
				((Texture)val2).filterMode = (FilterMode)0;
				val2.Apply();
				if (!texturePack.Textures.TryAdd(((Object)val2).name, val2))
				{
					RHLog.Error("Failed to add " + text4 + " because texture of that name already exists in the same pack!", 233, "C:\\Dev\\VSProjects\\ResourcefulHands\\Types\\TexturePack.cs");
				}
			}
			num3 = 0;
			new ConcurrentStack<Tuple<int, int, float[], string>>();
			new List<Task>();
			array4 = array3;
			foreach (string text6 in array4)
			{
				RHLog.Info($"Queuing sounds ({num3++}/{num2})", 242, "C:\\Dev\\VSProjects\\ResourcefulHands\\Types\\TexturePack.cs");
				string text7 = Path.GetExtension(text6).ToLower();
				if (text7.Contains("ogg"))
				{
					RHLog.Warning(text7 + " isn't supported! Only mp3, wav, aiff, wma, acc files are supported! [at: " + text6 + "]", 246, "C:\\Dev\\VSProjects\\ResourcefulHands\\Types\\TexturePack.cs");
					continue;
				}
				StreamedAudioClip streamedAudioClip = new StreamedAudioClip(text6);
				texturePack.RawSounds.Add(streamedAudioClip);
				AudioClip clip = streamedAudioClip.clip;
				((Object)clip).name = Path.GetFileNameWithoutExtension(text6);
				if (!texturePack.Sounds.TryAdd(((Object)clip).name, clip))
				{
					RHLog.Error("Failed to add " + text6 + " because texture of that name already exists in the same pack!", 256, "C:\\Dev\\VSProjects\\ResourcefulHands\\Types\\TexturePack.cs");
				}
			}
			return texturePack;
		}
	}
	public class UI_RHPack : MonoBehaviour
	{
		public RawImage? Icon;

		public TextMeshProUGUI? Title;

		public TextMeshProUGUI? Author;

		public Button? SteamAuthor;

		public TextMeshProUGUI? Description;

		public TextMeshProUGUI? Guid;

		public Button? Up;

		public Button? Down;

		public Button? EnableToggle;

		public Image? EnableOn;

		public Image? EnableOff;

		private TexturePack _pack;

		private T? FindAt<T>(string path) where T : Component
		{
			Transform val = ((Component)this).transform;
			string[] array = path.Split('/');
			foreach (string text in array)
			{
				val = val.Find(text);
				if ((Object)(object)val == (Object)null)
				{
					return default(T);
				}
			}
			return ((Component)val).GetComponentInChildren<T>();
		}

		public void Awake()
		{
			Icon = FindAt<RawImage>("IconContainer/Icon");
			Title = FindAt<TextMeshProUGUI>("Title");
			Author = FindAt<TextMeshProUGUI>("AuthorPanel/Author");
			SteamAuthor = FindAt<Button>("AuthorPanel/ViewOnSteam");
			Description = FindAt<TextMeshProUGUI>("Desc");
			Guid = FindAt<TextMeshProUGUI>("Guid");
			Up = FindAt<Button>("Up/Arrow");
			Down = FindAt<Button>("Down/Arrow");
			EnableToggle = FindAt<Button>("Disable");
			EnableOff = FindAt<Image>("Disable/Toggle/OffImg");
			EnableOn = FindAt<Image>("Disable/Toggle/ToggleImg");
		}

		public void Load(TexturePack pack, bool active = true)
		{
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Expected O, but got Unknown
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Expected O, but got Unknown
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Expected O, but got Unknown
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Expected O, but got Unknown
			TexturePack pack2 = pack;
			_pack = pack2;
			Icon.texture = (Texture)(object)_pack.Icon;
			((TMP_Text)Title).text = _pack.name;
			((TMP_Text)Author).text = _pack.author;
			((TMP_Text)Description).text = _pack.desc;
			((TMP_Text)Guid).text = _pack.guid;
			((Behaviour)EnableOff).enabled = !active;
			((Behaviour)EnableOn).enabled = active;
			if (pack2.steamid != 0)
			{
				Button? steamAuthor = SteamAuthor;
				if (steamAuthor != null)
				{
					((UnityEvent)steamAuthor.onClick).AddListener((UnityAction)delegate
					{
						//IL_000b: Unknown result type (might be due to invalid IL or missing references)
						SteamFriends.OpenUserOverlay(SteamId.op_Implicit(pack2.steamid), "steamid");
					});
				}
			}
			else
			{
				Button? steamAuthor2 = SteamAuthor;
				if (steamAuthor2 != null)
				{
					((Component)steamAuthor2).gameObject.SetActive(false);
				}
			}
			((UnityEvent)Up.onClick).AddListener((UnityAction)delegate
			{
				RHCommands.MovePack(_pack, isUp: true);
				UI_RHPacksList.Instance?.BuildList();
				ConfigEntry<bool>? lazyManip3 = RHConfig.LazyManip;
				if (lazyManip3 != null && lazyManip3.Value)
				{
					Plugin.RefreshTextures();
					Plugin.RefreshSounds();
				}
				else
				{
					ResourcePacksManager.ReloadPacks_Internal();
				}
			});
			((UnityEvent)Down.onClick).AddListener((UnityAction)delegate
			{
				RHCommands.MovePack(_pack, isUp: false);
				UI_RHPacksList.Instance?.BuildList();
				ConfigEntry<bool>? lazyManip2 = RHConfig.LazyManip;
				if (lazyManip2 != null && lazyManip2.Value)
				{
					Plugin.RefreshTextures();
					Plugin.RefreshSounds();
				}
				else
				{
					ResourcePacksManager.ReloadPacks_Internal();
				}
			});
			((UnityEvent)EnableToggle.onClick).AddListener((UnityAction)delegate
			{
				_pack.IsActive = !_pack.IsActive;
				UI_RHPacksList.Instance?.BuildList();
				ConfigEntry<bool>? lazyManip = RHConfig.LazyManip;
				if (lazyManip != null && lazyManip.Value)
				{
					Plugin.RefreshTextures();
					Plugin.RefreshSounds();
				}
				else
				{
					ResourcePacksManager.ReloadPacks_Internal();
				}
			});
		}
	}
	public class UI_RHPacksList : MonoBehaviour
	{
		[CompilerGenerated]
		private sealed class <EnableCoroutine>d__5 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public UI_RHPacksList <>4__this;

			object? IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object? IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <EnableCoroutine>d__5(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_003b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0045: Expected O, but got Unknown
				int num = <>1__state;
				UI_RHPacksList uI_RHPacksList = <>4__this;
				switch (num)
				{
				default:
					return false;
				case 0:
				{
					<>1__state = -1;
					Transform? container2 = uI_RHPacksList.container;
					if (container2 != null)
					{
						((Component)container2).gameObject.SetActive(false);
					}
					<>2__current = (object)new WaitForSecondsRealtime(0.075f);
					<>1__state = 1;
					return true;
				}
				case 1:
				{
					<>1__state = -1;
					Transform? container = uI_RHPacksList.container;
					if (container != null)
					{
						((Component)container).gameObject.SetActive(true);
					}
					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();
			}
		}

		public static UI_RHPacksList? Instance;

		public ScrollRect? scrollRect;

		public Transform? container;

		public UI_RHPack? packTemplate;

		public void Awake()
		{
			Instance = this;
			scrollRect = ((Component)this).GetComponentInChildren<ScrollRect>();
			container = (Transform?)(object)scrollRect.content;
			packTemplate = ((Component)container.Find("Pack")).gameObject.AddComponent<UI_RHPack>();
			((Component)packTemplate).gameObject.SetActive(false);
		}

		[IteratorStateMachine(typeof(<EnableCoroutine>d__5))]
		private IEnumerator EnableCoroutine()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <EnableCoroutine>d__5(0)
			{
				<>4__this = this
			};
		}

		public void OnEnable()
		{
			BuildList();
			CoroutineDispatcher.Dispatch(EnableCoroutine());
		}

		private void ClearList()
		{
			if ((Object)(object)container == (Object)null || (Object)(object)packTemplate == (Object)null)
			{
				return;
			}
			for (int i = 0; i < container.childCount; i++)
			{
				Transform child = container.GetChild(i);
				if (!((Object)(object)child == (Object)(object)((Component)packTemplate).transform))
				{
					Object.Destroy((Object)(object)((Component)child).gameObject);
				}
			}
		}

		public void BuildList()
		{
			ClearList();
			foreach (TexturePack loadedPack in ResourcePacksManager.LoadedPacks)
			{
				UI_RHPack uI_RHPack = Object.Instantiate<UI_RHPack>(packTemplate, container);
				if (!((Object)(object)uI_RHPack == (Object)null))
				{
					TexturePack pack1 = loadedPack;
					uI_RHPack.Load(loadedPack, ResourcePacksManager.ActivePacks.FirstOrDefault((TexturePack p) => p == pack1) != null);
					((Object)((Component)uI_RHPack).gameObject).name = loadedPack.guid;
					((Component)uI_RHPack).gameObject.SetActive(true);
				}
			}
		}
	}
}
namespace ResourcefulHands.Patches
{
	[HarmonyPatch(typeof(Image))]
	public static class ImagePatches
	{
		[HarmonyPatch(/*Could not decode attribute arguments.*/)]
		[HarmonyPostfix]
		public static void Getter_sprite_Postfix(Image __instance, ref Sprite __result)
		{
			if (!((Object)(object)__result == (Object)null))
			{
				__result = SpriteRendererPatches.GetSprite(__result);
			}
		}
	}
	[HarmonyPatch(typeof(SpriteRenderer))]
	public static class SpriteRendererPatches
	{
		private static bool dontPatch = false;

		internal static Dictionary<string, Sprite> _customSpriteCache { get; private set; } = new Dictionary<string, Sprite>();


		public static Sprite? GetSprite(Sprite sprite)
		{
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)sprite == (Object)null)
			{
				return sprite;
			}
			bool num = ((Object)sprite).name.EndsWith(" [modified asset]");
			string text = ((Object)sprite).name;
			if (num)
			{
				text = text.Substring(0, text.Length - " [modified asset]".Length);
			}
			if (_customSpriteCache.TryGetValue(text, out Sprite value))
			{
				if ((Object)(object)value != (Object)null)
				{
					return value;
				}
				_customSpriteCache.Remove(text);
			}
			Texture2D textureFromPacks = ResourcePacksManager.GetTextureFromPacks(((Object)sprite.texture).name);
			if ((Object)(object)textureFromPacks == (Object)null)
			{
				return sprite;
			}
			Rect rect = sprite.rect;
			float num2 = Mathf.Clamp(((Rect)(ref rect)).x, 0f, (float)((Texture)textureFromPacks).width);
			rect = sprite.rect;
			float num3 = Mathf.Clamp(((Rect)(ref rect)).y, 0f, (float)((Texture)textureFromPacks).height);
			rect = sprite.rect;
			float num4 = Mathf.Clamp(((Rect)(ref rect)).width, 0f, (float)((Texture)textureFromPacks).width - num2);
			rect = sprite.rect;
			float num5 = Mathf.Clamp(((Rect)(ref rect)).height, 0f, (float)((Texture)textureFromPacks).height - num3);
			Rect val = new Rect(num2, num3, num4, num5);
			float x = sprite.pivot.x;
			rect = sprite.rect;
			float num6 = x / ((Rect)(ref rect)).width;
			float y = sprite.pivot.y;
			rect = sprite.rect;
			Sprite val2 = Sprite.Create(textureFromPacks, val, new Vector2(num6, y / ((Rect)(ref rect)).height), sprite.pixelsPerUnit);
			((Object)val2).name = text + " [modified asset]";
			_customSpriteCache.Add(text, val2);
			return val2;
		}

		[HarmonyPatch(/*Could not decode attribute arguments.*/)]
		[HarmonyPostfix]
		private static void Constructor_Postfix(SpriteRenderer __instance)
		{
			__instance.sprite = __instance.sprite;
		}

		[HarmonyPatch(/*Could not decode attribute arguments.*/)]
		[HarmonyPostfix]
		private static void Getter_Postfix(SpriteRenderer __instance, ref Sprite __result)
		{
			if (dontPatch)
			{
				dontPatch = false;
				return;
			}
			__result = GetSprite(__result);
			dontPatch = true;
			__instance.sprite = __result;
		}

		[HarmonyPatch(/*Could not decode attribute arguments.*/)]
		[HarmonyPostfix]
		private static void Setter_Prefix(SpriteRenderer __instance, ref Sprite value)
		{
			if (dontPatch)
			{
				dontPatch = false;
				return;
			}
			value = GetSprite(value);
			dontPatch = true;
			__instance.sprite = value;
		}
	}
	[HarmonyPatch(typeof(AudioSource))]
	public static class AudioSourcePatches
	{
		private static bool dontPatch;

		[HarmonyPatch(/*Could not decode attribute arguments.*/)]
		[HarmonyPostfix]
		private static void Constructor_Postfix(AudioSource __instance)
		{
			if ((Object)(object)__instance == (Object)null || (Object)(object)__instance.clip == (Object)null)
			{
				return;
			}
			AudioClip soundFromPacks = ResourcePacksManager.GetSoundFromPacks(((Object)__instance.clip).name);
			if ((Object)(object)soundFromPacks != (Object)null)
			{
				__instance.clip = soundFromPacks;
				if (__instance.playOnAwake && Time.timeSinceLevelLoad <= 0.25f && !__instance.isPlaying)
				{
					dontPatch = true;
					__instance.Play();
				}
			}
		}

		[HarmonyPatch("set_clip")]
		[HarmonyPostfix]
		private static void Setter_Postfix(AudioSource __instance, ref AudioClip value)
		{
			if (dontPatch)
			{
				dontPatch = false;
			}
			else
			{
				if ((Object)(object)value == (Object)null)
				{
					return;
				}
				AudioClip soundFromPacks = ResourcePacksManager.GetSoundFromPacks(((Object)value).name);
				if (!((Object)(object)soundFromPacks != (Object)null))
				{
					return;
				}
				dontPatch = true;
				__instance.clip = soundFromPacks;
				value = soundFromPacks;
				if (__instance.playOnAwake && Time.timeSinceLevelLoad <= 0.25f && !__instance.isPlaying)
				{
					dontPatch = true;
					if (((Behaviour)__instance).enabled)
					{
						__instance.Play();
					}
				}
			}
		}

		[HarmonyPatch("get_clip")]
		[HarmonyPostfix]
		private static void Getter_Postfix(AudioSource __instance, ref AudioClip __result)
		{
			if (dontPatch)
			{
				dontPatch = false;
			}
			else
			{
				if ((Object)(object)__result == (Object)null)
				{
					return;
				}
				AudioClip soundFromPacks = ResourcePacksManager.GetSoundFromPacks(((Object)__result).name);
				if (!((Object)(object)soundFromPacks != (Object)null))
				{
					return;
				}
				dontPatch = true;
				__instance.clip = soundFromPacks;
				__result = soundFromPacks;
				if (__instance.playOnAwake && Time.timeSinceLevelLoad <= 0.25f && !__instance.isPlaying)
				{
					dontPatch = true;
					if (((Behaviour)__instance).enabled)
					{
						__instance.Play();
					}
				}
			}
		}

		[HarmonyPatch("Play", new Type[] { typeof(double) })]
		[HarmonyPostfix]
		private static void Play_Prefix(AudioSource __instance, double delay)
		{
			if (dontPatch)
			{
				dontPatch = false;
			}
			else if (!((Object)(object)__instance.clip == (Object)null))
			{
				__instance.clip = __instance.clip;
			}
		}

		[HarmonyPatch("PlayHelper", new Type[]
		{
			typeof(AudioSource),
			typeof(ulong)
		})]
		[HarmonyPostfix]
		private static void PlayHelper_Prefix(AudioSource source, ulong delay)
		{
			if (dontPatch)
			{
				dontPatch = false;
			}
			else if (!((Object)(object)source.clip == (Object)null))
			{
				source.clip = source.clip;
			}
		}
	}
	[HarmonyPatch(typeof(Material))]
	public static class MaterialPatches
	{
		private static bool dontPatch = false;

		internal static Dictionary<string, Texture> previousTextures = new Dictionary<string, Texture>();

		private static readonly int MainTex = Shader.PropertyToID("_MainTex");

		public static void SetMainTexture(Material m, Texture texture)
		{
			dontPatch = true;
			m.mainTexture = texture;
		}

		public static Texture GetMainTexture(Material m)
		{
			dontPatch = true;
			return m.mainTexture;
		}

		[HarmonyPatch("get_mainTexture")]
		[HarmonyPostfix]
		private static void Getter_Postfix(Material __instance, ref Texture __result)
		{
			if (dontPatch)
			{
				dontPatch = false;
			}
			else
			{
				if ((Object)(object)__instance == (Object)null || !__instance.HasTexture(MainTex))
				{
					return;
				}
				dontPatch = true;
				Texture mainTexture = __instance.mainTexture;
				if (!((Object)(object)mainTexture == (Object)null))
				{
					Texture2D textureFromPacks = ResourcePacksManager.GetTextureFromPacks(((Object)mainTexture).name);
					if (!((Object)(object)textureFromPacks == (Object)null))
					{
						((Object)textureFromPacks).name = ((Object)mainTexture).name + " [replaced]";
						previousTextures.TryAdd(((Object)mainTexture).name, mainTexture);
						__instance.mainTexture = (Texture)(object)textureFromPacks;
					}
				}
			}
		}

		[HarmonyPatch("set_mainTexture")]
		[HarmonyPostfix]
		private static void Setter_Prefix(Material __instance, ref Texture value)
		{
			if (dontPatch)
			{
				dontPatch = false;
			}
			else
			{
				if ((Object)(object)__instance == (Object)null || !__instance.HasTexture(MainTex))
				{
					return;
				}
				dontPatch = true;
				Texture mainTexture = __instance.mainTexture;
				if (!((Object)(object)mainTexture == (Object)null))
				{
					Texture2D textureFromPacks = ResourcePacksManager.GetTextureFromPacks(((Object)mainTexture).name);
					if (!((Object)(object)textureFromPacks == (Object)null))
					{
						((Object)textureFromPacks).name = ((Object)mainTexture).name + " [replaced]";
						previousTextures.TryAdd(((Object)mainTexture).name, mainTexture);
						__instance.mainTexture = (Texture)(object)textureFromPacks;
					}
				}
			}
		}
	}
	[HarmonyPatch(typeof(Renderer))]
	public static class RendererPatches
	{
		private static readonly int MainTex = Shader.PropertyToID("_MainTex");

		[HarmonyPatch(/*Could not decode attribute arguments.*/)]
		[HarmonyPostfix]
		private static void Constructor_Postfix(Renderer __instance)
		{
			Material[] sharedMaterials = __instance.sharedMaterials;
			foreach (Material val in sharedMaterials)
			{
				if (val.HasProperty(MainTex))
				{
					_ = val.mainTexture;
				}
			}
		}

		public static void Patch(ref Material material)
		{
			if (!((Object)(object)material == (Object)null) && material.HasProperty(MainTex))
			{
				_ = material.mainTexture;
			}
		}

		[HarmonyPatch("get_material")]
		[HarmonyPostfix]
		private static void Getter_material_Postfix(Renderer __instance, ref Material __result)
		{
			Patch(ref __result);
		}

		[HarmonyPatch("set_material")]
		[HarmonyPostfix]
		private static void Setter_material_Prefix(Renderer __instance, ref Material value)
		{
			Patch(ref value);
		}

		[HarmonyPatch("get_materials")]
		[HarmonyPostfix]
		private static void Getter_materials_Postfix(Renderer __instance, ref Material[] __result)
		{
			for (int i = 0; i < __result.Length; i++)
			{
				Patch(ref __result[i]);
			}
		}

		[HarmonyPatch("set_materials")]
		[HarmonyPostfix]
		private static void Setter_materials_Prefix(Renderer __instance, ref Material[] value)
		{
			for (int i = 0; i < value.Length; i++)
			{
				Patch(ref value[i]);
			}
		}

		[HarmonyPatch("get_sharedMaterial")]
		[HarmonyPostfix]
		private static void Getter_sharedMaterial_Postfix(Renderer __instance, ref Material __result)
		{
			Patch(ref __result);
		}

		[HarmonyPatch("set_sharedMaterial")]
		[HarmonyPostfix]
		private static void Setter_sharedMaterial_Prefix(Renderer __instance, ref Material value)
		{
			Patch(ref value);
		}

		[HarmonyPatch("get_sharedMaterials")]
		[HarmonyPostfix]
		private static void Getter_sharedMaterials_Postfix(Renderer __instance, ref Material[] __result)
		{
			for (int i = 0; i < __result.Length; i++)
			{
				Patch(ref __result[i]);
			}
		}

		[HarmonyPatch("set_sharedMaterials")]
		[HarmonyPostfix]
		private static void Setter_sharedMaterials_Prefix(Renderer __instance, ref Material[] value)
		{
			for (int i = 0; i < value.Length; i++)
			{
				Patch(ref value[i]);
			}
		}
	}
}