Decompiled source of Adaptive Trigger For PSVR2 v2.0.0

Niko666.Adaptive_Trigger_For_PSVR2.dll

Decompiled 5 days ago
using System;
using System.CodeDom.Compiler;
using System.Collections;
using System.Configuration;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using FistVR;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using PSVR2Toolkit;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyCompany("Niko666")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Implemented some Adaptive Trigger effects for chad PSVR2 controller enjoyers. REQUIRES PSVR2 Toolkit TO USE!")]
[assembly: AssemblyFileVersion("2.0.0.0")]
[assembly: AssemblyInformationalVersion("2.0.0")]
[assembly: AssemblyProduct("Niko666.Adaptive_Trigger_For_PSVR2")]
[assembly: AssemblyTitle("Adaptive_Trigger_For_PSVR2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("2.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NativeIntegerAttribute : Attribute
	{
		public readonly bool[] TransformFlags;

		public NativeIntegerAttribute()
		{
			TransformFlags = new bool[1] { true };
		}

		public NativeIntegerAttribute(bool[] P_0)
		{
			TransformFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace BepInEx
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	internal sealed class BepInAutoPluginAttribute : Attribute
	{
		public BepInAutoPluginAttribute(string id = null, string name = null, string version = null)
		{
		}
	}
}
namespace BepInEx.Preloader.Core.Patching
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	internal sealed class PatcherAutoPluginAttribute : Attribute
	{
		public PatcherAutoPluginAttribute(string id = null, string name = null, string version = null)
		{
		}
	}
}
namespace PSVR2Toolkit
{
	public enum VRControllerType : byte
	{
		Left,
		Right,
		Both
	}
	public enum GazeCalibrationReportMode : ushort
	{
		None,
		StartCalibration,
		CollectCalibrationPoint,
		DiscardCalibrationPoint,
		ComputeAndApplyCalibration,
		RetrieveCalibrationData,
		StopCalibration,
		SetEnabledEye,
		HardwareCalibrationRetrieve
	}
	public enum GazeCalibrationStatus : ushort
	{
		EyetrackingInactive,
		EyetrackingActive,
		CalibrationReady,
		DSPBusy,
		Computing,
		ComputeSucceeded,
		ComputeFailed,
		SettingEye
	}
	public enum GazeCalibrationResult : byte
	{
		Success,
		Failure,
		Discarded,
		Waiting
	}
	public enum hmd2_gaze_bool_t : uint
	{
		HMD2_GAZE_BOOL_FALSE,
		HMD2_GAZE_BOOL_TRUE
	}
	public enum hmd2_gaze_enabled_eye_t : byte
	{
		HMD2_GAZE_ENABLED_EYE_LEFT,
		HMD2_GAZE_ENABLED_EYE_RIGHT,
		HMD2_GAZE_ENABLED_EYE_BOTH
	}
	public enum ScePadTriggerEffectMode
	{
		SCE_PAD_TRIGGER_EFFECT_MODE_OFF,
		SCE_PAD_TRIGGER_EFFECT_MODE_FEEDBACK,
		SCE_PAD_TRIGGER_EFFECT_MODE_WEAPON,
		SCE_PAD_TRIGGER_EFFECT_MODE_VIBRATION,
		SCE_PAD_TRIGGER_EFFECT_MODE_MULTIPLE_POSITION_FEEDBACK,
		SCE_PAD_TRIGGER_EFFECT_MODE_SLOPE_FEEDBACK,
		SCE_PAD_TRIGGER_EFFECT_MODE_MULTIPLE_POSITION_VIBRATION
	}
	[StructLayout(LayoutKind.Sequential, Pack = 1)]
	public struct hmd2_gaze_vec2_t
	{
		public float x;

		public float y;
	}
	[StructLayout(LayoutKind.Sequential, Pack = 1)]
	public struct hmd2_gaze_vec3_t
	{
		public float x;

		public float y;

		public float z;
	}
	[StructLayout(LayoutKind.Sequential, Pack = 1)]
	public struct hmd2_gaze_lens_config_t
	{
		public hmd2_gaze_vec3_t left;

		public hmd2_gaze_vec3_t right;
	}
	[StructLayout(LayoutKind.Sequential, Pack = 4)]
	public struct hmd2_gaze_wearable_eye_t
	{
		public hmd2_gaze_bool_t is_gaze_origin_valid;

		public hmd2_gaze_vec3_t gaze_origin_mm;

		public hmd2_gaze_bool_t is_gaze_dir_valid;

		public hmd2_gaze_vec3_t gaze_dir_norm;

		public hmd2_gaze_bool_t is_pupil_dia_valid;

		public float pupil_dia_mm;

		public hmd2_gaze_bool_t is_pupil_pos_in_sensor_area_valid;

		public hmd2_gaze_vec2_t pupil_pos_in_sensor_area;

		public hmd2_gaze_bool_t is_pos_guide_valid;

		public hmd2_gaze_vec2_t pos_guide;

		public hmd2_gaze_bool_t is_blink_valid;

		public hmd2_gaze_bool_t blink;
	}
	[StructLayout(LayoutKind.Sequential, Pack = 8)]
	public struct hmd2_gaze_wearable_data_t
	{
		public long timestamp;

		public uint frame_counter;

		public hmd2_gaze_wearable_eye_t left;

		public hmd2_gaze_wearable_eye_t right;

		public hmd2_gaze_bool_t is_gaze_origin_combined_valid;

		public hmd2_gaze_vec3_t gaze_origin_combined_mm;

		public hmd2_gaze_bool_t is_gaze_dir_combined_valid;

		public hmd2_gaze_vec3_t gaze_dir_combined_norm;

		public hmd2_gaze_bool_t is_convergence_distance_valid;
	}
	[StructLayout(LayoutKind.Sequential, Pack = 8)]
	public struct hmd2_gaze_foveated_gaze_t
	{
		public long timestamp;

		public uint frame_counter;

		public uint tracking_state;

		public hmd2_gaze_vec3_t gaze_dir_left_norm;

		public hmd2_gaze_vec3_t gaze_dir_right_norm;

		public hmd2_gaze_vec3_t gaze_dir_combined_norm;

		public float convergence_distance_mm;
	}
	[StructLayout(LayoutKind.Sequential, Pack = 8)]
	public struct hmd2_gaze_status_t
	{
		public byte magic0;

		public byte magic1;

		public ushort version;

		public uint size;

		public float exp_l;

		public float exp_r;

		public uint led_status;

		public uint exp_counter_l;

		public uint exp_counter_r;

		public uint led_counter;

		public int dsp_return_code;

		public hmd2_gaze_lens_config_t lens_config;

		public uint user_calibration_id;

		public hmd2_gaze_vec3_t fr_gaze_origin;

		public hmd2_gaze_enabled_eye_t enabled_eye;

		public byte motor_sequence;

		public byte motor_strength;

		public hmd2_gaze_wearable_data_t wearable;

		public hmd2_gaze_foveated_gaze_t foveated;
	}
	[StructLayout(LayoutKind.Explicit, Size = 48)]
	public struct ScePadTriggerEffectCommandData
	{
		[FieldOffset(0)]
		public byte feedbackPosition;

		[FieldOffset(1)]
		public byte feedbackStrength;

		[FieldOffset(0)]
		public byte weaponStartPosition;

		[FieldOffset(1)]
		public byte weaponEndPosition;

		[FieldOffset(2)]
		public byte weaponStrength;

		[FieldOffset(0)]
		public byte vibrationPosition;

		[FieldOffset(1)]
		public byte vibrationAmplitude;

		[FieldOffset(2)]
		public byte vibrationFrequency;

		[FieldOffset(0)]
		public byte multiplePositionFeedbackStrength0;

		[FieldOffset(1)]
		public byte multiplePositionFeedbackStrength1;

		[FieldOffset(2)]
		public byte multiplePositionFeedbackStrength2;

		[FieldOffset(3)]
		public byte multiplePositionFeedbackStrength3;

		[FieldOffset(4)]
		public byte multiplePositionFeedbackStrength4;

		[FieldOffset(5)]
		public byte multiplePositionFeedbackStrength5;

		[FieldOffset(6)]
		public byte multiplePositionFeedbackStrength6;

		[FieldOffset(7)]
		public byte multiplePositionFeedbackStrength7;

		[FieldOffset(8)]
		public byte multiplePositionFeedbackStrength8;

		[FieldOffset(9)]
		public byte multiplePositionFeedbackStrength9;

		[FieldOffset(0)]
		public byte slopeStartPosition;

		[FieldOffset(1)]
		public byte slopeEndPosition;

		[FieldOffset(2)]
		public byte slopeStartStrength;

		[FieldOffset(3)]
		public byte slopeEndStrength;

		[FieldOffset(0)]
		public byte multiplePositionVibrationFrequency;

		[FieldOffset(1)]
		public byte multiplePositionVibrationAmplitude0;

		[FieldOffset(2)]
		public byte multiplePositionVibrationAmplitude1;

		[FieldOffset(3)]
		public byte multiplePositionVibrationAmplitude2;

		[FieldOffset(4)]
		public byte multiplePositionVibrationAmplitude3;

		[FieldOffset(5)]
		public byte multiplePositionVibrationAmplitude4;

		[FieldOffset(6)]
		public byte multiplePositionVibrationAmplitude5;

		[FieldOffset(7)]
		public byte multiplePositionVibrationAmplitude6;

		[FieldOffset(8)]
		public byte multiplePositionVibrationAmplitude7;

		[FieldOffset(9)]
		public byte multiplePositionVibrationAmplitude8;

		[FieldOffset(10)]
		public byte multiplePositionVibrationAmplitude9;

		public void SetMultiplePositionFeedbackStrength(byte[] strength)
		{
			if (strength == null)
			{
				throw new ArgumentNullException("strength");
			}
			int num = Math.Min(strength.Length, 10);
			if (num > 0)
			{
				multiplePositionFeedbackStrength0 = strength[0];
			}
			if (num > 1)
			{
				multiplePositionFeedbackStrength1 = strength[1];
			}
			if (num > 2)
			{
				multiplePositionFeedbackStrength2 = strength[2];
			}
			if (num > 3)
			{
				multiplePositionFeedbackStrength3 = strength[3];
			}
			if (num > 4)
			{
				multiplePositionFeedbackStrength4 = strength[4];
			}
			if (num > 5)
			{
				multiplePositionFeedbackStrength5 = strength[5];
			}
			if (num > 6)
			{
				multiplePositionFeedbackStrength6 = strength[6];
			}
			if (num > 7)
			{
				multiplePositionFeedbackStrength7 = strength[7];
			}
			if (num > 8)
			{
				multiplePositionFeedbackStrength8 = strength[8];
			}
			if (num > 9)
			{
				multiplePositionFeedbackStrength9 = strength[9];
			}
		}

		public void SetMultiplePositionVibrationAmplitude(byte[] amplitude)
		{
			if (amplitude == null)
			{
				throw new ArgumentNullException("amplitude");
			}
			int num = Math.Min(amplitude.Length, 10);
			if (num > 0)
			{
				multiplePositionVibrationAmplitude0 = amplitude[0];
			}
			if (num > 1)
			{
				multiplePositionVibrationAmplitude1 = amplitude[1];
			}
			if (num > 2)
			{
				multiplePositionVibrationAmplitude2 = amplitude[2];
			}
			if (num > 3)
			{
				multiplePositionVibrationAmplitude3 = amplitude[3];
			}
			if (num > 4)
			{
				multiplePositionVibrationAmplitude4 = amplitude[4];
			}
			if (num > 5)
			{
				multiplePositionVibrationAmplitude5 = amplitude[5];
			}
			if (num > 6)
			{
				multiplePositionVibrationAmplitude6 = amplitude[6];
			}
			if (num > 7)
			{
				multiplePositionVibrationAmplitude7 = amplitude[7];
			}
			if (num > 8)
			{
				multiplePositionVibrationAmplitude8 = amplitude[8];
			}
			if (num > 9)
			{
				multiplePositionVibrationAmplitude9 = amplitude[9];
			}
		}
	}
	[StructLayout(LayoutKind.Sequential, Pack = 4)]
	public struct ScePadTriggerEffectCommand
	{
		public ScePadTriggerEffectMode mode;

		public uint padding;

		public ScePadTriggerEffectCommandData commandData;
	}
	[StructLayout(LayoutKind.Sequential, Pack = 1)]
	public struct TriggerEffectCommandPayload
	{
		public VRControllerType controllerType;

		public ScePadTriggerEffectCommand command;
	}
	[StructLayout(LayoutKind.Explicit, Size = 13)]
	public struct GazeCalibrationPacket
	{
		[FieldOffset(0)]
		public float x;

		[FieldOffset(4)]
		public float y;

		[FieldOffset(8)]
		public float z;

		[FieldOffset(12)]
		public GazeCalibrationResult result;

		[FieldOffset(12)]
		public hmd2_gaze_enabled_eye_t eyeEnabled;
	}
	[StructLayout(LayoutKind.Explicit, Size = 15)]
	public struct GazeCalibrationCommand
	{
		[FieldOffset(0)]
		public GazeCalibrationReportMode reportMode;

		[FieldOffset(0)]
		public GazeCalibrationStatus status;

		[FieldOffset(2)]
		public GazeCalibrationPacket payload;
	}
	public static class PSVR2ToolkitCAPI
	{
		[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
		private delegate int psvr2_toolkit_init_delegate();

		[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
		private delegate void psvr2_toolkit_deinit_delegate();

		[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
		private delegate bool psvr2_toolkit_gaze_status_delegate(ref hmd2_gaze_status_t pGazeStatus, uint timeoutMs);

		[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
		private delegate bool psvr2_toolkit_gaze_image_delegate(ref IntPtr pGazeImage, uint timeoutMs);

		[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
		private delegate void psvr2_toolkit_write_pcm_delegate(VRControllerType controllerType, IntPtr pcm);

		[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
		private delegate void psvr2_toolkit_wait_for_pcm_delegate();

		[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
		private delegate void psvr2_toolkit_set_trigger_effect_delegate(VRControllerType controllerType, ref ScePadTriggerEffectCommand command);

		[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
		private delegate void psvr2_toolkit_set_hmd_rumble_delegate(byte rumbleHz);

		[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
		private delegate GazeCalibrationCommand psvr2_toolkit_private_send_gaze_set_command_delegate(GazeCalibrationCommand command);

		[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
		private delegate GazeCalibrationCommand psvr2_toolkit_private_send_gaze_get_command_delegate(GazeCalibrationCommand command);

		[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
		private delegate void psvr2_toolkit_private_set_usb_connection_state_delegate(bool connected);

		private static psvr2_toolkit_init_delegate _init;

		private static psvr2_toolkit_deinit_delegate _deinit;

		private static psvr2_toolkit_gaze_status_delegate _gaze_status;

		private static psvr2_toolkit_gaze_image_delegate _gaze_image;

		private static psvr2_toolkit_write_pcm_delegate _write_pcm;

		private static psvr2_toolkit_wait_for_pcm_delegate _wait_for_pcm;

		private static psvr2_toolkit_set_trigger_effect_delegate _set_trigger_effect;

		private static psvr2_toolkit_set_hmd_rumble_delegate _set_hmd_rumble;

		private static psvr2_toolkit_private_send_gaze_set_command_delegate _private_send_gaze_set_command;

		private static psvr2_toolkit_private_send_gaze_get_command_delegate _private_send_gaze_get_command;

		private static psvr2_toolkit_private_set_usb_connection_state_delegate _private_set_usb_connection_state;

		private static IntPtr _moduleHandle = IntPtr.Zero;

		private static readonly object _lock = new object();

		public static IntPtr ModuleHandle
		{
			get
			{
				EnsureLoaded();
				return _moduleHandle;
			}
		}

		[DllImport("psvr2_toolkit_capi_loader", CallingConvention = CallingConvention.Cdecl)]
		private static extern IntPtr psvr2_toolkit_loader_get_module_handle();

		[DllImport("psvr2_toolkit_capi_loader", CallingConvention = CallingConvention.Cdecl)]
		private static extern nuint psvr2_toolkit_loader_get_module_path(IntPtr buffer, nuint bufferSize);

		public static string GetModulePath()
		{
			EnsureLoaded();
			try
			{
				nuint num = psvr2_toolkit_loader_get_module_path(IntPtr.Zero, 0u);
				if (num == 0)
				{
					return string.Empty;
				}
				IntPtr intPtr = Marshal.AllocHGlobal((int)(num + 1));
				try
				{
					psvr2_toolkit_loader_get_module_path(intPtr, num + 1);
					return Marshal.PtrToStringAnsi(intPtr);
				}
				finally
				{
					Marshal.FreeHGlobal(intPtr);
				}
			}
			catch
			{
				return "Unknown (Failed to query loader)";
			}
		}

		private static void EnsureLoaded()
		{
			if (_moduleHandle != IntPtr.Zero)
			{
				return;
			}
			lock (_lock)
			{
				if (!(_moduleHandle != IntPtr.Zero))
				{
					try
					{
						_moduleHandle = psvr2_toolkit_loader_get_module_handle();
					}
					catch (DllNotFoundException inner)
					{
						throw new DllNotFoundException("Could not load the loader library 'psvr2_toolkit_capi_loader'. Make sure 'psvr2_toolkit_capi_loader.dll' is in your application directory or search path.", inner);
					}
					if (_moduleHandle == IntPtr.Zero)
					{
						throw new InvalidOperationException("psvr2_toolkit_loader_get_module_handle returned NULL. Make sure psvr2tk_capi_path.txt contains the correct directory of 'psvr2_toolkit_capi.dll' and the dll exists in that directory.");
					}
					_init = GetExport<psvr2_toolkit_init_delegate>("psvr2_toolkit_init");
					_deinit = GetExport<psvr2_toolkit_deinit_delegate>("psvr2_toolkit_deinit");
					_gaze_status = GetExport<psvr2_toolkit_gaze_status_delegate>("psvr2_toolkit_gaze_status");
					_gaze_image = GetExport<psvr2_toolkit_gaze_image_delegate>("psvr2_toolkit_gaze_image");
					_write_pcm = GetExport<psvr2_toolkit_write_pcm_delegate>("psvr2_toolkit_write_pcm");
					_wait_for_pcm = GetExport<psvr2_toolkit_wait_for_pcm_delegate>("psvr2_toolkit_wait_for_pcm");
					_set_trigger_effect = GetExport<psvr2_toolkit_set_trigger_effect_delegate>("psvr2_toolkit_set_trigger_effect");
					_set_hmd_rumble = GetExport<psvr2_toolkit_set_hmd_rumble_delegate>("psvr2_toolkit_set_hmd_rumble");
					_private_send_gaze_set_command = GetExport<psvr2_toolkit_private_send_gaze_set_command_delegate>("psvr2_toolkit_private_send_gaze_set_command");
					_private_send_gaze_get_command = GetExport<psvr2_toolkit_private_send_gaze_get_command_delegate>("psvr2_toolkit_private_send_gaze_get_command");
					_private_set_usb_connection_state = GetExport<psvr2_toolkit_private_set_usb_connection_state_delegate>("psvr2_toolkit_private_set_usb_connection_state");
				}
			}
		}

		private static T GetExport<T>(string name) where T : Delegate
		{
			IntPtr procAddress = GetProcAddress(_moduleHandle, name);
			if (procAddress == IntPtr.Zero)
			{
				throw new EntryPointNotFoundException("Could not find entry point '" + name + "' in the loaded PSVR2 Toolkit CAPI library.");
			}
			return (T)Marshal.GetDelegateForFunctionPointer(procAddress, typeof(T));
		}

		private static IntPtr GetProcAddress(IntPtr hModule, string procName)
		{
			Type type = Type.GetType("System.Runtime.InteropServices.NativeLibrary, System.Runtime.InteropServices");
			if ((object)type != null)
			{
				MethodInfo method = type.GetMethod("GetExport", new Type[2]
				{
					typeof(IntPtr),
					typeof(string)
				});
				if ((object)method != null)
				{
					try
					{
						return (IntPtr)method.Invoke(null, new object[2] { hModule, procName });
					}
					catch
					{
					}
				}
			}
			return Win32GetProcAddress(hModule, procName);
		}

		[DllImport("kernel32.dll", CharSet = CharSet.Ansi, EntryPoint = "GetProcAddress", ExactSpelling = true, SetLastError = true)]
		private static extern IntPtr Win32GetProcAddress(IntPtr hModule, string procName);

		[DllImport("libdl", CharSet = CharSet.Ansi, EntryPoint = "dlsym")]
		private static extern IntPtr UnixDlsym(IntPtr handle, string symbol);

		[DllImport("libdl.so.2", CharSet = CharSet.Ansi, EntryPoint = "dlsym")]
		private static extern IntPtr UnixDlsym2(IntPtr handle, string symbol);

		public static int Init()
		{
			EnsureLoaded();
			return _init();
		}

		public static void Deinit()
		{
			EnsureLoaded();
			_deinit();
		}

		public static bool GetGazeStatus(ref hmd2_gaze_status_t gazeStatus, uint timeoutMs)
		{
			EnsureLoaded();
			return _gaze_status(ref gazeStatus, timeoutMs);
		}

		public static bool GetGazeImage(ref byte[] gazeImage, uint timeoutMs)
		{
			if (gazeImage == null)
			{
				throw new ArgumentNullException("gazeImage");
			}
			if (gazeImage.Length < 2097408)
			{
				throw new ArgumentException("Array size must be at least 0x200100 bytes.", "gazeImage");
			}
			EnsureLoaded();
			IntPtr pGazeImage = IntPtr.Zero;
			bool num = _gaze_image(ref pGazeImage, timeoutMs);
			if (num && pGazeImage != IntPtr.Zero)
			{
				Marshal.Copy(pGazeImage, gazeImage, 0, 2097408);
			}
			return num;
		}

		public static bool GetGazeImage(ref IntPtr pGazeImage, uint timeoutMs)
		{
			EnsureLoaded();
			return _gaze_image(ref pGazeImage, timeoutMs);
		}

		public unsafe static void WritePcm(VRControllerType controllerType, byte[] pcm)
		{
			if (pcm == null)
			{
				throw new ArgumentNullException("pcm");
			}
			if (pcm.Length < 32)
			{
				throw new ArgumentException("PCM array must be at least 32 bytes.", "pcm");
			}
			EnsureLoaded();
			fixed (byte* ptr = pcm)
			{
				_write_pcm(controllerType, (IntPtr)ptr);
			}
		}

		public static void WritePcm(VRControllerType controllerType, IntPtr pcm)
		{
			if (pcm == IntPtr.Zero)
			{
				throw new ArgumentNullException("pcm");
			}
			EnsureLoaded();
			_write_pcm(controllerType, pcm);
		}

		public static void WaitForPcm()
		{
			EnsureLoaded();
			_wait_for_pcm();
		}

		public static void SetTriggerEffect(VRControllerType controllerType, ref ScePadTriggerEffectCommand command)
		{
			EnsureLoaded();
			_set_trigger_effect(controllerType, ref command);
		}

		public static void SetHmdRumble(byte rumbleHz)
		{
			EnsureLoaded();
			_set_hmd_rumble(rumbleHz);
		}

		public static GazeCalibrationCommand SendGazeSetCommand(GazeCalibrationCommand command)
		{
			EnsureLoaded();
			return _private_send_gaze_set_command(command);
		}

		public static GazeCalibrationCommand SendGazeGetCommand(GazeCalibrationCommand command)
		{
			EnsureLoaded();
			return _private_send_gaze_get_command(command);
		}

		public static void SetUsbConnectionState(bool connected)
		{
			EnsureLoaded();
			_private_set_usb_connection_state(connected);
		}
	}
}
namespace Niko666
{
	[BepInProcess("h3vr.exe")]
	[BepInPlugin("Niko666.Adaptive_Trigger_For_PSVR2", "Adaptive_Trigger_For_PSVR2", "2.0.0")]
	public class AdaptiveTrigger : BaseUnityPlugin
	{
		public enum HeadsetVibrationType
		{
			Disabled,
			OnHit,
			OnRecoil,
			Both
		}

		public static ConfigEntry<VRControllerType> ControllerToUse;

		public static ConfigEntry<HeadsetVibrationType> HeadsetVibration;

		public static ConfigEntry<byte> HeadsetVibrationFrequency;

		public static ConfigEntry<bool> AllowDualStageTriggerEffect;

		public static ConfigEntry<bool> DisableEffectWhenEmpty;

		public static ConfigEntry<byte> ClickyEffectStrength;

		public static ConfigEntry<byte> RecoilFeedbackStrength;

		public static ConfigEntry<bool> UseVibrationFeedbackForRecoil;

		public static ConfigEntry<byte> VibrationFrequency;

		public static ConfigEntry<bool> OverrideTriggerEffectPos;

		public static ConfigEntry<byte> OverrideStartPos;

		public static ConfigEntry<byte> OverrideEndPos;

		public static int _leftShotsSoFar;

		public static int _rightShotsSoFar;

		public static bool _LeftHandTriggerEffectApplied;

		public static bool _LeftHandRecoilEffectApplied;

		public static bool _LeftHandTriggerEffectCleared;

		public static bool _RightHandTriggerEffectApplied;

		public static bool _RightHandRecoilEffectApplied;

		public static bool _RightHandTriggerEffectCleared;

		private static Coroutine _headsetVibrationCoroutine;

		public const string Id = "Niko666.Adaptive_Trigger_For_PSVR2";

		public static AdaptiveTrigger Instance { get; private set; }

		internal static ManualLogSource Logger { get; private set; }

		public static string Name => "Adaptive_Trigger_For_PSVR2";

		public static string Version => "2.0.0";

		public void Awake()
		{
			SetDllDirectory(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location));
			Instance = this;
			ControllerToUse = ((BaseUnityPlugin)this).Config.Bind<VRControllerType>("General", "ControllerToUse", VRControllerType.Both, "Enable Adaptive Trigger effect on selected controllers only. (Both, Left, Right)");
			HeadsetVibration = ((BaseUnityPlugin)this).Config.Bind<HeadsetVibrationType>("General", "HeadsetVibration", HeadsetVibrationType.Both, "Enable headset vibration effect. (Disabled, OnHit, OnRecoil, Both)");
			HeadsetVibrationFrequency = ((BaseUnityPlugin)this).Config.Bind<byte>("General", "HeadsetVibrationFrequency", (byte)15, "Headset vibration frequency. (1-25)");
			AllowDualStageTriggerEffect = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "AllowDualStageTriggerEffect", true, "Enable dual stage trigger effect. This will attempt to add a little bit of resistance before the each \"stage\" of the trigger. (I have no idea how a real Dual Stage trigger feels so sorry if it doesn't feel right)");
			DisableEffectWhenEmpty = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "DisableEffectWhenEmpty", false, "Disable trigger effect when the gun is empty or the hammer is not cocked.");
			ClickyEffectStrength = ((BaseUnityPlugin)this).Config.Bind<byte>("General", "ClickyEffectStrength", (byte)4, "Effect strength of clicky trigger effect. Going too high might cause weak recoil effect. (1-8)");
			RecoilFeedbackStrength = ((BaseUnityPlugin)this).Config.Bind<byte>("General", "RecoilFeedbackStrength", (byte)8, "Effect strength of firearm recoil effect. (0-8)");
			UseVibrationFeedbackForRecoil = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "UseVibrationFeedbackForRecoil", false, "Use vibration-based feedback for recoil effect. By default the mod use force-based feedback to emulate the recoil \"kick\" effect, but it doesn't work well with extremely high RPM weapons when doing full-auto shooting. Turning this option on will make the trigger vibrates instead of kicking, which is more suitable for full-auto shooting but worse the feeling when single-shot. ");
			VibrationFrequency = ((BaseUnityPlugin)this).Config.Bind<byte>("General", "VibrationFrequency", (byte)50, "Vibration frequency for recoil effect when 'UseVibrationFeedbackForRecoil' is enabled. (1-255)");
			OverrideTriggerEffectPos = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "OverrideTriggerEffectPos", false, "Override trigger effect position with user set values instead of reading from firearm's trigger thresholds. Not recommend but could be useful if you want to. Also this will disable dual stage trigger effect and empty effect.");
			OverrideStartPos = ((BaseUnityPlugin)this).Config.Bind<byte>("General", "OverrideStartPos", (byte)2, "Override start position of the trigger effect. (0-9)");
			OverrideEndPos = ((BaseUnityPlugin)this).Config.Bind<byte>("General", "OverrideStartPos", (byte)7, "Override end position of the trigger effect. (0-9)");
			Logger = ((BaseUnityPlugin)this).Logger;
			try
			{
				PSVR2ToolkitCAPI.Init();
				Logger.LogMessage((object)"PSVR2 Toolkit CAPI Initialized.");
				Harmony.CreateAndPatchAll(typeof(AdaptiveTriggerPatch), (string)null);
				Logger.LogMessage((object)("Fuk U Sony! Sent from Niko666.Adaptive_Trigger_For_PSVR2 " + Version));
			}
			catch (Exception ex)
			{
				Logger.LogError((object)("Failed to initialize PSVR2 Toolkit CAPI: " + ex.Message + "\n You need to install or update PSVR2 Toolkit!"));
			}
		}

		public void OnDestroy()
		{
			if (_headsetVibrationCoroutine != null)
			{
				((MonoBehaviour)this).StopCoroutine(_headsetVibrationCoroutine);
			}
			PSVR2ToolkitCAPI.SetHmdRumble(0);
			SetTriggerEffectOff(VRControllerType.Both);
			PSVR2ToolkitCAPI.Deinit();
			Logger.LogMessage((object)"PSVR2 Toolkit CAPI Deinitialized. It is now safe to turn off your computer.");
		}

		private static void SetTriggerEffectOff(VRControllerType controller)
		{
			ScePadTriggerEffectCommand command = new ScePadTriggerEffectCommand
			{
				mode = ScePadTriggerEffectMode.SCE_PAD_TRIGGER_EFFECT_MODE_OFF
			};
			PSVR2ToolkitCAPI.SetTriggerEffect(controller, ref command);
		}

		public static void ShotFired(FVRFireArm fireArm)
		{
			if ((Object)(object)((FVRInteractiveObject)fireArm).m_hand != (Object)null)
			{
				if (((FVRInteractiveObject)fireArm).m_hand.IsThisTheRightHand)
				{
					_rightShotsSoFar++;
				}
				else
				{
					_leftShotsSoFar++;
				}
			}
		}

		public static void ApplyTriggerEffect(byte startPos, byte endPos, VRControllerType Hand, float buzztime)
		{
			bool flag = ControllerToUse.Value == Hand || ControllerToUse.Value == VRControllerType.Both;
			if (Hand != VRControllerType.Left && Hand != VRControllerType.Right)
			{
				return;
			}
			bool num = Hand == VRControllerType.Left;
			ref bool reference = ref num ? ref _LeftHandTriggerEffectCleared : ref _RightHandTriggerEffectCleared;
			ref bool reference2 = ref num ? ref _LeftHandTriggerEffectApplied : ref _RightHandTriggerEffectApplied;
			ref bool reference3 = ref num ? ref _LeftHandRecoilEffectApplied : ref _RightHandRecoilEffectApplied;
			ref int reference4 = ref num ? ref _leftShotsSoFar : ref _rightShotsSoFar;
			reference = false;
			if (reference4 != 0)
			{
				if (!reference3 && flag)
				{
					if (UseVibrationFeedbackForRecoil.Value)
					{
						ScePadTriggerEffectCommand command = new ScePadTriggerEffectCommand
						{
							mode = ScePadTriggerEffectMode.SCE_PAD_TRIGGER_EFFECT_MODE_VIBRATION,
							commandData = 
							{
								vibrationPosition = 0,
								vibrationAmplitude = RecoilFeedbackStrength.Value,
								vibrationFrequency = VibrationFrequency.Value
							}
						};
						PSVR2ToolkitCAPI.SetTriggerEffect(Hand, ref command);
					}
					else
					{
						ScePadTriggerEffectCommand command2 = new ScePadTriggerEffectCommand
						{
							mode = ScePadTriggerEffectMode.SCE_PAD_TRIGGER_EFFECT_MODE_FEEDBACK,
							commandData = 
							{
								feedbackPosition = 0,
								feedbackStrength = RecoilFeedbackStrength.Value
							}
						};
						PSVR2ToolkitCAPI.SetTriggerEffect(Hand, ref command2);
					}
					reference3 = true;
				}
				if (buzztime > 0.01f && flag)
				{
					ScePadTriggerEffectCommand command3 = new ScePadTriggerEffectCommand
					{
						mode = ScePadTriggerEffectMode.SCE_PAD_TRIGGER_EFFECT_MODE_SLOPE_FEEDBACK,
						commandData = 
						{
							slopeStartPosition = (byte)Mathf.Clamp(startPos - 1, 0, 9),
							slopeEndPosition = (byte)Mathf.Clamp(endPos - 1, 0, 9),
							slopeStartStrength = 1,
							slopeEndStrength = ClickyEffectStrength.Value
						}
					};
					PSVR2ToolkitCAPI.SetTriggerEffect(Hand, ref command3);
					reference3 = false;
					reference4 = 0;
				}
			}
			else if (!reference2 && flag)
			{
				ScePadTriggerEffectCommand command4 = new ScePadTriggerEffectCommand
				{
					mode = ScePadTriggerEffectMode.SCE_PAD_TRIGGER_EFFECT_MODE_SLOPE_FEEDBACK,
					commandData = 
					{
						slopeStartPosition = (byte)Mathf.Clamp(startPos - 1, 0, 9),
						slopeEndPosition = (byte)Mathf.Clamp(endPos - 1, 0, 9),
						slopeStartStrength = 1,
						slopeEndStrength = ClickyEffectStrength.Value
					}
				};
				PSVR2ToolkitCAPI.SetTriggerEffect(Hand, ref command4);
				reference2 = true;
			}
		}

		public static void ClearTriggerEffect(VRControllerType Hand)
		{
			switch (Hand)
			{
			case VRControllerType.Left:
				if (!_LeftHandTriggerEffectCleared)
				{
					SetTriggerEffectOff(VRControllerType.Left);
					_LeftHandTriggerEffectApplied = false;
					_LeftHandRecoilEffectApplied = false;
					_leftShotsSoFar = 0;
					_LeftHandTriggerEffectCleared = true;
				}
				break;
			case VRControllerType.Right:
				if (!_RightHandTriggerEffectCleared)
				{
					SetTriggerEffectOff(VRControllerType.Right);
					_RightHandTriggerEffectApplied = false;
					_RightHandRecoilEffectApplied = false;
					_rightShotsSoFar = 0;
					_RightHandTriggerEffectCleared = true;
				}
				break;
			case VRControllerType.Both:
				if (!_LeftHandTriggerEffectCleared || !_RightHandTriggerEffectCleared)
				{
					SetTriggerEffectOff(VRControllerType.Both);
					_LeftHandTriggerEffectApplied = false;
					_LeftHandRecoilEffectApplied = false;
					_leftShotsSoFar = 0;
					_LeftHandTriggerEffectCleared = true;
					_RightHandTriggerEffectApplied = false;
					_RightHandRecoilEffectApplied = false;
					_rightShotsSoFar = 0;
					_RightHandTriggerEffectCleared = true;
				}
				break;
			}
		}

		public static void ApplyHeadsetVibration(float duration, byte freq)
		{
			if (_headsetVibrationCoroutine != null)
			{
				((MonoBehaviour)Instance).StopCoroutine(_headsetVibrationCoroutine);
			}
			_headsetVibrationCoroutine = ((MonoBehaviour)Instance).StartCoroutine(VibrationFadeRoutine(duration, freq));
		}

		private static IEnumerator VibrationFadeRoutine(float duration, byte startFreq)
		{
			byte clampedStartFreq = (byte)Mathf.Clamp((int)startFreq, 0, 25);
			float elapsedTime = 0f;
			while (elapsedTime < duration)
			{
				elapsedTime += Time.deltaTime;
				PSVR2ToolkitCAPI.SetHmdRumble((byte)Mathf.Lerp((float)(int)clampedStartFreq, 0f, elapsedTime / duration));
				yield return null;
			}
			PSVR2ToolkitCAPI.SetHmdRumble(0);
			_headsetVibrationCoroutine = null;
		}

		[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
		[return: MarshalAs(UnmanagedType.Bool)]
		private static extern bool SetDllDirectory(string lpPathName);
	}
	internal class AdaptiveTriggerPatch : MonoBehaviour
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static ShotFired <0>__ShotFired;
		}

		[HarmonyPatch(typeof(SteamVR_LoadLevel), "Begin")]
		[HarmonyPrefix]
		public static bool BeginPatch()
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Expected O, but got Unknown
			if ((Object)(object)GM.CurrentSceneSettings != (Object)null)
			{
				FVRSceneSettings currentSceneSettings = GM.CurrentSceneSettings;
				object obj = <>O.<0>__ShotFired;
				if (obj == null)
				{
					ShotFired val = AdaptiveTrigger.ShotFired;
					<>O.<0>__ShotFired = val;
					obj = (object)val;
				}
				currentSceneSettings.ShotFiredEvent -= (ShotFired)obj;
			}
			((BaseUnityPlugin)AdaptiveTrigger.Instance).Config.Reload();
			AdaptiveTrigger._LeftHandTriggerEffectCleared = false;
			AdaptiveTrigger._RightHandTriggerEffectCleared = false;
			AdaptiveTrigger.ClearTriggerEffect(VRControllerType.Both);
			return true;
		}

		[HarmonyPatch(typeof(FVRFireArm), "Awake")]
		[HarmonyPostfix]
		public static void ShotDetect()
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			FVRSceneSettings currentSceneSettings = GM.CurrentSceneSettings;
			object obj = <>O.<0>__ShotFired;
			if (obj == null)
			{
				ShotFired val = AdaptiveTrigger.ShotFired;
				<>O.<0>__ShotFired = val;
				obj = (object)val;
			}
			currentSceneSettings.ShotFiredEvent += (ShotFired)obj;
		}

		[HarmonyPatch(typeof(FVRPlayerBody), "HitEffect")]
		[HarmonyPrefix]
		public static bool HitEffectPatch()
		{
			if (AdaptiveTrigger.HeadsetVibration.Value == AdaptiveTrigger.HeadsetVibrationType.OnHit || AdaptiveTrigger.HeadsetVibration.Value == AdaptiveTrigger.HeadsetVibrationType.Both)
			{
				AdaptiveTrigger.ApplyHeadsetVibration(3f, AdaptiveTrigger.HeadsetVibrationFrequency.Value);
			}
			return true;
		}

		[HarmonyPatch(typeof(FVRViveHand), "Update")]
		[HarmonyPostfix]
		public static void ClearEffectOnDropButAlsoDoHeadsetVibration(FVRViveHand __instance)
		{
			if ((Object)(object)__instance.CurrentInteractable == (Object)null)
			{
				AdaptiveTrigger.ClearTriggerEffect(__instance.IsThisTheRightHand ? VRControllerType.Right : VRControllerType.Left);
			}
			if ((Object)(object)__instance.CurrentInteractable != (Object)null && __instance.CurrentInteractable is FVRFireArm && __instance.m_isBuzzing && (AdaptiveTrigger._rightShotsSoFar > 0 || AdaptiveTrigger._leftShotsSoFar > 0) && (AdaptiveTrigger.HeadsetVibration.Value == AdaptiveTrigger.HeadsetVibrationType.OnRecoil || AdaptiveTrigger.HeadsetVibration.Value == AdaptiveTrigger.HeadsetVibrationType.Both) && (Object)(object)__instance.m_curBuzz != (Object)null)
			{
				AdaptiveTrigger.ApplyHeadsetVibration(__instance.m_curBuzz.BuzzLength, AdaptiveTrigger.HeadsetVibrationFrequency.Value);
			}
		}

		private static bool IsWeaponEmpty(FVRFireArm w)
		{
			Handgun val = (Handgun)(object)((w is Handgun) ? w : null);
			int num;
			if (val == null)
			{
				BAP val2 = (BAP)(object)((w is BAP) ? w : null);
				num = ((val2 != null && (Object)(object)((FVRFireArm)val2).Magazine != (Object)null) ? 1 : 0);
			}
			else
			{
				num = (((Object)(object)((FVRFireArm)val).Magazine != (Object)null) ? 1 : 0);
			}
			bool flag = (byte)num != 0;
			Handgun val3 = (Handgun)(object)((w is Handgun) ? w : null);
			int num2;
			if (val3 == null)
			{
				BAP val4 = (BAP)(object)((w is BAP) ? w : null);
				num2 = ((val4 != null && ((FVRFireArm)val4).Magazine.HasARound()) ? 1 : 0);
			}
			else
			{
				num2 = (((FVRFireArm)val3).Magazine.HasARound() ? 1 : 0);
			}
			bool flag2 = (byte)num2 != 0;
			bool flag3 = ((Handgun)(((w is Handgun) ? w : null)?)).m_isHammerCocked ?? ((BAP)(((w is BAP) ? w : null)?)).m_isHammerCocked ?? ((Airgun)(((w is Airgun) ? w : null)?)).m_isHammerCocked ?? ((RailTater)(((w is RailTater) ? w : null)?)).m_isHammerCocked ?? ((SingleActionRevolver)(((w is SingleActionRevolver) ? w : null)?)).m_isHammerCocked ?? false;
			bool flag4 = ((Handgun)(((w is Handgun) ? w : null)?)).Chamber.IsFull ?? ((BAP)(((w is BAP) ? w : null)?)).Chamber.IsFull ?? ((Airgun)(((w is Airgun) ? w : null)?)).Chamber.IsFull ?? ((RailTater)(((w is RailTater) ? w : null)?)).Chamber.IsFull ?? false;
			if (!flag || flag2 || flag4 || flag3)
			{
				if (!flag && !flag4)
				{
					return !flag3;
				}
				return false;
			}
			return true;
		}

		[HarmonyPatch(typeof(FVRFireArm), "FVRUpdate")]
		[HarmonyPostfix]
		public static void GlobalTriggerEffect(FVRFireArm __instance)
		{
			if (!((Object)(object)((FVRInteractiveObject)__instance).m_hand != (Object)null))
			{
				return;
			}
			if ((Object)(object)((FVRPhysicalObject)__instance).savedGrip != (Object)null)
			{
				AdaptiveTrigger.ClearTriggerEffect(((FVRInteractiveObject)__instance).m_hand.IsThisTheRightHand ? VRControllerType.Right : VRControllerType.Left);
				return;
			}
			AdaptiveTrigger._LeftHandTriggerEffectCleared = false;
			AdaptiveTrigger._RightHandTriggerEffectCleared = false;
			byte startPos;
			byte endPos;
			if (AdaptiveTrigger.OverrideTriggerEffectPos.Value)
			{
				startPos = (byte)Mathf.Clamp((int)AdaptiveTrigger.OverrideStartPos.Value, 0, 9);
				endPos = (byte)Mathf.Clamp((int)AdaptiveTrigger.OverrideEndPos.Value, 0, 9);
				AdaptiveTrigger.ApplyTriggerEffect(startPos, endPos, ((FVRInteractiveObject)__instance).m_hand.IsThisTheRightHand ? VRControllerType.Right : VRControllerType.Left, ((FVRInteractiveObject)__instance).m_hand.m_buzztime);
				return;
			}
			ClosedBoltWeapon val = (ClosedBoltWeapon)(object)((__instance is ClosedBoltWeapon) ? __instance : null);
			if (val == null)
			{
				OpenBoltReceiver val2 = (OpenBoltReceiver)(object)((__instance is OpenBoltReceiver) ? __instance : null);
				if (val2 == null)
				{
					Handgun val3 = (Handgun)(object)((__instance is Handgun) ? __instance : null);
					if (val3 == null)
					{
						TubeFedShotgun val4 = (TubeFedShotgun)(object)((__instance is TubeFedShotgun) ? __instance : null);
						if (val4 == null)
						{
							BoltActionRifle val5 = (BoltActionRifle)(object)((__instance is BoltActionRifle) ? __instance : null);
							if (val5 == null)
							{
								if (!(__instance is BreakActionWeapon))
								{
									if (!(__instance is Revolver))
									{
										SingleActionRevolver val6 = (SingleActionRevolver)(object)((__instance is SingleActionRevolver) ? __instance : null);
										if (val6 == null)
										{
											RevolvingShotgun val7 = (RevolvingShotgun)(object)((__instance is RevolvingShotgun) ? __instance : null);
											if (val7 == null)
											{
												LAPD2019 val8 = (LAPD2019)(object)((__instance is LAPD2019) ? __instance : null);
												if (val8 == null)
												{
													BAP val9 = (BAP)(object)((__instance is BAP) ? __instance : null);
													if (val9 == null)
													{
														if (!(__instance is PotatoGun))
														{
															GrappleGun val10 = (GrappleGun)(object)((__instance is GrappleGun) ? __instance : null);
															if (val10 == null)
															{
																Airgun val11 = (Airgun)(object)((__instance is Airgun) ? __instance : null);
																if (val11 == null)
																{
																	CarlGustaf val12 = (CarlGustaf)(object)((__instance is CarlGustaf) ? __instance : null);
																	if (val12 == null)
																	{
																		RailTater val13 = (RailTater)(object)((__instance is RailTater) ? __instance : null);
																		if (val13 == null)
																		{
																			FlameThrower val14 = (FlameThrower)(object)((__instance is FlameThrower) ? __instance : null);
																			if (val14 == null)
																			{
																				sblp val15 = (sblp)(object)((__instance is sblp) ? __instance : null);
																				if (val15 != null)
																				{
																					startPos = (byte)Mathf.Clamp((int)(val15.TriggerResetThreshold * 10f - 1f), 0, 9);
																					endPos = (byte)Mathf.Clamp((int)(val15.TriggerFiringThreshold * 10f - 1f), 0, 9);
																					AdaptiveTrigger.ApplyTriggerEffect(startPos, endPos, ((FVRInteractiveObject)__instance).m_hand.IsThisTheRightHand ? VRControllerType.Right : VRControllerType.Left, ((FVRInteractiveObject)__instance).m_hand.m_buzztime);
																				}
																				else
																				{
																					startPos = 2;
																					endPos = 7;
																					AdaptiveTrigger.ApplyTriggerEffect(startPos, endPos, ((FVRInteractiveObject)__instance).m_hand.IsThisTheRightHand ? VRControllerType.Right : VRControllerType.Left, ((FVRInteractiveObject)__instance).m_hand.m_buzztime);
																				}
																			}
																			else
																			{
																				startPos = 3;
																				endPos = (byte)Mathf.Clamp((int)(val14.TriggerFiringThreshold * 10f - 1f), 0, 9);
																				AdaptiveTrigger.ApplyTriggerEffect(startPos, endPos, ((FVRInteractiveObject)__instance).m_hand.IsThisTheRightHand ? VRControllerType.Right : VRControllerType.Left, ((FVRInteractiveObject)__instance).m_hand.m_buzztime);
																			}
																		}
																		else
																		{
																			startPos = (byte)Mathf.Clamp((int)(val13.TriggerResetThreshold * 10f - 1f), 0, 9);
																			endPos = (byte)Mathf.Clamp((int)(val13.TriggerFiringThreshold * 10f - 1f), 0, 9);
																			if (AdaptiveTrigger.DisableEffectWhenEmpty.Value && !val13.m_isHammerCocked)
																			{
																				AdaptiveTrigger.ClearTriggerEffect(((FVRInteractiveObject)__instance).m_hand.IsThisTheRightHand ? VRControllerType.Right : VRControllerType.Left);
																			}
																			else
																			{
																				AdaptiveTrigger.ApplyTriggerEffect(startPos, endPos, ((FVRInteractiveObject)__instance).m_hand.IsThisTheRightHand ? VRControllerType.Right : VRControllerType.Left, ((FVRInteractiveObject)__instance).m_hand.m_buzztime);
																			}
																		}
																	}
																	else
																	{
																		startPos = (byte)Mathf.Clamp((int)(val12.TriggerResetThreshold * 10f - 1f), 0, 9);
																		endPos = (byte)Mathf.Clamp((int)(val12.TriggerFiringThreshold * 10f - 1f), 0, 9);
																		AdaptiveTrigger.ApplyTriggerEffect(startPos, endPos, ((FVRInteractiveObject)__instance).m_hand.IsThisTheRightHand ? VRControllerType.Right : VRControllerType.Left, ((FVRInteractiveObject)__instance).m_hand.m_buzztime);
																	}
																}
																else
																{
																	startPos = (byte)Mathf.Clamp((int)(val11.TriggerResetThreshold * 10f - 1f), 0, 9);
																	endPos = (byte)Mathf.Clamp((int)(val11.TriggerFiringThreshold * 10f - 1f), 0, 9);
																	if (AdaptiveTrigger.DisableEffectWhenEmpty.Value && !val11.m_isHammerCocked)
																	{
																		AdaptiveTrigger.ClearTriggerEffect(((FVRInteractiveObject)__instance).m_hand.IsThisTheRightHand ? VRControllerType.Right : VRControllerType.Left);
																	}
																	else
																	{
																		AdaptiveTrigger.ApplyTriggerEffect(startPos, endPos, ((FVRInteractiveObject)__instance).m_hand.IsThisTheRightHand ? VRControllerType.Right : VRControllerType.Left, ((FVRInteractiveObject)__instance).m_hand.m_buzztime);
																	}
																}
															}
															else
															{
																startPos = (byte)Mathf.Clamp((int)(val10.TriggerResetThreshold * 10f - 1f), 0, 9);
																endPos = (byte)Mathf.Clamp((int)(val10.TriggerBreakThreshold * 10f - 1f), 0, 9);
																AdaptiveTrigger.ApplyTriggerEffect(startPos, endPos, ((FVRInteractiveObject)__instance).m_hand.IsThisTheRightHand ? VRControllerType.Right : VRControllerType.Left, ((FVRInteractiveObject)__instance).m_hand.m_buzztime);
															}
														}
														else
														{
															startPos = 4;
															endPos = 7;
															AdaptiveTrigger.ApplyTriggerEffect(startPos, endPos, ((FVRInteractiveObject)__instance).m_hand.IsThisTheRightHand ? VRControllerType.Right : VRControllerType.Left, ((FVRInteractiveObject)__instance).m_hand.m_buzztime);
														}
													}
													else
													{
														startPos = (byte)Mathf.Clamp((int)(val9.TriggerResetThreshold * 10f - 1f), 0, 9);
														endPos = (byte)Mathf.Clamp((int)(val9.TriggerFiringThreshold * 10f - 1f), 0, 9);
														if (AdaptiveTrigger.DisableEffectWhenEmpty.Value && IsWeaponEmpty((FVRFireArm)(object)val9))
														{
															AdaptiveTrigger.ClearTriggerEffect(((FVRInteractiveObject)__instance).m_hand.IsThisTheRightHand ? VRControllerType.Right : VRControllerType.Left);
														}
														else
														{
															AdaptiveTrigger.ApplyTriggerEffect(startPos, endPos, ((FVRInteractiveObject)__instance).m_hand.IsThisTheRightHand ? VRControllerType.Right : VRControllerType.Left, ((FVRInteractiveObject)__instance).m_hand.m_buzztime);
														}
													}
												}
												else
												{
													startPos = (byte)Mathf.Clamp((int)(val8.TriggerResetThreshold * 10f - 1f), 0, 9);
													endPos = (byte)Mathf.Clamp((int)(val8.TriggerFireThreshold * 10f - 1f), 0, 9);
													AdaptiveTrigger.ApplyTriggerEffect(startPos, endPos, ((FVRInteractiveObject)__instance).m_hand.IsThisTheRightHand ? VRControllerType.Right : VRControllerType.Left, ((FVRInteractiveObject)__instance).m_hand.m_buzztime);
												}
											}
											else
											{
												startPos = (byte)Mathf.Clamp((int)(val7.TriggerResetThreshold * 10f - 1f), 0, 9);
												endPos = (byte)Mathf.Clamp((int)(val7.TriggerFiringThreshold * 10f - 1f), 0, 9);
												AdaptiveTrigger.ApplyTriggerEffect(startPos, endPos, ((FVRInteractiveObject)__instance).m_hand.IsThisTheRightHand ? VRControllerType.Right : VRControllerType.Left, ((FVRInteractiveObject)__instance).m_hand.m_buzztime);
											}
										}
										else
										{
											startPos = (byte)Mathf.Clamp((int)(val6.TriggerThreshold * 10f - 2f), 0, 9);
											endPos = (byte)Mathf.Clamp((int)(val6.TriggerThreshold * 10f - 1f), 0, 9);
											if (AdaptiveTrigger.DisableEffectWhenEmpty.Value && !val6.m_isHammerCocked)
											{
												AdaptiveTrigger.ClearTriggerEffect(((FVRInteractiveObject)__instance).m_hand.IsThisTheRightHand ? VRControllerType.Right : VRControllerType.Left);
											}
											else
											{
												AdaptiveTrigger.ApplyTriggerEffect(startPos, endPos, ((FVRInteractiveObject)__instance).m_hand.IsThisTheRightHand ? VRControllerType.Right : VRControllerType.Left, ((FVRInteractiveObject)__instance).m_hand.m_buzztime);
											}
										}
									}
									else
									{
										startPos = 2;
										endPos = 9;
										AdaptiveTrigger.ApplyTriggerEffect(startPos, endPos, ((FVRInteractiveObject)__instance).m_hand.IsThisTheRightHand ? VRControllerType.Right : VRControllerType.Left, ((FVRInteractiveObject)__instance).m_hand.m_buzztime);
									}
								}
								else
								{
									startPos = 4;
									endPos = 7;
									AdaptiveTrigger.ApplyTriggerEffect(startPos, endPos, ((FVRInteractiveObject)__instance).m_hand.IsThisTheRightHand ? VRControllerType.Right : VRControllerType.Left, ((FVRInteractiveObject)__instance).m_hand.m_buzztime);
								}
							}
							else
							{
								startPos = (byte)Mathf.Clamp((int)(val5.TriggerResetThreshold * 10f - 1f), 0, 9);
								endPos = (byte)Mathf.Clamp((int)(val5.TriggerFiringThreshold * 10f - 1f), 0, 9);
								if (AdaptiveTrigger.DisableEffectWhenEmpty.Value && IsWeaponEmpty((FVRFireArm)(object)val5))
								{
									AdaptiveTrigger.ClearTriggerEffect(((FVRInteractiveObject)__instance).m_hand.IsThisTheRightHand ? VRControllerType.Right : VRControllerType.Left);
								}
								else
								{
									AdaptiveTrigger.ApplyTriggerEffect(startPos, endPos, ((FVRInteractiveObject)__instance).m_hand.IsThisTheRightHand ? VRControllerType.Right : VRControllerType.Left, ((FVRInteractiveObject)__instance).m_hand.m_buzztime);
								}
							}
						}
						else
						{
							startPos = (byte)Mathf.Clamp((int)(val4.TriggerResetThreshold * 10f - 1f), 0, 9);
							endPos = (byte)Mathf.Clamp((int)(val4.TriggerBreakThreshold * 10f - 1f), 0, 9);
							if (AdaptiveTrigger.DisableEffectWhenEmpty.Value && IsWeaponEmpty((FVRFireArm)(object)val4))
							{
								AdaptiveTrigger.ClearTriggerEffect(((FVRInteractiveObject)__instance).m_hand.IsThisTheRightHand ? VRControllerType.Right : VRControllerType.Left);
							}
							else
							{
								AdaptiveTrigger.ApplyTriggerEffect(startPos, endPos, ((FVRInteractiveObject)__instance).m_hand.IsThisTheRightHand ? VRControllerType.Right : VRControllerType.Left, ((FVRInteractiveObject)__instance).m_hand.m_buzztime);
							}
						}
					}
					else
					{
						startPos = (byte)Mathf.Clamp((int)(val3.TriggerResetThreshold * 10f - 1f), 0, 9);
						endPos = (byte)Mathf.Clamp((int)(val3.TriggerBreakThreshold * 10f - 1f), 0, 9);
						if (AdaptiveTrigger.DisableEffectWhenEmpty.Value && IsWeaponEmpty((FVRFireArm)(object)val3))
						{
							AdaptiveTrigger.ClearTriggerEffect(((FVRInteractiveObject)__instance).m_hand.IsThisTheRightHand ? VRControllerType.Right : VRControllerType.Left);
						}
						else
						{
							AdaptiveTrigger.ApplyTriggerEffect(startPos, endPos, ((FVRInteractiveObject)__instance).m_hand.IsThisTheRightHand ? VRControllerType.Right : VRControllerType.Left, ((FVRInteractiveObject)__instance).m_hand.m_buzztime);
						}
					}
				}
				else
				{
					startPos = (byte)Mathf.Clamp((int)(val2.TriggerResetThreshold * 10f - 1f), 0, 9);
					endPos = (byte)Mathf.Clamp((int)(val2.TriggerFiringThreshold * 10f - 1f), 0, 9);
					if (AdaptiveTrigger.DisableEffectWhenEmpty.Value && IsWeaponEmpty((FVRFireArm)(object)val2))
					{
						AdaptiveTrigger.ClearTriggerEffect(((FVRInteractiveObject)__instance).m_hand.IsThisTheRightHand ? VRControllerType.Right : VRControllerType.Left);
					}
					else
					{
						AdaptiveTrigger.ApplyTriggerEffect(startPos, endPos, ((FVRInteractiveObject)__instance).m_hand.IsThisTheRightHand ? VRControllerType.Right : VRControllerType.Left, ((FVRInteractiveObject)__instance).m_hand.m_buzztime);
					}
				}
				return;
			}
			startPos = (byte)Mathf.Clamp((int)(val.TriggerResetThreshold * 10f - 1f), 0, 9);
			endPos = (byte)Mathf.Clamp((int)(val.TriggerFiringThreshold * 10f - 1f), 0, 9);
			if (AdaptiveTrigger.DisableEffectWhenEmpty.Value && IsWeaponEmpty((FVRFireArm)(object)val))
			{
				AdaptiveTrigger.ClearTriggerEffect(((FVRInteractiveObject)__instance).m_hand.IsThisTheRightHand ? VRControllerType.Right : VRControllerType.Left);
			}
			else if (val.UsesDualStageFullAuto && AdaptiveTrigger.AllowDualStageTriggerEffect.Value)
			{
				if (val.m_triggerFloat < val.TriggerFiringThreshold)
				{
					startPos = (byte)Mathf.Clamp((int)(val.TriggerResetThreshold * 10f - 1f), 0, 9);
					endPos = (byte)Mathf.Clamp((int)(val.TriggerFiringThreshold * 10f - 1f), 0, 9);
					AdaptiveTrigger.ApplyTriggerEffect(startPos, endPos, ((FVRInteractiveObject)__instance).m_hand.IsThisTheRightHand ? VRControllerType.Right : VRControllerType.Left, ((FVRInteractiveObject)__instance).m_hand.m_buzztime);
				}
				else
				{
					startPos = (byte)Mathf.Clamp((int)(val.TriggerFiringThreshold * 10f - 1f), 0, 9);
					endPos = (byte)Mathf.Clamp((int)(val.TriggerDualStageThreshold * 10f - 1f), 0, 9);
					AdaptiveTrigger.ApplyTriggerEffect(startPos, endPos, ((FVRInteractiveObject)__instance).m_hand.IsThisTheRightHand ? VRControllerType.Right : VRControllerType.Left, ((FVRInteractiveObject)__instance).m_hand.m_buzztime);
				}
			}
			else
			{
				AdaptiveTrigger.ApplyTriggerEffect(startPos, endPos, ((FVRInteractiveObject)__instance).m_hand.IsThisTheRightHand ? VRControllerType.Right : VRControllerType.Left, ((FVRInteractiveObject)__instance).m_hand.m_buzztime);
			}
		}

		[HarmonyPatch(typeof(AttachableFirearmPhysicalObject), "UpdateInteraction")]
		[HarmonyPostfix]
		public static void AttachableFirearmPhysicalObjectTriggerEffect(AttachableFirearmPhysicalObject __instance)
		{
			if ((Object)(object)((FVRInteractiveObject)__instance).m_hand != (Object)null)
			{
				AdaptiveTrigger._LeftHandTriggerEffectCleared = false;
				AdaptiveTrigger._RightHandTriggerEffectCleared = false;
				byte startPos = 2;
				byte endPos = 7;
				if (AdaptiveTrigger.OverrideTriggerEffectPos.Value)
				{
					startPos = (byte)Mathf.Clamp(AdaptiveTrigger.OverrideStartPos.Value + 1, 0, 10);
					endPos = (byte)Mathf.Clamp(AdaptiveTrigger.OverrideEndPos.Value + 1, 0, 10);
				}
				AdaptiveTrigger.ApplyTriggerEffect(startPos, endPos, ((FVRInteractiveObject)__instance).m_hand.IsThisTheRightHand ? VRControllerType.Right : VRControllerType.Left, ((FVRInteractiveObject)__instance).m_hand.m_buzztime);
			}
		}

		[HarmonyPatch(typeof(AttachableFirearmInterface), "UpdateInteraction")]
		[HarmonyPostfix]
		public static void AttachableFirearmInterfaceTriggerEffect(AttachableFirearmInterface __instance)
		{
			if ((Object)(object)((FVRInteractiveObject)__instance).m_hand != (Object)null)
			{
				AdaptiveTrigger._LeftHandTriggerEffectCleared = false;
				AdaptiveTrigger._RightHandTriggerEffectCleared = false;
				byte startPos = 2;
				byte endPos = 7;
				if (AdaptiveTrigger.OverrideTriggerEffectPos.Value)
				{
					startPos = (byte)Mathf.Clamp(AdaptiveTrigger.OverrideStartPos.Value + 1, 0, 10);
					endPos = (byte)Mathf.Clamp(AdaptiveTrigger.OverrideEndPos.Value + 1, 0, 10);
				}
				AdaptiveTrigger.ApplyTriggerEffect(startPos, endPos, ((FVRInteractiveObject)__instance).m_hand.IsThisTheRightHand ? VRControllerType.Right : VRControllerType.Left, ((FVRInteractiveObject)__instance).m_hand.m_buzztime);
			}
		}
	}
}
namespace plugin.Properties
{
	[CompilerGenerated]
	[GeneratedCode("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.14.0.0")]
	internal sealed class Settings : ApplicationSettingsBase
	{
		private static Settings defaultInstance = (Settings)(object)SettingsBase.Synchronized((SettingsBase)(object)new Settings());

		public static Settings Default => defaultInstance;
	}
}

System.Threading.Tasks.NET35.dll

Decompiled 5 days ago
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Concurrent.Partitioners;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Globalization;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Security;
using System.Text;
using System.Threading;

[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyFileVersion("3.0.2.0")]
[assembly: AssemblyCompany("Robert McLaws")]
[assembly: Guid("693242a3-2f03-494f-b531-ab6265dfeedb")]
[assembly: AssemblyTitle("System.Threading.Tasks.NET35")]
[assembly: AssemblyDescription("The Mono port of the Task Parallel Library ported to .NET 3.5")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyProduct("System.Threading.Tasks.NET35")]
[assembly: AssemblyCopyright("Copyright © 2011 Robert McLaws. Contains code originally Copyright © 2009-2012 Xamarin.")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: AssemblyVersion("3.0.2.0")]
namespace System.Threading
{
	[ComVisible(true)]
	public sealed class Timer : MarshalByRefObject, IDisposable
	{
		private sealed class TimerComparer : IComparer
		{
			public int Compare(object x, object y)
			{
				if (!(x is Timer timer))
				{
					return -1;
				}
				if (!(y is Timer timer2))
				{
					return 1;
				}
				long num = timer.next_run - timer2.next_run;
				if (num == 0)
				{
					if (x != y)
					{
						return -1;
					}
					return 0;
				}
				if (num <= 0)
				{
					return -1;
				}
				return 1;
			}
		}

		private sealed class Scheduler
		{
			private static Scheduler instance;

			private SortedList list;

			private ManualResetEvent changed;

			private static WaitCallback TimerCaller;

			public static Scheduler Instance => instance;

			static Scheduler()
			{
				TimerCaller = TimerCB;
				instance = new Scheduler();
			}

			private Scheduler()
			{
				changed = new ManualResetEvent(initialState: false);
				list = new SortedList(new TimerComparer(), 1024);
				Thread thread = new Thread(SchedulerThread);
				thread.IsBackground = true;
				thread.Start();
			}

			public void Remove(Timer timer)
			{
				if (timer.next_run == 0 || timer.next_run == long.MaxValue)
				{
					return;
				}
				lock (this)
				{
					InternalRemove(timer);
				}
			}

			public void Change(Timer timer, long new_next_run)
			{
				bool flag = false;
				lock (this)
				{
					InternalRemove(timer);
					if (new_next_run == long.MaxValue)
					{
						timer.next_run = new_next_run;
						return;
					}
					if (!timer.disposed)
					{
						timer.next_run = new_next_run;
						Add(timer);
						flag = list.GetByIndex(0) == timer;
					}
				}
				if (flag)
				{
					changed.Set();
				}
			}

			private int FindByDueTime(long nr)
			{
				int i = 0;
				int num = list.Count - 1;
				if (num < 0)
				{
					return -1;
				}
				if (num < 20)
				{
					for (; i <= num; i++)
					{
						Timer timer = (Timer)list.GetByIndex(i);
						if (timer.next_run == nr)
						{
							return i;
						}
						if (timer.next_run > nr)
						{
							return -1;
						}
					}
					return -1;
				}
				while (i <= num)
				{
					int num2 = i + (num - i >> 1);
					Timer timer2 = (Timer)list.GetByIndex(num2);
					if (nr == timer2.next_run)
					{
						return num2;
					}
					if (nr > timer2.next_run)
					{
						i = num2 + 1;
					}
					else
					{
						num = num2 - 1;
					}
				}
				return -1;
			}

			private void Add(Timer timer)
			{
				int num = FindByDueTime(timer.next_run);
				if (num != -1)
				{
					bool flag = ((long.MaxValue - timer.next_run > 20000) ? true : false);
					Timer timer2;
					do
					{
						num++;
						if (flag)
						{
							timer.next_run++;
						}
						else
						{
							timer.next_run--;
						}
						if (num >= list.Count)
						{
							break;
						}
						timer2 = (Timer)list.GetByIndex(num);
					}
					while (timer2.next_run == timer.next_run);
				}
				list.Add(timer, timer);
			}

			private int InternalRemove(Timer timer)
			{
				int num = list.IndexOfKey(timer);
				if (num >= 0)
				{
					list.RemoveAt(num);
				}
				return num;
			}

			private static void TimerCB(object o)
			{
				Timer timer = (Timer)o;
				try
				{
					timer.callback(timer.state);
				}
				catch
				{
				}
			}

			private void SchedulerThread()
			{
				Thread.CurrentThread.Name = "Timer-Scheduler";
				ArrayList arrayList = new ArrayList(512);
				while (true)
				{
					int num = -1;
					long ticks = DateTime.Now.Ticks;
					lock (this)
					{
						changed.Reset();
						int num2 = list.Count;
						int num3;
						for (num3 = 0; num3 < num2; num3++)
						{
							Timer timer = (Timer)list.GetByIndex(num3);
							if (timer.next_run > ticks)
							{
								break;
							}
							list.RemoveAt(num3);
							num2--;
							num3--;
							ThreadPool.QueueUserWorkItem(TimerCaller, timer);
							long period_ms = timer.period_ms;
							long due_time_ms = timer.due_time_ms;
							if (period_ms == -1 || ((period_ms == 0 || period_ms == -1) && due_time_ms != -1))
							{
								timer.next_run = long.MaxValue;
							}
							else
							{
								timer.next_run = DateTime.Now.Ticks + 10000 * timer.period_ms;
								arrayList.Add(timer);
							}
						}
						num2 = arrayList.Count;
						for (num3 = 0; num3 < num2; num3++)
						{
							Timer timer2 = (Timer)arrayList[num3];
							Add(timer2);
						}
						arrayList.Clear();
						ShrinkIfNeeded(arrayList, 512);
						int capacity = list.Capacity;
						num2 = list.Count;
						if (capacity > 1024 && num2 > 0 && capacity / num2 > 3)
						{
							list.Capacity = num2 * 2;
						}
						long num4 = long.MaxValue;
						if (list.Count > 0)
						{
							num4 = ((Timer)list.GetByIndex(0)).next_run;
						}
						num = -1;
						if (num4 != long.MaxValue)
						{
							long num5 = num4 - DateTime.Now.Ticks;
							num = (int)(num5 / 10000);
							if (num < 0)
							{
								num = 0;
							}
						}
					}
					changed.WaitOne(num);
				}
			}

			private void ShrinkIfNeeded(ArrayList list, int initial)
			{
				int capacity = list.Capacity;
				int count = list.Count;
				if (capacity > initial && count > 0 && capacity / count > 3)
				{
					list.Capacity = count * 2;
				}
			}
		}

		private const long MaxValue = 4294967294L;

		private static Scheduler scheduler = Scheduler.Instance;

		private TimerCallback callback;

		private object state;

		private long due_time_ms;

		private long period_ms;

		private long next_run;

		private bool disposed;

		public Timer(TimerCallback callback, object state, int dueTime, int period)
		{
			Init(callback, state, dueTime, period);
		}

		public Timer(TimerCallback callback, object state, long dueTime, long period)
		{
			Init(callback, state, dueTime, period);
		}

		public Timer(TimerCallback callback, object state, TimeSpan dueTime, TimeSpan period)
		{
			Init(callback, state, (long)dueTime.TotalMilliseconds, (long)period.TotalMilliseconds);
		}

		[CLSCompliant(false)]
		public Timer(TimerCallback callback, object state, uint dueTime, uint period)
		{
			Init(callback, state, (dueTime == uint.MaxValue) ? (-1L) : ((long)dueTime), (period == uint.MaxValue) ? (-1L) : ((long)period));
		}

		public Timer(TimerCallback callback)
		{
			Init(callback, this, -1L, -1L);
		}

		private void Init(TimerCallback callback, object state, long dueTime, long period)
		{
			if (callback == null)
			{
				throw new ArgumentNullException("callback");
			}
			this.callback = callback;
			this.state = state;
			Change(dueTime, period, first: true);
		}

		public bool Change(int dueTime, int period)
		{
			return Change(dueTime, period, first: false);
		}

		public bool Change(TimeSpan dueTime, TimeSpan period)
		{
			return Change((long)dueTime.TotalMilliseconds, (long)period.TotalMilliseconds, first: false);
		}

		[CLSCompliant(false)]
		public bool Change(uint dueTime, uint period)
		{
			long dueTime2 = ((dueTime == uint.MaxValue) ? (-1L) : ((long)dueTime));
			long period2 = ((period == uint.MaxValue) ? (-1L) : ((long)period));
			return Change(dueTime2, period2, first: false);
		}

		public void Dispose()
		{
			if (!disposed)
			{
				disposed = true;
				scheduler.Remove(this);
			}
		}

		public bool Change(long dueTime, long period)
		{
			return Change(dueTime, period, first: false);
		}

		private bool Change(long dueTime, long period, bool first)
		{
			if (dueTime > 4294967294u)
			{
				throw new ArgumentOutOfRangeException("dueTime", "Due time too large");
			}
			if (period > 4294967294u)
			{
				throw new ArgumentOutOfRangeException("period", "Period too large");
			}
			if (dueTime < -1)
			{
				throw new ArgumentOutOfRangeException("dueTime");
			}
			if (period < -1)
			{
				throw new ArgumentOutOfRangeException("period");
			}
			if (disposed)
			{
				return false;
			}
			due_time_ms = dueTime;
			period_ms = period;
			long new_next_run;
			if (dueTime == 0)
			{
				new_next_run = 0L;
			}
			else if (dueTime < 0)
			{
				new_next_run = long.MaxValue;
				if (first)
				{
					next_run = new_next_run;
					return true;
				}
			}
			else
			{
				new_next_run = dueTime * 10000 + DateTime.Now.Ticks;
			}
			scheduler.Change(this, new_next_run);
			return true;
		}

		public bool Dispose(WaitHandle notifyObject)
		{
			if (notifyObject == null)
			{
				throw new ArgumentNullException("notifyObject");
			}
			Dispose();
			return true;
		}
	}
}
namespace System.Collections.Concurrent
{
	internal class SplitOrderedList<TKey, T>
	{
		private class Node
		{
			public bool Marked;

			public ulong Key;

			public TKey SubKey;

			public T Data;

			public Node Next;

			public Node Init(ulong key, TKey subKey, T data)
			{
				Key = key;
				SubKey = subKey;
				Data = data;
				Marked = false;
				Next = null;
				return this;
			}

			public Node Init(ulong key)
			{
				Key = key;
				Data = default(T);
				Next = null;
				Marked = false;
				SubKey = default(TKey);
				return this;
			}

			public Node Init(Node wrapped)
			{
				Marked = true;
				Next = wrapped;
				Key = 0uL;
				Data = default(T);
				SubKey = default(TKey);
				return this;
			}
		}

		private class NodeObjectPool : ObjectPool<Node>
		{
			protected override Node Creator()
			{
				return new Node();
			}
		}

		private struct SimpleRwLock
		{
			private const int RwWait = 1;

			private const int RwWrite = 2;

			private const int RwRead = 4;

			private int rwlock;

			public void EnterReadLock()
			{
				SpinWait spinWait = default(SpinWait);
				while (true)
				{
					if ((rwlock & 3) > 0)
					{
						spinWait.SpinOnce();
						continue;
					}
					if ((Interlocked.Add(ref rwlock, 4) & 1) == 0)
					{
						break;
					}
					Interlocked.Add(ref rwlock, -4);
				}
			}

			public void ExitReadLock()
			{
				Interlocked.Add(ref rwlock, -4);
			}

			public void EnterWriteLock()
			{
				SpinWait spinWait = default(SpinWait);
				while (true)
				{
					int num = rwlock;
					if (num < 2)
					{
						if (Interlocked.CompareExchange(ref rwlock, 2, num) == num)
						{
							break;
						}
						num = rwlock;
					}
					while ((num & 1) == 0 && Interlocked.CompareExchange(ref rwlock, num | 1, num) != num)
					{
						num = rwlock;
					}
					while (rwlock > 1)
					{
						spinWait.SpinOnce();
					}
				}
			}

			public void ExitWriteLock()
			{
				Interlocked.Add(ref rwlock, -2);
			}
		}

		private const int MaxLoad = 5;

		private const uint BucketSize = 512u;

		private static readonly NodeObjectPool pool = new NodeObjectPool();

		private Node head;

		private Node tail;

		private Node[] buckets = new Node[512];

		private int count;

		private int size = 2;

		private SimpleRwLock slim = default(SimpleRwLock);

		private readonly IEqualityComparer<TKey> comparer;

		private static readonly byte[] reverseTable = new byte[256]
		{
			0, 128, 64, 192, 32, 160, 96, 224, 16, 144,
			80, 208, 48, 176, 112, 240, 8, 136, 72, 200,
			40, 168, 104, 232, 24, 152, 88, 216, 56, 184,
			120, 248, 4, 132, 68, 196, 36, 164, 100, 228,
			20, 148, 84, 212, 52, 180, 116, 244, 12, 140,
			76, 204, 44, 172, 108, 236, 28, 156, 92, 220,
			60, 188, 124, 252, 2, 130, 66, 194, 34, 162,
			98, 226, 18, 146, 82, 210, 50, 178, 114, 242,
			10, 138, 74, 202, 42, 170, 106, 234, 26, 154,
			90, 218, 58, 186, 122, 250, 6, 134, 70, 198,
			38, 166, 102, 230, 22, 150, 86, 214, 54, 182,
			118, 246, 14, 142, 78, 206, 46, 174, 110, 238,
			30, 158, 94, 222, 62, 190, 126, 254, 1, 129,
			65, 193, 33, 161, 97, 225, 17, 145, 81, 209,
			49, 177, 113, 241, 9, 137, 73, 201, 41, 169,
			105, 233, 25, 153, 89, 217, 57, 185, 121, 249,
			5, 133, 69, 197, 37, 165, 101, 229, 21, 149,
			85, 213, 53, 181, 117, 245, 13, 141, 77, 205,
			45, 173, 109, 237, 29, 157, 93, 221, 61, 189,
			125, 253, 3, 131, 67, 195, 35, 163, 99, 227,
			19, 147, 83, 211, 51, 179, 115, 243, 11, 139,
			75, 203, 43, 171, 107, 235, 27, 155, 91, 219,
			59, 187, 123, 251, 7, 135, 71, 199, 39, 167,
			103, 231, 23, 151, 87, 215, 55, 183, 119, 247,
			15, 143, 79, 207, 47, 175, 111, 239, 31, 159,
			95, 223, 63, 191, 127, 255
		};

		private static readonly byte[] logTable = new byte[256]
		{
			255, 0, 1, 1, 2, 2, 2, 2, 3, 3,
			3, 3, 3, 3, 3, 3, 4, 4, 4, 4,
			4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
			4, 4, 5, 5, 5, 5, 5, 5, 5, 5,
			5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
			5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
			5, 5, 5, 5, 6, 6, 6, 6, 6, 6,
			6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
			6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
			6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
			6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
			6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
			6, 6, 6, 6, 6, 6, 6, 6, 7, 7,
			7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
			7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
			7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
			7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
			7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
			7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
			7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
			7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
			7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
			7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
			7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
			7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
			7, 7, 7, 7, 7, 7
		};

		public int Count => count;

		public SplitOrderedList(IEqualityComparer<TKey> comparer)
		{
			this.comparer = comparer;
			head = new Node().Init(0uL);
			tail = new Node().Init(ulong.MaxValue);
			head.Next = tail;
			SetBucket(0u, head);
		}

		public T InsertOrUpdate(uint key, TKey subKey, Func<T> addGetter, Func<T, T> updateGetter)
		{
			if (InsertInternal(key, subKey, default(T), addGetter, out var current))
			{
				return current.Data;
			}
			return current.Data = updateGetter(current.Data);
		}

		public T InsertOrUpdate(uint key, TKey subKey, T addValue, T updateValue)
		{
			if (InsertInternal(key, subKey, addValue, null, out var current))
			{
				return current.Data;
			}
			return current.Data = updateValue;
		}

		public bool Insert(uint key, TKey subKey, T data)
		{
			Node current;
			return InsertInternal(key, subKey, data, null, out current);
		}

		public T InsertOrGet(uint key, TKey subKey, T data, Func<T> dataCreator)
		{
			InsertInternal(key, subKey, data, dataCreator, out var current);
			return current.Data;
		}

		private bool InsertInternal(uint key, TKey subKey, T data, Func<T> dataCreator, out Node current)
		{
			Node node = pool.Take().Init(ComputeRegularKey(key), subKey, data);
			uint num = key % (uint)size;
			Node startPoint;
			if ((startPoint = GetBucket(num)) == null)
			{
				startPoint = InitializeBucket(num);
			}
			if (!ListInsert(node, startPoint, out current, dataCreator))
			{
				return false;
			}
			int num2 = size;
			if (Interlocked.Increment(ref count) / num2 > 5 && (num2 & 0x40000000) == 0)
			{
				Interlocked.CompareExchange(ref size, 2 * num2, num2);
			}
			current = node;
			return true;
		}

		public bool Find(uint key, TKey subKey, out T data)
		{
			uint num = key % (uint)size;
			data = default(T);
			Node startPoint;
			if ((startPoint = GetBucket(num)) == null)
			{
				startPoint = InitializeBucket(num);
			}
			if (!ListFind(ComputeRegularKey(key), subKey, startPoint, out var data2))
			{
				return false;
			}
			data = data2.Data;
			return !data2.Marked;
		}

		public bool CompareExchange(uint key, TKey subKey, T data, Func<T, bool> check)
		{
			uint num = key % (uint)size;
			Node startPoint;
			if ((startPoint = GetBucket(num)) == null)
			{
				startPoint = InitializeBucket(num);
			}
			if (!ListFind(ComputeRegularKey(key), subKey, startPoint, out var data2))
			{
				return false;
			}
			if (!check(data2.Data))
			{
				return false;
			}
			data2.Data = data;
			return true;
		}

		public bool Delete(uint key, TKey subKey, out T data)
		{
			uint num = key % (uint)size;
			Node startPoint;
			if ((startPoint = GetBucket(num)) == null)
			{
				startPoint = InitializeBucket(num);
			}
			if (!ListDelete(startPoint, ComputeRegularKey(key), subKey, out data))
			{
				return false;
			}
			Interlocked.Decrement(ref count);
			return true;
		}

		public IEnumerator<T> GetEnumerator()
		{
			for (Node node = head.Next; node != tail; node = node.Next)
			{
				while (node.Marked || (node.Key & 1) == 0)
				{
					node = node.Next;
					if (node == tail)
					{
						yield break;
					}
				}
				yield return node.Data;
			}
		}

		private Node InitializeBucket(uint b)
		{
			uint parent = GetParent(b);
			Node startPoint;
			if ((startPoint = GetBucket(parent)) == null)
			{
				startPoint = InitializeBucket(parent);
			}
			Node node = pool.Take().Init(ComputeDummyKey(b));
			if (!ListInsert(node, startPoint, out var current, null))
			{
				return current;
			}
			return SetBucket(b, node);
		}

		private static uint GetParent(uint v)
		{
			uint num;
			uint num2;
			int num3 = (((num = v >> 16) == 0) ? (((num2 = v >> 8) != 0) ? (8 + logTable[num2]) : logTable[v]) : (((num2 = num >> 8) != 0) ? (24 + logTable[num2]) : (16 + logTable[num])));
			return (uint)(v & ~(1 << num3));
		}

		private static ulong ComputeRegularKey(uint key)
		{
			return ComputeDummyKey(key) | 1;
		}

		private static ulong ComputeDummyKey(uint key)
		{
			return (ulong)(uint)((reverseTable[key & 0xFF] << 24) | (reverseTable[(key >> 8) & 0xFF] << 16) | (reverseTable[(key >> 16) & 0xFF] << 8) | reverseTable[(key >> 24) & 0xFF]) << 1;
		}

		private Node GetBucket(uint index)
		{
			if (index >= buckets.Length)
			{
				return null;
			}
			return buckets[index];
		}

		private Node SetBucket(uint index, Node node)
		{
			try
			{
				slim.EnterReadLock();
				CheckSegment(index, readLockTaken: true);
				Interlocked.CompareExchange(ref buckets[index], node, null);
				return buckets[index];
			}
			finally
			{
				slim.ExitReadLock();
			}
		}

		private void CheckSegment(uint segment, bool readLockTaken)
		{
			if (segment < buckets.Length)
			{
				return;
			}
			if (readLockTaken)
			{
				slim.ExitReadLock();
			}
			try
			{
				slim.EnterWriteLock();
				while (segment >= buckets.Length)
				{
					Array.Resize(ref buckets, buckets.Length * 2);
				}
			}
			finally
			{
				slim.ExitWriteLock();
			}
			if (readLockTaken)
			{
				slim.EnterReadLock();
			}
		}

		private Node ListSearch(ulong key, TKey subKey, ref Node left, Node h)
		{
			Node node = null;
			Node node2 = null;
			while (true)
			{
				Node node3 = h;
				Node next = node3.Next;
				do
				{
					if (!next.Marked)
					{
						left = node3;
						node = next;
					}
					node3 = (next.Marked ? next.Next : next);
					if (node3 == tail)
					{
						break;
					}
					next = node3.Next;
				}
				while (next.Marked || node3.Key < key || (next.Key == key && !comparer.Equals(subKey, node3.SubKey)));
				node2 = node3;
				if (node == node2)
				{
					if (node2 == tail || !node2.Next.Marked)
					{
						return node2;
					}
				}
				else if (Interlocked.CompareExchange(ref left.Next, node2, node) == node)
				{
					pool.Release(node);
					if (node2 == tail || !node2.Next.Marked)
					{
						break;
					}
				}
			}
			return node2;
		}

		private bool ListDelete(Node startPoint, ulong key, TKey subKey, out T data)
		{
			Node node = null;
			Node node2 = null;
			Node left = null;
			data = default(T);
			Node node3 = null;
			while (true)
			{
				node = ListSearch(key, subKey, ref left, startPoint);
				if (node == tail || node.Key != key || !comparer.Equals(subKey, node.SubKey))
				{
					return false;
				}
				data = node.Data;
				node2 = node.Next;
				if (!node2.Marked)
				{
					if (node3 == null)
					{
						node3 = pool.Take();
					}
					node3.Init(node2);
					if (Interlocked.CompareExchange(ref node.Next, node3, node2) == node2)
					{
						break;
					}
				}
			}
			if (Interlocked.CompareExchange(ref left.Next, node2, node) != node)
			{
				ListSearch(node.Key, subKey, ref left, startPoint);
			}
			else
			{
				pool.Release(node);
			}
			return true;
		}

		private bool ListInsert(Node newNode, Node startPoint, out Node current, Func<T> dataCreator)
		{
			ulong key = newNode.Key;
			Node node = null;
			Node left = null;
			do
			{
				node = (current = ListSearch(key, newNode.SubKey, ref left, startPoint));
				if (node != tail && node.Key == key && comparer.Equals(newNode.SubKey, node.SubKey))
				{
					return false;
				}
				newNode.Next = node;
				if (dataCreator != null)
				{
					newNode.Data = dataCreator();
				}
			}
			while (Interlocked.CompareExchange(ref left.Next, newNode, node) != node);
			return true;
		}

		private bool ListFind(ulong key, TKey subKey, Node startPoint, out Node data)
		{
			Node node = null;
			Node left = null;
			data = null;
			node = (data = ListSearch(key, subKey, ref left, startPoint));
			if (node != tail && node.Key == key)
			{
				return comparer.Equals(subKey, node.SubKey);
			}
			return false;
		}
	}
	internal abstract class ObjectPool<T> where T : class
	{
		private const int capacity = 20;

		private const int bit = 134217728;

		private readonly T[] buffer;

		private int addIndex;

		private int removeIndex;

		public ObjectPool()
		{
			buffer = new T[20];
			for (int i = 0; i < 20; i++)
			{
				buffer[i] = Creator();
			}
			addIndex = 19;
		}

		protected abstract T Creator();

		public T Take()
		{
			if ((addIndex & -134217729) - 1 == removeIndex)
			{
				return Creator();
			}
			int num = 3;
			int num2;
			T result;
			do
			{
				num2 = removeIndex;
				if ((addIndex & -134217729) - 1 == num2 || num == 0)
				{
					return Creator();
				}
				result = buffer[num2 % 20];
			}
			while (Interlocked.CompareExchange(ref removeIndex, num2 + 1, num2) != num2 && --num > -1);
			return result;
		}

		public void Release(T obj)
		{
			if (obj == null || addIndex - removeIndex >= 19)
			{
				return;
			}
			int num = 3;
			int num2;
			while (true)
			{
				num2 = addIndex;
				if ((num2 & 0x8000000) <= 0)
				{
					if (num2 - removeIndex >= 19)
					{
						return;
					}
					if (Interlocked.CompareExchange(ref addIndex, num2 + 1 + 134217728, num2) == num2 || --num <= 0)
					{
						break;
					}
				}
			}
			buffer[num2 % 20] = obj;
			addIndex -= 134217728;
		}
	}
	public static class Partitioner
	{
		public static OrderablePartitioner<TSource> Create<TSource>(IEnumerable<TSource> source)
		{
			if (source is IList<TSource> list)
			{
				return Create(list, loadBalance: true);
			}
			return new EnumerablePartitioner<TSource>(source);
		}

		public static OrderablePartitioner<TSource> Create<TSource>(TSource[] array, bool loadBalance)
		{
			return Create((IList<TSource>)array, loadBalance);
		}

		public static OrderablePartitioner<TSource> Create<TSource>(IList<TSource> list, bool loadBalance)
		{
			return new ListPartitioner<TSource>(list);
		}

		public static OrderablePartitioner<Tuple<int, int>> Create(int fromInclusive, int toExclusive)
		{
			int num = (toExclusive - fromInclusive) / (Environment.ProcessorCount * 3);
			if (num < 1)
			{
				num = 1;
			}
			return Create(fromInclusive, toExclusive, num);
		}

		public static OrderablePartitioner<Tuple<int, int>> Create(int fromInclusive, int toExclusive, int rangeSize)
		{
			if (fromInclusive >= toExclusive)
			{
				throw new ArgumentOutOfRangeException("toExclusive");
			}
			if (rangeSize <= 0)
			{
				throw new ArgumentOutOfRangeException("rangeSize");
			}
			return new UserRangePartitioner(fromInclusive, toExclusive, rangeSize);
		}

		public static OrderablePartitioner<Tuple<long, long>> Create(long fromInclusive, long toExclusive)
		{
			long num = (toExclusive - fromInclusive) / (Environment.ProcessorCount * 3);
			if (num < 1)
			{
				num = 1L;
			}
			return Create(fromInclusive, toExclusive, num);
		}

		public static OrderablePartitioner<Tuple<long, long>> Create(long fromInclusive, long toExclusive, long rangeSize)
		{
			if (rangeSize <= 0)
			{
				throw new ArgumentOutOfRangeException("rangeSize");
			}
			if (fromInclusive >= toExclusive)
			{
				throw new ArgumentOutOfRangeException("toExclusive");
			}
			return new UserLongRangePartitioner(fromInclusive, toExclusive, rangeSize);
		}
	}
	public abstract class Partitioner<TSource>
	{
		public virtual bool SupportsDynamicPartitions => false;

		public virtual IEnumerable<TSource> GetDynamicPartitions()
		{
			if (!SupportsDynamicPartitions)
			{
				throw new NotSupportedException();
			}
			return null;
		}

		public abstract IList<IEnumerator<TSource>> GetPartitions(int partitionCount);
	}
}
namespace System.Threading.Tasks
{
	internal class TaskConstants<T>
	{
		internal static readonly Task<T> Canceled;

		static TaskConstants()
		{
			TaskCompletionSource<T> taskCompletionSource = new TaskCompletionSource<T>();
			taskCompletionSource.SetCanceled();
			Canceled = taskCompletionSource.Task;
		}
	}
}
namespace System
{
	[Serializable]
	[ComVisible(true)]
	public class OperationCanceledException : SystemException
	{
		private const int Result = -2146233029;

		private CancellationToken? token;

		public CancellationToken CancellationToken
		{
			get
			{
				if (!token.HasValue)
				{
					return CancellationToken.None;
				}
				return token.Value;
			}
		}

		public OperationCanceledException()
			: base("The operation was canceled.")
		{
			base.HResult = -2146233029;
		}

		public OperationCanceledException(string message)
			: base(message)
		{
			base.HResult = -2146233029;
		}

		public OperationCanceledException(string message, Exception innerException)
			: base(message, innerException)
		{
			base.HResult = -2146233029;
		}

		protected OperationCanceledException(SerializationInfo info, StreamingContext context)
			: base(info, context)
		{
		}

		public OperationCanceledException(CancellationToken token)
			: this()
		{
			this.token = token;
		}

		public OperationCanceledException(string message, CancellationToken token)
			: this(message)
		{
			this.token = token;
		}

		public OperationCanceledException(string message, Exception innerException, CancellationToken token)
			: base(message, innerException)
		{
			this.token = token;
		}
	}
}
namespace System.Collections
{
	[Serializable]
	[ComVisible(true)]
	public sealed class Comparer : IComparer
	{
		public static readonly Comparer Default = new Comparer();

		public static readonly Comparer DefaultInvariant = new Comparer(CultureInfo.InvariantCulture);

		private CompareInfo m_compareInfo;

		private Comparer()
		{
		}

		public Comparer(CultureInfo culture)
		{
			if (culture == null)
			{
				throw new ArgumentNullException("culture");
			}
			m_compareInfo = culture.CompareInfo;
		}

		public int Compare(object a, object b)
		{
			if (a == b)
			{
				return 0;
			}
			if (a == null)
			{
				return -1;
			}
			if (b == null)
			{
				return 1;
			}
			if (m_compareInfo != null)
			{
				string text = a as string;
				string text2 = b as string;
				if (text != null && text2 != null)
				{
					return m_compareInfo.Compare(text, text2);
				}
			}
			if (a is IComparable)
			{
				return (a as IComparable).CompareTo(b);
			}
			if (b is IComparable)
			{
				return -(b as IComparable).CompareTo(a);
			}
			throw new ArgumentException("Neither 'a' nor 'b' implements IComparable.");
		}
	}
}
namespace System.Threading
{
	public struct CancellationTokenRegistration : IDisposable, IEquatable<CancellationTokenRegistration>
	{
		private int id;

		private CancellationTokenSource source;

		internal CancellationTokenRegistration(int id, CancellationTokenSource source)
		{
			this.id = id;
			this.source = source;
		}

		public void Dispose()
		{
			source.RemoveCallback(this);
		}

		public bool Equals(CancellationTokenRegistration other)
		{
			if (id == other.id)
			{
				return source == other.source;
			}
			return false;
		}

		public static bool operator ==(CancellationTokenRegistration left, CancellationTokenRegistration right)
		{
			return left.Equals(right);
		}

		public static bool operator !=(CancellationTokenRegistration left, CancellationTokenRegistration right)
		{
			return !left.Equals(right);
		}

		public override int GetHashCode()
		{
			return id.GetHashCode() ^ source.GetHashCode();
		}

		public override bool Equals(object obj)
		{
			if (!(obj is CancellationTokenRegistration))
			{
				return false;
			}
			return Equals((CancellationTokenRegistration)obj);
		}
	}
}
namespace System.Collections.Concurrent
{
	public abstract class OrderablePartitioner<TSource> : Partitioner<TSource>
	{
		private class ProxyEnumerator : IEnumerator<TSource>, IEnumerator, IDisposable
		{
			private IEnumerator<KeyValuePair<long, TSource>> internalEnumerator;

			object IEnumerator.Current => Current;

			public TSource Current { get; private set; }

			internal ProxyEnumerator(IEnumerator<KeyValuePair<long, TSource>> enumerator)
			{
				internalEnumerator = enumerator;
			}

			public void Dispose()
			{
				internalEnumerator.Dispose();
			}

			public bool MoveNext()
			{
				if (!internalEnumerator.MoveNext())
				{
					return false;
				}
				Current = internalEnumerator.Current.Value;
				return true;
			}

			public void Reset()
			{
				internalEnumerator.Reset();
			}
		}

		private bool keysOrderedInEachPartition;

		private bool keysOrderedAcrossPartitions;

		private bool keysNormalized;

		public bool KeysOrderedInEachPartition => keysOrderedInEachPartition;

		public bool KeysOrderedAcrossPartitions => keysOrderedAcrossPartitions;

		public bool KeysNormalized => keysNormalized;

		protected OrderablePartitioner(bool keysOrderedInEachPartition, bool keysOrderedAcrossPartitions, bool keysNormalized)
		{
			this.keysOrderedInEachPartition = keysOrderedInEachPartition;
			this.keysOrderedAcrossPartitions = keysOrderedAcrossPartitions;
			this.keysNormalized = keysNormalized;
		}

		public override IEnumerable<TSource> GetDynamicPartitions()
		{
			foreach (KeyValuePair<long, TSource> item in GetOrderableDynamicPartitions())
			{
				KeyValuePair<long, TSource> keyValuePair = item;
				yield return keyValuePair.Value;
			}
		}

		public override IList<IEnumerator<TSource>> GetPartitions(int partitionCount)
		{
			IEnumerator<TSource>[] array = new IEnumerator<TSource>[partitionCount];
			IList<IEnumerator<KeyValuePair<long, TSource>>> orderablePartitions = GetOrderablePartitions(partitionCount);
			for (int i = 0; i < orderablePartitions.Count; i++)
			{
				array[i] = new ProxyEnumerator(orderablePartitions[i]);
			}
			return array;
		}

		private IEnumerator<TSource> GetProxyEnumerator(IEnumerator<KeyValuePair<long, TSource>> enumerator)
		{
			while (enumerator.MoveNext())
			{
				yield return enumerator.Current.Value;
			}
		}

		public abstract IList<IEnumerator<KeyValuePair<long, TSource>>> GetOrderablePartitions(int partitionCount);

		public virtual IEnumerable<KeyValuePair<long, TSource>> GetOrderableDynamicPartitions()
		{
			if (!SupportsDynamicPartitions)
			{
				throw new NotSupportedException();
			}
			return null;
		}
	}
}
namespace System.Collections.Concurrent.Partitioners
{
	internal class UserRangePartitioner : OrderablePartitioner<Tuple<int, int>>
	{
		private readonly int start;

		private readonly int end;

		private readonly int rangeSize;

		public UserRangePartitioner(int start, int end, int rangeSize)
			: base(keysOrderedInEachPartition: true, keysOrderedAcrossPartitions: true, keysNormalized: true)
		{
			this.start = start;
			this.end = end;
			this.rangeSize = rangeSize;
		}

		public override IList<IEnumerator<KeyValuePair<long, Tuple<int, int>>>> GetOrderablePartitions(int partitionCount)
		{
			if (partitionCount <= 0)
			{
				throw new ArgumentOutOfRangeException("partitionCount");
			}
			int currentIndex = 0;
			Func<int> getNextIndex = () => Interlocked.Increment(ref currentIndex) - 1;
			IEnumerator<KeyValuePair<long, Tuple<int, int>>>[] array = new IEnumerator<KeyValuePair<long, Tuple<int, int>>>[partitionCount];
			for (int i = 0; i < partitionCount; i++)
			{
				array[i] = GetEnumerator(getNextIndex);
			}
			return array;
		}

		private IEnumerator<KeyValuePair<long, Tuple<int, int>>> GetEnumerator(Func<int> getNextIndex)
		{
			while (true)
			{
				int index = getNextIndex();
				int sliceStart = index * rangeSize + start;
				if (sliceStart < end)
				{
					yield return new KeyValuePair<long, Tuple<int, int>>(index, Tuple.Create(sliceStart, Math.Min(end, sliceStart + rangeSize)));
					_ = sliceStart + rangeSize;
					continue;
				}
				break;
			}
		}
	}
	internal class UserLongRangePartitioner : OrderablePartitioner<Tuple<long, long>>
	{
		private readonly long start;

		private readonly long end;

		private readonly long rangeSize;

		public UserLongRangePartitioner(long start, long end, long rangeSize)
			: base(keysOrderedInEachPartition: true, keysOrderedAcrossPartitions: true, keysNormalized: true)
		{
			this.start = start;
			this.end = end;
			this.rangeSize = rangeSize;
		}

		public override IList<IEnumerator<KeyValuePair<long, Tuple<long, long>>>> GetOrderablePartitions(int partitionCount)
		{
			if (partitionCount <= 0)
			{
				throw new ArgumentOutOfRangeException("partitionCount");
			}
			long currentIndex = 0L;
			Func<long> getNextIndex = () => Interlocked.Increment(ref currentIndex) - 1;
			IEnumerator<KeyValuePair<long, Tuple<long, long>>>[] array = new IEnumerator<KeyValuePair<long, Tuple<long, long>>>[partitionCount];
			for (int i = 0; i < partitionCount; i++)
			{
				array[i] = GetEnumerator(getNextIndex);
			}
			return array;
		}

		private IEnumerator<KeyValuePair<long, Tuple<long, long>>> GetEnumerator(Func<long> getNextIndex)
		{
			while (true)
			{
				long index = getNextIndex();
				long sliceStart = index * rangeSize + start;
				if (sliceStart < end)
				{
					yield return new KeyValuePair<long, Tuple<long, long>>(index, Tuple.Create(sliceStart, Math.Min(end, sliceStart + rangeSize)));
					_ = sliceStart + rangeSize;
					continue;
				}
				break;
			}
		}
	}
}
namespace System
{
	public static class Tuple
	{
		public static Tuple<T1, T2, T3, T4, T5, T6, T7, Tuple<T8>> Create<T1, T2, T3, T4, T5, T6, T7, T8>(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6, T7 item7, T8 item8)
		{
			return new Tuple<T1, T2, T3, T4, T5, T6, T7, Tuple<T8>>(item1, item2, item3, item4, item5, item6, item7, new Tuple<T8>(item8));
		}

		public static Tuple<T1, T2, T3, T4, T5, T6, T7> Create<T1, T2, T3, T4, T5, T6, T7>(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6, T7 item7)
		{
			return new Tuple<T1, T2, T3, T4, T5, T6, T7>(item1, item2, item3, item4, item5, item6, item7);
		}

		public static Tuple<T1, T2, T3, T4, T5, T6> Create<T1, T2, T3, T4, T5, T6>(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6)
		{
			return new Tuple<T1, T2, T3, T4, T5, T6>(item1, item2, item3, item4, item5, item6);
		}

		public static Tuple<T1, T2, T3, T4, T5> Create<T1, T2, T3, T4, T5>(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5)
		{
			return new Tuple<T1, T2, T3, T4, T5>(item1, item2, item3, item4, item5);
		}

		public static Tuple<T1, T2, T3, T4> Create<T1, T2, T3, T4>(T1 item1, T2 item2, T3 item3, T4 item4)
		{
			return new Tuple<T1, T2, T3, T4>(item1, item2, item3, item4);
		}

		public static Tuple<T1, T2, T3> Create<T1, T2, T3>(T1 item1, T2 item2, T3 item3)
		{
			return new Tuple<T1, T2, T3>(item1, item2, item3);
		}

		public static Tuple<T1, T2> Create<T1, T2>(T1 item1, T2 item2)
		{
			return new Tuple<T1, T2>(item1, item2);
		}

		public static Tuple<T1> Create<T1>(T1 item1)
		{
			return new Tuple<T1>(item1);
		}
	}
}
namespace System.Threading.Tasks
{
	[DebuggerDisplay("Id = {Id}, Status = {Status}")]
	[DebuggerTypeProxy(typeof(TaskDebuggerView))]
	public class Task : IDisposable, IAsyncResult
	{
		internal const TaskCreationOptions WorkerTaskNotSupportedOptions = TaskCreationOptions.PreferFairness | TaskCreationOptions.LongRunning;

		private const TaskCreationOptions MaxTaskCreationOptions = TaskCreationOptions.PreferFairness | TaskCreationOptions.LongRunning | TaskCreationOptions.AttachedToParent | TaskCreationOptions.DenyChildAttach | TaskCreationOptions.HideScheduler;

		[ThreadStatic]
		private static Task current;

		[ThreadStatic]
		private static Action<Task> childWorkAdder;

		internal readonly Task parent;

		private readonly Task contAncestor;

		private static int id = -1;

		private static readonly TaskFactory defaultFactory = new TaskFactory();

		private CountdownEvent childTasks;

		private int taskId;

		private TaskCreationOptions taskCreationOptions;

		internal TaskScheduler scheduler;

		private TaskExceptionSlot exSlot;

		private TaskStatus status;

		private TaskActionInvoker invoker;

		private object state;

		internal AtomicBooleanValue executing;

		private TaskCompletionQueue<IContinuation> continuations;

		private CancellationToken token;

		private CancellationTokenRegistration? cancellationRegistration;

		public static TaskFactory Factory => defaultFactory;

		public static int? CurrentId => current?.Id;

		public AggregateException Exception
		{
			get
			{
				if (exSlot == null)
				{
					return null;
				}
				exSlot.Observed = true;
				return exSlot.Exception;
			}
		}

		public bool IsCanceled => status == TaskStatus.Canceled;

		public bool IsCompleted => status >= TaskStatus.RanToCompletion;

		public bool IsFaulted => status == TaskStatus.Faulted;

		public TaskCreationOptions CreationOptions => taskCreationOptions & (TaskCreationOptions.PreferFairness | TaskCreationOptions.LongRunning | TaskCreationOptions.AttachedToParent | TaskCreationOptions.DenyChildAttach | TaskCreationOptions.HideScheduler);

		public TaskStatus Status
		{
			get
			{
				return status;
			}
			internal set
			{
				status = value;
				Thread.MemoryBarrier();
			}
		}

		private TaskExceptionSlot ExceptionSlot
		{
			get
			{
				if (exSlot != null)
				{
					return exSlot;
				}
				Interlocked.CompareExchange(ref exSlot, new TaskExceptionSlot(this), null);
				return exSlot;
			}
		}

		public object AsyncState => state;

		bool IAsyncResult.CompletedSynchronously => true;

		WaitHandle IAsyncResult.AsyncWaitHandle => null;

		public int Id => taskId;

		private bool IsContinuation => contAncestor != null;

		internal Task ContinuationAncestor => contAncestor;

		internal string DisplayActionMethod
		{
			get
			{
				Delegate action = invoker.Action;
				if ((object)action != null)
				{
					return action.Method.ToString();
				}
				return "<none>";
			}
		}

		internal Task Parent => parent;

		public Task(Action action)
			: this(action, TaskCreationOptions.None)
		{
		}

		public Task(Action action, TaskCreationOptions creationOptions)
			: this(action, CancellationToken.None, creationOptions)
		{
		}

		public Task(Action action, CancellationToken cancellationToken)
			: this(action, cancellationToken, TaskCreationOptions.None)
		{
		}

		public Task(Action action, CancellationToken cancellationToken, TaskCreationOptions creationOptions)
			: this(TaskActionInvoker.Create(action), null, cancellationToken, creationOptions, current)
		{
			if (action == null)
			{
				throw new ArgumentNullException("action");
			}
			if (creationOptions > (TaskCreationOptions.PreferFairness | TaskCreationOptions.LongRunning | TaskCreationOptions.AttachedToParent | TaskCreationOptions.DenyChildAttach | TaskCreationOptions.HideScheduler) || creationOptions < TaskCreationOptions.None)
			{
				throw new ArgumentOutOfRangeException("creationOptions");
			}
		}

		public Task(Action<object> action, object state)
			: this(action, state, TaskCreationOptions.None)
		{
		}

		public Task(Action<object> action, object state, TaskCreationOptions creationOptions)
			: this(action, state, CancellationToken.None, creationOptions)
		{
		}

		public Task(Action<object> action, object state, CancellationToken cancellationToken)
			: this(action, state, cancellationToken, TaskCreationOptions.None)
		{
		}

		public Task(Action<object> action, object state, CancellationToken cancellationToken, TaskCreationOptions creationOptions)
			: this(TaskActionInvoker.Create(action), state, cancellationToken, creationOptions, current)
		{
			if (action == null)
			{
				throw new ArgumentNullException("action");
			}
			if (creationOptions > (TaskCreationOptions.PreferFairness | TaskCreationOptions.LongRunning | TaskCreationOptions.AttachedToParent | TaskCreationOptions.DenyChildAttach | TaskCreationOptions.HideScheduler) || creationOptions < TaskCreationOptions.None)
			{
				throw new ArgumentOutOfRangeException("creationOptions");
			}
		}

		internal Task(TaskActionInvoker invoker, object state, CancellationToken cancellationToken, TaskCreationOptions creationOptions, Task parent, Task contAncestor = null)
		{
			this.invoker = invoker;
			taskCreationOptions = creationOptions;
			this.state = state;
			taskId = Interlocked.Increment(ref id);
			status = (cancellationToken.IsCancellationRequested ? TaskStatus.Canceled : TaskStatus.Created);
			token = cancellationToken;
			this.parent = parent;
			this.contAncestor = contAncestor;
			if (CheckTaskOptions(taskCreationOptions, TaskCreationOptions.AttachedToParent))
			{
				parent?.AddChild();
			}
			if (token.CanBeCanceled)
			{
				cancellationRegistration = token.Register(delegate(object l)
				{
					((Task)l).CancelReal();
				}, this);
			}
		}

		private static bool CheckTaskOptions(TaskCreationOptions opt, TaskCreationOptions member)
		{
			return (opt & member) == member;
		}

		public void Start()
		{
			Start(TaskScheduler.Current);
		}

		public void Start(TaskScheduler scheduler)
		{
			if (scheduler == null)
			{
				throw new ArgumentNullException("scheduler");
			}
			if (status >= TaskStatus.WaitingToRun)
			{
				throw new InvalidOperationException("The Task is not in a valid state to be started.");
			}
			if (IsContinuation)
			{
				throw new InvalidOperationException("Start may not be called on a continuation task");
			}
			SetupScheduler(scheduler);
			Schedule();
		}

		internal void SetupScheduler(TaskScheduler scheduler)
		{
			this.scheduler = scheduler;
			Status = TaskStatus.WaitingForActivation;
		}

		public void RunSynchronously()
		{
			RunSynchronously(TaskScheduler.Current);
		}

		public void RunSynchronously(TaskScheduler scheduler)
		{
			if (scheduler == null)
			{
				throw new ArgumentNullException("scheduler");
			}
			if (Status > TaskStatus.WaitingForActivation)
			{
				throw new InvalidOperationException("The task is not in a valid state to be started");
			}
			SetupScheduler(scheduler);
			TaskStatus taskStatus = status;
			Status = TaskStatus.WaitingToRun;
			try
			{
				if (scheduler.RunInline(this))
				{
					return;
				}
			}
			catch (Exception innerException)
			{
				throw new TaskSchedulerException(innerException);
			}
			Status = taskStatus;
			Start(scheduler);
			Wait();
		}

		public Task ContinueWith(Action<Task> continuationAction)
		{
			return ContinueWith(continuationAction, TaskContinuationOptions.None);
		}

		public Task ContinueWith(Action<Task> continuationAction, TaskContinuationOptions continuationOptions)
		{
			return ContinueWith(continuationAction, CancellationToken.None, continuationOptions, TaskScheduler.Current);
		}

		public Task ContinueWith(Action<Task> continuationAction, CancellationToken cancellationToken)
		{
			return ContinueWith(continuationAction, cancellationToken, TaskContinuationOptions.None, TaskScheduler.Current);
		}

		public Task ContinueWith(Action<Task> continuationAction, TaskScheduler scheduler)
		{
			return ContinueWith(continuationAction, CancellationToken.None, TaskContinuationOptions.None, scheduler);
		}

		public Task ContinueWith(Action<Task> continuationAction, CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
		{
			if (continuationAction == null)
			{
				throw new ArgumentNullException("continuationAction");
			}
			if (scheduler == null)
			{
				throw new ArgumentNullException("scheduler");
			}
			return ContinueWith(TaskActionInvoker.Create(continuationAction), cancellationToken, continuationOptions, scheduler);
		}

		internal Task ContinueWith(TaskActionInvoker invoker, CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
		{
			Task task = new Task(invoker, null, cancellationToken, GetCreationOptions(continuationOptions), parent, this);
			ContinueWithCore(task, continuationOptions, scheduler);
			return task;
		}

		public Task<TResult> ContinueWith<TResult>(Func<Task, TResult> continuationFunction)
		{
			return ContinueWith(continuationFunction, TaskContinuationOptions.None);
		}

		public Task<TResult> ContinueWith<TResult>(Func<Task, TResult> continuationFunction, TaskContinuationOptions continuationOptions)
		{
			return ContinueWith(continuationFunction, CancellationToken.None, continuationOptions, TaskScheduler.Current);
		}

		public Task<TResult> ContinueWith<TResult>(Func<Task, TResult> continuationFunction, CancellationToken cancellationToken)
		{
			return ContinueWith(continuationFunction, cancellationToken, TaskContinuationOptions.None, TaskScheduler.Current);
		}

		public Task<TResult> ContinueWith<TResult>(Func<Task, TResult> continuationFunction, TaskScheduler scheduler)
		{
			return ContinueWith(continuationFunction, CancellationToken.None, TaskContinuationOptions.None, scheduler);
		}

		public Task<TResult> ContinueWith<TResult>(Func<Task, TResult> continuationFunction, CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
		{
			if (continuationFunction == null)
			{
				throw new ArgumentNullException("continuationFunction");
			}
			if (scheduler == null)
			{
				throw new ArgumentNullException("scheduler");
			}
			return ContinueWith<TResult>(TaskActionInvoker.Create(continuationFunction), cancellationToken, continuationOptions, scheduler);
		}

		internal Task<TResult> ContinueWith<TResult>(TaskActionInvoker invoker, CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
		{
			Task<TResult> task = new Task<TResult>(invoker, null, cancellationToken, GetCreationOptions(continuationOptions), parent, this);
			ContinueWithCore(task, continuationOptions, scheduler);
			return task;
		}

		internal void ContinueWithCore(Task continuation, TaskContinuationOptions options, TaskScheduler scheduler)
		{
			if ((options & (TaskContinuationOptions.OnlyOnRanToCompletion | TaskContinuationOptions.NotOnRanToCompletion)) == (TaskContinuationOptions.OnlyOnRanToCompletion | TaskContinuationOptions.NotOnRanToCompletion) || (options & (TaskContinuationOptions.OnlyOnRanToCompletion | TaskContinuationOptions.NotOnRanToCompletion)) == (TaskContinuationOptions.OnlyOnRanToCompletion | TaskContinuationOptions.NotOnRanToCompletion) || (options & (TaskContinuationOptions.OnlyOnRanToCompletion | TaskContinuationOptions.NotOnRanToCompletion)) == (TaskContinuationOptions.OnlyOnRanToCompletion | TaskContinuationOptions.NotOnRanToCompletion))
			{
				throw new ArgumentException("continuationOptions", "Some options are mutually exclusive");
			}
			continuation.scheduler = scheduler;
			continuation.Status = TaskStatus.WaitingForActivation;
			ContinueWith(new System.Threading.Tasks.TaskContinuation(continuation, options));
		}

		internal void ContinueWith(IContinuation continuation)
		{
			if (IsCompleted)
			{
				continuation.Execute();
				return;
			}
			continuations.Add(continuation);
			if (IsCompleted && continuations.Remove(continuation))
			{
				continuation.Execute();
			}
		}

		private void RemoveContinuation(IContinuation continuation)
		{
			continuations.Remove(continuation);
		}

		internal static TaskCreationOptions GetCreationOptions(TaskContinuationOptions kind)
		{
			TaskCreationOptions taskCreationOptions = TaskCreationOptions.None;
			if ((kind & TaskContinuationOptions.AttachedToParent) > TaskContinuationOptions.None)
			{
				taskCreationOptions |= TaskCreationOptions.AttachedToParent;
			}
			if ((kind & TaskContinuationOptions.PreferFairness) > TaskContinuationOptions.None)
			{
				taskCreationOptions |= TaskCreationOptions.PreferFairness;
			}
			if ((kind & TaskContinuationOptions.LongRunning) > TaskContinuationOptions.None)
			{
				taskCreationOptions |= TaskCreationOptions.LongRunning;
			}
			return taskCreationOptions;
		}

		internal void Schedule()
		{
			Status = TaskStatus.WaitingToRun;
			if (scheduler != TaskScheduler.Current || childWorkAdder == null || CheckTaskOptions(taskCreationOptions, TaskCreationOptions.PreferFairness))
			{
				scheduler.QueueTask(this);
			}
			else
			{
				childWorkAdder(this);
			}
		}

		private void ThreadStart()
		{
			if (!executing.TryRelaxedSet())
			{
				return;
			}
			if (cancellationRegistration.HasValue)
			{
				cancellationRegistration.Value.Dispose();
				cancellationRegistration = null;
			}
			current = this;
			TaskScheduler.Current = scheduler;
			if (!token.IsCancellationRequested)
			{
				status = TaskStatus.Running;
				try
				{
					InnerInvoke();
				}
				catch (OperationCanceledException ex)
				{
					if (token != CancellationToken.None && ex.CancellationToken == token)
					{
						CancelReal();
					}
					else
					{
						HandleGenericException(ex);
					}
				}
				catch (Exception e)
				{
					HandleGenericException(e);
				}
			}
			else
			{
				CancelReal();
			}
			Finish();
		}

		internal bool TrySetCanceled()
		{
			if (IsCompleted)
			{
				return false;
			}
			if (!executing.TryRelaxedSet())
			{
				SpinWait spinWait = default(SpinWait);
				while (!IsCompleted)
				{
					spinWait.SpinOnce();
				}
				return false;
			}
			CancelReal();
			return true;
		}

		internal bool TrySetException(AggregateException aggregate)
		{
			if (IsCompleted)
			{
				return false;
			}
			if (!executing.TryRelaxedSet())
			{
				SpinWait spinWait = default(SpinWait);
				while (!IsCompleted)
				{
					spinWait.SpinOnce();
				}
				return false;
			}
			HandleGenericException(aggregate);
			return true;
		}

		internal void Execute(Action<Task> childAdder)
		{
			childWorkAdder = childAdder;
			Execute();
		}

		internal void Execute()
		{
			ThreadStart();
		}

		internal void AddChild()
		{
			if (childTasks == null)
			{
				Interlocked.CompareExchange(ref childTasks, new CountdownEvent(1), null);
			}
			childTasks.AddCount();
		}

		internal void ChildCompleted(AggregateException childEx)
		{
			if (childEx != null)
			{
				if (ExceptionSlot.ChildExceptions == null)
				{
					Interlocked.CompareExchange(ref ExceptionSlot.ChildExceptions, new ConcurrentQueue<AggregateException>(), null);
				}
				ExceptionSlot.ChildExceptions.Enqueue(childEx);
			}
			if (childTasks.Signal() && status == TaskStatus.WaitingForChildrenToComplete)
			{
				Status = TaskStatus.RanToCompletion;
				ProcessChildExceptions();
				ProcessCompleteDelegates();
				if (CheckTaskOptions(taskCreationOptions, TaskCreationOptions.AttachedToParent) && parent != null)
				{
					parent.ChildCompleted(Exception);
				}
			}
		}

		private void InnerInvoke()
		{
			if (IsContinuation)
			{
				invoker.Invoke(contAncestor, state, this);
			}
			else
			{
				invoker.Invoke(this, state, this);
			}
		}

		internal void Finish()
		{
			if (childTasks != null)
			{
				childTasks.Signal();
			}
			if (status == TaskStatus.Running)
			{
				if (childTasks == null || childTasks.IsSet)
				{
					Status = TaskStatus.RanToCompletion;
				}
				else
				{
					Status = TaskStatus.WaitingForChildrenToComplete;
				}
			}
			if (status == TaskStatus.RanToCompletion)
			{
				ProcessCompleteDelegates();
			}
			current = null;
			TaskScheduler.Current = null;
			if (cancellationRegistration.HasValue)
			{
				cancellationRegistration.Value.Dispose();
			}
			if (CheckTaskOptions(taskCreationOptions, TaskCreationOptions.AttachedToParent) && parent != null && status != TaskStatus.WaitingForChildrenToComplete)
			{
				parent.ChildCompleted(Exception);
			}
		}

		private void ProcessCompleteDelegates()
		{
			if (continuations.HasElements)
			{
				IContinuation continuation;
				while (continuations.TryGetNextCompletion(out continuation))
				{
					continuation.Execute();
				}
			}
		}

		private void ProcessChildExceptions()
		{
			if (exSlot != null && exSlot.ChildExceptions != null)
			{
				if (ExceptionSlot.Exception == null)
				{
					exSlot.Exception = new AggregateException();
				}
				AggregateException result;
				while (exSlot.ChildExceptions.TryDequeue(out result))
				{
					exSlot.Exception.AddChildException(result);
				}
			}
		}

		internal void CancelReal()
		{
			Status = TaskStatus.Canceled;
			ProcessCompleteDelegates();
		}

		private void HandleGenericException(Exception e)
		{
			HandleGenericException(new AggregateException(e));
		}

		private void HandleGenericException(AggregateException e)
		{
			ExceptionSlot.Exception = e;
			Thread.MemoryBarrier();
			Status = TaskStatus.Faulted;
			ProcessCompleteDelegates();
		}

		internal void WaitOnChildren()
		{
			if (Status == TaskStatus.WaitingForChildrenToComplete && childTasks != null)
			{
				childTasks.Wait();
			}
		}

		public void Wait()
		{
			Wait(-1, CancellationToken.None);
		}

		public void Wait(CancellationToken cancellationToken)
		{
			Wait(-1, cancellationToken);
		}

		public bool Wait(TimeSpan timeout)
		{
			return Wait(CheckTimeout(timeout), CancellationToken.None);
		}

		public bool Wait(int millisecondsTimeout)
		{
			return Wait(millisecondsTimeout, CancellationToken.None);
		}

		public bool Wait(int millisecondsTimeout, CancellationToken cancellationToken)
		{
			if (millisecondsTimeout < -1)
			{
				throw new ArgumentOutOfRangeException("millisecondsTimeout");
			}
			bool flag = true;
			if (!IsCompleted)
			{
				if (Status == TaskStatus.WaitingToRun && millisecondsTimeout == -1 && scheduler != null)
				{
					Execute();
				}
				if (!IsCompleted)
				{
					ManualResetEventSlim manualResetEventSlim = new ManualResetEventSlim();
					ManualEventSlot continuation = new ManualEventSlot(manualResetEventSlim);
					try
					{
						ContinueWith(continuation);
						flag = manualResetEventSlim.Wait(millisecondsTimeout, cancellationToken);
					}
					finally
					{
						if (!flag)
						{
							RemoveContinuation(continuation);
						}
						manualResetEventSlim.Dispose();
					}
				}
			}
			if (IsCanceled)
			{
				throw new AggregateException(new TaskCanceledException(this));
			}
			AggregateException exception = Exception;
			if (exception != null)
			{
				throw exception;
			}
			if (childTasks != null)
			{
				childTasks.Wait();
			}
			return flag;
		}

		public static void WaitAll(params Task[] tasks)
		{
			WaitAll(tasks, -1, CancellationToken.None);
		}

		public static void WaitAll(Task[] tasks, CancellationToken cancellationToken)
		{
			WaitAll(tasks, -1, cancellationToken);
		}

		public static bool WaitAll(Task[] tasks, TimeSpan timeout)
		{
			return WaitAll(tasks, CheckTimeout(timeout), CancellationToken.None);
		}

		public static bool WaitAll(Task[] tasks, int millisecondsTimeout)
		{
			return WaitAll(tasks, millisecondsTimeout, CancellationToken.None);
		}

		public static bool WaitAll(Task[] tasks, int millisecondsTimeout, CancellationToken cancellationToken)
		{
			if (tasks == null)
			{
				throw new ArgumentNullException("tasks");
			}
			bool flag = true;
			foreach (Task task in tasks)
			{
				if (task == null)
				{
					throw new ArgumentNullException("tasks", "the tasks argument contains a null element");
				}
				flag &= task.Status == TaskStatus.RanToCompletion;
			}
			if (!flag)
			{
				CountdownEvent countdownEvent = new CountdownEvent(tasks.Length);
				CountdownEventSlot continuation = new CountdownEventSlot(countdownEvent);
				try
				{
					foreach (Task task2 in tasks)
					{
						task2.ContinueWith(continuation);
					}
					flag = countdownEvent.Wait(millisecondsTimeout, cancellationToken);
				}
				finally
				{
					List<Exception> list = null;
					foreach (Task task3 in tasks)
					{
						if (flag)
						{
							if (task3.Status != TaskStatus.RanToCompletion)
							{
								if (list == null)
								{
									list = new List<Exception>();
								}
								if (task3.Exception != null)
								{
									list.AddRange(task3.Exception.InnerExceptions);
								}
								else
								{
									list.Add(new TaskCanceledException(task3));
								}
							}
						}
						else
						{
							task3.RemoveContinuation(continuation);
						}
					}
					countdownEvent.Dispose();
					if (list != null)
					{
						throw new AggregateException(list);
					}
				}
			}
			return flag;
		}

		public static int WaitAny(params Task[] tasks)
		{
			return WaitAny(tasks, -1, CancellationToken.None);
		}

		public static int WaitAny(Task[] tasks, TimeSpan timeout)
		{
			return WaitAny(tasks, CheckTimeout(timeout));
		}

		public static int WaitAny(Task[] tasks, int millisecondsTimeout)
		{
			return WaitAny(tasks, millisecondsTimeout, CancellationToken.None);
		}

		public static int WaitAny(Task[] tasks, CancellationToken cancellationToken)
		{
			return WaitAny(tasks, -1, cancellationToken);
		}

		public static int WaitAny(Task[] tasks, int millisecondsTimeout, CancellationToken cancellationToken)
		{
			if (tasks == null)
			{
				throw new ArgumentNullException("tasks");
			}
			if (millisecondsTimeout < -1)
			{
				throw new ArgumentOutOfRangeException("millisecondsTimeout");
			}
			CheckForNullTasks(tasks);
			if (tasks.Length > 0)
			{
				ManualResetEventSlim manualResetEventSlim = new ManualResetEventSlim();
				ManualEventSlot continuation = new ManualEventSlot(manualResetEventSlim);
				bool flag = false;
				try
				{
					for (int i = 0; i < tasks.Length; i++)
					{
						Task task = tasks[i];
						if (task.IsCompleted)
						{
							return i;
						}
						task.ContinueWith(continuation);
					}
					if (!(flag = manualResetEventSlim.Wait(millisecondsTimeout, cancellationToken)))
					{
						return -1;
					}
				}
				finally
				{
					if (!flag)
					{
						foreach (Task task2 in tasks)
						{
							task2.RemoveContinuation(continuation);
						}
					}
					manualResetEventSlim.Dispose();
				}
			}
			int result = -1;
			for (int k = 0; k < tasks.Length; k++)
			{
				Task task3 = tasks[k];
				if (task3.IsCompleted)
				{
					result = k;
					break;
				}
			}
			return result;
		}

		private static int CheckTimeout(TimeSpan timeout)
		{
			try
			{
				return checked((int)timeout.TotalMilliseconds);
			}
			catch (OverflowException)
			{
				throw new ArgumentOutOfRangeException("timeout");
			}
		}

		private static void CheckForNullTasks(Task[] tasks)
		{
			foreach (Task task in tasks)
			{
				if (task == null)
				{
					throw new ArgumentNullException("tasks", "the tasks argument contains a null element");
				}
			}
		}

		public void Dispose()
		{
			Dispose(disposing: true);
		}

		protected virtual void Dispose(bool disposing)
		{
			if (!IsCompleted)
			{
				throw new InvalidOperationException("A task may only be disposed if it is in a completion state");
			}
			if (disposing)
			{
				invoker = null;
				state = null;
				if (cancellationRegistration.HasValue)
				{
					cancellationRegistration.Value.Dispose();
				}
			}
		}

		public Task ContinueWith(Action<Task, object> continuationAction, object state)
		{
			return ContinueWith(continuationAction, state, CancellationToken.None, TaskContinuationOptions.None, TaskScheduler.Current);
		}

		public Task ContinueWith(Action<Task, object> continuationAction, object state, CancellationToken cancellationToken)
		{
			return ContinueWith(continuationAction, state, cancellationToken, TaskContinuationOptions.None, TaskScheduler.Current);
		}

		public Task ContinueWith(Action<Task, object> continuationAction, object state, TaskContinuationOptions continuationOptions)
		{
			return ContinueWith(continuationAction, state, CancellationToken.None, continuationOptions, TaskScheduler.Current);
		}

		public Task ContinueWith(Action<Task, object> continuationAction, object state, TaskScheduler scheduler)
		{
			return ContinueWith(continuationAction, state, CancellationToken.None, TaskContinuationOptions.None, scheduler);
		}

		public Task ContinueWith(Action<Task, object> continuationAction, object state, CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
		{
			if (continuationAction == null)
			{
				throw new ArgumentNullException("continuationAction");
			}
			if (scheduler == null)
			{
				throw new ArgumentNullException("scheduler");
			}
			Task task = new Task(TaskActionInvoker.Create(continuationAction), state, cancellationToken, GetCreationOptions(continuationOptions), parent, this);
			ContinueWithCore(task, continuationOptions, scheduler);
			return task;
		}

		public Task<TResult> ContinueWith<TResult>(Func<Task, object, TResult> continuationFunction, object state)
		{
			return ContinueWith(continuationFunction, state, CancellationToken.None, TaskContinuationOptions.None, TaskScheduler.Current);
		}

		public Task<TResult> ContinueWith<TResult>(Func<Task, object, TResult> continuationFunction, object state, TaskContinuationOptions continuationOptions)
		{
			return ContinueWith(continuationFunction, state, CancellationToken.None, continuationOptions, TaskScheduler.Current);
		}

		public Task<TResult> ContinueWith<TResult>(Func<Task, object, TResult> continuationFunction, object state, CancellationToken cancellationToken)
		{
			return ContinueWith(continuationFunction, state, cancellationToken, TaskContinuationOptions.None, TaskScheduler.Current);
		}

		public Task<TResult> ContinueWith<TResult>(Func<Task, object, TResult> continuationFunction, object state, TaskScheduler scheduler)
		{
			return ContinueWith(continuationFunction, state, CancellationToken.None, TaskContinuationOptions.None, scheduler);
		}

		public Task<TResult> ContinueWith<TResult>(Func<Task, object, TResult> continuationFunction, object state, CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
		{
			if (continuationFunction == null)
			{
				throw new ArgumentNullException("continuationFunction");
			}
			if (scheduler == null)
			{
				throw new ArgumentNullException("scheduler");
			}
			Task<TResult> task = new Task<TResult>(TaskActionInvoker.Create(continuationFunction), state, cancellationToken, GetCreationOptions(continuationOptions), parent, this);
			ContinueWithCore(task, continuationOptions, scheduler);
			return task;
		}

		public static Task<TResult> FromResult<TResult>(TResult result)
		{
			TaskCompletionSource<TResult> taskCompletionSource = new TaskCompletionSource<TResult>();
			taskCompletionSource.SetResult(result);
			return taskCompletionSource.Task;
		}

		public static Task Run(Action action)
		{
			return Run(action, CancellationToken.None);
		}

		public static Task Run(Action action, CancellationToken cancellationToken)
		{
			if (cancellationToken.IsCancellationRequested)
			{
				return TaskConstants.Canceled;
			}
			Task task = new Task(action, cancellationToken, TaskCreationOptions.DenyChildAttach);
			task.Start();
			return task;
		}

		public static Task Run(Func<Task> function)
		{
			return Run(function, CancellationToken.None);
		}

		public static Task Run(Func<Task> function, CancellationToken cancellationToken)
		{
			if (cancellationToken.IsCancellationRequested)
			{
				return TaskConstants.Canceled;
			}
			Task<Task> task = new Task<Task>(function, cancellationToken);
			task.Start();
			return task;
		}

		public static Task<TResult> Run<TResult>(Func<TResult> function)
		{
			return Run(function, CancellationToken.None);
		}

		public static Task<TResult> Run<TResult>(Func<TResult> function, CancellationToken cancellationToken)
		{
			if (cancellationToken.IsCancellationRequested)
			{
				return TaskConstants<TResult>.Canceled;
			}
			Task<TResult> task = new Task<TResult>(function, cancellationToken, TaskCreationOptions.DenyChildAttach);
			task.Start();
			return task;
		}
	}
}
namespace System.Collections.Concurrent
{
	public interface IProducerConsumerCollection<T> : IEnumerable<T>, ICollection, IEnumerable
	{
		bool TryAdd(T item);

		bool TryTake(out T item);

		T[] ToArray();

		void CopyTo(T[] array, int index);
	}
	[DebuggerTypeProxy(typeof(CollectionDebuggerView<>))]
	[DebuggerDisplay("Count={Count}")]
	public class ConcurrentQueue<T> : IProducerConsumerCollection<T>, IEnumerable<T>, ICollection, IEnumerable
	{
		private class Node
		{
			public T Value;

			public Node Next;
		}

		private class NodeObjectPool : ObjectPool<Node>
		{
			protected override Node Creator()
			{
				return new Node();
			}
		}

		private Node head = new Node();

		private Node tail;

		private int count;

		private static readonly NodeObjectPool pool = new NodeObjectPool();

		private object syncRoot = new object();

		bool ICollection.IsSynchronized => true;

		object ICollection.SyncRoot => syncRoot;

		public int Count => count;

		public bool IsEmpty => count == 0;

		private static Node ZeroOut(Node node)
		{
			node.Value = default(T);
			node.Next = null;
			return node;
		}

		public ConcurrentQueue()
		{
			tail = head;
		}

		public ConcurrentQueue(IEnumerable<T> collection)
			: this()
		{
			foreach (T item in collection)
			{
				Enqueue(item);
			}
		}

		public void Enqueue(T item)
		{
			Node node = pool.Take();
			node.Value = item;
			Node node2 = null;
			Node node3 = null;
			bool flag = false;
			while (!flag)
			{
				node2 = tail;
				node3 = node2.Next;
				if (tail == node2)
				{
					if (node3 == null)
					{
						flag = Interlocked.CompareExchange(ref tail.Next, node, null) == null;
					}
					else
					{
						Interlocked.CompareExchange(ref tail, node3, node2);
					}
				}
			}
			Interlocked.CompareExchange(ref tail, node, node2);
			Interlocked.Increment(ref count);
		}

		bool IProducerConsumerCollection<T>.TryAdd(T item)
		{
			Enqueue(item);
			return true;
		}

		public bool TryDequeue(out T result)
		{
			result = default(T);
			bool flag = false;
			while (!flag)
			{
				Node node = head;
				Node node2 = tail;
				Node next = node.Next;
				if (node != head)
				{
					continue;
				}
				if (node == node2)
				{
					if (next != null)
					{
						Interlocked.CompareExchange(ref tail, next, node2);
					}
					result = default(T);
					return false;
				}
				result = next.Value;
				flag = Interlocked.CompareExchange(ref head, next, node) == node;
				if (flag)
				{
					pool.Release(ZeroOut(node));
				}
			}
			Interlocked.Decrement(ref count);
			return true;
		}

		public bool TryPeek(out T result)
		{
			if (IsEmpty)
			{
				result = default(T);
				return false;
			}
			Node next = head.Next;
			result = next.Value;
			return true;
		}

		internal void Clear()
		{
			count = 0;
			tail = (head = new Node());
		}

		IEnumerator IEnumerable.GetEnumerator()
		{
			return InternalGetEnumerator();
		}

		public IEnumerator<T> GetEnumerator()
		{
			return InternalGetEnumerator();
		}

		private IEnumerator<T> InternalGetEnumerator()
		{
			Node my_head = head;
			while (true)
			{
				Node next;
				my_head = (next = my_head.Next);
				if (next != null)
				{
					yield return my_head.Value;
					continue;
				}
				break;
			}
		}

		void ICollection.CopyTo(Array array, int index)
		{
			if (array is T[] array2)
			{
				CopyTo(array2, index);
			}
		}

		public void CopyTo(T[] array, int index)
		{
			IEnumerator<T> enumerator = InternalGetEnumerator();
			int num = index;
			while (enumerator.MoveNext())
			{
				array[num++] = enumerator.Current;
			}
		}

		public T[] ToArray()
		{
			T[] array = new T[count];
			CopyTo(array, 0);
			return array;
		}

		bool IProducerConsumerCollection<T>.TryTake(out T item)
		{
			return TryDequeue(out item);
		}
	}
}
namespace System
{
	[Serializable]
	[DebuggerDisplay("Count = {InnerExceptions.Count}")]
	public class AggregateException : Exception
	{
		private const string defaultMessage = "One or more errors occured";

		private List<Exception> innerExceptions = new List<Exception>();

		public ReadOnlyCollection<Exception> InnerExceptions => innerExceptions.AsReadOnly();

		public AggregateException()
			: base("One or more errors occured")
		{
		}

		public AggregateException(string message)
			: base(message)
		{
		}

		public AggregateException(string message, Exception innerException)
			: base(message, innerException)
		{
			if (innerException == null)
			{
				throw new ArgumentNullException("innerException");
			}
			innerExceptions.Add(innerException);
		}

		protected AggregateException(SerializationInfo info, StreamingContext context)
			: base(info, context)
		{
		}

		public AggregateException(params Exception[] innerExceptions)
			: this(string.Empty, innerExceptions)
		{
		}

		public AggregateException(string message, params Exception[] innerExceptions)
			: base(message, (innerExceptions == null || innerExceptions.Length == 0) ? null : innerExceptions[0])
		{
			if (innerExceptions == null)
			{
				throw new ArgumentNullException("innerExceptions");
			}
			foreach (Exception ex in innerExceptions)
			{
				if (ex == null)
				{
					throw new ArgumentException("One of the inner exception is null", "innerExceptions");
				}
			}
			this.innerExceptions.AddRange(innerExceptions);
		}

		public AggregateException(IEnumerable<Exception> innerExceptions)
			: this("One or more errors occured", innerExceptions)
		{
		}

		public AggregateException(string message, IEnumerable<Exception> innerExceptions)
			: this(message, new List<Exception>(innerExceptions).ToArray())
		{
		}

		public AggregateException Flatten()
		{
			List<Exception> list = new List<Exception>();
			foreach (Exception innerException in innerExceptions)
			{
				if (innerException is AggregateException ex)
				{
					list.AddRange(ex.Flatten().InnerExceptions);
				}
				else
				{
					list.Add(innerException);
				}
			}
			return new AggregateException(list);
		}

		public void Handle(Func<Exception, bool> predicate)
		{
			List<Exception> list = new List<Exception>();
			foreach (Exception innerException in innerExceptions)
			{
				try
				{
					if (!predicate(innerException))
					{
						list.Add(innerException);
					}
				}
				catch
				{
					throw new AggregateException(list);
				}
			}
			if (list.Count > 0)
			{
				throw new AggregateException(list);
			}
		}

		internal void AddChildException(AggregateException childEx)
		{
			if (innerExceptions == null)
			{
				innerExceptions = new List<Exception>();
			}
			if (childEx != null)
			{
				innerExceptions.Add(childEx);
			}
		}

		public override string ToString()
		{
			StringBuilder stringBuilder = new StringBuilder(base.ToString());
			int num = -1;
			foreach (Exception innerException in innerExceptions)
			{
				stringBuilder.Append(Environment.NewLine);
				stringBuilder.Append(" --> (Inner exception ");
				stringBuilder.Append(++num);
				stringBuilder.Append(") ");
				stringBuilder.Append(innerException.ToString());
				stringBuilder.Append(Environment.NewLine);
			}
			return stringBuilder.ToString();
		}

		public override void GetObjectData(SerializationInfo info, StreamingContext context)
		{
			throw new NotImplementedException();
		}

		public override Exception GetBaseException()
		{
			if (innerExceptions == null || innerExceptions.Count == 0)
			{
				return this;
			}
			return innerExceptions[0].GetBaseException();
		}
	}
}
namespace System.Threading.Tasks
{
	internal class TaskExceptionSlot
	{
		public volatile AggregateException Exception;

		public volatile bool Observed;

		public ConcurrentQueue<AggregateException> ChildExceptions;

		private Task parent;

		public TaskExceptionSlot(Task parent)
		{
			this.parent = parent;
		}

		~TaskExceptionSlot()
		{
			if (Exception != null && (!Observed && !TaskScheduler.FireUnobservedEvent(parent, Exception).Observed))
			{
				parent = null;
				throw Exception;
			}
		}
	}
	internal abstract class TaskActionInvoker
	{
		private sealed class EmptyTaskActionInvoker : TaskActionInvoker
		{
			public override Delegate Action => null;

			public override void Invoke(Task owner, object state, Task context)
			{
			}
		}

		private sealed class ActionInvoke : TaskActionInvoker
		{
			private readonly Action action;

			public override Delegate Action => action;

			public ActionInvoke(Action action)
			{
				this.action = action;
			}

			public override void Invoke(Task owner, object state, Task context)
			{
				action();
			}
		}

		private sealed class ActionObjectInvoke : TaskActionInvoker
		{
			private readonly Action<object> action;

			public override Delegate Action => action;

			public ActionObjectInvoke(Action<object> action)
			{
				this.action = action;
			}

			public override void Invoke(Task owner, object state, Task context)
			{
				action(state);
			}
		}

		private sealed class ActionTaskInvoke : TaskActionInvoker
		{
			private readonly Action<Task> action;

			public override Delegate Action => action;

			public ActionTaskInvoke(Action<Task> action)
			{
				this.action = action;
			}

			public override void Invoke(Task owner, object state, Task context)
			{
				action(owner);
			}
		}

		private sealed class ActionTasksInvoke : TaskActionInvoker
		{
			private readonly Action<Task[]> action;

			private readonly Task[] tasks;

			public override Delegate Action => action;

			public ActionTasksInvoke(Action<Task[]> action, Task[] tasks)
			{
				this.action = action;
				this.tasks = tasks;
			}

			public override void Invoke(Task owner, object state, Task context)
			{
				action(tasks);
			}
		}

		private sealed class ActionTaskObjectInvoke : TaskActionInvoker
		{
			private readonly Action<Task, object> action;

			public override Delegate Action => action;

			public ActionTaskObjectInvoke(Action<Task, object> action)
			{
				this.action = action;
			}

			public override void Invoke(Task owner, object state, Task context)
			{
				action(owner, state);
			}
		}

		private sealed class ActionTaskObjectInvoke<TResult> : TaskActionInvoker
		{
			private readonly Action<Task<TResult>, object> action;

			public override Delegate Action => action;

			public ActionTaskObjectInvoke(Action<Task<TResult>, object> action)
			{
				this.action = action;
			}

			public override void Invoke(Task owner, object state, Task context)
			{
				action((Task<TResult>)owner, state);
			}
		}

		private sealed class ActionTaskInvoke<TResult> : TaskActionInvoker
		{
			private readonly Action<Task<TResult>> action;

			public override Delegate Action => action;

			public ActionTaskInvoke(Action<Task<TResult>> action)
			{
				this.action = action;
			}

			public override void Invoke(Task owner, object state, Task context)
			{
				action((Task<TResult>)owner);
			}
		}

		private sealed class ActionTaskSelected : TaskActionInvoker
		{
			private readonly Action<Task> action;

			private readonly Task[] tasks;

			public override Delegate Action => action;

			public ActionTaskSelected(Action<Task> action, Task[] tasks)
			{
				this.action = action;
				this.tasks = tasks;
			}

			public override void Invoke(Task owner, object state, Task context)
			{
				int result = ((Task<int>)owner).Result;
				action(tasks[result]);
			}
		}

		private sealed class FuncInvoke<TResult> : TaskActionInvoker
		{
			private readonly Func<TResult> action;

			public override Delegate Action => action;

			public FuncInvoke(Func<TResult> action)
			{
				this.action = action;
			}

			public override void Invoke(Task owner, object state, Task context)
			{
				((Task<TResult>)context).Result = action();
			}
		}

		private sealed class FuncTaskInvoke<TResult> : TaskActionInvoker
		{
			private readonly Func<Task, TResult> action;

			public override Delegate Action => action;

			public FuncTaskInvoke(Func<Task, TResult> action)
			{
				this.action = action;
			}

			public override void Invoke(Task owner, object state, Task context)
			{
				((Task<TResult>)context).Result = action(owner);
			}
		}

		private sealed class FuncTasksInvoke<TResult> : TaskActionInvoker
		{
			private readonly Func<Task[], TResult> action;

			private readonly Task[] tasks;

			public override Delegate Action => action;

			public FuncTasksInvoke(Func<Task[], TResult> action, Task[] tasks)
			{
				this.action = action;
				this.tasks = tasks;
			}

			public override void Invoke(Task owner, object state, Task context)
			{
				((Task<TResult>)context).Result = action(tasks);
			}
		}

		private sealed class FuncTaskSelected<TResult> : TaskActionInvoker
		{
			private readonly Func<Task, TResult> action;

			private readonly Task[] tasks;

			public override Delegate Action => action;

			public FuncTaskSelected(Func<Task, TResult> action, Task[] tasks)
			{
				this.action = action;
				this.tasks = tasks;
			}

			public override void Invoke(Task owner, object state, Task context)
			{
				int result = ((Task<int>)owner).Result;
				((Task<TResult>)context).Result = action(tasks[result]);
			}
		}

		private sealed class FuncTaskInvoke<TResult, TNewResult> : TaskActionInvoker
		{
			private readonly Func<Task<TResult>, TNewResult> action;

			public override Delegate Action => action;

			public FuncTaskInvoke(Func<Task<TResult>, TNewResult> action)
			{
				this.action = action;
			}

			public override void Invoke(Task owner, object state, Task context)
			{
				((Task<TNewResult>)context).Result = action((Task<TResult>)owner);
			}
		}

		private sealed class FuncObjectInvoke<TResult> : TaskActionInvoker
		{
			private readonly Func<object, TResult> action;

			public override Delegate Action => action;

			public FuncObjectInvoke(Func<object, TResult> action)
			{
				this.action = action;
			}

			public override void Invoke(Task owner, object state, Task context)
			{
				((Task<TResult>)context).Result = action(state);
			}
		}

		private sealed class FuncTaskObjectInvoke<TResult> : TaskActionInvoker
		{
			private readonly Func<Task, object, TResult> action;

			public override Delegate Action => action;

			public FuncTaskObjectInvoke(Func<Task, object, TResult> action)
			{
				this.action = action;
			}

			public override void Invoke(Task owner, object state, Task context)
			{
				((Task<TResult>)context).Result = action(owner, state);
			}
		}

		private sealed class FuncTaskObjectInvoke<TResult, TNewResult> : TaskActionInvoker
		{
			private readonly Func<Task<TResult>, object, TNewResult> action;

			public override Delegate Action => action;

			public FuncTaskObjectInvoke(Func<Task<TResult>, object, TNewResult> action)
			{
				this.action = action;
			}

			public override void Invoke(Task owner, object state, Task context)
			{
				((Task<TNewResult>)context).Result = action((Task<TResult>)owner, state);
			}
		}

		public static readonly TaskActionInvoker Empty = new EmptyTaskActionInvoker();

		public abstract Delegate Action { get; }

		public static TaskActionInvoker Create(Action action)
		{
			return new ActionInvoke(action);
		}

		public static TaskActionInvoker Create(Action<object> action)
		{
			return new ActionObjectInvoke(action);
		}

		public static TaskActionInvoker Create(Action<Task> action)
		{
			return new ActionTaskInvoke(action);
		}

		public static TaskActionInvoker Create(Action<Task, object> action)
		{
			return new ActionTaskObjectInvoke(action);
		}

		public static TaskActionInvoker Create<TResult>(Action<Task<TResult>> action)
		{
			return new ActionTaskInvoke<TResult>(action);
		}

		public static TaskActionInvoker Create<TResult>(Action<Task<TResult>, object> action)
		{
			return new ActionTaskObjectInvoke<TResult>(action);
		}

		public static TaskActionInvoker Create<TResult>(Func<TResult> action)
		{
			return new FuncInvoke<TResult>(action);
		}

		public static TaskActionInvoker Create<TResult>(Func<object, TResult> action)
		{
			return new FuncObjectInvoke<TResult>(action);
		}

		public static TaskActionInvoker Create<TResult>(Func<Task, TResult> action)
		{
			return new FuncTaskInvoke<TResult>(action);
		}

		public static TaskActionInvoker Create<TResult>(Func<Task, object, TResult> action)
		{
			return new FuncTaskObjectInvoke<TResult>(action);
		}

		public static TaskActionInvoker Create<TResult, TNewResult>(Func<Task<TResult>, TNewResult> action)
		{
			return new FuncTaskInvoke<TResult, TNewResult>(action);
		}

		public static TaskActionInvoker Create<TResult, TNewResult>(Func<Task<TResult>, object, TNewResult> action)
		{
			return new FuncTaskObjectInvoke<TResult, TNewResult>(action);
		}

		public static TaskActionInvoker Create(Action<Task[]> action, Task[] tasks)
		{
			return new ActionTasksInvoke(action, tasks);
		}

		public static TaskActionInvoker Create<TResult>(Func<Task[], TResult> action, Task[] tasks)
		{
			return new FuncTasksInvoke<TResult>(action, tasks);
		}

		public static TaskActionInvoker Create(Action<Task> action, Task[] tasks)
		{
			return new ActionTaskSelected(action, tasks);
		}

		public static TaskActionInvoker Create<TResult>(Func<Task, TResult> action, Task[] tasks)
		{
			return new FuncTaskSelected<TResult>(action, tasks);
		}

		public abstract void Invoke(Task owner, object state, Task context);
	}
}
namespace System.Collections
{
	[Serializable]
	internal class ArrayList : IList, ICollection, IEnumerable
	{
		private sealed class ArrayListEnumerator : IEnumerator
		{
			private object m_Current;

			private ArrayList m_List;

			private int m_Pos;

			private int m_Index;

			private int m_Count;

			private int m_ExpectedStateChanges;

			public object Current
			{
				get
				{
					if (m_Pos == m_Index - 1)
					{
						throw new InvalidOperationException("Enumerator unusable (Reset pending, or past end of array.");
					}
					return m_Current;
				}
			}

			public ArrayListEnumerator(ArrayList list)
				: this(list, 0, list.Count)
			{
			}

			public object Clone()
			{
				return MemberwiseClone();
			}

			public ArrayListEnumerator(ArrayList list, int index, int count)
			{
				m_List = list;
				m_Index = index;
				m_Count = count;
				m_Pos = m_Index - 1;
				m_Current = null;
				m_ExpectedStateChanges = list._version;
			}

			public bool MoveNext()
			{
				if (m_List._version != m_ExpectedStateChanges)
				{
					throw new InvalidOperationException("List has changed.");
				}
				m_Pos++;
				if (m_Pos - m_Index < m_Count)
				{
					m_Current = m_List[m_Pos];
					return true;
				}
				return false;
			}

			public void Reset()
			{
				m_Current = null;
				m_Pos = m_Index - 1;
			}
		}

		private sealed class SimpleEnumerator : IEnumerator
		{
			private ArrayList list;

			private object currentElement;

			private int index;

			private int version;

			private static object endFlag = new object();

			public object Current
			{
				get
				{
					if (currentElement == endFlag)
					{
						if (index == -1)
						{
							throw new InvalidOperationException("Enumerator not started");
						}
						throw new InvalidOperationException("Enumerator ended");
					}
					return currentElement;
				}
			}

			public SimpleEnumerator(ArrayList list)
			{
				this.list = list;
				index = -1;
				version = list._version;
				currentElement = endFlag;
			}

			public object Clone()
			{
				return MemberwiseClone();
			}

			public bool MoveNext()
			{
				if (version != list._version)
				{
					throw new InvalidOperationException("List has changed.");
				}
				if (++index < list.Count)
				{
					currentElement = list[index];
					return true;
				}
				currentElement = endFlag;
				return false;
			}

			public void Reset()
			{
				if (version != list._version)
				{
					throw new InvalidOperationException("List has changed.");
				}
				currentElement = endFlag;
				index = -1;
			}
		}

		[Serializable]
		private sealed class ArrayListAdapter : ArrayList
		{
			private sealed class EnumeratorWithRange : IEnumerator
			{
				private int m_StartIndex;

				private int m_Count;

				private int m_MaxCount;

				private IEnumerator m_Enumerator;

				public object Current => m_Enumerator.Current;

				public EnumeratorWithRange(IEnumerator enumerator, int index, int count)
				{
					m_Count = 0;
					m_StartIndex = index;
					m_MaxCount = count;
					m_Enumerator = enumerator;
					Reset();
				}

				public object Clone()
				{
					return MemberwiseClone();
				}

				public bool MoveNext()
				{
					if (m_Count >= m_MaxCount)
					{
						return false;
					}
					m_Count++;
					return m_Enumerator.MoveNext();
				}

				public void Reset()
				{
					m_Count = 0;
					m_Enumerator.Reset();
					for (int i = 0; i < m_StartIndex; i++)
					{
						m_Enumerator.MoveNext();
					}
				}
			}

			private IList m_Adaptee;

			public override object this[int index]
			{
				get
				{
					return m_Adaptee[index];
				}
				set
				{
					m_Adaptee[index] = value;
				}
			}

			public override int Count => m_Adaptee.Count;

			public override int Capacity
			{
				get
				{
					return m_Adaptee.Count;
				}
				set
				{
					if (value < m_Adaptee.Count)
					{
						throw new ArgumentException("capacity");
					}
				}
			}

			public override bool IsFixedSize => m_Adaptee.IsFixedSize;

			public override bool IsReadOnly => m_Adaptee.IsReadOnly;

			public override object SyncRoot => m_Adaptee.SyncRoot;

			public override bool IsSynchronized => m_Adaptee.IsSynchronized;

			public ArrayListAdapter(IList adaptee)
				: base(0, forceZeroSize: true)
			{
				m_Adaptee = adaptee;
			}

			public override int Add(object value)
			{
				return m_Adaptee.Add(value);
			}

			public override void Clear()
			{
				m_Adaptee.Clear();
			}

			public override bool Contains(object value)
			{
				return m_Adaptee.Contains(value);
			}

			public override int IndexOf(object value)
			{
				return m_Adaptee.IndexOf(value);
			}

			public override int IndexOf(object value, int startIndex)
			{
				return IndexOf(value, startIndex, m_Adaptee.Count - startIndex);
			}

			public override int IndexOf(object value, int startIndex, int count)
			{
				if (startIndex < 0 || startIndex > m_Adaptee.Count)
				{
					ThrowNewArgumentOutOfRangeException("startIndex", startIndex, "Does not specify valid index.");
				}
				if (count < 0)
				{
					ThrowNewArgumentOutOfRangeException("count", count, "Can't be less than 0.");
				}
				if (startIndex > m_Adaptee.Count - count)
				{
					throw new ArgumentOutOfRangeException("count", "Start index and count do not specify a valid range.");
				}
				if (value == null)
				{
					for (int i = startIndex; i < startIndex + count; i++)
					{
						if (m_Adaptee[i] == null)
						{
							return i;
						}
					}
				}
				else
				{
					for (int j = startIndex; j < startIndex + count; j++)
					{
						if (value.Equals(m_Adaptee[j]))
						{
							return j;
						}
					}
				}
				return -1;
			}

			public override int LastIndexOf(object value)
			{
				return LastIndexOf(value, m_Adaptee.Count - 1);
			}

			public override int LastIndexOf(object value, int startIndex)
			{
				return LastIndexOf(value, startIndex, startIndex + 1);
			}

			public override int LastIndexOf(object value, int startIndex, int count)
			{
				if (startIndex < 0)
				{
					ThrowNewArgumentOutOfRangeException("startIndex", startIndex, "< 0");
				}
				if (count < 0)
				{
					ThrowNewArgumentOutOfRangeException("count", count, "count is negative.");
				}
				if (startIndex - count + 1 < 0)
				{
					ThrowNewArgumentOutOfRangeException("count", count, "count is too large.");
				}
				if (value == null)
				{
					for (int num = startIndex; num > startIndex - count; num--)
					{
						if (m_Adaptee[num] == null)
						{
							return num;
						}
					}
				}
				else
				{
					for (int num2 = startIndex; num2 > startIndex - count; num2--)
					{
						if (value.Equals(m_Adaptee[num2]))
						{
							return num2;
						}
					}
				}
				return -1;
			}

			public override void Insert(int index, object value)
			{
				m_Adaptee.Insert(index, value);
			}

			public override void InsertRange(int index, ICollection c)
			{
				if (c == null)
				{
					throw new ArgumentNullException("c");
				}
				if (index > m_Adaptee.Count)
				{
					ThrowNewArgumentOutOfRangeException("index", index, "Index must be >= 0 and <= Count.");
				}
				foreach (object item in c)
				{
					m_Adaptee.Insert(index++, item);
				}
			}

			public override void Remove(object value)
			{
				m_Adaptee.Remove(value);
			}

			public override void RemoveAt(int index)
			{
				m_Adaptee.RemoveAt(index);
			}

			public override void RemoveRange(int index, int count)
			{
				CheckRange(index, count, m_Adaptee.Count);
				for (int i = 0; i < count; i++)
				{
					m_Adaptee.RemoveAt(index);
				}
			}

			public override void Reverse()
			{
				Reverse(0, m_Adaptee.Count);
			}

			public override void Reverse(int index, int count)
			{
				CheckRange(index, count, m_Adaptee.Count);
				for (int i = 0; i < count / 2; i++)
				{
					object value = m_Adaptee[i + index];
					m_Adaptee[i + index] = m_Adaptee[index + count - i + index - 1];
					m_Adaptee[index + count - i + index - 1] = value;
				}
			}

			public override void SetRange(int index, ICollection c)
			{
				if (c == null)
				{
					throw new ArgumentNullException("c");
				}
				if (index < 0 || index + c.Count > m_Adaptee.Count)
				{
					throw new ArgumentOutOfRangeException("index");
				}
				int num = index;
				foreach (object item in c)
				{
					m_Adaptee[num++] = item;
				}
			}

			public override void CopyTo(Array array)
			{
				m_Adaptee.CopyTo(array, 0);
			}

			public override void CopyTo(Array array, int index)
			{
				m_Adaptee.CopyTo(array, index);
			}

			public override void CopyTo(int index, Array array, int arrayIndex, int count)
			{
				if (index < 0)
				{
					ThrowNewArgumentOutOfRangeException("index", index, "Can't be less than zero.");
				}
				if (arrayIndex < 0)
				{
					ThrowNewArgumentOutOfRangeException("arrayIndex", arrayIndex, "Can't be less than zero.");
				}
				if (count < 0)
				{
					ThrowNewArgumentOutOfRangeException("index", index, "Can't be less than zero.");
				}
				if (index >= m_Adaptee.Count)
				{
					throw new ArgumentException("Can't be more or equal to list count.", "index");
				}
				if (array.Rank > 1)
				{
					throw new ArgumentException("Can't copy into multi-dimensional array.");
				}
				if (arrayIndex >= array.Length)
				{
					throw new ArgumentException("arrayIndex can't be greater than array.Length - 1.");
				}
				if (array.Length - arrayIndex + 1 < count)
				{
					throw new ArgumentException("Destination array is too small.");
				}
				if (index > m_Adaptee.Count - count)
				{
					throw new ArgumentException("Index and count do not denote a valid range of elements.", "index");
				}
				for (int i = 0; i < count; i++)
				{
					array.SetValue(m_Adaptee[index + i], arrayIndex + i);
				}
			}

			public override IEnumerator GetEnumerator()
			{
				return m_Adaptee.GetEnumerator();
			}

			public override IEnumerator GetEnumerator(int index, int count)
			{
				CheckRange(index, count, m_Adaptee.Count);
				return new EnumeratorWithRange(m_Adaptee.GetEnumerator(), index, count);
			}

			public override void AddRange(ICollection c)
			{
				foreach (object item in c)
				{
					m_Adaptee.Add(item);
				}
			}

			public override int BinarySearch(object value)
			{
				return BinarySearch(value, null);
			}

			public override int BinarySearch(object value, IComparer comparer)
			{
				return BinarySearch(0, m_Adaptee.Count, value, comparer);
			}

			public override int BinarySearch(int index, int count, object value, IComparer comparer)
			{
				CheckRange(index, count, m_Adaptee.Count);
				if (comparer == null)
				{
					comparer = Comparer.Default;
				}
				int num = index;
				int num2 = index + count - 1;
				while (num <= num2)
				{
					int num3 = num + (num2 - num) / 2;
					int num4 = comparer.Compare(value, m_Adaptee[num3]);
					if (num4 < 0)
					{
						num2 = num3 - 1;
						continue;
					}
					if (num4 > 0)
					{
						num = num3 + 1;
						continue;
					}
					return num3;
				}
				return ~num;
			}

			public override object Clone()
			{
				return new ArrayListAdapter(m_Adaptee);
			}

			public override ArrayList GetRange(int index, int count)
			{
				CheckRange(index, count, m_Adaptee.Count);
				return new RangedArrayList(this, index, count);
			}

			public override void TrimToSize()
			{
			}

			public override void Sort()
			{
				Sort(Comparer.Default);
			}

			public override void Sort(IComparer comparer)
			{
				Sort(0, m_Adaptee.Count, comparer);
			}

			public override void Sort(int index, int count, IComparer comparer)
			{
				CheckRange(index, count, m_Adaptee.Count);
				if (comparer == null)
				{
					comparer = Comparer.Default;
				}
				QuickSort(m_Adaptee, index, index + count - 1, comparer);
			}

			private static void Swap(IList list, int x, int y)
			{
				object value = list[x];
				list[x] = list[y];
				list[y] = value;
			}

			internal static void QuickSort(IList list, int left, int right, IComparer comparer)
			{
				if (left >= right)
				{
					return;
				}
				int num = left + (right - left) / 2;
				if (comparer.Compare(list[num], list[left]) < 0)
				{
					Swap(list, num, left);
				}
				if (comparer.Compare(list[right], list[left]) < 0)
				{
					Swap(list, right, left);
				}
				if (comparer.Compare(list[right], list[num]) < 0)
				{
					Swap(list, right, num);
				}
				if (right - left + 1 <= 3)
				{
					return;
				}
				Swap(list, right - 1, num);
				object y = list[right - 1];
				int num2 = left;
				int num3 = right - 1;
				while (true)
				{
					if (comparer.Compare(list[++num2], y) >= 0)
					{
						while (comparer.Compare(list[--num3], y) > 0)
						{
						}
						if (num2 >= num3)
						{
							break;
						}
						Swap(list, num2, num3);
					}
				}
				Swap(list, right - 1, num2);
				QuickSort(list, left, num2 - 1, comparer);
				QuickSort(list, num2 + 1, right, comparer);
			}

			public override object[] ToArray()
			{
				object[] array = new object[m_Adaptee.Count];
				m_Adaptee.CopyTo(array, 0);
				return array;
			}

			public override Array ToArray(Type elementType)
			{
				Array array = Array.CreateInstance(elementType, m_Adaptee.Count);
				m_Adaptee.CopyTo(array, 0);
				return array;
			}
		}

		[Serializable]
		private class ArrayListWrapper : ArrayList
		{
			protected ArrayList m_InnerArrayList;

			public override object this[int index]
			{
				get
				{
					return m_InnerArrayList[index];
				}
				set
				{
					m_InnerArrayList[index] = value;
				}
			}

			public override int Count => m_InnerArrayList.Count;

			public override int Capacity
			{
				get
				{
					return m_InnerArrayList.Capacity;
				}
				set
				{
					m_InnerArrayList.Capacity = value;
				}
			}

			public override bool IsFixedSize => m_InnerArrayList.IsFixedSize;

			public override bool IsReadOnly => m_InnerArrayList.IsReadOnly;

			public override bool IsSynchronized => m_InnerArrayList.IsSynchronized;

			public override object SyncRoot => m_InnerArrayList.SyncRoot;

			public ArrayListWrapper(ArrayList innerArrayList)
			{
				m_InnerArrayList = innerArrayList;
			}

			public override int Add(object value)
			{
				return m_InnerArrayList.Add(value);
			}

			public override void Clear()
			{
				m_InnerArrayList.Clear();
			}

			public override bool Contains(object value)
			{
				return m_InnerArrayList.Contains(value);
			}

			public override int IndexOf(object value)
			{
				return m_InnerArrayList.IndexOf(value);
			}

			public override int IndexOf(object value, int startIndex)
			{
				return m_InnerArrayList.IndexOf(value, startIndex);
			}

			public override int IndexOf(object value, int startIndex, int count)
			{
				return m_InnerArrayList.IndexOf(value, startIndex, count);
			}

			public override int LastIndexOf(object value)
			{
				return m_InnerArrayList.LastIndexOf(value);
			}

			public override int LastIndexOf(object value, int startIndex)
			{
				return m_InnerArrayList.LastIndexOf(value, startIndex);
			}

			public override int LastIndexOf(object value, int startIndex, int count)
			{
				return m_InnerArrayList.LastIndexOf(value, startIndex, count);
			}

			public override void Insert(int index, object value)
			{
				m_InnerArrayList.Insert(index, value);
			}

			public override void InsertRange(int index, ICollection c)
			{
				m_InnerArrayList.InsertRange(index, c);
			}

			public override void Remove(object value)
			{
				m_InnerArrayList.Remove(value);
			}

			public override void RemoveAt(int index)
			{
				m_InnerArrayList.RemoveAt(index);
			}

			public override void RemoveRange(int index, int count)
			{
				m_InnerArrayList.RemoveRange(index, count);
			}

			public override void Reverse()
			{
				m_InnerArrayList.Reverse();
			}

			public override void Reverse(int index, int count)
			{
				m_InnerArrayList.Reverse(index, count);
			}

			public override void SetRange(int index, ICollection c)
			{
				m_InnerArrayList.SetRange(index, c);
			}

			public override void CopyTo(Array array)
			{
				m_InnerArrayList.CopyTo(array);
			}

			public override void CopyTo(Array array, int index)
			{
				m_InnerArrayList.CopyTo(array, index);
			}

			public override void CopyTo(int index, Array array, int arrayIndex, int count)
			{
				m_InnerArrayList.CopyTo(index, array, arrayIndex, count);
			}

			public override IEnumerator GetEnumerator()
			{
				return m_InnerArrayList.GetEnumerator();
			}

			public override IEnumerator GetEnumerator(int index, int count)
			{
				return m_InnerArrayList.GetEnumerator(index, count);
			}

			public override void AddRange(ICollection c)
			{
				m_InnerArrayList.AddRange(c);
			}

			public override int BinarySearch(object value)
			{
				return m_InnerArrayList.BinarySearch(value);
			}

			public override int BinarySearch(object value, IComparer comparer)
			{
				return m_InnerArrayList.BinarySearch(value, comparer);
			}

			public override int BinarySearch(int index, int count, object value, IComparer comparer)
			{
				return m_InnerArrayList.BinarySearch(index, count, value, comparer);
			}

			public override object Clone()
			{
				return m_InnerArrayList.Clone();
			}

			public override ArrayList GetRange(int index, int count)
			{
				return m_InnerArrayList.GetRange(index, count);
			}

			public override void TrimToSize()
			{
				m_InnerArrayList.TrimToSize();
			}

			public override void Sort()
			{
				m_InnerArrayList.Sort();
			}

			public override void Sort(IComparer comparer)
			{
				m_InnerArrayList.Sort(comparer);
			}

			public override void Sort(int index, int count, IComparer comparer)
			{
				m_InnerArrayList.Sort(index, count, comparer);
			}

			public override object[] ToArray()
			{
				return m_InnerArrayList.ToArray();
			}

			public override Array ToArray(Type elementType)
			{
				return m_InnerArrayList.ToArray(elementType);
			}
		}

		[Serializable]
		private sealed class SynchronizedArrayListWrapper : ArrayListWrapper
		{
			private object m_SyncRoot;

			public override object this[int index]
			{
				get
				{
					lock (m_SyncRoot)
					{
						return m_InnerArrayList[index];
					}
				}
				set
				{
					lock (m_SyncRoot)
					{
						m_InnerArrayList[index] = value;
					}
				}
			}

			public override int Count
			{
				get
				{
					lock (m_SyncRoot)
					{
						return m_InnerArrayList.Count;
					}
				}
			}

			public override int Capacity
			{
				get
				{
					lock (m_SyncRoot)
					{
						return m_InnerArrayList.Capacity;
					}
				}
				set
				{
					lock (m_SyncRoot)
					{
						m_InnerArrayList.Capacity = value;
					}
				}
			}

			public override bool IsFixedSize
			{
				get
				{
					lock (m_SyncRoot)
					{
						return m_InnerArrayList.IsFixedSize;
					}
				}
			}

			public override bool IsReadOnly
			{
				get
				{
					lock (m_SyncRoot)
					{
						return m_InnerArrayList.IsReadOnly;
					}
				}
			}

			public override bool IsSynchronized => true;

			public override object SyncRoot => m_SyncRoot;

			internal SynchronizedArrayListWrapper(ArrayList innerArrayList)
				: base(innerArrayList)
			{
				m_SyncRoot = innerArrayList.SyncRoot;
			}

			public override int Add(object value)
			{
				lock (m_SyncRoot)
				{
					return m_InnerArrayList.Add(value);
				}
			}

			public override void Clear()
			{
				lock (m_SyncRoot)
				{
					m_InnerArrayList.Clear();
				}
			}

			public override bool Contains(object value)
			{
				lock (m_SyncRoot)
				{
					return m_InnerArrayList.Contains(value);
				}
			}

			public override int IndexOf(object value)
			{
				lock (m_SyncRoot)
				{
					return m_InnerArrayList.IndexOf(value);
				}
			}

			public override int IndexOf(object value, int startIndex)
			{
				lock (m_SyncRoot)
				{
					return m_InnerArrayList.IndexOf(value, startIndex);
				}
			}

			public override int IndexOf(object value, int startIndex, int count)
			{
				lock (m_S