Decompiled source of Receiver 2 Modding Kit v1.6.2

Receiver2ModdingKit.dll

Decompiled a month ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using FMOD;
using FMOD.Studio;
using FMODUnity;
using HarmonyLib;
using ImGuiNET;
using Mono.Cecil;
using MonoMod.Utils.Cil;
using Receiver2;
using Receiver2ModdingKit.CustomRounds;
using Receiver2ModdingKit.CustomSounds;
using Receiver2ModdingKit.Editor;
using Receiver2ModdingKit.Gamemodes;
using Receiver2ModdingKit.Helpers;
using Receiver2ModdingKit.Logging;
using Receiver2ModdingKit.ModInstaller;
using Receiver2ModdingKit.Thunderstore;
using Rewired;
using RewiredConsts;
using SharpCompress.Archives;
using SharpCompress.Common;
using SharpCompress.Readers;
using SimpleJSON;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;
using Wolfire;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.0.0")]
[module: UnverifiableCode]
namespace Receiver2ModdingKit
{
	public static class ModPersistentData
	{
		private const string k_PersistentDataKeyName = "mod_persistent_data";

		private static JSONObject persistent_data = new JSONObject();

		public static void AddPersistentData(PluginInfo pluginInfo, JSONObject data)
		{
			((JSONNode)persistent_data).Add(pluginInfo.Metadata.GUID, (JSONNode)(object)data);
		}

		public static JSONObject GetPersistentData(PluginInfo pluginInfo)
		{
			return ((JSONNode)persistent_data)[pluginInfo.Metadata.GUID].AsObject;
		}

		[HarmonyPatch(typeof(PersistentPlayerData), "Serialize")]
		[HarmonyPostfix]
		private static void AddDataToSave(JSONObject __result)
		{
			try
			{
				((JSONNode)__result).Add("mod_persistent_data", (JSONNode)(object)persistent_data);
			}
			catch
			{
			}
		}

		[HarmonyPatch(typeof(PersistentPlayerData), "Deserialize")]
		[HarmonyPostfix]
		private static void RetrieveDataFromSave(JSONNode jn)
		{
			try
			{
				persistent_data = jn["mod_persistent_data"].AsObject;
			}
			catch
			{
			}
		}
	}
	internal class EditorInput
	{
		public static bool GetKeyDown(KeyCode key)
		{
			return false;
		}

		public static bool GetKeyUp(KeyCode key)
		{
			return false;
		}

		public static bool GetKey(KeyCode key)
		{
			return false;
		}

		public static Vector3 GetMousePos()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			return Vector3.zero;
		}

		public static Ray MouseRay()
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			return default(Ray);
		}
	}
	public static class Extensions
	{
		internal static JSONObject current_gun_data;

		internal static bool lah_force_bullet_display;

		internal static Queue<Tuple<PoseSpring, float>> pose_spring_overrides = new Queue<Tuple<PoseSpring, float>>();

		internal static bool unlock_cursor;

		internal static bool confine_cursor;

		internal static bool freeze_camera_rotation;

		internal static Type konType = null;

		public static Harmony getConsoleColorHarmonyInstance;

		public static Harmony logEventArgsToStringHarmonyInstance;

		public static ConsoleColor BackgroundColor
		{
			get
			{
				return (ConsoleColor)(konType?.GetProperty("BackgroundColor").GetMethod.Invoke(null, null));
			}
			set
			{
				konType?.GetProperty("BackgroundColor").SetMethod.Invoke(null, new object[1] { value });
			}
		}

		public static ShellCasingScript GetBullet(this LocalAimHandler lah, Preset cartridge_dimension)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected I4, but got Unknown
			return lah.GetBullet((Preset[])(object)new Preset[1] { (Preset)(int)cartridge_dimension });
		}

		public static ShellCasingScript GetBullet(this LocalAimHandler lah, uint cartridge_dimension)
		{
			return lah.GetBullet((Preset[])(object)new Preset[1] { (Preset)cartridge_dimension });
		}

		public static ShellCasingScript GetBullet(this LocalAimHandler lah, Preset[] cartridge_dimensions)
		{
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Expected O, but got Unknown
			if ((Object)(object)lah == (Object)null)
			{
				Debug.LogError((object)"(Extension) LocalAimHandler.GetBullet(): This LocalAimHandler instance is null");
				return null;
			}
			if (cartridge_dimensions == null)
			{
				Debug.LogError((object)"(Extension) LocalAimHandler.GetBullet(): You have to provide a CartridgeSpec array");
				return null;
			}
			object obj = ReflectionManager.LAH_Get_Last_Bullet.Invoke(lah, new object[1] { cartridge_dimensions });
			if (obj == null)
			{
				return null;
			}
			return (ShellCasingScript)ReflectionManager.LAH_BulletInventory_item.GetValue(obj);
		}

		public static ShellCasingScript GetBullet(this LocalAimHandler lah, uint[] cartridge_dimensions)
		{
			return lah.GetBullet(cartridge_dimensions.Cast<Preset>().ToArray());
		}

		public static void ShowBullets(this LocalAimHandler lah, bool show_bullets)
		{
			lah_force_bullet_display = show_bullets;
		}

		public static void ForceCursorUnlock(bool unlock, bool confine)
		{
			unlock_cursor = unlock;
			confine_cursor = confine;
		}

		public static void ShakeBullets(this LocalAimHandler lah)
		{
			if ((Object)(object)lah != (Object)null)
			{
				ReflectionManager.LAH_bullet_shake_time.SetValue(lah, Time.time);
			}
		}

		public static float GetSpringState(this LocalAimHandler lah, PoseSpring spring)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)lah == (Object)null)
			{
				Debug.LogError((object)"(Extension) LocalAimHandler.GetSpringState(): This LocalAimHandler instance is null");
				return 0f;
			}
			return ((Spring)ReflectionManager.LAH_pose_springs[spring].GetValue(lah)).state;
		}

		public static void OverrideSpringState(this LocalAimHandler lah, PoseSpring spring, float amount)
		{
			pose_spring_overrides.Enqueue(new Tuple<PoseSpring, float>(spring, amount));
		}

		public static bool TryGetChild(this DirectoryInfo dir, string child_directory_name, out DirectoryInfo child_directory)
		{
			string path = Path.Combine(dir.FullName, child_directory_name);
			child_directory = new DirectoryInfo(path);
			return Directory.Exists(path);
		}

		public static void Disable(this ActiveItem active_item)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			active_item.item_type = (Type)6;
		}

		public static void SetItemSpawn(this ActiveItem active_item, InventoryItem item, JSONObject persistentData = null)
		{
			active_item.SetItemSpawn(((Object)(object)item != (Object)null) ? item.InternalName : "", persistentData);
		}

		public static void SetItemSpawn(this ActiveItem active_item, string item_internal_name, JSONObject persistentData = null)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			active_item.item_type = (Type)11;
			active_item.internal_name = item_internal_name;
			if ((JSONNode)(object)persistentData != (object)null)
			{
				active_item.persistent_data = persistentData;
			}
		}

		public static bool AddItemsToSpawnList(this ReceiverCoreScript core_script, params InventoryItem[] items)
		{
			if (ModLoader.rcs_prefab_list_locked)
			{
				ModLoader.prefab_list_queue.AddRange(items);
				return false;
			}
			core_script.generic_prefabs = core_script.generic_prefabs.Concat(items).ToArray();
			return true;
		}

		public static JSONObject GetCheckpointData(this ReceiverCoreScript core_script)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			return (JSONObject)(((object)current_gun_data) ?? ((object)new JSONObject()));
		}

		public static void RemovePersistentListeners(this UnityEventBase unity_event)
		{
			if (unity_event.GetPersistentEventCount() != 0)
			{
				object value = ReflectionManager.UEB_persistent_calls.GetValue(unity_event);
				ReflectionManager.PCG_Clear.Invoke(value, new object[0]);
			}
		}

		public static void MoveTo(this FileInfo source_file, string destination_file, bool overwrite)
		{
			if (overwrite && File.Exists(destination_file))
			{
				File.Delete(destination_file);
			}
			source_file.MoveTo(destination_file);
		}

		public static BepInPlugin GetBepInAttribute(this BaseUnityPlugin plugin)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			return (BepInPlugin)Attribute.GetCustomAttribute(((object)plugin).GetType(), typeof(BepInPlugin));
		}

		public static bool TryFindObjectOfType<T>(out T result) where T : Object
		{
			return (Object)(object)(result = Object.FindObjectOfType<T>()) != (Object)null;
		}

		public static bool TryFindObjectsOfType<T>(out T[] result) where T : Object
		{
			return (result = Object.FindObjectsOfType<T>()) != null;
		}

		public static List<CodeInstruction> ToCodeInstructions(this MethodInfo methodInfo, Dictionary<CodeInstruction, CodeInstruction> replaceInstructionWith = null)
		{
			List<CodeInstruction> originalInstructions = PatchProcessor.GetOriginalInstructions((MethodBase)methodInfo, (ILGenerator)null);
			if (replaceInstructionWith != null)
			{
				for (int i = 0; i < originalInstructions.Count; i++)
				{
					if (replaceInstructionWith.TryGetValue(originalInstructions[i], out var value))
					{
						originalInstructions[i] = value;
					}
				}
			}
			return originalInstructions;
		}

		public static List<CodeInstruction> ToCodeInstructionsClipLast(this MethodInfo methodInfo, out List<Label> extractedLabels, Dictionary<CodeInstruction, CodeInstruction> replaceInstructionWith = null)
		{
			List<CodeInstruction> originalInstructions = PatchProcessor.GetOriginalInstructions((MethodBase)methodInfo, (ILGenerator)null);
			if (replaceInstructionWith != null)
			{
				for (int i = 0; i < originalInstructions.Count; i++)
				{
					if (replaceInstructionWith.TryGetValue(originalInstructions[i], out var value))
					{
						originalInstructions[i] = value;
					}
				}
			}
			extractedLabels = CodeInstructionExtensions.ExtractLabels(originalInstructions.Last());
			originalInstructions.Remove(originalInstructions.Last());
			return originalInstructions;
		}

		public static void LogWithCustomLevelName(this ManualLogSource logger, object data, string levelName)
		{
			logEventArgsToStringHarmonyInstance = Harmony.CreateAndPatchAll(typeof(HarmonyManager.LogEventArgsToStringPatch), (string)null);
			HarmonyManager.LogEventArgsToStringPatch.levelName = levelName;
			logger.Log((LogLevel)696969, data);
			logEventArgsToStringHarmonyInstance.UnpatchSelf();
		}

		public static void LogWithCustomLevelNameAndColor(this ManualLogSource logger, object data, string levelName, ConsoleColor color)
		{
			getConsoleColorHarmonyInstance = Harmony.CreateAndPatchAll(typeof(HarmonyManager.GetConsoleColorPatch), (string)null);
			HarmonyManager.GetConsoleColorPatch.consoleColor = color;
			logEventArgsToStringHarmonyInstance = Harmony.CreateAndPatchAll(typeof(HarmonyManager.LogEventArgsToStringPatch), (string)null);
			HarmonyManager.LogEventArgsToStringPatch.levelName = levelName;
			logger.Log((LogLevel)696969, data);
			logEventArgsToStringHarmonyInstance.UnpatchSelf();
			getConsoleColorHarmonyInstance.UnpatchSelf();
		}

		public static void LogWithColor(this ManualLogSource logger, LogLevel logLevel, object data, ConsoleColor color)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			getConsoleColorHarmonyInstance = Harmony.CreateAndPatchAll(typeof(HarmonyManager.GetConsoleColorPatch), (string)null);
			HarmonyManager.GetConsoleColorPatch.consoleColor = color;
			logger.Log(logLevel, data);
			getConsoleColorHarmonyInstance.UnpatchSelf();
		}

		public static void LogDebugWithColor(this ManualLogSource logger, object data, ConsoleColor color)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Expected O, but got Unknown
			if (getConsoleColorHarmonyInstance == null)
			{
				getConsoleColorHarmonyInstance = new Harmony("GetConsoleColor");
			}
			getConsoleColorHarmonyInstance = Harmony.CreateAndPatchAll(typeof(HarmonyManager.GetConsoleColorPatch), (string)null);
			HarmonyManager.GetConsoleColorPatch.consoleColor = color;
			logger.LogDebug(data);
			getConsoleColorHarmonyInstance.UnpatchSelf();
		}

		public static void LogErrorWithColor(this ManualLogSource logger, object data, ConsoleColor color)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Expected O, but got Unknown
			if (getConsoleColorHarmonyInstance == null)
			{
				getConsoleColorHarmonyInstance = new Harmony("GetConsoleColor");
			}
			getConsoleColorHarmonyInstance = Harmony.CreateAndPatchAll(typeof(HarmonyManager.GetConsoleColorPatch), (string)null);
			HarmonyManager.GetConsoleColorPatch.consoleColor = color;
			logger.LogError(data);
			getConsoleColorHarmonyInstance.UnpatchSelf();
		}

		public static void LogFatalWithColor(this ManualLogSource logger, object data, ConsoleColor color)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Expected O, but got Unknown
			if (getConsoleColorHarmonyInstance == null)
			{
				getConsoleColorHarmonyInstance = new Harmony("GetConsoleColor");
			}
			getConsoleColorHarmonyInstance = Harmony.CreateAndPatchAll(typeof(HarmonyManager.GetConsoleColorPatch), (string)null);
			HarmonyManager.GetConsoleColorPatch.consoleColor = color;
			logger.LogFatal(data);
			getConsoleColorHarmonyInstance.UnpatchSelf();
		}

		public static void LogInfoWithColor(this ManualLogSource logger, object data, ConsoleColor color)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Expected O, but got Unknown
			if (getConsoleColorHarmonyInstance == null)
			{
				getConsoleColorHarmonyInstance = new Harmony("GetConsoleColor");
			}
			getConsoleColorHarmonyInstance = Harmony.CreateAndPatchAll(typeof(HarmonyManager.GetConsoleColorPatch), (string)null);
			HarmonyManager.GetConsoleColorPatch.consoleColor = color;
			logger.LogInfo(data);
			getConsoleColorHarmonyInstance.UnpatchSelf();
		}

		public static void LogMessageWithColor(this ManualLogSource logger, object data, ConsoleColor color)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Expected O, but got Unknown
			if (getConsoleColorHarmonyInstance == null)
			{
				getConsoleColorHarmonyInstance = new Harmony("GetConsoleColor");
			}
			getConsoleColorHarmonyInstance = Harmony.CreateAndPatchAll(typeof(HarmonyManager.GetConsoleColorPatch), (string)null);
			HarmonyManager.GetConsoleColorPatch.consoleColor = color;
			logger.LogMessage(data);
			getConsoleColorHarmonyInstance.UnpatchSelf();
		}

		public static void LogWarningWithColor(this ManualLogSource logger, object data, ConsoleColor color)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Expected O, but got Unknown
			if (getConsoleColorHarmonyInstance == null)
			{
				getConsoleColorHarmonyInstance = new Harmony("GetConsoleColor");
			}
			getConsoleColorHarmonyInstance = Harmony.CreateAndPatchAll(typeof(HarmonyManager.GetConsoleColorPatch), (string)null);
			HarmonyManager.GetConsoleColorPatch.consoleColor = color;
			logger.LogWarning(data);
			getConsoleColorHarmonyInstance.UnpatchSelf();
		}
	}
	public static class HarmonyManager
	{
		internal static class HarmonyInstances
		{
			public static Harmony Core;

			public static Harmony Transpilers;

			public static Harmony DebugPatches;

			public static Harmony Thunderstore;

			public static Harmony CustomSounds;

			public static Harmony ModHelpEntry;

			public static Harmony ModGameMode;

			public static Harmony CustomRoundTypes;

			public static Harmony ModPersistentData;
		}

		private static class Transpilers
		{
			private static GameModeMusicSpec current_working_music_spec;

			[HarmonyPatch(typeof(GunScript), "Update")]
			[HarmonyTranspiler]
			private static IEnumerable<CodeInstruction> GunScriptTranspiler(IEnumerable<CodeInstruction> instructions)
			{
				//IL_001c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0022: Expected O, but got Unknown
				//IL_0043: Unknown result type (might be due to invalid IL or missing references)
				//IL_0049: Expected O, but got Unknown
				//IL_0057: Unknown result type (might be due to invalid IL or missing references)
				//IL_005d: Expected O, but got Unknown
				//IL_006b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0071: Expected O, but got Unknown
				//IL_008a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0090: Expected O, but got Unknown
				//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
				//IL_00be: Expected O, but got Unknown
				return new SmartCodeMatcher(instructions).MatchForward(false, new CodeMatch((OpCode?)OpCodes.Ldarg_0, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Ldfld, (object)AccessTools.Field(typeof(GunScript), "gun_model"), (string)null), new CodeMatch((OpCode?)OpCodes.Ldc_I4_1, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Bne_Un, (object)null, (string)null)).Advance().InsertAndAdvance(new CodeInstruction(OpCodes.Ldarg_0, (object)null))
					.InsertAndAdvance(new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(ModGunScript), "UpdateModGun", (Type[])null, (Type[])null)))
					.InstructionEnumeration();
			}

			[HarmonyPatch(typeof(GunScript), "UpdateSlide")]
			[HarmonyTranspiler]
			private static IEnumerable<CodeInstruction> GunScriptSlideTranspiler(IEnumerable<CodeInstruction> instructions)
			{
				//IL_0031: Unknown result type (might be due to invalid IL or missing references)
				//IL_0037: Expected O, but got Unknown
				//IL_0081: Unknown result type (might be due to invalid IL or missing references)
				//IL_0087: Expected O, but got Unknown
				return new SmartCodeMatcher(instructions).MatchForward(false, new CodeMatch((OpCode?)OpCodes.Call, (object)AccessTools.Method(typeof(GunScript), "AccelFromChangeAndTime", (Type[])null, (Type[])null), (string)null)).SetOperandAndAdvance(AccessTools.Method(typeof(ModGunScript), "CalculateSlideAcceleration", (Type[])null, (Type[])null)).MatchForward(false, new CodeMatch((OpCode?)OpCodes.Call, (object)AccessTools.Method(typeof(GunScript), "AccelFromChangeAndTime", (Type[])null, (Type[])null), (string)null))
					.SetOperandAndAdvance(AccessTools.Method(typeof(ModGunScript), "CalculateSlideAccelerationTime", (Type[])null, (Type[])null))
					.RemoveInstructions(2)
					.InstructionEnumeration();
			}

			[HarmonyPatch(typeof(RuntimeTileLevelGenerator), "PopulateItems")]
			[HarmonyTranspiler]
			private static IEnumerable<CodeInstruction> PopulateItemsTranspiler(IEnumerable<CodeInstruction> instructions)
			{
				//IL_002f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0035: Expected O, but got Unknown
				//IL_0043: Unknown result type (might be due to invalid IL or missing references)
				//IL_0049: Expected O, but got Unknown
				//IL_0075: Unknown result type (might be due to invalid IL or missing references)
				//IL_007b: Expected O, but got Unknown
				return new SmartCodeMatcher(instructions).MatchForward(false, new CodeMatch((OpCode?)OpCodes.Ldfld, (object)AccessTools.Field(typeof(GunScript), "gun_type"), (string)null), new CodeMatch((OpCode?)OpCodes.Ldc_I4_1, (object)null, (string)null)).SetOperandAndAdvance(AccessTools.Field(typeof(GunScript), "magazine_root_types")).InsertAndAdvance(new CodeInstruction(OpCodes.Ldlen, (object)null))
					.SetOpcodeAndAdvance(OpCodes.Ldc_I4_0)
					.SetOpcodeAndAdvance(OpCodes.Bne_Un_S)
					.InstructionEnumeration();
			}

			[HarmonyPatch(typeof(LocalAimHandler), "HandleGunControls")]
			[HarmonyTranspiler]
			private static IEnumerable<CodeInstruction> LAHGunControlsTranspiler(IEnumerable<CodeInstruction> instructions)
			{
				//IL_001c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0022: Expected O, but got Unknown
				//IL_0043: Unknown result type (might be due to invalid IL or missing references)
				//IL_0049: Expected O, but got Unknown
				//IL_0057: Unknown result type (might be due to invalid IL or missing references)
				//IL_005d: Expected O, but got Unknown
				//IL_006b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0071: Expected O, but got Unknown
				//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ba: Expected O, but got Unknown
				//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d9: Expected O, but got Unknown
				return new SmartCodeMatcher(instructions).MatchForward(false, new CodeMatch((OpCode?)OpCodes.Ldarg_1, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Ldfld, (object)AccessTools.Field(typeof(GunScript), "gun_model"), (string)null), new CodeMatch((OpCode?)OpCodes.Ldc_I4_5, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Bne_Un, (object)null, (string)null)).Advance().SetOperandAndAdvance(AccessTools.Field(typeof(GunScript), "slide_lock_is_safety"))
					.SetOpcodeAndAdvance(OpCodes.Ldc_I4_1)
					.MatchForward(false, new CodeMatch((OpCode?)OpCodes.Leave, (object)null, (string)null))
					.Advance()
					.Insert(new CodeInstruction(OpCodes.Nop, (object)null))
					.InstructionEnumeration();
			}

			[HarmonyPatch(typeof(LocalAimHandler), "UpdateLooseBulletDisplay")]
			[HarmonyTranspiler]
			private static IEnumerable<CodeInstruction> LAHBulletDisplayTranspiler(IEnumerable<CodeInstruction> instructions)
			{
				//IL_001c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0022: Expected O, but got Unknown
				//IL_0045: Unknown result type (might be due to invalid IL or missing references)
				//IL_004b: Expected O, but got Unknown
				//IL_0059: Unknown result type (might be due to invalid IL or missing references)
				//IL_005f: Expected O, but got Unknown
				//IL_0092: Unknown result type (might be due to invalid IL or missing references)
				//IL_0098: Expected O, but got Unknown
				//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c1: Expected O, but got Unknown
				//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d5: Expected O, but got Unknown
				//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
				//IL_0101: Expected O, but got Unknown
				SmartCodeMatcher smartCodeMatcher = new SmartCodeMatcher(instructions).MatchForward(true, new CodeMatch((OpCode?)OpCodes.Ldnull, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Call, (object)AccessTools.Method(typeof(Object), "op_Equality", (Type[])null, (Type[])null), (string)null), new CodeMatch((OpCode?)OpCodes.Brtrue, (object)null, (string)null));
				if (smartCodeMatcher.IsValid)
				{
					CodeInstruction instruction = smartCodeMatcher.Instruction;
					smartCodeMatcher.Start().MatchForward(false, new CodeMatch((OpCode?)OpCodes.Ldarg_0, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Call, (object)AccessTools.Method(typeof(LocalAimHandler), "get_IsHoldingMagazine", (Type[])null, (Type[])null), (string)null), new CodeMatch((OpCode?)OpCodes.Brfalse, (object)null, (string)null)).InsertAndAdvance(new CodeInstruction(OpCodes.Ldsfld, (object)AccessTools.Field(typeof(Extensions), "lah_force_bullet_display")))
						.Insert(instruction);
				}
				return smartCodeMatcher.InstructionEnumeration();
			}

			[HarmonyPatch(typeof(LocalAimHandler), "HandleGunControls")]
			[HarmonyTranspiler]
			private static IEnumerable<CodeInstruction> LAHHandleGunControlsTranspiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
			{
				//IL_002f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0035: Expected O, but got Unknown
				//IL_004f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0055: Expected O, but got Unknown
				//IL_0063: Unknown result type (might be due to invalid IL or missing references)
				//IL_0069: Expected O, but got Unknown
				//IL_0077: Unknown result type (might be due to invalid IL or missing references)
				//IL_007d: Expected O, but got Unknown
				//IL_0096: Unknown result type (might be due to invalid IL or missing references)
				//IL_009c: Expected O, but got Unknown
				//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b3: Expected O, but got Unknown
				//IL_010a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0110: Expected O, but got Unknown
				//IL_012d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0133: Expected O, but got Unknown
				//IL_014a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0150: Expected O, but got Unknown
				//IL_0186: Unknown result type (might be due to invalid IL or missing references)
				//IL_018c: Expected O, but got Unknown
				//IL_019e: Unknown result type (might be due to invalid IL or missing references)
				//IL_01a4: Expected O, but got Unknown
				//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
				//IL_01c7: Expected O, but got Unknown
				//IL_01e2: Unknown result type (might be due to invalid IL or missing references)
				//IL_01e8: Expected O, but got Unknown
				//IL_01fa: Unknown result type (might be due to invalid IL or missing references)
				//IL_0200: Expected O, but got Unknown
				SmartCodeMatcher smartCodeMatcher = new SmartCodeMatcher(instructions, generator).MatchForward(true, new CodeMatch((OpCode?)OpCodes.Stfld, (object)AccessTools.Field(typeof(GunScript), "mag_seated_wrong"), (string)null)).MatchBack(true, new CodeMatch((OpCode?)OpCodes.Call, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Call, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Newobj, (object)null, (string)null)).Advance()
					.InsertAndAdvance(new CodeInstruction(OpCodes.Ldarg_1, (object)null), new CodeInstruction(OpCodes.Isinst, (object)typeof(ModGunScript)))
					.Insert(OpCodes.Call, (object)AccessTools.Method(typeof(Vector3), "op_Multiply", new Type[2]
					{
						typeof(Vector3),
						typeof(float)
					}, (Type[])null))
					.CreateBranch(OpCodes.Brfalse_S, (CodeInstruction[])(object)new CodeInstruction[2]
					{
						new CodeInstruction(OpCodes.Ldarg_1, (object)null),
						new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(ModGunScript), "GetMagSmackStrength", (Type[])null, (Type[])null))
					}, (CodeInstruction[])(object)new CodeInstruction[1]
					{
						new CodeInstruction(OpCodes.Ldc_R4, (object)1f)
					});
				LocalBuilder localBuilder = generator.DeclareLocal(typeof(Vector3));
				smartCodeMatcher.Advance().InsertAndAdvance(new CodeInstruction(OpCodes.Stloc, (object)localBuilder.LocalIndex), new CodeInstruction(OpCodes.Ldloca, (object)localBuilder.LocalIndex), new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(Time), "get_time", (Type[])null, (Type[])null)), new CodeInstruction(OpCodes.Stfld, (object)AccessTools.Field(typeof(Vector3), "z")), new CodeInstruction(OpCodes.Ldloc, (object)localBuilder.LocalIndex));
				return smartCodeMatcher.InstructionEnumeration();
			}

			[HarmonyPatch(typeof(LocalAimHandler), "Update")]
			[HarmonyTranspiler]
			private static IEnumerable<CodeInstruction> LAHUpdateXRayTranspiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
			{
				//IL_0002: Unknown result type (might be due to invalid IL or missing references)
				//IL_002f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0035: Expected O, but got Unknown
				//IL_0063: Unknown result type (might be due to invalid IL or missing references)
				//IL_0069: Expected O, but got Unknown
				//IL_0071: Unknown result type (might be due to invalid IL or missing references)
				//IL_0077: Expected O, but got Unknown
				return new CodeMatcher(instructions, (ILGenerator)null).MatchForward(true, (CodeMatch[])(object)new CodeMatch[1]
				{
					new CodeMatch((OpCode?)OpCodes.Ldfld, (object)AccessTools.Field(typeof(LocalAimHandler), "inspect_x_ray_timer"), (string)null)
				}).Advance(2).InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[2]
				{
					new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(Time), "get_timeScale", (Type[])null, (Type[])null)),
					new CodeInstruction(OpCodes.Div, (object)null)
				})
					.InstructionEnumeration();
			}

			[HarmonyPatch(typeof(MagazineScript), "UpdateRoundPositions")]
			[HarmonyTranspiler]
			private static IEnumerable<CodeInstruction> MagazineFollowerTranspiler(IEnumerable<CodeInstruction> instructions)
			{
				//IL_001c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0022: Expected O, but got Unknown
				//IL_0030: Unknown result type (might be due to invalid IL or missing references)
				//IL_0036: Expected O, but got Unknown
				//IL_0044: Unknown result type (might be due to invalid IL or missing references)
				//IL_004a: Expected O, but got Unknown
				//IL_006f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0075: Expected O, but got Unknown
				return new SmartCodeMatcher(instructions).MatchForward(true, new CodeMatch((OpCode?)OpCodes.Brfalse, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Ldc_R4, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Ldarg_0, (object)null, (string)null)).Advance(-1).RemoveInstruction()
					.MatchForward(false, new CodeMatch((OpCode?)OpCodes.Sub, (object)null, (string)null))
					.RemoveInstruction()
					.InstructionEnumeration();
			}

			[HarmonyPatch(typeof(MenuManagerScript), "Update")]
			[HarmonyTranspiler]
			private static IEnumerable<CodeInstruction> ModGameModeSupressMenu(IEnumerable<CodeInstruction> instructions)
			{
				//IL_001c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0022: Expected O, but got Unknown
				//IL_0045: Unknown result type (might be due to invalid IL or missing references)
				//IL_004b: Expected O, but got Unknown
				//IL_0069: Unknown result type (might be due to invalid IL or missing references)
				//IL_0073: Expected O, but got Unknown
				//IL_0092: Unknown result type (might be due to invalid IL or missing references)
				//IL_009c: Expected O, but got Unknown
				//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b6: Expected O, but got Unknown
				//IL_00be: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c4: Expected O, but got Unknown
				return new SmartCodeMatcher(instructions).MatchForward(false, new CodeMatch((OpCode?)OpCodes.Ldc_I4_0, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Call, (object)AccessTools.Method(typeof(Cursor), "set_visible", (Type[])null, (Type[])null), (string)null)).SetInstruction(new CodeInstruction(OpCodes.Ldsfld, (object)AccessTools.Field(typeof(ModGameModeManager), "DisplayGameModeMenu"))).Advance(2)
					.SetInstruction(new CodeInstruction(OpCodes.Ldsfld, (object)AccessTools.Field(typeof(ModGameModeManager), "DisplayGameModeMenu")))
					.Advance()
					.Insert(new CodeInstruction(OpCodes.Ldc_I4_0, (object)null), new CodeInstruction(OpCodes.Ceq, (object)null))
					.InstructionEnumeration();
			}

			[HarmonyPatch(typeof(MusicScript), "Update")]
			[HarmonyTranspiler]
			private static IEnumerable<CodeInstruction> ModGameModeMusic(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
			{
				//IL_001e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0024: Expected O, but got Unknown
				//IL_003b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0041: Expected O, but got Unknown
				//IL_0062: Unknown result type (might be due to invalid IL or missing references)
				//IL_0068: Expected O, but got Unknown
				//IL_00af: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b5: Expected O, but got Unknown
				//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c3: Expected O, but got Unknown
				//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
				//IL_00e6: Expected O, but got Unknown
				//IL_0100: Unknown result type (might be due to invalid IL or missing references)
				//IL_0106: Expected O, but got Unknown
				//IL_0121: Unknown result type (might be due to invalid IL or missing references)
				//IL_0127: Expected O, but got Unknown
				//IL_0144: Unknown result type (might be due to invalid IL or missing references)
				//IL_014a: Expected O, but got Unknown
				//IL_0165: Unknown result type (might be due to invalid IL or missing references)
				//IL_016b: Expected O, but got Unknown
				//IL_0179: Unknown result type (might be due to invalid IL or missing references)
				//IL_017f: Expected O, but got Unknown
				//IL_0190: Unknown result type (might be due to invalid IL or missing references)
				//IL_0196: Expected O, but got Unknown
				//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
				//IL_01b7: Expected O, but got Unknown
				//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
				//IL_01d9: Expected O, but got Unknown
				//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
				//IL_01eb: Expected O, but got Unknown
				//IL_0227: Unknown result type (might be due to invalid IL or missing references)
				//IL_022d: Expected O, but got Unknown
				//IL_024a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0250: Expected O, but got Unknown
				//IL_026b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0271: Expected O, but got Unknown
				//IL_0279: Unknown result type (might be due to invalid IL or missing references)
				//IL_027f: Expected O, but got Unknown
				//IL_029a: Unknown result type (might be due to invalid IL or missing references)
				//IL_02a0: Expected O, but got Unknown
				//IL_02bb: Unknown result type (might be due to invalid IL or missing references)
				//IL_02c1: Expected O, but got Unknown
				//IL_02dc: Unknown result type (might be due to invalid IL or missing references)
				//IL_02e2: Expected O, but got Unknown
				//IL_02ea: Unknown result type (might be due to invalid IL or missing references)
				//IL_02f0: Expected O, but got Unknown
				//IL_030c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0312: Expected O, but got Unknown
				//IL_032e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0334: Expected O, but got Unknown
				//IL_0350: Unknown result type (might be due to invalid IL or missing references)
				//IL_0356: Expected O, but got Unknown
				//IL_035f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0365: Expected O, but got Unknown
				//IL_0381: Unknown result type (might be due to invalid IL or missing references)
				//IL_0387: Expected O, but got Unknown
				//IL_03a3: Unknown result type (might be due to invalid IL or missing references)
				//IL_03a9: Expected O, but got Unknown
				//IL_03c5: Unknown result type (might be due to invalid IL or missing references)
				//IL_03cb: Expected O, but got Unknown
				//IL_03d4: Unknown result type (might be due to invalid IL or missing references)
				//IL_03da: Expected O, but got Unknown
				//IL_03f6: Unknown result type (might be due to invalid IL or missing references)
				//IL_03fc: Expected O, but got Unknown
				//IL_0418: Unknown result type (might be due to invalid IL or missing references)
				//IL_041e: Expected O, but got Unknown
				//IL_043a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0440: Expected O, but got Unknown
				//IL_0449: Unknown result type (might be due to invalid IL or missing references)
				//IL_044f: Expected O, but got Unknown
				//IL_0461: Unknown result type (might be due to invalid IL or missing references)
				//IL_0467: Expected O, but got Unknown
				//IL_0483: Unknown result type (might be due to invalid IL or missing references)
				//IL_0489: Expected O, but got Unknown
				SmartCodeMatcher smartCodeMatcher = new SmartCodeMatcher(instructions, generator);
				smartCodeMatcher.MatchForward(false, new CodeMatch((OpCode?)OpCodes.Ldarg_0, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Ldc_R4, (object)1f, (string)null), new CodeMatch((OpCode?)OpCodes.Stfld, (object)AccessTools.Field(typeof(MusicScript), "main_menu"), (string)null));
				smartCodeMatcher.Advance().RemoveInstructions(2).Advance(-1);
				smartCodeMatcher.SetAndAdvance(OpCodes.Ldloc_0, null).InsertAndAdvance(new CodeInstruction(OpCodes.Ldfld, (object)AccessTools.Field(typeof(ReceiverCoreScript), "game_mode")), new CodeInstruction(OpCodes.Ldnull, (object)null), new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(Object), "op_Inequality", (Type[])null, (Type[])null)));
				smartCodeMatcher.CreateBranch(OpCodes.Brfalse, (CodeInstruction[])(object)new CodeInstruction[4]
				{
					new CodeInstruction(OpCodes.Ldloc_0, (object)null),
					new CodeInstruction(OpCodes.Ldfld, (object)AccessTools.Field(typeof(ReceiverCoreScript), "game_mode")),
					new CodeInstruction(OpCodes.Callvirt, (object)AccessTools.Method(typeof(GameModeBase), "GetGameMode", (Type[])null, (Type[])null)),
					new CodeInstruction(OpCodes.Ldsfld, (object)AccessTools.Field(typeof(ModGameModeBase), "ModGameMode"))
				}, (CodeInstruction[])(object)new CodeInstruction[3]
				{
					new CodeInstruction(OpCodes.Ldarg_0, (object)null),
					new CodeInstruction(OpCodes.Ldc_R4, (object)1f),
					new CodeInstruction(OpCodes.Stfld, (object)AccessTools.Field(typeof(MusicScript), "main_menu"))
				});
				smartCodeMatcher.MatchBack(false, new CodeMatch((OpCode?)OpCodes.Brfalse, (object)null, (string)null));
				CodeInstruction val = new CodeInstruction(smartCodeMatcher.Instruction);
				val.opcode = OpCodes.Bne_Un;
				smartCodeMatcher.Advance(5);
				smartCodeMatcher.InsertAndAdvance(val, new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(ModGameModeManager), "get_CurrentGameMode", (Type[])null, (Type[])null)), new CodeInstruction(OpCodes.Callvirt, (object)AccessTools.Method(typeof(ModGameModeBase), "GetMusicParams", (Type[])null, (Type[])null)), new CodeInstruction(OpCodes.Stsfld, (object)AccessTools.Field(typeof(Transpilers), "current_working_music_spec")), new CodeInstruction(OpCodes.Ldarg_0, (object)null), new CodeInstruction(OpCodes.Ldsfld, (object)AccessTools.Field(typeof(Transpilers), "current_working_music_spec")), new CodeInstruction(OpCodes.Ldfld, (object)AccessTools.Field(typeof(GameModeMusicSpec), "target_global_gain")), new CodeInstruction(OpCodes.Stfld, (object)AccessTools.Field(typeof(MusicScript), "target_global_gain")), new CodeInstruction(OpCodes.Ldarg_0, (object)null), new CodeInstruction(OpCodes.Ldsfld, (object)AccessTools.Field(typeof(Transpilers), "current_working_music_spec")), new CodeInstruction(OpCodes.Ldfld, (object)AccessTools.Field(typeof(GameModeMusicSpec), "gain_recover_delay")), new CodeInstruction(OpCodes.Stfld, (object)AccessTools.Field(typeof(MusicScript), "gain_recover_delay")), new CodeInstruction(OpCodes.Ldarg_0, (object)null), new CodeInstruction(OpCodes.Ldsfld, (object)AccessTools.Field(typeof(Transpilers), "current_working_music_spec")), new CodeInstruction(OpCodes.Ldfld, (object)AccessTools.Field(typeof(GameModeMusicSpec), "danger")), new CodeInstruction(OpCodes.Stfld, (object)AccessTools.Field(typeof(MusicScript), "danger")), new CodeInstruction(OpCodes.Ldarg_0, (object)null), new CodeInstruction(OpCodes.Ldsfld, (object)AccessTools.Field(typeof(Transpilers), "current_working_music_spec")), new CodeInstruction(OpCodes.Ldfld, (object)AccessTools.Field(typeof(GameModeMusicSpec), "mystical")), new CodeInstruction(OpCodes.Stfld, (object)AccessTools.Field(typeof(MusicScript), "mystical")), new CodeInstruction(OpCodes.Ldarg_0, (object)null), new CodeInstruction(OpCodes.Ldc_R4, (object)0f), new CodeInstruction(OpCodes.Stfld, (object)AccessTools.Field(typeof(MusicScript), "main_menu")));
				return smartCodeMatcher.InstructionEnumeration();
			}

			[HarmonyPatch(typeof(ReceiverCoreScript), "LoadCheckpoint")]
			[HarmonyTranspiler]
			private static IEnumerable<CodeInstruction> ModGameModeLoad(IEnumerable<CodeInstruction> instructions)
			{
				//IL_001c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0022: Expected O, but got Unknown
				//IL_004a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0050: Expected O, but got Unknown
				return new SmartCodeMatcher(instructions).MatchForward(false, new CodeMatch((OpCode?)OpCodes.Stloc_3, (object)null, (string)null)).InsertAndAdvance(new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(ModGameModeManager), "ChooseGameModeFromJSON", (Type[])null, (Type[])null))).InstructionEnumeration();
			}

			[HarmonyPatch(typeof(ReceiverCoreScript), "TriggerCheckpoint")]
			[HarmonyTranspiler]
			private static IEnumerable<CodeInstruction> ModGameModeSave(IEnumerable<CodeInstruction> instructions)
			{
				//IL_0027: Unknown result type (might be due to invalid IL or missing references)
				//IL_002d: Expected O, but got Unknown
				//IL_003b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0041: Expected O, but got Unknown
				SmartCodeMatcher smartCodeMatcher = new SmartCodeMatcher(instructions);
				smartCodeMatcher.MatchForward(true, new CodeMatch((OpCode?)OpCodes.Constrained, (object)typeof(GameMode), (string)null), new CodeMatch((OpCode?)OpCodes.Callvirt, (object)null, (string)null));
				smartCodeMatcher.Advance();
				smartCodeMatcher.InsertAndAdvance(OpCodes.Pop);
				smartCodeMatcher.Insert(OpCodes.Call, (object)AccessTools.Method(typeof(ModGameModeManager), "GetGameModeName", (Type[])null, (Type[])null));
				return smartCodeMatcher.InstructionEnumeration();
			}

			[HarmonyPatch(/*Could not decode attribute arguments.*/)]
			[HarmonyTranspiler]
			private static IEnumerable<CodeInstruction> ImDoingBad(IEnumerable<CodeInstruction> instructions)
			{
				//IL_0025: Unknown result type (might be due to invalid IL or missing references)
				//IL_002b: Expected O, but got Unknown
				//IL_0060: Unknown result type (might be due to invalid IL or missing references)
				//IL_0066: Expected O, but got Unknown
				//IL_0092: Unknown result type (might be due to invalid IL or missing references)
				//IL_0098: Expected O, but got Unknown
				//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c1: Expected O, but got Unknown
				//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
				//IL_00fc: Expected O, but got Unknown
				//IL_0128: Unknown result type (might be due to invalid IL or missing references)
				//IL_012e: Expected O, but got Unknown
				return new SmartCodeMatcher(instructions).MatchForward(false, new CodeMatch((OpCode?)OpCodes.Ldc_I4, (object)437, (string)null), new CodeMatch((OpCode?)OpCodes.Call, (object)AccessTools.Method(typeof(Encoding), "GetEncoding", new Type[1] { typeof(int) }, (Type[])null), (string)null)).RemoveInstructions(2).Insert(new CodeInstruction(OpCodes.Call, (object)AccessTools.PropertyGetter(typeof(Encoding), "Default")))
					.MatchForward(false, new CodeMatch((OpCode?)OpCodes.Ldc_I4, (object)437, (string)null), new CodeMatch((OpCode?)OpCodes.Call, (object)AccessTools.Method(typeof(Encoding), "GetEncoding", new Type[1] { typeof(int) }, (Type[])null), (string)null))
					.RemoveInstructions(2)
					.Insert(new CodeInstruction(OpCodes.Call, (object)AccessTools.PropertyGetter(typeof(Encoding), "Default")))
					.InstructionEnumeration();
			}
		}

		private static class DebugTranspilers
		{
			[HarmonyPatch(typeof(MenuManagerScript), "UpdateDeveloperMenu")]
			[HarmonyTranspiler]
			private static IEnumerable<CodeInstruction> DevMenuTranspiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
			{
				//IL_0022: Unknown result type (might be due to invalid IL or missing references)
				//IL_0028: Expected O, but got Unknown
				//IL_004e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0054: Expected O, but got Unknown
				//IL_007a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0080: Expected O, but got Unknown
				//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
				//IL_00da: Expected O, but got Unknown
				//IL_0102: Unknown result type (might be due to invalid IL or missing references)
				//IL_0108: Expected O, but got Unknown
				//IL_011f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0125: Expected O, but got Unknown
				//IL_016c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0172: Expected O, but got Unknown
				//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
				//IL_01c1: Expected O, but got Unknown
				//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
				//IL_01ef: Expected O, but got Unknown
				//IL_0227: Unknown result type (might be due to invalid IL or missing references)
				//IL_022d: Expected O, but got Unknown
				//IL_0255: Unknown result type (might be due to invalid IL or missing references)
				//IL_025b: Expected O, but got Unknown
				SmartCodeMatcher smartCodeMatcher = new SmartCodeMatcher(instructions, generator);
				return smartCodeMatcher.MatchForward(false, new CodeMatch((OpCode?)OpCodes.Ldstr, (object)"Subtitles", (string)null)).SetAndAdvance(OpCodes.Ldstr, "Tapes Unlock Debug").InsertAndAdvance(new CodeInstruction(OpCodes.Ldstr, (object)""))
					.InsertAndAdvance(new CodeInstruction(OpCodes.Ldsfld, (object)AccessTools.Field(typeof(ModTapeManager), "tapes_debug_window_open")))
					.InsertAndAdvance(new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(ImGui), "MenuItem", new Type[3]
					{
						typeof(string),
						typeof(string),
						typeof(bool)
					}, (Type[])null)))
					.InsertAndAdvance(new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(ModTapeManager), "SwitchMenuVisible", (Type[])null, (Type[])null)))
					.Insert(new CodeInstruction(OpCodes.Ldstr, (object)"Subtitles"))
					.Advance(-1)
					.InsertBranch(OpCodes.Brfalse, smartCodeMatcher.Pos + 1)
					.MatchForward(false, new CodeMatch((OpCode?)OpCodes.Call, (object)AccessTools.Method(typeof(ImGui), "EndMainMenuBar", (Type[])null, (Type[])null), (string)null))
					.SetAndAdvance(OpCodes.Ldstr, "Modding")
					.InsertAndAdvance(new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(ImGui), "BeginMenu", new Type[1] { typeof(string) }, (Type[])null)))
					.Insert(new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(ImGui), "EndMainMenuBar", (Type[])null, (Type[])null)))
					.InsertBranchAndAdvance(OpCodes.Brfalse, smartCodeMatcher.Pos)
					.InsertAndAdvance(new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(ModInfoAsset), "DisplayImGuiControls", (Type[])null, (Type[])null)))
					.InsertAndAdvance(new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(ImGui), "EndMenu", (Type[])null, (Type[])null)))
					.InstructionEnumeration();
			}

			[HarmonyPatch(typeof(AudioManager), "Update")]
			[HarmonyTranspiler]
			private static IEnumerable<CodeInstruction> AudioDebugMenuTranspiler(IEnumerable<CodeInstruction> instructions)
			{
				//IL_0031: Unknown result type (might be due to invalid IL or missing references)
				//IL_0037: Expected O, but got Unknown
				//IL_005f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0065: Expected O, but got Unknown
				return new SmartCodeMatcher(instructions).MatchForward(false, new CodeMatch((OpCode?)OpCodes.Call, (object)AccessTools.Method(typeof(ImGui), "End", (Type[])null, (Type[])null), (string)null)).InsertAndAdvance(new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(ModAudioManager), "DrawImGUIDebug", (Type[])null, (Type[])null))).InstructionEnumeration();
			}
		}

		private static class R2ModManPatches
		{
			[HarmonyPatch(typeof(Locale), "GetTapeSubtitle", new Type[]
			{
				typeof(string),
				typeof(LocaleID)
			})]
			[HarmonyPostfix]
			public static void PatchLocaleSubtitles(string tape_id, LocaleID locale_id, ref TapeSubtitles __result)
			{
				ModTapeManager.TryReplaceSubtitles(tape_id, ref __result);
			}

			[HarmonyPatch(typeof(ReceiverCoreScript), "Awake")]
			[HarmonyTranspiler]
			private static IEnumerable<CodeInstruction> R2MMCoreTranspiler(IEnumerable<CodeInstruction> instructions)
			{
				//IL_001c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0022: Expected O, but got Unknown
				//IL_0045: Unknown result type (might be due to invalid IL or missing references)
				//IL_004b: Expected O, but got Unknown
				//IL_0073: Unknown result type (might be due to invalid IL or missing references)
				//IL_0079: Expected O, but got Unknown
				return new SmartCodeMatcher(instructions).MatchForward(false, new CodeMatch((OpCode?)OpCodes.Ldarg_0, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Call, (object)AccessTools.Method(typeof(ReceiverCoreScript), "LoadPersistentData", (Type[])null, (Type[])null), (string)null)).Insert(new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(Receiver2ModdingKit.Thunderstore.Thunderstore), "InstallGuns", (Type[])null, (Type[])null))).InstructionEnumeration();
			}

			[HarmonyPatch(typeof(ReceiverCoreScript), "Awake")]
			[HarmonyPostfix]
			private static void InstallGameModesSmile()
			{
				Receiver2ModdingKit.Thunderstore.Thunderstore.InstallGameModes();
			}

			[HarmonyPatch(typeof(TapeManager), "OnEnable")]
			[HarmonyTranspiler]
			private static IEnumerable<CodeInstruction> R2MMTapesTranspiler(IEnumerable<CodeInstruction> instructions)
			{
				//IL_001c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0022: Expected O, but got Unknown
				//IL_0043: Unknown result type (might be due to invalid IL or missing references)
				//IL_0049: Expected O, but got Unknown
				//IL_006c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0072: Expected O, but got Unknown
				//IL_0085: Unknown result type (might be due to invalid IL or missing references)
				//IL_008b: Expected O, but got Unknown
				//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b9: Expected O, but got Unknown
				return new SmartCodeMatcher(instructions).MatchForward(true, new CodeMatch((OpCode?)OpCodes.Ldarg_0, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Ldfld, (object)AccessTools.Field(typeof(TapeManager), "tape_prefabs_all"), (string)null), new CodeMatch((OpCode?)OpCodes.Callvirt, (object)AccessTools.Method(typeof(List<GameObject>), "get_Count", (Type[])null, (Type[])null), (string)null)).InsertAndAdvance(new CodeInstruction(OpCodes.Ldarg_0, (object)null)).Insert(new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(Receiver2ModdingKit.Thunderstore.Thunderstore), "InstallTapes", (Type[])null, (Type[])null)))
					.InstructionEnumeration();
			}

			[HarmonyPatch(typeof(ModulePrefabsList), "OnEnable")]
			[HarmonyTranspiler]
			private static IEnumerable<CodeInstruction> R2MMTilesTranspiler(IEnumerable<CodeInstruction> instructions)
			{
				//IL_001c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0022: Expected O, but got Unknown
				//IL_0030: Unknown result type (might be due to invalid IL or missing references)
				//IL_0036: Expected O, but got Unknown
				//IL_0044: Unknown result type (might be due to invalid IL or missing references)
				//IL_004a: Expected O, but got Unknown
				//IL_0058: Unknown result type (might be due to invalid IL or missing references)
				//IL_005e: Expected O, but got Unknown
				//IL_006c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0072: Expected O, but got Unknown
				//IL_008b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0091: Expected O, but got Unknown
				//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
				//IL_00bf: Expected O, but got Unknown
				return new SmartCodeMatcher(instructions).MatchForward(true, new CodeMatch((OpCode?)OpCodes.Ldloc_2, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Ldloc_1, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Ldlen, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Conv_I4, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Blt, (object)null, (string)null)).Advance(2).InsertAndAdvance(new CodeInstruction(OpCodes.Ldarg_0, (object)null))
					.Insert(new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(Receiver2ModdingKit.Thunderstore.Thunderstore), "InstallTiles", (Type[])null, (Type[])null)))
					.InstructionEnumeration();
			}
		}

		internal static class GetConsoleColorPatch
		{
			internal static ConsoleColor consoleColor;

			[HarmonyPatch(typeof(LogLevelExtensions), "GetConsoleColor")]
			[HarmonyPostfix]
			internal static void ChangeGetColorResult(ref ConsoleColor __result)
			{
				__result = consoleColor;
			}
		}

		internal static class LogEventArgsToStringPatch
		{
			internal static string levelName;

			[HarmonyPatch(typeof(LogEventArgs), "ToString")]
			[HarmonyPostfix]
			internal static void ChangeLogEventArgsLevel(LogEventArgs __instance, ref string __result)
			{
				__result = $"[{levelName,-7}:{__instance.Source.SourceName,10}] {__instance.Data}";
			}
		}

		private static void DisplayInstructions(CodeMatcher code_matcher, int breadth)
		{
			DisplayInstructions(code_matcher, breadth, (Action<string>)Debug.LogError);
		}

		private static void DisplayInstructions(CodeMatcher code_matcher, int breadth, Action<string> logger)
		{
			int num = Mathf.Max(code_matcher.Pos - breadth, 0);
			int num2 = Mathf.Min(code_matcher.Pos + breadth + 1, code_matcher.Length - 1);
			for (int i = num; i < code_matcher.Pos; i++)
			{
				logger(((object)code_matcher.InstructionAt(i - code_matcher.Pos)).ToString());
			}
			logger(string.Concat(code_matcher.Instruction, " <"));
			for (int j = code_matcher.Pos + 1; j < num2; j++)
			{
				logger(((object)code_matcher.InstructionAt(j - code_matcher.Pos)).ToString());
			}
		}

		[HarmonyPatch(typeof(TapesMenuScript), "Awake")]
		[HarmonyPrefix]
		private static void AddMissingTapeEntryCategory(Dictionary<TapeGroupID, MenuEntryCategories> ___menuCategoryMappings)
		{
			___menuCategoryMappings.Add((TapeGroupID)7, (MenuEntryCategories)60);
		}

		[HarmonyPatch(typeof(ReceiverCoreScript), "LoadModGun")]
		[HarmonyPrefix]
		private static void CheckFolderForSigmaBundles(string directoryName)
		{
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			string[] files = Directory.GetFiles(directoryName);
			foreach (string text in files)
			{
				if (!(Path.GetExtension(text) == ".sigma"))
				{
					continue;
				}
				IArchive val = ArchiveFactory.Open(text, (ReaderOptions)null);
				try
				{
					foreach (IArchiveEntry entry in val.Entries)
					{
						if (!Path.GetExtension(((IEntry)entry).Key).Contains(((object)SystemInfo.operatingSystemFamily/*cast due to .constrained prefix*/).ToString().ToLower()))
						{
							continue;
						}
						using Stream stream = entry.OpenEntryStream();
						byte[] array = new byte[((IEntry)entry).Size];
						stream.Read(array, 0, (int)((IEntry)entry).Size);
						using FileStream fileStream = File.Create(Path.Combine(directoryName, ((IEntry)entry).Key));
						fileStream.Write(array, 0, array.Length);
					}
				}
				finally
				{
					((IDisposable)val)?.Dispose();
				}
				File.Delete(text);
			}
		}

		[HarmonyPatch(typeof(GunScript), "CanHolster")]
		[HarmonyPrefix]
		private static bool PatchGunHolster(GunScript __instance, ref bool __result)
		{
			if (__instance is ModGunScript modGunScript)
			{
				__result = modGunScript.CanHolster();
				return false;
			}
			return true;
		}

		[HarmonyPatch(typeof(MenuManagerScript), "Update")]
		[HarmonyPostfix]
		private static void ForceCursorState()
		{
			if (Extensions.unlock_cursor)
			{
				Cursor.visible = true;
				Cursor.lockState = (CursorLockMode)(Extensions.confine_cursor ? 2 : 0);
			}
		}

		[HarmonyPatch(typeof(MagazineScript), "UpdateRoundPositions")]
		[HarmonyPostfix]
		private static void PatchMagazineRoundPositions(ref MagazineScript __instance)
		{
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
			if (__instance is DoubleStackMagazine)
			{
				for (int i = 0; i < __instance.NumRounds(); i++)
				{
					ShellCasingScript val = __instance.rounds[i];
					bool flag = i % 2 == 0 == (__instance.rounds.Count % 2 == 0) != __instance.round_position_params.mirror_double_stack;
					((Component)val).transform.localPosition = new Vector3((Vector3.right * ((Component)val).GetComponent<BoxCollider>().size.x * __instance.round_position_params.param_e * (float)((!flag) ? 1 : (-1))).x, ((Component)val).transform.localPosition.y, ((Component)val).transform.localPosition.z);
				}
				if (__instance.extracting)
				{
					ShellCasingScript val2 = __instance.rounds[0];
					float num = Mathf.InverseLerp(Vector3.Dot(((Component)((InventoryItem)__instance).slot).transform.Find("barrel/point_round_entering").position, ((Component)__instance).transform.forward), Vector3.Dot(__instance.round_top.position, ((Component)__instance).transform.forward), Vector3.Dot(((Component)((InventoryItem)__instance).slot).transform.Find("slide/point_chambered_round").position, ((Component)__instance).transform.forward));
					bool flag2 = __instance.rounds.Count % 2 == 0 != __instance.round_position_params.mirror_double_stack;
					((Component)val2).transform.localPosition = new Vector3((((Component)val2).transform.right * ((Component)val2).GetComponent<BoxCollider>().size.x * __instance.round_position_params.param_e * (float)((!flag2) ? 1 : (-1))).x * num, ((Component)val2).transform.localPosition.y, ((Component)val2).transform.localPosition.z);
				}
			}
		}

		[HarmonyPatch(typeof(MagazineScript), "Awake")]
		[HarmonyPostfix]
		private static void UpdateSpringOnAwake(MagazineScript __instance)
		{
			if (Object.op_Implicit((Object)(object)__instance.spring))
			{
				__instance.spring.UpdateScale();
			}
		}

		[HarmonyPatch(typeof(TapesMenuScript), "OnLoad")]
		[HarmonyPrefix]
		private static void PatchTapeMenuLoad()
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Invalid comparison between Unknown and I4
			if ((int)ReceiverCoreScript.Instance().game_mode.GetGameMode() == 3)
			{
				ModTapeManager.PrepareTapesForCompound();
			}
			else
			{
				ModTapeManager.PrepareTapesForGame();
			}
		}

		[HarmonyPatch(typeof(TapesMenuScript), "CreateMenuEntries")]
		[HarmonyPrefix]
		private static void PrePatchTapeCreateMenuEntries(ref TapesMenuScript __instance)
		{
			ModTapeManager.Init();
			GameObject ecsPrefab = Object.Instantiate<GameObject>(GameObject.Find("ReceiverCore/Menus/Overlay Menu Canvas/Aspect Ratio Fitter/New Pause Menu/Backdrop1/Sub-Menu Layout Group/New Tape Menu/Entries Layout/ScrollableContent Variant/Viewport/Content/Standard/Invalid"));
			__instance.ecsPrefab = ecsPrefab;
		}

		[HarmonyPatch(typeof(TapesMenuScript), "CreateMenuEntries")]
		[HarmonyPostfix]
		private static void PostPatchTapeCreateMenuEntries(TapesMenuScript __instance)
		{
			ModTapeManager.CreateModTapes(__instance);
		}

		[HarmonyPatch(typeof(CartridgeSpec), "SetFromPreset")]
		[HarmonyPrefix]
		private static bool PatchSetCartridge(Preset preset, ref CartridgeSpec __instance)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			if (ModShellCasingScript.mod_cartridges.ContainsKey(preset))
			{
				__instance = ModShellCasingScript.mod_cartridges[preset];
				return false;
			}
			return true;
		}

		public static void PrintMethodIL(Type type, string name, bool original = false)
		{
			PrintMethodIL(AccessTools.Method(type, name, (Type[])null, (Type[])null), original);
		}

		public static void PrintMethodIL(MethodInfo method, bool original = false)
		{
			List<CodeInstruction> list = (original ? PatchProcessor.GetOriginalInstructions((MethodBase)method, (ILGenerator)null) : PatchProcessor.GetCurrentInstructions((MethodBase)method, int.MaxValue, (ILGenerator)null));
			int count = list.Count;
			for (int i = 0; i < count; i++)
			{
				Debug.Log((object)list[i]);
			}
		}

		[HarmonyPatch(typeof(ReceiverCoreScript), "Awake")]
		[HarmonyPostfix]
		private static void PatchCoreAwake(List<GameObject> ___gun_prefabs_all)
		{
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Expected O, but got Unknown
			foreach (GameObject item in ___gun_prefabs_all)
			{
				ModGunScript component = item.GetComponent<ModGunScript>();
				if ((Object)(object)component != (Object)null)
				{
					try
					{
						ModLoader.LoadGun(component);
					}
					catch (Exception ex)
					{
						Debug.LogError((object)("Error happened when loading gun " + ((InventoryItem)component).InternalName));
						Debug.LogError((object)ex);
					}
				}
			}
			ModLoader.Finish();
			ReceiverCoreScript.Instance().player_prefab.GetComponent<PlayerScript>().main_camera_prefab.GetComponent<Camera>().nearClipPlane = 0.02f;
			string[] files = Directory.GetFiles(Path.Combine(Application.persistentDataPath, "Tapes"), "*.srt", SearchOption.AllDirectories);
			for (int i = 0; i < files.Length; i++)
			{
				FileInfo fileInfo = new FileInfo(files[i]);
				ModTapeManager.RegisterSubtitles(fileInfo.Name.Replace(".srt", ""), fileInfo);
			}
			try
			{
				ModdingKitConfig.Initialize();
			}
			catch
			{
				Debug.LogError((object)"An error accured when trying to create settings for the Modding Kit");
			}
			foreach (AssetBundle allLoadedAssetBundle in AssetBundle.GetAllLoadedAssetBundles())
			{
				BankList[] array = allLoadedAssetBundle.LoadAllAssets<BankList>();
				if (array != null)
				{
					ModAudioManager.LoadBanksFromLists(array);
				}
			}
			foreach (TapeContent modTape in ReceiverCoreScript.Instance().tape_loadout_asset.GetModTapes())
			{
				LocaleTapeMenuEntry val = new LocaleTapeMenuEntry();
				val.name = "Invalid";
				val.id_string = modTape.tape_id_string;
				val.title = modTape.title;
				val.description = modTape.text;
				Locale.active_locale_tape_menu_entries_string.Add(modTape.tape_id_string, val);
			}
			Delegate[] invocationList = ModdingKitEvents.ExecuteOnStartup.GetInvocationList();
			foreach (Delegate obj2 in invocationList)
			{
				try
				{
					obj2.DynamicInvoke();
				}
				catch (Exception ex2)
				{
					Debug.LogError((object)("Failed invoking startup event for method " + obj2.Method.Name + ";\nDumping stack trace:"));
					Debug.LogError((object)ex2);
				}
			}
		}

		[HarmonyPatch(typeof(ShellCasingScript), "CollisionSound")]
		[HarmonyPrefix]
		private static bool PatchCollisionSound(BallisticMaterial material, ref ShellCasingScript __instance)
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Expected I4, but got Unknown
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			if (((InventoryItem)__instance).physics_collided || !(__instance is ModShellCasingScript))
			{
				return true;
			}
			ModShellCasingScript modShellCasingScript = (ModShellCasingScript)(object)__instance;
			((InventoryItem)modShellCasingScript).physics_collided = true;
			if (!((ShellCasingScript)modShellCasingScript).IsSpent())
			{
				AudioManager.PlayOneShot3D(modShellCasingScript.sound_bullet_fall_hard, ((Component)modShellCasingScript).transform.position, 1f, 1f);
				return false;
			}
			MaterialLabel material_label = material.material_label;
			switch (material_label - 1)
			{
			case 0:
			case 1:
			case 2:
			case 4:
			case 5:
			case 7:
			case 13:
			case 14:
			case 18:
				AudioManager.PlayOneShot3D(modShellCasingScript.sound_shell_casing_impact_hard, ((Component)modShellCasingScript).transform.position, 1f, 1f);
				break;
			case 3:
			case 6:
			case 8:
			case 9:
			case 10:
			case 11:
			case 12:
				AudioManager.PlayOneShot3D(modShellCasingScript.sound_shell_casing_impact_soft, ((Component)modShellCasingScript).transform.position, 1f, 1f);
				break;
			}
			return false;
		}

		[HarmonyPatch(typeof(MagazineScript), "Awake")]
		[HarmonyPrefix]
		private static void PatchMagazineAwake(MagazineScript __instance)
		{
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			SpringCompressInstance[] componentsInChildren = ((Component)__instance).GetComponentsInChildren<SpringCompressInstance>();
			foreach (SpringCompressInstance val in componentsInChildren)
			{
				if ((Object)(object)val == (Object)null)
				{
					Debug.LogError((object)("Null spring in magazine \"" + ((InventoryItem)__instance).InternalName + "\""));
				}
				else if (!(((Vector3)(ref val.orig_center)).magnitude > 0f))
				{
					val.orig_center = (((Component)val).transform.InverseTransformPoint(val.new_top.position) + ((Component)val).transform.InverseTransformPoint(val.new_bottom.position)) / 2f;
					val.orig_dist = Vector3.Distance(val.new_top.position, val.new_bottom.position);
				}
			}
		}

		[HarmonyPatch(typeof(RuntimeTileLevelGenerator), "SpawnMagazine")]
		[HarmonyPostfix]
		private static void PatchSpawnMagazine(ref ActiveItem __result)
		{
			if (!ModdingKitEvents.ItemSpawnHandlers.ContainsKey(ReceiverCoreScript.Instance().CurrentLoadout.gun_internal_name))
			{
				return;
			}
			foreach (ModdingKitEvents.OnItemSpawn item in ModdingKitEvents.ItemSpawnHandlers[ReceiverCoreScript.Instance().CurrentLoadout.gun_internal_name])
			{
				try
				{
					if (item(ref __result))
					{
						break;
					}
				}
				catch (Exception ex)
				{
					Debug.LogError((object)("Failed invoking item spawn event method " + item.Method.Name + " for gun " + ReceiverCoreScript.Instance().CurrentLoadout.gun_internal_name + ";\nDumping stack trace:"));
					Debug.LogError((object)ex);
				}
			}
		}

		[HarmonyPatch(typeof(PlayerLoadout), "Deserialize")]
		[HarmonyPrefix]
		private static void PatchDeserializeLoadout(JSONNode jn_root)
		{
			if (jn_root.HasKey("gun_persistent_data"))
			{
				Extensions.current_gun_data = jn_root["gun_persistent_data"].AsObject;
			}
		}

		[HarmonyPatch(typeof(PlayerLoadout), "Serialize")]
		[HarmonyPostfix]
		private static void PatchSerializeLoadout(ref JSONObject __result)
		{
			GunScript val = default(GunScript);
			if ((Object)(object)LocalAimHandler.player_instance != (Object)null && LocalAimHandler.player_instance.TryGetGun(ref val) && val is ModGunScript)
			{
				((JSONNode)__result)["gun_persistent_data"] = (JSONNode)(object)(val as ModGunScript).EncodeJSON((JSONNode)(object)((StorableMonoBehaviour)val).GetPersistentData());
			}
		}

		[HarmonyPatch(typeof(PlayerLoadout), "Reserialize")]
		[HarmonyPostfix]
		private static void PatchReserializeLoadout()
		{
			Extensions.current_gun_data = null;
		}

		[HarmonyPatch(typeof(ReceiverCoreScript), "SpawnGun")]
		[HarmonyPostfix]
		private static void PatchSpawnGun(ref GunScript __result)
		{
			if (!((Object)(object)__result == (Object)null) && __result is ModGunScript && (__result as ModGunScript).OwnData((JSONNode)(object)Extensions.current_gun_data))
			{
				((StorableMonoBehaviour)__result).SetPersistentData((__result as ModGunScript).DecodeJSON((JSONNode)(object)Extensions.current_gun_data));
			}
		}

		[HarmonyPatch(typeof(SettingsMenuScript), "OnKeybindsClick")]
		[HarmonyPostfix]
		private static void PatchOpenKeybinds()
		{
			GunScript val = default(GunScript);
			if (!((Object)(object)LocalAimHandler.player_instance == (Object)null) && LocalAimHandler.player_instance.TryGetGun(ref val))
			{
				KeybindsManager.SetKeybindsActive(val.weapon_group_name);
			}
		}

		[HarmonyPatch(typeof(RankingProgressionGameMode), "EvaluateNextLoadout")]
		[HarmonyPrefix]
		private static void PatchEvaluateLoadout(ref HashSet<string> ___campaign_loadouts)
		{
			string[] loadout_names = ReceiverCoreScript.Instance().weapon_loadout_asset.GetAllLoadoutNames();
			___campaign_loadouts.RemoveWhere((string loadout_name) => !loadout_names.Contains(loadout_name));
		}

		[HarmonyPatch(typeof(ReceiverCoreScript), "GetWorldGenerationConfigurationFromName")]
		[HarmonyPostfix]
		private static void PatchGetWCG(ref WorldGenerationConfiguration __result)
		{
			if (__result != null)
			{
				string[] loadout_names = ReceiverCoreScript.Instance().weapon_loadout_asset.GetAllLoadoutNames();
				__result.loadouts.RemoveAll(delegate(LoadoutValue loadout)
				{
					string name = loadout.name;
					return !loadout_names.Contains(name);
				});
			}
		}

		[HarmonyPatch(typeof(RankingProgressionCampaign), "LoadFile")]
		[HarmonyPostfix]
		private static void PatchLoadCampaign(string filename)
		{
			JSONNode val = ReceiverCoreScript.LoadJSONFile(filename);
			if (val.HasKey("use_modded_guns") && val["use_modded_guns"].AsBool && !ModdedGunsCampaignManager.modded_guns_campaigns.Contains(filename))
			{
				ModdedGunsCampaignManager.modded_guns_campaigns.Add(filename);
			}
		}

		[HarmonyPatch(typeof(WorldGenerationConfiguration), "Deserialize")]
		[HarmonyPostfix]
		private static void PatchLoadWCG(ref WorldGenerationConfiguration __result)
		{
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Expected O, but got Unknown
			GameModeBase game_mode = ReceiverCoreScript.Instance().game_mode;
			if (!((Object)(object)game_mode != (Object)null) || !(game_mode is RankingProgressionGameMode))
			{
				return;
			}
			string item = AccessTools.Field(typeof(RankingProgressionGameMode), "campaign_path").GetValue(game_mode) as string;
			if (!ModdedGunsCampaignManager.modded_guns_campaigns.Contains(item))
			{
				return;
			}
			string[] loadout_names = ReceiverCoreScript.Instance().weapon_loadout_asset.GetAllLoadoutNames();
			__result.loadouts.RemoveAll((LoadoutValue loadout) => !loadout_names.Contains(loadout.name));
			string[] array = loadout_names;
			foreach (string loadout_name in array)
			{
				if (!ReceiverCoreScript.Instance().weapon_loadout_asset.GetLoadoutPrefab(loadout_name).gun_internal_name.StartsWith("wolfire") && !__result.loadouts.Any((LoadoutValue loadout_value) => loadout_value.name == loadout_name))
				{
					__result.loadouts.Add(new LoadoutValue
					{
						name = loadout_name
					});
				}
			}
		}

		[HarmonyPatch(typeof(LocalAimHandler), "StepRecoil")]
		[HarmonyPostfix]
		private static void PatchStepRecoil()
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Invalid comparison between Unknown and I4
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			Hand[] hands = LocalAimHandler.player_instance.hands;
			foreach (Hand val in hands)
			{
				if ((int)val.state == 1)
				{
					ModGunScript modGunScript = val.slot.contents[0] as ModGunScript;
					if ((Object)(object)modGunScript != (Object)null)
					{
						Vector3 value = val.recoil_events.Last();
						Vector2 stepRecoilMultiplier = modGunScript.GetStepRecoilMultiplier();
						value.x *= stepRecoilMultiplier.x;
						value.y *= stepRecoilMultiplier.y;
						val.recoil_events[val.recoil_events.Count - 1] = value;
					}
				}
			}
		}

		[HarmonyPatch(typeof(LocalAimHandler), "UpdateLooseBulletDisplay")]
		[HarmonyPrefix]
		private static void ShowBulletInventoryIfCanInsertRoundInChamber(LocalAimHandler __instance)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Expected O, but got Unknown
			int handWithState = __instance.GetHandWithState((State)1);
			if (handWithState != -1)
			{
				GunScript val = (GunScript)__instance.hands[handWithState].slot.contents[0];
				if (__instance.GetHandWithState((State)2) == -1 && (val.IsSlideLockedOpen() || (val.SlideLockIsSafety() && val.IsSafetyOn() && !val.IsThereAChamberedRound() && !val.IsThereAMagInGun() && ((SimpleMover)val.slide).amount > 0.2f)))
				{
					Extensions.lah_force_bullet_display = true;
					return;
				}
			}
			Extensions.lah_force_bullet_display = false;
		}

		[HarmonyPatch(typeof(LocalAimHandler), "HandleGunControls")]
		[HarmonyPostfix]
		private static void PatchHandleSprings()
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			LocalAimHandler obj = default(LocalAimHandler);
			if (LocalAimHandler.TryGetInstance(ref obj))
			{
				while (Extensions.pose_spring_overrides.Count > 0)
				{
					Tuple<PoseSpring, float> tuple = Extensions.pose_spring_overrides.Dequeue();
					((Spring)ReflectionManager.LAH_pose_springs[tuple.Item1].GetValue(obj)).target_state = tuple.Item2;
				}
			}
		}

		[HarmonyPatch(typeof(GunScript), "FireBullet")]
		[HarmonyPrefix]
		private static bool PatchFireEmptyShell(ShellCasingScript round)
		{
			if ((Object)(object)round == (Object)null || round.IsSpent())
			{
				return false;
			}
			return true;
		}

		internal static void UnpatchAll()
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Expected O, but got Unknown
			FieldInfo[] fields = typeof(HarmonyInstances).GetFields();
			for (int i = 0; i < fields.Length; i++)
			{
				Harmony val = (Harmony)fields[i].GetValue(null);
				if (val != null)
				{
					val.UnpatchSelf();
				}
			}
		}

		private static IEnumerator FixLegacySounds()
		{
			yield return null;
			foreach (MethodBase patchedMethod in HarmonyInstances.CustomSounds.GetPatchedMethods())
			{
				Patches patchInfo = Harmony.GetPatchInfo(patchedMethod);
				if (patchInfo.Owners.Count != 1)
				{
					HarmonyInstances.CustomSounds.Unpatch(patchedMethod, (HarmonyPatchType)1, patchInfo.Owners.First((string ownerID) => ownerID != HarmonyInstances.CustomSounds.Id));
					continue;
				}
				break;
			}
		}

		private static IEnumerator WaitForModel10ToSpawn()
		{
			GunScript[] array = Object.FindObjectsOfType<GunScript>();
			for (int i = 0; i < array.Length; i++)
			{
				if ((int)array[i].gun_model == 2)
				{
					Object.Instantiate<GunScript>(ReceiverCoreScript.Instance().GetGunPrefab(ReceiverCoreScript.Instance().CurrentLoadout.gun_internal_name), ((Component)array[i]).transform.position, ((Component)array[i]).transform.rotation);
					((Component)array[i]).gameObject.SetActive(false);
					break;
				}
			}
			yield break;
		}

		internal static void Initialize()
		{
			HarmonyInstances.Core = Harmony.CreateAndPatchAll(typeof(HarmonyManager), (string)null);
			HarmonyInstances.Transpilers = Harmony.CreateAndPatchAll(typeof(Transpilers), (string)null);
			HarmonyInstances.ModHelpEntry = Harmony.CreateAndPatchAll(typeof(ModHelpEntryManager), (string)null);
			HarmonyInstances.CustomSounds = Harmony.CreateAndPatchAll(typeof(ModAudioPatches), (string)null);
			HarmonyInstances.ModGameMode = Harmony.CreateAndPatchAll(typeof(ModGameModeManager), (string)null);
			HarmonyInstances.CustomRoundTypes = Harmony.CreateAndPatchAll(typeof(CustomRoundTypes.Patches), (string)null);
			HarmonyInstances.ModPersistentData = Harmony.CreateAndPatchAll(typeof(ModPersistentData), (string)null);
			Harmony.CreateAndPatchAll(typeof(FMODLookForTapeFilterBytes), (string)null);
			if (Receiver2ModdingKit.Thunderstore.Thunderstore.LaunchedWithR2ModMan)
			{
				HarmonyInstances.Thunderstore = Harmony.CreateAndPatchAll(typeof(R2ModManPatches), (string)null);
			}
			((MonoBehaviour)ModdingKitCorePlugin.instance).StartCoroutine(FixLegacySounds());
		}
	}
	public class Keybind
	{
		public interface KeyMapping
		{
			int GetKey();

			bool IsRedirect();
		}

		public class KeyboardKey : KeyMapping
		{
			private KeyCode key;

			public KeyboardKey(KeyCode key)
			{
				//IL_0007: Unknown result type (might be due to invalid IL or missing references)
				//IL_0008: Unknown result type (might be due to invalid IL or missing references)
				this.key = key;
			}

			public int GetKey()
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0007: Expected I4, but got Unknown
				return (int)key;
			}

			public bool IsRedirect()
			{
				return false;
			}
		}

		public class KeyRedirect : KeyMapping
		{
			private int action_id;

			public KeyRedirect(int action_id)
			{
				this.action_id = action_id;
			}

			public int GetKey()
			{
				return action_id;
			}

			public bool IsRedirect()
			{
				return true;
			}
		}

		public string name;

		public string gun_name = "";

		public KeyMapping key;

		public int fallback_action_id;

		public Keybind(string keybind_menu_name, int fallback_action_id, KeyMapping default_value = null)
		{
			name = keybind_menu_name;
			this.fallback_action_id = fallback_action_id;
			key = default_value;
		}

		public string GetLongName()
		{
			return gun_name + "::" + name;
		}
	}
	public class KeybindContainer
	{
		public string gun_name;

		public GameObject category_object;

		public ModKeybindComponent[] keybind_components;

		public bool active { get; private set; }

		public void SetActive(bool active)
		{
			this.active = active;
			category_object.SetActive(active);
			ModKeybindComponent[] array = keybind_components;
			for (int i = 0; i < array.Length; i++)
			{
				((Component)array[i]).gameObject.SetActive(active);
			}
		}
	}
	internal static class KeybindsManager
	{
		internal static GameObject keybinds_menu_banner = null;

		internal static GameObject keybinds_menu_space = null;

		internal static List<KeybindContainer> custom_keybinds = new List<KeybindContainer>();

		private static Dictionary<string, int> m_rewired_actions = null;

		internal static Dictionary<string, int> rewired_actions
		{
			get
			{
				//IL_0044: Unknown result type (might be due to invalid IL or missing references)
				//IL_0049: Unknown result type (might be due to invalid IL or missing references)
				//IL_004a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0050: Invalid comparison between Unknown and I4
				//IL_0057: Unknown result type (might be due to invalid IL or missing references)
				if (m_rewired_actions == null)
				{
					m_rewired_actions = new Dictionary<string, int> { { "None", -1 } };
					FieldInfo[] fields = typeof(Action).GetFields(BindingFlags.Static | BindingFlags.Public);
					for (int i = 0; i < fields.Length; i++)
					{
						int num = (int)fields[i].GetValue(null);
						LocaleUIString val = ControllerBindingScript.RewiredActionToButtonLabel(num, (Pole)0);
						if ((int)val != 151)
						{
							m_rewired_actions.Add(Locale.GetUIString(val), num);
						}
					}
				}
				return m_rewired_actions;
			}
		}

		public static bool IsKeybindRegistered(string weapon_group_name)
		{
			return custom_keybinds.Any((KeybindContainer keybind) => keybind.gun_name == weapon_group_name);
		}

		public static KeybindContainer GetKeybinds(string weapon_group_name)
		{
			return custom_keybinds.First((KeybindContainer keybind) => keybind.gun_name == weapon_group_name);
		}

		public static bool TryGetKeybinds(string weapon_group_name, out KeybindContainer keybind_container)
		{
			foreach (KeybindContainer custom_keybind in custom_keybinds)
			{
				if (custom_keybind.gun_name == weapon_group_name)
				{
					keybind_container = custom_keybind;
					return true;
				}
			}
			keybind_container = null;
			return false;
		}

		public static void DeactivateAllKeybinds()
		{
			if ((Object)(object)keybinds_menu_banner != (Object)null)
			{
				keybinds_menu_banner.SetActive(false);
			}
			if ((Object)(object)keybinds_menu_space != (Object)null)
			{
				keybinds_menu_space.SetActive(false);
			}
			foreach (KeybindContainer custom_keybind in custom_keybinds)
			{
				custom_keybind.SetActive(active: false);
			}
		}

		public static void SetKeybindsActive(string weapon_group_name)
		{
			bool active = false;
			foreach (KeybindContainer custom_keybind in custom_keybinds)
			{
				if (custom_keybind.gun_name == weapon_group_name)
				{
					custom_keybind.SetActive(active: true);
					active = true;
				}
				else
				{
					custom_keybind.SetActive(active: false);
				}
			}
			if ((Object)(object)keybinds_menu_banner != (Object)null)
			{
				keybinds_menu_banner.SetActive(active);
			}
			if ((Object)(object)keybinds_menu_space != (Object)null)
			{
				keybinds_menu_space.SetActive(active);
			}
		}
	}
	public class ModKeybindComponent : MonoBehaviour
	{
		public Keybind keybind;

		public Button keyboard_binding;

		public TextMeshProUGUI keyboard_binding_text;

		public DropdownComponent redirect_binding;

		public Button clear_button;

		private IEnumerator PickKeyCoroutine()
		{
			SettingsMenuManager.ShowKeyBindDialog(((Object)this).name);
			while (!Input.GetKeyDown((KeyCode)27))
			{
				foreach (KeyCode value in Enum.GetValues(typeof(KeyCode)))
				{
					if (Input.GetKeyDown(value))
					{
						redirect_binding.Select(0);
						keybind.key = new Keybind.KeyboardKey(value);
						((TMP_Text)keyboard_binding_text).text = ((object)value/*cast due to .constrained prefix*/).ToString();
						SettingsMenuManager.HideKeyBindDialog();
						ModdingKitConfig.UpdateKeybindValue(keybind);
						yield break;
					}
				}
				yield return null;
			}
			SettingsMenuManager.HideKeyBindDialog();
		}

		public void Awake()
		{
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Expected O, but got Unknown
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Expected O, but got Unknown
			if (keybind.key.IsRedirect())
			{
				for (int i = 0; i < redirect_binding.dropdown.options.Count; i++)
				{
					string text = redirect_binding.dropdown.options[i].text;
					if (KeybindsManager.rewired_actions[text] == keybind.key.GetKey())
					{
						string key = KeybindsManager.rewired_actions.Keys.ElementAt(i);
						keybind.key = new Keybind.KeyRedirect(KeybindsManager.rewired_actions[key]);
						((TMP_Text)keyboard_binding_text).text = "";
						break;
					}
				}
			}
			else
			{
				((TMP_Text)keyboard_binding_text).text = ((object)(KeyCode)keybind.key.GetKey()/*cast due to .constrained prefix*/).ToString();
			}
			((UnityEvent)keyboard_binding.onClick).AddListener((UnityAction)delegate
			{
				((MonoBehaviour)ModdingKitCorePlugin.instance).StartCoroutine(PickKeyCoroutine());
			});
			((UnityEvent<int>)(object)redirect_binding.OnChange).AddListener((UnityAction<int>)delegate(int index)
			{
				string key2 = KeybindsManager.rewired_actions.Keys.ElementAt(index);
				keybind.key = new Keybind.KeyRedirect(KeybindsManager.rewired_actions[key2]);
				((TMP_Text)keyboard_binding_text).text = "";
				ModdingKitConfig.UpdateKeybindValue(keybind);
			});
			((UnityEvent)clear_button.onClick).AddListener((UnityAction)delegate
			{
				((TMP_Text)keyboard_binding_text).text = "";
				redirect_binding.Select(0);
				keybind.key = new Keybind.KeyRedirect(-1);
				ModdingKitConfig.UpdateKeybindValue(keybind);
			});
		}
	}
	public class Metadata<T> : Component
	{
		public string Name { get; private set; }

		public T Value { get; private set; }

		public void Set(T value)
		{
			Set(Name, value);
		}

		public void Set(string name, T value)
		{
			Name = name;
			Value = value;
		}
	}
	public static class MetadataExtensions
	{
		public static Metadata<T> AddMeta<T>(this GameObject gobj, string name, T value)
		{
			Metadata<T>[] components = gobj.GetComponents<Metadata<T>>();
			foreach (Metadata<T> metadata in components)
			{
				if (metadata.Name == name)
				{
					metadata.Set(value);
					return metadata;
				}
			}
			Metadata<T> metadata2 = gobj.AddComponent<Metadata<T>>();
			metadata2.Set(name, value);
			return metadata2;
		}

		public static Metadata<T> SetMeta<T>(this GameObject gobj, string name, T value)
		{
			Metadata<T>[] components = gobj.GetComponents<Metadata<T>>();
			foreach (Metadata<T> metadata in components)
			{
				if (metadata.Name == name)
				{
					metadata.Set(value);
					return metadata;
				}
			}
			return gobj.AddMeta(name, value);
		}

		public static Metadata<T> SetMeta<T>(this Component comp, string name, T value)
		{
			Metadata<T>[] components = comp.GetComponents<Metadata<T>>();
			foreach (Metadata<T> metadata in components)
			{
				if (metadata.Name == name)
				{
					metadata.Set(value);
					return metadata;
				}
			}
			return comp.gameObject.AddMeta(name, value);
		}

		public static T GetMeta<T>(this GameObject gobj, string name)
		{
			Metadata<T>[] components = gobj.GetComponents<Metadata<T>>();
			foreach (Metadata<T> metadata in components)
			{
				if (metadata.Name == name)
				{
					return metadata.Value;
				}
			}
			return default(T);
		}

		public static T GetMeta<T>(this Component comp, string name)
		{
			Metadata<T>[] components = comp.GetComponents<Metadata<T>>();
			foreach (Metadata<T> metadata in components)
			{
				if (metadata.Name == name)
				{
					return metadata.Value;
				}
			}
			return default(T);
		}
	}
	[RequireComponent(typeof(InventorySlot), typeof(LevelItem))]
	public abstract class ModGunScript : GunScript, ISerializationCallbackReceiver
	{
		[Serializable]
		public class ModLocaleTactics
		{
			public string title;

			[TextArea]
			public string description;

			public LocaleTactics GetLocaleTactics(GunScript gun)
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				//IL_0005: Unknown result type (might be due to invalid IL or missing references)
				//IL_0011: Unknown result type (might be due to invalid IL or missing references)
				//IL_0032: Unknown result type (might be due to invalid IL or missing references)
				//IL_003f: Expected O, but got Unknown
				return new LocaleTactics
				{
					gun_internal_name = gun.weapon_group_name,
					title = (Utility.IsNullOrWhiteSpace(title) ? ((InventoryItem)gun).InternalName : title),
					text = description
				};
			}
		}

		[Tooltip("All objects in the prefab should have the same activation status, most desirably they should be deactivated")]
		public GameObject muzzle_flash_prefab;

		public bool visible_in_spawnmenu = true;

		public bool spawns_in_dreaming = true;

		public float magazine_shake_strength_multiplier = 1f;

		public float slide_return_time = 0.04f;

		public ModHelpEntry help_entry;

		public ModLocaleTactics locale_tactics;

		[SerializeField]
		[HideInInspector]
		private bool help_entry_generate;

		[SerializeField]
		[HideInInspector]
		private string help_entry_name;

		[SerializeField]
		[HideInInspector]
		private Sprite help_entry_info_sprite;

		[SerializeField]
		[HideInInspector]
		private string help_entry_title;

		[SerializeField]
		[HideInInspector]
		private string help_entry_description;

		[SerializeField]
		[HideInInspector]
		private string locale_tactics_title;

		[SerializeField]
		[HideInInspector]
		private string locale_tactics_description;

		[Tooltip("List of custom audio events used by the gun, created via RMB -> Create -> Receiver 2 Modding -> Custom Sounds List")]
		public CustomSoundsList audio;

		protected bool _disconnector_needs_reset
		{
			get
			{
				return ReflectionManager.GS_disconnector_needs_reset.Invoke((GunScript)(object)this);
			}
			set
			{
				ReflectionManager.GS_disconnector_needs_reset.Invoke((GunScript)(object)this) = value;
			}
		}

		protected float _hammer_halfcocked
		{
			get
			{
				return ReflectionManager.GS_hammer_halfcocked.Invoke((GunScript)(object)this);
			}
			set
			{
				ReflectionManager.GS_hammer_halfcocked.Invoke((GunScript)(object)this) = value;
			}
		}

		protected float _hammer_cocked_val
		{
			get
			{
				return ReflectionManager.GS_hammer_cocked_val.Invoke((GunScript)(object)this);
			}
			set
			{
				ReflectionManager.GS_hammer_cocked_val.Invoke((GunScript)(object)this) = value;
			}
		}

		protected int _hammer_state
		{
			get
			{
				return ReflectionManager.GS_hammer_state.Invoke((GunScript)(object)this);
			}
			set
			{
				ReflectionManager.GS_hammer_state.Invoke((GunScript)(object)this) = value;
			}
		}

		protected bool _slide_stop_locked
		{
			get
			{
				return ReflectionManager.GS_slide_stop_locked.Invoke((GunScript)(object)this);
			}
			set
			{
				ReflectionManager.GS_slide_stop_locked.Invoke((GunScript)(object)this) = value;
			}
		}

		protected LinearMover _select_fire
		{
			get
			{
				return ReflectionManager.GS_select_fire.Invoke((GunScript)(object)this);
			}
			set
			{
				ReflectionManager.GS_select_fire.Invoke((GunScript)(object)this) = value;
			}
		}

		protected float _yoke_open
		{
			get
			{
				return ReflectionManager.GS_yoke_open.Invoke((GunScript)(object)this);
			}
			set
			{
				ReflectionManager.GS_yoke_open.Invoke((GunScript)(object)this) = value;
			}
		}

		protected int _current_firing_mode_index
		{
			get
			{
				return ReflectionManager.GS_current_firing_mode_index.Invoke((GunScript)(object)this);
			}
			set
			{
				ReflectionManager.GS_current_firing_mode_index.Invoke((GunScript)(object)this) = value;
			}
		}

		protected LinearMover _firing_pin
		{
			get
			{
				return ReflectionManager.GS_firing_pin.Invoke((GunScript)(object)this);
			}
			set
			{
				ReflectionManager.GS_firing_pin.Invoke((GunScript)(object)this) = value;
			}
		}

		public PlayerInput player_input { get; protected set; }

		public KeybindContainer keybinds { get; protected set; }

		internal static void UpdateModGun(GunScript gun)
		{
			if (gun is ModGunScript)
			{
				try
				{
					((ModGunScript)(object)gun).UpdateGun();
				}
				catch (Exception ex)
				{
					Debug.LogError((object)$"Catched exception during {((InventoryItem)gun).InternalName}'s UpdateGun");
					Debug.LogException(ex);
				}
			}
		}

		protected static float InterpCurve(in float[] curve, float time)
		{
			if (curve == null || curve.Length < 2)
			{
				Debug.LogError((object)"ModGunScript.InterpCurve(): curve parameter must contain at least 2 elements");
				return 0f;
			}
			if (time <= curve[0])
			{
				return curve[1];
			}
			if (time >= curve[curve.Length - 2])
			{
				return curve[curve.Length - 1];
			}
			for (int i = 0; i < curve.Length - 2; i += 2)
			{
				if (time <= curve[i + 2])
				{
					float num = Mathf.InverseLerp(curve[i], curve[i + 2], time);
					return Mathf.Lerp(curve[i + 1], curve[i + 3], num);
				}
			}
			return curve[1];
		}

		protected void TryFireBullet(float dry_fire_volume = 1f)
		{
			if (Object.op_Implicit((Object)(object)base.round_in_chamber) && !base.round_in_chamber.IsSpent() && ((SimpleMover)base.slide).amount == 0f)
			{
				((GunScript)this).FireBullet(base.round_in_chamber);
				return;
			}
			base.recoil_transfer_x -= Random.Range(15f, 30f);
			base.recoil_transfer_y += Random.Range(-20f, 20f);
			base.dry_fired = true;
			ReceiverEvents.TriggerEvent((ReceiverEventTypeInt)13, (!((Object)(object)base.round_in_chamber != (Object)null)) ? 1 : 2);
			AudioManager.PlayOneShotAttached(base.sound_dry_fire, ((Component)this).gameObject, dry_fire_volume);
		}

		protected void TryFireBullet(float dry_fire_volume, Action<ShellCasingScript> on_fire)
		{
			if (Object.op_Implicit((Object)(object)base.round_in_chamber) && !base.round_in_chamber.IsSpent() && ((SimpleMover)base.slide).amount == 0f)
			{
				on_fire(base.round_in_chamber);
				return;
			}
			base.recoil_transfer_x -= Random.Range(15f, 30f);
			base.recoil_transfer_y += Random.Range(-20f, 20f);
			base.dry_fired = true;
			ReceiverEvents.TriggerEvent((ReceiverEventTypeInt)13, (!((Object)(object)base.round_in_chamber != (Object)null)) ? 1 : 2);
			AudioManager.PlayOneShotAttached(base.sound_dry_fire, ((Component)this).gameObject, dry_fire_volume);
		}

		protected void UpdateAnimatedComponents()
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: 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_0025: Unknown result type (might be due to invalid IL or missing references)
			AnimatedMover[] animated_components = base.animated_components;
			foreach (AnimatedMover val in animated_components)
			{
				((GunScript)this).ApplyTransform(val.anim_path, val.mover.amount, val.component);
			}
		}

		protected void SetArmorPiercing(bool armor_piercing)
		{
			if (armor_piercing != base.armor_piercing)
			{
				base.armor_piercing = armor_piercing;
				TurretArmor[] array = Object.FindObjectsOfType<TurretArmor>();
				for (int i = 0; i < array.Length; i++)
				{
					((Component)array[i]).SendMessage("UpdateMaterial", (object)this);
				}
			}
		}

		protected void Awake()
		{
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0248: Unknown result type (might be due to invalid IL or missing references)
			//IL_024f: Expected O, but got Unknown
			player_input = new PlayerInput((GunScript)(object)this);
			using (new TransformDebugScope())
			{
				try
				{
					((GunScript)this).Awake();
				}
				catch (NullReferenceException ex)
				{
					Debug.LogError((object)$"Catched exception during {((InventoryItem)this).InternalName}'s Awake");
					if (!string.IsNullOrEmpty(TransformDebugScope.last_target))
					{
						Debug.LogError((object)("You seem to be missing the " + TransformDebugScope.last_target + " transform."));
					}
					else
					{
						Debug.LogError((object)"Carefully check if you've assigned all the fields properly and if there aren't any missing references");
					}
					Debug.LogError((object)ex);
				}
			}
			UpdatedSpring[] update_springs = base.update_springs;
			foreach (UpdatedSpring val in update_springs)
			{
				if ((Object)(object)val.spring == (Object)null)
				{
					Debug.LogError((object)("Null spring in gun \"" + ((InventoryItem)this).InternalName + "\""));
					continue;
				}
				val.spring.orig_center = (((Component)val.spring).transform.InverseTransformPoint(val.spring.new_top.position) + ((Component)val.spring).transform.InverseTransformPoint(val.spring.new_bottom.position)) / 2f;
				val.spring.orig_dist = Vector3.Distance(val.spring.new_top.position, val.spring.new_bottom.position);
			}
			if ((Object)(object)audio != (Object)null)
			{
				audio.SetGun(this);
				ModdingKitConfig.AddConfigEventListener(delegate(object sender, SettingChangedEventArgs args)
				{
					if (args.ChangedSetting.Definition.Key == "Use Custom Sounds")
					{
						audio.SetSoundEvents();
					}
				});
				audio.SetSoundEvents();
			}
			GameObject object_prefab = muzzle_flash_prefab;
			bool flag = true;
			if ((Object)(object)object_prefab == (Object)null)
			{
				object_prefab = base.pooled_muzzle_flash.object_prefab;
			}
			if ((Object)(object)object_prefab != (Object)null && ObjectPool.pools != null)
			{
				ObjectPool val2 = ObjectPool.pools["MuzzleFlashPool"];
				Dictionary<string, int> dictionary = ReflectionManager.OP_pool_map.GetValue(val2) as Diction

SharpCompress.dll

Decompiled a month ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Reflection.Emit;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Cryptography;
using System.Security.Permissions;
using System.Text;
using SharpCompress.Archives.GZip;
using SharpCompress.Archives.Rar;
using SharpCompress.Archives.SevenZip;
using SharpCompress.Archives.Tar;
using SharpCompress.Archives.Zip;
using SharpCompress.Common;
using SharpCompress.Common.GZip;
using SharpCompress.Common.Rar;
using SharpCompress.Common.Rar.Headers;
using SharpCompress.Common.SevenZip;
using SharpCompress.Common.Tar;
using SharpCompress.Common.Tar.Headers;
using SharpCompress.Common.Zip;
using SharpCompress.Common.Zip.Headers;
using SharpCompress.Compressors;
using SharpCompress.Compressors.BZip2;
using SharpCompress.Compressors.Deflate;
using SharpCompress.Compressors.Deflate64;
using SharpCompress.Compressors.Filters;
using SharpCompress.Compressors.LZMA;
using SharpCompress.Compressors.LZMA.LZ;
using SharpCompress.Compressors.LZMA.RangeCoder;
using SharpCompress.Compressors.LZMA.Utilites;
using SharpCompress.Compressors.PPMd;
using SharpCompress.Compressors.PPMd.H;
using SharpCompress.Compressors.PPMd.I1;
using SharpCompress.Compressors.Rar;
using SharpCompress.Compressors.Rar.UnpackV1;
using SharpCompress.Compressors.Rar.UnpackV1.Decode;
using SharpCompress.Compressors.Rar.UnpackV1.PPM;
using SharpCompress.Compressors.Rar.UnpackV2017;
using SharpCompress.Compressors.Rar.VM;
using SharpCompress.Compressors.Xz;
using SharpCompress.Compressors.Xz.Filters;
using SharpCompress.Converters;
using SharpCompress.Crypto;
using SharpCompress.IO;
using SharpCompress.Readers;
using SharpCompress.Readers.GZip;
using SharpCompress.Readers.Rar;
using SharpCompress.Readers.Tar;
using SharpCompress.Readers.Zip;
using SharpCompress.Writers;
using SharpCompress.Writers.GZip;
using SharpCompress.Writers.Tar;
using SharpCompress.Writers.Zip;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("SharpCompress")]
[assembly: AssemblyProduct("SharpCompress")]
[assembly: InternalsVisibleTo("SharpCompress.Test,PublicKey=002400000480000094000000060200000024000052534131000400000100010059acfa17d26c447a4d03f16eaa72c9187c04f16e6569dd168b080e39a6f5c9fd00f28c768cd8e9a089d5a0e1b34ccd971488e7afe030ce5ce8df2053cf12ec89f6d38065c434c09ee6af3ee284c5dc08f44774b679bf39298e57efe30d4b00aecf9e4f6f8448b2cb0146d8956dfcab606cc64a0ac38c60a7d78b0d65d3b98dc0")]
[assembly: InternalsVisibleTo("SharpCompress.Test.Portable,PublicKey=002400000480000094000000060200000024000052534131000400000100010059acfa17d26c447a4d03f16eaa72c9187c04f16e6569dd168b080e39a6f5c9fd00f28c768cd8e9a089d5a0e1b34ccd971488e7afe030ce5ce8df2053cf12ec89f6d38065c434c09ee6af3ee284c5dc08f44774b679bf39298e57efe30d4b00aecf9e4f6f8448b2cb0146d8956dfcab606cc64a0ac38c60a7d78b0d65d3b98dc0")]
[assembly: CLSCompliant(true)]
[assembly: TargetFramework(".NETFramework,Version=v4.5", FrameworkDisplayName = ".NET Framework 4.5")]
[assembly: AssemblyCompany("Adam Hathcock")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("SharpCompress is a compression library for NET Standard 1.0 that can unrar, decompress 7zip, decompress xz, zip/unzip, tar/untar lzip/unlzip, bzip2/unbzip2 and gzip/ungzip with forward-only reading and file random access APIs. Write support for zip/tar/bzip2/gzip is implemented.")]
[assembly: AssemblyFileVersion("0.24.0")]
[assembly: AssemblyInformationalVersion("0.24.0")]
[assembly: NeutralResourcesLanguage("en-US")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.24.0.0")]
[module: UnverifiableCode]
namespace SharpCompress
{
	internal static class AssemblyInfo
	{
		internal const string PublicKeySuffix = ",PublicKey=002400000480000094000000060200000024000052534131000400000100010059acfa17d26c447a4d03f16eaa72c9187c04f16e6569dd168b080e39a6f5c9fd00f28c768cd8e9a089d5a0e1b34ccd971488e7afe030ce5ce8df2053cf12ec89f6d38065c434c09ee6af3ee284c5dc08f44774b679bf39298e57efe30d4b00aecf9e4f6f8448b2cb0146d8956dfcab606cc64a0ac38c60a7d78b0d65d3b98dc0";
	}
	public class Lazy<T>
	{
		private readonly Func<T> _lazyFunc;

		private bool _evaluated;

		private T _value;

		public T Value
		{
			get
			{
				if (!_evaluated)
				{
					_value = _lazyFunc();
					_evaluated = true;
				}
				return _value;
			}
		}

		public Lazy(Func<T> lazyFunc)
		{
			_lazyFunc = lazyFunc;
		}
	}
	internal class LazyReadOnlyCollection<T> : ICollection<T>, IEnumerable<T>, IEnumerable
	{
		private class LazyLoader : IEnumerator<T>, IDisposable, IEnumerator
		{
			private readonly LazyReadOnlyCollection<T> lazyReadOnlyCollection;

			private bool disposed;

			private int index = -1;

			public T Current => lazyReadOnlyCollection.backing[index];

			object IEnumerator.Current => Current;

			internal LazyLoader(LazyReadOnlyCollection<T> lazyReadOnlyCollection)
			{
				this.lazyReadOnlyCollection = lazyReadOnlyCollection;
			}

			public void Dispose()
			{
				if (!disposed)
				{
					disposed = true;
				}
			}

			public bool MoveNext()
			{
				if (index + 1 < lazyReadOnlyCollection.backing.Count)
				{
					index++;
					return true;
				}
				if (!lazyReadOnlyCollection.fullyLoaded && lazyReadOnlyCollection.source.MoveNext())
				{
					lazyReadOnlyCollection.backing.Add(lazyReadOnlyCollection.source.Current);
					index++;
					return true;
				}
				lazyReadOnlyCollection.fullyLoaded = true;
				return false;
			}

			public void Reset()
			{
				throw new NotSupportedException();
			}
		}

		private readonly List<T> backing = new List<T>();

		private readonly IEnumerator<T> source;

		private bool fullyLoaded;

		public int Count
		{
			get
			{
				EnsureFullyLoaded();
				return backing.Count;
			}
		}

		public bool IsReadOnly => true;

		public LazyReadOnlyCollection(IEnumerable<T> source)
		{
			this.source = source.GetEnumerator();
		}

		internal void EnsureFullyLoaded()
		{
			if (!fullyLoaded)
			{
				this.ForEach(delegate
				{
				});
				fullyLoaded = true;
			}
		}

		internal IEnumerable<T> GetLoaded()
		{
			return backing;
		}

		public void Add(T item)
		{
			throw new NotSupportedException();
		}

		public void Clear()
		{
			throw new NotSupportedException();
		}

		public bool Contains(T item)
		{
			EnsureFullyLoaded();
			return backing.Contains(item);
		}

		public void CopyTo(T[] array, int arrayIndex)
		{
			EnsureFullyLoaded();
			backing.CopyTo(array, arrayIndex);
		}

		public bool Remove(T item)
		{
			throw new NotSupportedException();
		}

		public IEnumerator<T> GetEnumerator()
		{
			return new LazyLoader(this);
		}

		IEnumerator IEnumerable.GetEnumerator()
		{
			return GetEnumerator();
		}
	}
	internal class ReadOnlyCollection<T> : ICollection<T>, IEnumerable<T>, IEnumerable
	{
		private readonly ICollection<T> collection;

		public int Count => collection.Count;

		public bool IsReadOnly => true;

		public ReadOnlyCollection(ICollection<T> collection)
		{
			this.collection = collection;
		}

		public void Add(T item)
		{
			throw new NotSupportedException();
		}

		public void Clear()
		{
			throw new NotSupportedException();
		}

		public bool Contains(T item)
		{
			return collection.Contains(item);
		}

		public void CopyTo(T[] array, int arrayIndex)
		{
			collection.CopyTo(array, arrayIndex);
		}

		public bool Remove(T item)
		{
			throw new NotSupportedException();
		}

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

		IEnumerator IEnumerable.GetEnumerator()
		{
			throw new NotSupportedException();
		}
	}
	internal static class Utility
	{
		private static readonly Action<IntPtr, byte, uint> MemsetDelegate = CreateMemsetDelegate();

		public static ReadOnlyCollection<T> ToReadOnly<T>(this IEnumerable<T> items)
		{
			return new ReadOnlyCollection<T>(items.ToList());
		}

		public static int URShift(int number, int bits)
		{
			if (number >= 0)
			{
				return number >> bits;
			}
			return (number >> bits) + (2 << ~bits);
		}

		public static long URShift(long number, int bits)
		{
			if (number >= 0)
			{
				return number >> bits;
			}
			return (number >> bits) + (2L << ~bits);
		}

		public static void Fill<T>(T[] array, int fromindex, int toindex, T val) where T : struct
		{
			if (array.Length == 0)
			{
				throw new NullReferenceException();
			}
			if (fromindex > toindex)
			{
				throw new ArgumentException();
			}
			if (fromindex < 0 || array.Length < toindex)
			{
				throw new IndexOutOfRangeException();
			}
			for (int i = ((fromindex > 0) ? fromindex-- : fromindex); i < toindex; i++)
			{
				array[i] = val;
			}
		}

		private static Action<IntPtr, byte, uint> CreateMemsetDelegate()
		{
			DynamicMethod dynamicMethod = new DynamicMethod("Memset", MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard, null, new Type[3]
			{
				typeof(IntPtr),
				typeof(byte),
				typeof(uint)
			}, typeof(Utility), skipVisibility: true);
			ILGenerator iLGenerator = dynamicMethod.GetILGenerator();
			iLGenerator.Emit(OpCodes.Ldarg_0);
			iLGenerator.Emit(OpCodes.Ldarg_1);
			iLGenerator.Emit(OpCodes.Ldarg_2);
			iLGenerator.Emit(OpCodes.Initblk);
			iLGenerator.Emit(OpCodes.Ret);
			return (Action<IntPtr, byte, uint>)dynamicMethod.CreateDelegate(typeof(Action<IntPtr, byte, uint>));
		}

		public static void Memset(byte[] array, byte what, int length)
		{
			GCHandle gCHandle = GCHandle.Alloc(array, GCHandleType.Pinned);
			MemsetDelegate(gCHandle.AddrOfPinnedObject(), what, (uint)length);
			gCHandle.Free();
		}

		public static void Memset<T>(T[] array, T what, int length)
		{
			for (int i = 0; i < length; i++)
			{
				array[i] = what;
			}
		}

		public static void FillFast<T>(T[] array, T val) where T : struct
		{
			for (int i = 0; i < array.Length; i++)
			{
				array[i] = val;
			}
		}

		public static void FillFast<T>(T[] array, int start, int length, T val) where T : struct
		{
			int num = start + length;
			for (int i = start; i < num; i++)
			{
				array[i] = val;
			}
		}

		public static void Fill<T>(T[] array, T val) where T : struct
		{
			Fill(array, 0, array.Length, val);
		}

		public static void SetSize(this List<byte> list, int count)
		{
			if (count > list.Count)
			{
				for (int i = list.Count; i < count; i++)
				{
					list.Add(0);
				}
			}
			else
			{
				byte[] array = new byte[count];
				list.CopyTo(array, 0);
				list.Clear();
				list.AddRange(array);
			}
		}

		public static void AddRange<T>(this ICollection<T> destination, IEnumerable<T> source)
		{
			foreach (T item in source)
			{
				destination.Add(item);
			}
		}

		public static void ForEach<T>(this IEnumerable<T> items, Action<T> action)
		{
			foreach (T item in items)
			{
				action(item);
			}
		}

		public static void Copy(Array sourceArray, long sourceIndex, Array destinationArray, long destinationIndex, long length)
		{
			if (sourceIndex > int.MaxValue || sourceIndex < int.MinValue)
			{
				throw new ArgumentOutOfRangeException();
			}
			if (destinationIndex > int.MaxValue || destinationIndex < int.MinValue)
			{
				throw new ArgumentOutOfRangeException();
			}
			if (length > int.MaxValue || length < int.MinValue)
			{
				throw new ArgumentOutOfRangeException();
			}
			Array.Copy(sourceArray, (int)sourceIndex, destinationArray, (int)destinationIndex, (int)length);
		}

		public static IEnumerable<T> AsEnumerable<T>(this T item)
		{
			yield return item;
		}

		public static void CheckNotNull(this object obj, string name)
		{
			if (obj == null)
			{
				throw new ArgumentNullException(name);
			}
		}

		public static void CheckNotNullOrEmpty(this string obj, string name)
		{
			obj.CheckNotNull(name);
			if (obj.Length == 0)
			{
				throw new ArgumentException("String is empty.");
			}
		}

		public static void Skip(this Stream source, long advanceAmount)
		{
			if (source.CanSeek)
			{
				source.Position += advanceAmount;
				return;
			}
			byte[] transferByteArray = GetTransferByteArray();
			int num = 0;
			int num2 = 0;
			do
			{
				num2 = transferByteArray.Length;
				if (num2 > advanceAmount)
				{
					num2 = (int)advanceAmount;
				}
				num = source.Read(transferByteArray, 0, num2);
				if (num > 0)
				{
					advanceAmount -= num;
					continue;
				}
				break;
			}
			while (advanceAmount != 0L);
		}

		public static void Skip(this Stream source)
		{
			byte[] transferByteArray = GetTransferByteArray();
			while (source.Read(transferByteArray, 0, transferByteArray.Length) == transferByteArray.Length)
			{
			}
		}

		public static DateTime DosDateToDateTime(ushort iDate, ushort iTime)
		{
			int year = iDate / 512 + 1980;
			int num = iDate % 512 / 32;
			int num2 = iDate % 512 % 32;
			int hour = iTime / 2048;
			int minute = iTime % 2048 / 32;
			int second = iTime % 2048 % 32 * 2;
			if (iDate == ushort.MaxValue || num == 0 || num2 == 0)
			{
				year = 1980;
				num = 1;
				num2 = 1;
			}
			if (iTime == ushort.MaxValue)
			{
				hour = (minute = (second = 0));
			}
			DateTime result;
			try
			{
				return new DateTime(year, num, num2, hour, minute, second, DateTimeKind.Local);
			}
			catch
			{
				result = default(DateTime);
			}
			return result;
		}

		public static uint DateTimeToDosTime(this DateTime? dateTime)
		{
			if (!dateTime.HasValue)
			{
				return 0u;
			}
			DateTime dateTime2 = dateTime.Value.ToLocalTime();
			return (uint)((dateTime2.Second / 2) | (dateTime2.Minute << 5) | (dateTime2.Hour << 11) | (dateTime2.Day << 16) | (dateTime2.Month << 21) | (dateTime2.Year - 1980 << 25));
		}

		public static DateTime DosDateToDateTime(uint iTime)
		{
			return DosDateToDateTime((ushort)(iTime / 65536), (ushort)(iTime % 65536));
		}

		public static DateTime UnixTimeToDateTime(long unixtime)
		{
			return new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(unixtime);
		}

		public static long TransferTo(this Stream source, Stream destination)
		{
			byte[] transferByteArray = GetTransferByteArray();
			long num = 0L;
			int count;
			while (ReadTransferBlock(source, transferByteArray, out count))
			{
				num += count;
				destination.Write(transferByteArray, 0, count);
			}
			return num;
		}

		public static long TransferTo(this Stream source, Stream destination, Entry entry, IReaderExtractionListener readerExtractionListener)
		{
			byte[] transferByteArray = GetTransferByteArray();
			int num = 0;
			long num2 = 0L;
			int count;
			while (ReadTransferBlock(source, transferByteArray, out count))
			{
				num2 += count;
				destination.Write(transferByteArray, 0, count);
				num++;
				readerExtractionListener.FireEntryExtractionProgress(entry, num2, num);
			}
			return num2;
		}

		private static bool ReadTransferBlock(Stream source, byte[] array, out int count)
		{
			return (count = source.Read(array, 0, array.Length)) != 0;
		}

		private static byte[] GetTransferByteArray()
		{
			return new byte[81920];
		}

		public static bool ReadFully(this Stream stream, byte[] buffer)
		{
			int num = 0;
			int num2;
			while ((num2 = stream.Read(buffer, num, buffer.Length - num)) > 0)
			{
				num += num2;
				if (num >= buffer.Length)
				{
					return true;
				}
			}
			return num >= buffer.Length;
		}

		public static string TrimNulls(this string source)
		{
			return source.Replace('\0', ' ').Trim();
		}

		public static bool BinaryEquals(this byte[] source, byte[] target)
		{
			if (source.Length != target.Length)
			{
				return false;
			}
			for (int i = 0; i < source.Length; i++)
			{
				if (source[i] != target[i])
				{
					return false;
				}
			}
			return true;
		}
	}
}
namespace SharpCompress.Writers
{
	public abstract class AbstractWriter : IWriter, IDisposable
	{
		private bool _isDisposed;

		protected Stream OutputStream { get; private set; }

		public ArchiveType WriterType { get; }

		protected WriterOptions WriterOptions { get; }

		protected AbstractWriter(ArchiveType type, WriterOptions writerOptions)
		{
			WriterType = type;
			WriterOptions = writerOptions;
		}

		protected void InitalizeStream(Stream stream)
		{
			OutputStream = stream;
		}

		public abstract void Write(string filename, Stream source, DateTime? modificationTime);

		protected virtual void Dispose(bool isDisposing)
		{
			if (isDisposing)
			{
				OutputStream.Dispose();
			}
		}

		public void Dispose()
		{
			if (!_isDisposed)
			{
				GC.SuppressFinalize(this);
				Dispose(isDisposing: true);
				_isDisposed = true;
			}
		}

		~AbstractWriter()
		{
			if (!_isDisposed)
			{
				Dispose(isDisposing: false);
				_isDisposed = true;
			}
		}
	}
	public interface IWriter : IDisposable
	{
		ArchiveType WriterType { get; }

		void Write(string filename, Stream source, DateTime? modificationTime);
	}
	public static class IWriterExtensions
	{
		public static void Write(this IWriter writer, string entryPath, Stream source)
		{
			writer.Write(entryPath, source, null);
		}

		public static void Write(this IWriter writer, string entryPath, FileInfo source)
		{
			if (!source.Exists)
			{
				throw new ArgumentException("Source does not exist: " + source.FullName);
			}
			using FileStream source2 = source.OpenRead();
			writer.Write(entryPath, source2, source.LastWriteTime);
		}

		public static void Write(this IWriter writer, string entryPath, string source)
		{
			writer.Write(entryPath, new FileInfo(source));
		}

		public static void WriteAll(this IWriter writer, string directory, string searchPattern = "*", SearchOption option = SearchOption.TopDirectoryOnly)
		{
			writer.WriteAll(directory, searchPattern, null, option);
		}

		public static void WriteAll(this IWriter writer, string directory, string searchPattern = "*", Expression<Func<string, bool>> fileSearchFunc = null, SearchOption option = SearchOption.TopDirectoryOnly)
		{
			if (!Directory.Exists(directory))
			{
				throw new ArgumentException("Directory does not exist: " + directory);
			}
			if (fileSearchFunc == null)
			{
				fileSearchFunc = (string n) => true;
			}
			foreach (string item in Directory.EnumerateFiles(directory, searchPattern, option).Where(fileSearchFunc.Compile()))
			{
				writer.Write(item.Substring(directory.Length), item);
			}
		}
	}
	public static class WriterFactory
	{
		public static IWriter Open(Stream stream, ArchiveType archiveType, WriterOptions writerOptions)
		{
			switch (archiveType)
			{
			case ArchiveType.GZip:
				if (writerOptions.CompressionType != CompressionType.GZip)
				{
					throw new InvalidFormatException("GZip archives only support GZip compression type.");
				}
				return new GZipWriter(stream, new GZipWriterOptions(writerOptions));
			case ArchiveType.Zip:
				return new ZipWriter(stream, new ZipWriterOptions(writerOptions));
			case ArchiveType.Tar:
				return new TarWriter(stream, new TarWriterOptions(writerOptions));
			default:
				throw new NotSupportedException("Archive Type does not have a Writer: " + archiveType);
			}
		}
	}
	public class WriterOptions : OptionsBase
	{
		public CompressionType CompressionType { get; set; }

		public WriterOptions(CompressionType compressionType)
		{
			CompressionType = compressionType;
		}

		public static implicit operator WriterOptions(CompressionType compressionType)
		{
			return new WriterOptions(compressionType);
		}
	}
}
namespace SharpCompress.Writers.Zip
{
	internal class ZipCentralDirectoryEntry
	{
		private readonly ZipCompressionMethod compression;

		private readonly string fileName;

		private readonly ArchiveEncoding archiveEncoding;

		internal DateTime? ModificationTime { get; set; }

		internal string Comment { get; set; }

		internal uint Crc { get; set; }

		internal ulong Compressed { get; set; }

		internal ulong Decompressed { get; set; }

		internal ushort Zip64HeaderOffset { get; set; }

		internal ulong HeaderOffset { get; }

		public ZipCentralDirectoryEntry(ZipCompressionMethod compression, string fileName, ulong headerOffset, ArchiveEncoding archiveEncoding)
		{
			this.compression = compression;
			this.fileName = fileName;
			HeaderOffset = headerOffset;
			this.archiveEncoding = archiveEncoding;
		}

		internal uint Write(Stream outputStream)
		{
			byte[] array = archiveEncoding.Encode(fileName);
			byte[] array2 = archiveEncoding.Encode(Comment);
			bool flag = Compressed >= uint.MaxValue || Decompressed >= uint.MaxValue;
			bool flag2 = flag || HeaderOffset >= uint.MaxValue;
			ZipCompressionMethod zipCompressionMethod = compression;
			uint value = (uint)(flag2 ? uint.MaxValue : Compressed);
			uint value2 = (uint)(flag2 ? uint.MaxValue : Decompressed);
			uint value3 = (uint)(flag2 ? uint.MaxValue : HeaderOffset);
			int num = (flag2 ? 32 : 0);
			byte b = (byte)(flag2 ? 45u : 20u);
			HeaderFlags headerFlags = (object.Equals(archiveEncoding.GetEncoding(), Encoding.UTF8) ? HeaderFlags.Efs : HeaderFlags.None);
			if (!outputStream.CanSeek)
			{
				if (!flag)
				{
					headerFlags |= HeaderFlags.UsePostDataDescriptor;
				}
				if (zipCompressionMethod == ZipCompressionMethod.LZMA)
				{
					headerFlags |= HeaderFlags.Bit1;
				}
			}
			if (Decompressed == 0L && Compressed == 0L)
			{
				zipCompressionMethod = ZipCompressionMethod.None;
			}
			byte[] obj = new byte[8] { 80, 75, 1, 2, 0, 0, 0, 0 };
			obj[4] = b;
			obj[6] = b;
			outputStream.Write(obj, 0, 8);
			outputStream.Write(DataConverter.LittleEndian.GetBytes((ushort)headerFlags), 0, 2);
			outputStream.Write(DataConverter.LittleEndian.GetBytes((ushort)zipCompressionMethod), 0, 2);
			outputStream.Write(DataConverter.LittleEndian.GetBytes(ModificationTime.DateTimeToDosTime()), 0, 4);
			outputStream.Write(DataConverter.LittleEndian.GetBytes(Crc), 0, 4);
			outputStream.Write(DataConverter.LittleEndian.GetBytes(value), 0, 4);
			outputStream.Write(DataConverter.LittleEndian.GetBytes(value2), 0, 4);
			outputStream.Write(DataConverter.LittleEndian.GetBytes((ushort)array.Length), 0, 2);
			outputStream.Write(DataConverter.LittleEndian.GetBytes((ushort)num), 0, 2);
			outputStream.Write(DataConverter.LittleEndian.GetBytes((ushort)array2.Length), 0, 2);
			outputStream.Write(DataConverter.LittleEndian.GetBytes((ushort)0), 0, 2);
			outputStream.Write(DataConverter.LittleEndian.GetBytes((ushort)0), 0, 2);
			outputStream.Write(DataConverter.LittleEndian.GetBytes((ushort)0), 0, 2);
			outputStream.Write(DataConverter.LittleEndian.GetBytes((ushort)33024), 0, 2);
			outputStream.Write(DataConverter.LittleEndian.GetBytes(value3), 0, 4);
			outputStream.Write(array, 0, array.Length);
			if (flag2)
			{
				outputStream.Write(DataConverter.LittleEndian.GetBytes((ushort)1), 0, 2);
				outputStream.Write(DataConverter.LittleEndian.GetBytes((ushort)(num - 4)), 0, 2);
				outputStream.Write(DataConverter.LittleEndian.GetBytes(Decompressed), 0, 8);
				outputStream.Write(DataConverter.LittleEndian.GetBytes(Compressed), 0, 8);
				outputStream.Write(DataConverter.LittleEndian.GetBytes(HeaderOffset), 0, 8);
				outputStream.Write(DataConverter.LittleEndian.GetBytes(0), 0, 4);
			}
			outputStream.Write(array2, 0, array2.Length);
			return (uint)(46 + array.Length + num + array2.Length);
		}
	}
	public class ZipWriter : AbstractWriter
	{
		internal class ZipWritingStream : Stream
		{
			private readonly CRC32 crc = new CRC32();

			private readonly ZipCentralDirectoryEntry entry;

			private readonly Stream originalStream;

			private readonly Stream writeStream;

			private readonly ZipWriter writer;

			private readonly ZipCompressionMethod zipCompressionMethod;

			private readonly CompressionLevel compressionLevel;

			private CountingWritableSubStream counting;

			private ulong decompressed;

			private bool limitsExceeded;

			private bool isDisposed;

			public override bool CanRead => false;

			public override bool CanSeek => false;

			public override bool CanWrite => true;

			public override long Length
			{
				get
				{
					throw new NotSupportedException();
				}
			}

			public override long Position
			{
				get
				{
					throw new NotSupportedException();
				}
				set
				{
					throw new NotSupportedException();
				}
			}

			internal ZipWritingStream(ZipWriter writer, Stream originalStream, ZipCentralDirectoryEntry entry, ZipCompressionMethod zipCompressionMethod, CompressionLevel compressionLevel)
			{
				this.writer = writer;
				this.originalStream = originalStream;
				this.writer = writer;
				this.entry = entry;
				this.zipCompressionMethod = zipCompressionMethod;
				this.compressionLevel = compressionLevel;
				writeStream = GetWriteStream(originalStream);
			}

			private Stream GetWriteStream(Stream writeStream)
			{
				counting = new CountingWritableSubStream(writeStream);
				Stream result = counting;
				switch (zipCompressionMethod)
				{
				case ZipCompressionMethod.None:
					return result;
				case ZipCompressionMethod.Deflate:
					return new DeflateStream(counting, CompressionMode.Compress, compressionLevel);
				case ZipCompressionMethod.BZip2:
					return new BZip2Stream(counting, CompressionMode.Compress, decompressConcatenated: false);
				case ZipCompressionMethod.LZMA:
				{
					counting.WriteByte(9);
					counting.WriteByte(20);
					counting.WriteByte(5);
					counting.WriteByte(0);
					LzmaStream lzmaStream = new LzmaStream(new LzmaEncoderProperties(!originalStream.CanSeek), isLzma2: false, counting);
					counting.Write(lzmaStream.Properties, 0, lzmaStream.Properties.Length);
					return lzmaStream;
				}
				case ZipCompressionMethod.PPMd:
					counting.Write(writer.PpmdProperties.Properties, 0, 2);
					return new PpmdStream(writer.PpmdProperties, counting, compress: true);
				default:
					throw new NotSupportedException("CompressionMethod: " + zipCompressionMethod);
				}
			}

			protected override void Dispose(bool disposing)
			{
				if (isDisposed)
				{
					return;
				}
				isDisposed = true;
				base.Dispose(disposing);
				if (!disposing)
				{
					return;
				}
				writeStream.Dispose();
				if (limitsExceeded)
				{
					originalStream.Dispose();
					return;
				}
				entry.Crc = (uint)crc.Crc32Result;
				entry.Compressed = counting.Count;
				entry.Decompressed = decompressed;
				bool flag = entry.Compressed >= uint.MaxValue || entry.Decompressed >= uint.MaxValue;
				uint compressed = (uint)(flag ? uint.MaxValue : counting.Count);
				uint uncompressed = (uint)(flag ? uint.MaxValue : entry.Decompressed);
				if (originalStream.CanSeek)
				{
					originalStream.Position = (long)(entry.HeaderOffset + 6);
					originalStream.WriteByte(0);
					if (counting.Count == 0L && entry.Decompressed == 0L)
					{
						originalStream.Position = (long)(entry.HeaderOffset + 8);
						originalStream.WriteByte(0);
						originalStream.WriteByte(0);
					}
					originalStream.Position = (long)(entry.HeaderOffset + 14);
					writer.WriteFooter(entry.Crc, compressed, uncompressed);
					if (flag && entry.Zip64HeaderOffset == 0)
					{
						throw new NotSupportedException("Attempted to write a stream that is larger than 4GiB without setting the zip64 option");
					}
					if (entry.Zip64HeaderOffset != 0)
					{
						originalStream.Position = (long)(entry.HeaderOffset + entry.Zip64HeaderOffset);
						originalStream.Write(DataConverter.LittleEndian.GetBytes((ushort)1), 0, 2);
						originalStream.Write(DataConverter.LittleEndian.GetBytes((ushort)16), 0, 2);
						originalStream.Write(DataConverter.LittleEndian.GetBytes(entry.Decompressed), 0, 8);
						originalStream.Write(DataConverter.LittleEndian.GetBytes(entry.Compressed), 0, 8);
					}
					originalStream.Position = writer.streamPosition + (long)entry.Compressed;
					writer.streamPosition += (long)entry.Compressed;
				}
				else
				{
					if (flag)
					{
						throw new NotSupportedException("Streams larger than 4GiB are not supported for non-seekable streams");
					}
					originalStream.Write(DataConverter.LittleEndian.GetBytes(134695760u), 0, 4);
					writer.WriteFooter(entry.Crc, compressed, uncompressed);
					writer.streamPosition += (long)(entry.Compressed + 16);
				}
				writer.entries.Add(entry);
			}

			public override void Flush()
			{
				writeStream.Flush();
			}

			public override int Read(byte[] buffer, int offset, int count)
			{
				throw new NotSupportedException();
			}

			public override long Seek(long offset, SeekOrigin origin)
			{
				throw new NotSupportedException();
			}

			public override void SetLength(long value)
			{
				throw new NotSupportedException();
			}

			public override void Write(byte[] buffer, int offset, int count)
			{
				if (entry.Zip64HeaderOffset == 0 && (limitsExceeded || decompressed + (uint)count > uint.MaxValue || counting.Count + (uint)count > uint.MaxValue))
				{
					throw new NotSupportedException("Attempted to write a stream that is larger than 4GiB without setting the zip64 option");
				}
				decompressed += (uint)count;
				crc.SlurpBlock(buffer, offset, count);
				writeStream.Write(buffer, offset, count);
				if (entry.Zip64HeaderOffset == 0 && (decompressed > uint.MaxValue || counting.Count > uint.MaxValue))
				{
					limitsExceeded = true;
					throw new NotSupportedException("Attempted to write a stream that is larger than 4GiB without setting the zip64 option");
				}
			}
		}

		private readonly CompressionType compressionType;

		private readonly CompressionLevel compressionLevel;

		private readonly List<ZipCentralDirectoryEntry> entries = new List<ZipCentralDirectoryEntry>();

		private readonly string zipComment;

		private long streamPosition;

		private PpmdProperties ppmdProps;

		private readonly bool isZip64;

		private PpmdProperties PpmdProperties
		{
			get
			{
				if (ppmdProps == null)
				{
					ppmdProps = new PpmdProperties();
				}
				return ppmdProps;
			}
		}

		public ZipWriter(Stream destination, ZipWriterOptions zipWriterOptions)
			: base(ArchiveType.Zip, zipWriterOptions)
		{
			zipComment = zipWriterOptions.ArchiveComment ?? string.Empty;
			isZip64 = zipWriterOptions.UseZip64;
			if (destination.CanSeek)
			{
				streamPosition = destination.Position;
			}
			compressionType = zipWriterOptions.CompressionType;
			compressionLevel = zipWriterOptions.DeflateCompressionLevel;
			if (base.WriterOptions.LeaveStreamOpen)
			{
				destination = new NonDisposingStream(destination);
			}
			InitalizeStream(destination);
		}

		protected override void Dispose(bool isDisposing)
		{
			if (isDisposing)
			{
				ulong num = 0uL;
				foreach (ZipCentralDirectoryEntry entry in entries)
				{
					num += entry.Write(base.OutputStream);
				}
				WriteEndRecord(num);
			}
			base.Dispose(isDisposing);
		}

		private static ZipCompressionMethod ToZipCompressionMethod(CompressionType compressionType)
		{
			return compressionType switch
			{
				CompressionType.None => ZipCompressionMethod.None, 
				CompressionType.Deflate => ZipCompressionMethod.Deflate, 
				CompressionType.BZip2 => ZipCompressionMethod.BZip2, 
				CompressionType.LZMA => ZipCompressionMethod.LZMA, 
				CompressionType.PPMd => ZipCompressionMethod.PPMd, 
				_ => throw new InvalidFormatException("Invalid compression method: " + compressionType), 
			};
		}

		public override void Write(string entryPath, Stream source, DateTime? modificationTime)
		{
			Write(entryPath, source, new ZipWriterEntryOptions
			{
				ModificationDateTime = modificationTime
			});
		}

		public void Write(string entryPath, Stream source, ZipWriterEntryOptions zipWriterEntryOptions)
		{
			using Stream destination = WriteToStream(entryPath, zipWriterEntryOptions);
			source.TransferTo(destination);
		}

		public Stream WriteToStream(string entryPath, ZipWriterEntryOptions options)
		{
			ZipCompressionMethod zipCompressionMethod = ToZipCompressionMethod(options.CompressionType ?? compressionType);
			entryPath = NormalizeFilename(entryPath);
			options.ModificationDateTime = options.ModificationDateTime ?? DateTime.Now;
			options.EntryComment = options.EntryComment ?? string.Empty;
			ZipCentralDirectoryEntry entry = new ZipCentralDirectoryEntry(zipCompressionMethod, entryPath, (ulong)streamPosition, base.WriterOptions.ArchiveEncoding)
			{
				Comment = options.EntryComment,
				ModificationTime = options.ModificationDateTime
			};
			bool value = isZip64;
			if (options.EnableZip64.HasValue)
			{
				value = options.EnableZip64.Value;
			}
			uint num = (uint)WriteHeader(entryPath, options, entry, value);
			streamPosition += num;
			return new ZipWritingStream(this, base.OutputStream, entry, zipCompressionMethod, options.DeflateCompressionLevel ?? compressionLevel);
		}

		private string NormalizeFilename(string filename)
		{
			filename = filename.Replace('\\', '/');
			int num = filename.IndexOf(':');
			if (num >= 0)
			{
				filename = filename.Remove(0, num + 1);
			}
			return filename.Trim(new char[1] { '/' });
		}

		private int WriteHeader(string filename, ZipWriterEntryOptions zipWriterEntryOptions, ZipCentralDirectoryEntry entry, bool useZip64)
		{
			if (!base.OutputStream.CanSeek && useZip64)
			{
				throw new NotSupportedException("Zip64 extensions are not supported on non-seekable streams");
			}
			ZipCompressionMethod zipCompressionMethod = ToZipCompressionMethod(zipWriterEntryOptions.CompressionType ?? compressionType);
			byte[] array = base.WriterOptions.ArchiveEncoding.Encode(filename);
			base.OutputStream.Write(DataConverter.LittleEndian.GetBytes(67324752u), 0, 4);
			if (zipCompressionMethod == ZipCompressionMethod.Deflate)
			{
				if (base.OutputStream.CanSeek && useZip64)
				{
					base.OutputStream.Write(new byte[2] { 45, 0 }, 0, 2);
				}
				else
				{
					base.OutputStream.Write(new byte[2] { 20, 0 }, 0, 2);
				}
			}
			else
			{
				base.OutputStream.Write(new byte[2] { 63, 0 }, 0, 2);
			}
			HeaderFlags headerFlags = (object.Equals(base.WriterOptions.ArchiveEncoding.GetEncoding(), Encoding.UTF8) ? HeaderFlags.Efs : HeaderFlags.None);
			if (!base.OutputStream.CanSeek)
			{
				headerFlags |= HeaderFlags.UsePostDataDescriptor;
				if (zipCompressionMethod == ZipCompressionMethod.LZMA)
				{
					headerFlags |= HeaderFlags.Bit1;
				}
			}
			base.OutputStream.Write(DataConverter.LittleEndian.GetBytes((ushort)headerFlags), 0, 2);
			base.OutputStream.Write(DataConverter.LittleEndian.GetBytes((ushort)zipCompressionMethod), 0, 2);
			base.OutputStream.Write(DataConverter.LittleEndian.GetBytes(zipWriterEntryOptions.ModificationDateTime.DateTimeToDosTime()), 0, 4);
			base.OutputStream.Write(new byte[12], 0, 12);
			base.OutputStream.Write(DataConverter.LittleEndian.GetBytes((ushort)array.Length), 0, 2);
			int num = 0;
			if (base.OutputStream.CanSeek && useZip64)
			{
				num = 20;
			}
			base.OutputStream.Write(DataConverter.LittleEndian.GetBytes((ushort)num), 0, 2);
			base.OutputStream.Write(array, 0, array.Length);
			if (num != 0)
			{
				base.OutputStream.Write(new byte[num], 0, num);
				entry.Zip64HeaderOffset = (ushort)(30 + array.Length);
			}
			return 30 + array.Length + num;
		}

		private void WriteFooter(uint crc, uint compressed, uint uncompressed)
		{
			base.OutputStream.Write(DataConverter.LittleEndian.GetBytes(crc), 0, 4);
			base.OutputStream.Write(DataConverter.LittleEndian.GetBytes(compressed), 0, 4);
			base.OutputStream.Write(DataConverter.LittleEndian.GetBytes(uncompressed), 0, 4);
		}

		private void WriteEndRecord(ulong size)
		{
			byte[] array = base.WriterOptions.ArchiveEncoding.Encode(zipComment);
			bool num = isZip64 || entries.Count > 65535 || streamPosition >= uint.MaxValue || size >= uint.MaxValue;
			uint value = (uint)((size >= uint.MaxValue) ? uint.MaxValue : size);
			uint num2 = (uint)((streamPosition >= uint.MaxValue) ? uint.MaxValue : streamPosition);
			if (num)
			{
				int num3 = 44;
				base.OutputStream.Write(new byte[4] { 80, 75, 6, 6 }, 0, 4);
				base.OutputStream.Write(DataConverter.LittleEndian.GetBytes((ulong)num3), 0, 8);
				base.OutputStream.Write(DataConverter.LittleEndian.GetBytes((ushort)0), 0, 2);
				base.OutputStream.Write(DataConverter.LittleEndian.GetBytes((ushort)45), 0, 2);
				base.OutputStream.Write(DataConverter.LittleEndian.GetBytes(0u), 0, 4);
				base.OutputStream.Write(DataConverter.LittleEndian.GetBytes(0u), 0, 4);
				base.OutputStream.Write(DataConverter.LittleEndian.GetBytes((ulong)entries.Count), 0, 8);
				base.OutputStream.Write(DataConverter.LittleEndian.GetBytes((ulong)entries.Count), 0, 8);
				base.OutputStream.Write(DataConverter.LittleEndian.GetBytes(size), 0, 8);
				base.OutputStream.Write(DataConverter.LittleEndian.GetBytes((ulong)streamPosition), 0, 8);
				base.OutputStream.Write(new byte[4] { 80, 75, 6, 7 }, 0, 4);
				base.OutputStream.Write(DataConverter.LittleEndian.GetBytes(0uL), 0, 4);
				base.OutputStream.Write(DataConverter.LittleEndian.GetBytes((ulong)streamPosition + size), 0, 8);
				base.OutputStream.Write(DataConverter.LittleEndian.GetBytes(0u), 0, 4);
				streamPosition += num3 + 20;
				num2 = ((streamPosition >= uint.MaxValue) ? uint.MaxValue : num2);
			}
			base.OutputStream.Write(new byte[8] { 80, 75, 5, 6, 0, 0, 0, 0 }, 0, 8);
			base.OutputStream.Write(DataConverter.LittleEndian.GetBytes((ushort)entries.Count), 0, 2);
			base.OutputStream.Write(DataConverter.LittleEndian.GetBytes((ushort)entries.Count), 0, 2);
			base.OutputStream.Write(DataConverter.LittleEndian.GetBytes(value), 0, 4);
			base.OutputStream.Write(DataConverter.LittleEndian.GetBytes(num2), 0, 4);
			base.OutputStream.Write(DataConverter.LittleEndian.GetBytes((ushort)array.Length), 0, 2);
			base.OutputStream.Write(array, 0, array.Length);
		}
	}
	public class ZipWriterEntryOptions
	{
		public CompressionType? CompressionType { get; set; }

		public CompressionLevel? DeflateCompressionLevel { get; set; }

		public string EntryComment { get; set; }

		public DateTime? ModificationDateTime { get; set; }

		public bool? EnableZip64 { get; set; }
	}
	public class ZipWriterOptions : WriterOptions
	{
		public CompressionLevel DeflateCompressionLevel { get; set; } = CompressionLevel.Default;

		public string ArchiveComment { get; set; }

		public bool UseZip64 { get; set; }

		public ZipWriterOptions(CompressionType compressionType)
			: base(compressionType)
		{
		}

		internal ZipWriterOptions(WriterOptions options)
			: base(options.CompressionType)
		{
			base.LeaveStreamOpen = options.LeaveStreamOpen;
			base.ArchiveEncoding = options.ArchiveEncoding;
			if (options is ZipWriterOptions zipWriterOptions)
			{
				UseZip64 = zipWriterOptions.UseZip64;
				DeflateCompressionLevel = zipWriterOptions.DeflateCompressionLevel;
				ArchiveComment = zipWriterOptions.ArchiveComment;
			}
		}
	}
}
namespace SharpCompress.Writers.Tar
{
	public class TarWriter : AbstractWriter
	{
		private readonly bool finalizeArchiveOnClose;

		public TarWriter(Stream destination, TarWriterOptions options)
			: base(ArchiveType.Tar, options)
		{
			finalizeArchiveOnClose = options.FinalizeArchiveOnClose;
			if (!destination.CanWrite)
			{
				throw new ArgumentException("Tars require writable streams.");
			}
			if (base.WriterOptions.LeaveStreamOpen)
			{
				destination = new NonDisposingStream(destination);
			}
			switch (options.CompressionType)
			{
			case CompressionType.BZip2:
				destination = new BZip2Stream(destination, CompressionMode.Compress, decompressConcatenated: false);
				break;
			case CompressionType.GZip:
				destination = new GZipStream(destination, CompressionMode.Compress);
				break;
			case CompressionType.LZip:
				destination = new LZipStream(destination, CompressionMode.Compress);
				break;
			default:
				throw new InvalidFormatException("Tar does not support compression: " + options.CompressionType);
			case CompressionType.None:
				break;
			}
			InitalizeStream(destination);
		}

		public override void Write(string filename, Stream source, DateTime? modificationTime)
		{
			Write(filename, source, modificationTime, null);
		}

		private string NormalizeFilename(string filename)
		{
			filename = filename.Replace('\\', '/');
			int num = filename.IndexOf(':');
			if (num >= 0)
			{
				filename = filename.Remove(0, num + 1);
			}
			return filename.Trim(new char[1] { '/' });
		}

		public void Write(string filename, Stream source, DateTime? modificationTime, long? size)
		{
			if (!source.CanSeek && !size.HasValue)
			{
				throw new ArgumentException("Seekable stream is required if no size is given.");
			}
			long size2 = size ?? source.Length;
			TarHeader tarHeader = new TarHeader(base.WriterOptions.ArchiveEncoding);
			tarHeader.LastModifiedTime = modificationTime ?? TarHeader.EPOCH;
			tarHeader.Name = NormalizeFilename(filename);
			tarHeader.Size = size2;
			tarHeader.Write(base.OutputStream);
			size = source.TransferTo(base.OutputStream);
			PadTo512(size.Value, forceZeros: false);
		}

		private void PadTo512(long size, bool forceZeros)
		{
			int num = (int)size % 512;
			if (num != 0 || forceZeros)
			{
				num = 512 - num;
				base.OutputStream.Write(new byte[num], 0, num);
			}
		}

		protected override void Dispose(bool isDisposing)
		{
			if (isDisposing)
			{
				if (finalizeArchiveOnClose)
				{
					PadTo512(0L, forceZeros: true);
					PadTo512(0L, forceZeros: true);
				}
				Stream outputStream = base.OutputStream;
				if (outputStream != null)
				{
					if (!(outputStream is BZip2Stream bZip2Stream))
					{
						if (outputStream is LZipStream lZipStream)
						{
							lZipStream.Finish();
						}
					}
					else
					{
						bZip2Stream.Finish();
					}
				}
			}
			base.Dispose(isDisposing);
		}
	}
	public class TarWriterOptions : WriterOptions
	{
		public bool FinalizeArchiveOnClose { get; }

		public TarWriterOptions(CompressionType compressionType, bool finalizeArchiveOnClose)
			: base(compressionType)
		{
			FinalizeArchiveOnClose = finalizeArchiveOnClose;
		}

		internal TarWriterOptions(WriterOptions options)
			: this(options.CompressionType, finalizeArchiveOnClose: true)
		{
			base.ArchiveEncoding = options.ArchiveEncoding;
		}
	}
}
namespace SharpCompress.Writers.GZip
{
	public class GZipWriter : AbstractWriter
	{
		private bool _wroteToStream;

		public GZipWriter(Stream destination, GZipWriterOptions options = null)
			: base(ArchiveType.GZip, options ?? new GZipWriterOptions())
		{
			if (base.WriterOptions.LeaveStreamOpen)
			{
				destination = new NonDisposingStream(destination);
			}
			InitalizeStream(new GZipStream(destination, CompressionMode.Compress, options?.CompressionLevel ?? CompressionLevel.Default, base.WriterOptions.ArchiveEncoding.GetEncoding()));
		}

		protected override void Dispose(bool isDisposing)
		{
			if (isDisposing)
			{
				base.OutputStream.Dispose();
			}
			base.Dispose(isDisposing);
		}

		public override void Write(string filename, Stream source, DateTime? modificationTime)
		{
			if (_wroteToStream)
			{
				throw new ArgumentException("Can only write a single stream to a GZip file.");
			}
			GZipStream gZipStream = base.OutputStream as GZipStream;
			gZipStream.FileName = filename;
			gZipStream.LastModified = modificationTime;
			source.TransferTo(gZipStream);
			_wroteToStream = true;
		}
	}
	public class GZipWriterOptions : WriterOptions
	{
		public CompressionLevel CompressionLevel { get; set; } = CompressionLevel.Default;

		public GZipWriterOptions()
			: base(CompressionType.GZip)
		{
		}

		internal GZipWriterOptions(WriterOptions options)
			: base(options.CompressionType)
		{
			base.LeaveStreamOpen = options.LeaveStreamOpen;
			base.ArchiveEncoding = options.ArchiveEncoding;
			if (options is GZipWriterOptions gZipWriterOptions)
			{
				CompressionLevel = gZipWriterOptions.CompressionLevel;
			}
		}
	}
}
namespace SharpCompress.Readers
{
	public abstract class AbstractReader<TEntry, TVolume> : IReader, IDisposable, IReaderExtractionListener, IExtractionListener where TEntry : Entry where TVolume : Volume
	{
		private bool completed;

		private IEnumerator<TEntry> entriesForCurrentReadStream;

		private bool wroteCurrentEntry;

		internal ReaderOptions Options { get; }

		public ArchiveType ArchiveType { get; }

		public abstract TVolume Volume { get; }

		public TEntry Entry => entriesForCurrentReadStream.Current;

		public bool Cancelled { get; private set; }

		IEntry IReader.Entry => Entry;

		public event EventHandler<ReaderExtractionEventArgs<IEntry>> EntryExtractionProgress;

		public event EventHandler<CompressedBytesReadEventArgs> CompressedBytesRead;

		public event EventHandler<FilePartExtractionBeginEventArgs> FilePartExtractionBegin;

		internal AbstractReader(ReaderOptions options, ArchiveType archiveType)
		{
			ArchiveType = archiveType;
			Options = options;
		}

		public void Dispose()
		{
			entriesForCurrentReadStream?.Dispose();
			Volume?.Dispose();
		}

		public void Cancel()
		{
			if (!completed)
			{
				Cancelled = true;
			}
		}

		public bool MoveToNextEntry()
		{
			if (completed)
			{
				return false;
			}
			if (Cancelled)
			{
				throw new InvalidOperationException("Reader has been cancelled.");
			}
			if (entriesForCurrentReadStream == null)
			{
				return LoadStreamForReading(RequestInitialStream());
			}
			if (!wroteCurrentEntry)
			{
				SkipEntry();
			}
			wroteCurrentEntry = false;
			if (NextEntryForCurrentStream())
			{
				return true;
			}
			completed = true;
			return false;
		}

		protected bool LoadStreamForReading(Stream stream)
		{
			entriesForCurrentReadStream?.Dispose();
			if (stream == null || !stream.CanRead)
			{
				throw new MultipartStreamRequiredException("File is split into multiple archives: '" + Entry.Key + "'. A new readable stream is required.  Use Cancel if it was intended.");
			}
			entriesForCurrentReadStream = GetEntries(stream).GetEnumerator();
			return entriesForCurrentReadStream.MoveNext();
		}

		protected virtual Stream RequestInitialStream()
		{
			return Volume.Stream;
		}

		internal virtual bool NextEntryForCurrentStream()
		{
			return entriesForCurrentReadStream.MoveNext();
		}

		protected abstract IEnumerable<TEntry> GetEntries(Stream stream);

		private void SkipEntry()
		{
			if (!Entry.IsDirectory)
			{
				Skip();
			}
		}

		private void Skip()
		{
			if (ArchiveType != ArchiveType.Rar && !Entry.IsSolid && Entry.CompressedSize > 0)
			{
				FilePart filePart = Entry.Parts.First();
				Stream rawStream = filePart.GetRawStream();
				if (rawStream != null)
				{
					long compressedSize = Entry.CompressedSize;
					rawStream.Skip(compressedSize);
					filePart.Skipped = true;
					return;
				}
			}
			using EntryStream source = OpenEntryStream();
			source.Skip();
		}

		public void WriteEntryTo(Stream writableStream)
		{
			if (wroteCurrentEntry)
			{
				throw new ArgumentException("WriteEntryTo or OpenEntryStream can only be called once.");
			}
			if (writableStream == null || !writableStream.CanWrite)
			{
				throw new ArgumentNullException("A writable Stream was required.  Use Cancel if that was intended.");
			}
			Write(writableStream);
			wroteCurrentEntry = true;
		}

		internal void Write(Stream writeStream)
		{
			using Stream source = OpenEntryStream();
			source.TransferTo(writeStream, Entry, this);
		}

		public EntryStream OpenEntryStream()
		{
			if (wroteCurrentEntry)
			{
				throw new ArgumentException("WriteEntryTo or OpenEntryStream can only be called once.");
			}
			EntryStream entryStream = GetEntryStream();
			wroteCurrentEntry = true;
			return entryStream;
		}

		protected EntryStream CreateEntryStream(Stream decompressed)
		{
			return new EntryStream(this, decompressed);
		}

		protected virtual EntryStream GetEntryStream()
		{
			return CreateEntryStream(Entry.Parts.First().GetCompressedStream());
		}

		void IExtractionListener.FireCompressedBytesRead(long currentPartCompressedBytes, long compressedReadBytes)
		{
			this.CompressedBytesRead?.Invoke(this, new CompressedBytesReadEventArgs
			{
				CurrentFilePartCompressedBytesRead = currentPartCompressedBytes,
				CompressedBytesRead = compressedReadBytes
			});
		}

		void IExtractionListener.FireFilePartExtractionBegin(string name, long size, long compressedSize)
		{
			this.FilePartExtractionBegin?.Invoke(this, new FilePartExtractionBeginEventArgs
			{
				CompressedSize = compressedSize,
				Size = size,
				Name = name
			});
		}

		void IReaderExtractionListener.FireEntryExtractionProgress(Entry entry, long bytesTransferred, int iterations)
		{
			this.EntryExtractionProgress?.Invoke(this, new ReaderExtractionEventArgs<IEntry>(entry, new ReaderProgress(entry, bytesTransferred, iterations)));
		}
	}
	public interface IReader : IDisposable
	{
		ArchiveType ArchiveType { get; }

		IEntry Entry { get; }

		bool Cancelled { get; }

		event EventHandler<ReaderExtractionEventArgs<IEntry>> EntryExtractionProgress;

		event EventHandler<CompressedBytesReadEventArgs> CompressedBytesRead;

		event EventHandler<FilePartExtractionBeginEventArgs> FilePartExtractionBegin;

		void WriteEntryTo(Stream writableStream);

		void Cancel();

		bool MoveToNextEntry();

		EntryStream OpenEntryStream();
	}
	public static class IReaderExtensions
	{
		public static void WriteEntryTo(this IReader reader, string filePath)
		{
			using Stream writableStream = File.Open(filePath, FileMode.Create, FileAccess.Write);
			reader.WriteEntryTo(writableStream);
		}

		public static void WriteEntryTo(this IReader reader, FileInfo filePath)
		{
			using Stream writableStream = filePath.Open(FileMode.Create);
			reader.WriteEntryTo(writableStream);
		}

		public static void WriteAllToDirectory(this IReader reader, string destinationDirectory, ExtractionOptions options = null)
		{
			while (reader.MoveToNextEntry())
			{
				reader.WriteEntryToDirectory(destinationDirectory, options);
			}
		}

		public static void WriteEntryToDirectory(this IReader reader, string destinationDirectory, ExtractionOptions options = null)
		{
			ExtractionMethods.WriteEntryToDirectory(reader.Entry, destinationDirectory, options, reader.WriteEntryToFile);
		}

		public static void WriteEntryToFile(this IReader reader, string destinationFileName, ExtractionOptions options = null)
		{
			ExtractionMethods.WriteEntryToFile(reader.Entry, destinationFileName, options, delegate(string x, FileMode fm)
			{
				using FileStream writableStream = File.Open(destinationFileName, fm);
				reader.WriteEntryTo(writableStream);
			});
		}
	}
	internal interface IReaderExtractionListener : IExtractionListener
	{
		void FireEntryExtractionProgress(Entry entry, long sizeTransferred, int iterations);
	}
	public static class ReaderFactory
	{
		public static IReader Open(Stream stream, ReaderOptions options = null)
		{
			stream.CheckNotNull("stream");
			options = options ?? new ReaderOptions
			{
				LeaveStreamOpen = false
			};
			RewindableStream rewindableStream = new RewindableStream(stream);
			rewindableStream.StartRecording();
			if (ZipArchive.IsZipFile(rewindableStream, options.Password))
			{
				rewindableStream.Rewind(stopRecording: true);
				return ZipReader.Open(rewindableStream, options);
			}
			rewindableStream.Rewind(stopRecording: false);
			if (GZipArchive.IsGZipFile(rewindableStream))
			{
				rewindableStream.Rewind(stopRecording: false);
				if (TarArchive.IsTarFile(new GZipStream(rewindableStream, CompressionMode.Decompress)))
				{
					rewindableStream.Rewind(stopRecording: true);
					return new TarReader(rewindableStream, options, CompressionType.GZip);
				}
				rewindableStream.Rewind(stopRecording: true);
				return GZipReader.Open(rewindableStream, options);
			}
			rewindableStream.Rewind(stopRecording: false);
			if (BZip2Stream.IsBZip2(rewindableStream))
			{
				rewindableStream.Rewind(stopRecording: false);
				if (TarArchive.IsTarFile(new BZip2Stream(new NonDisposingStream(rewindableStream), CompressionMode.Decompress, decompressConcatenated: false)))
				{
					rewindableStream.Rewind(stopRecording: true);
					return new TarReader(rewindableStream, options, CompressionType.BZip2);
				}
			}
			rewindableStream.Rewind(stopRecording: false);
			if (LZipStream.IsLZipFile(rewindableStream))
			{
				rewindableStream.Rewind(stopRecording: false);
				if (TarArchive.IsTarFile(new LZipStream(new NonDisposingStream(rewindableStream), CompressionMode.Decompress)))
				{
					rewindableStream.Rewind(stopRecording: true);
					return new TarReader(rewindableStream, options, CompressionType.LZip);
				}
			}
			rewindableStream.Rewind(stopRecording: false);
			if (RarArchive.IsRarFile(rewindableStream, options))
			{
				rewindableStream.Rewind(stopRecording: true);
				return RarReader.Open(rewindableStream, options);
			}
			rewindableStream.Rewind(stopRecording: false);
			if (TarArchive.IsTarFile(rewindableStream))
			{
				rewindableStream.Rewind(stopRecording: true);
				return TarReader.Open(rewindableStream, options);
			}
			rewindableStream.Rewind(stopRecording: false);
			if (XZStream.IsXZStream(rewindableStream))
			{
				rewindableStream.Rewind(stopRecording: true);
				if (TarArchive.IsTarFile(new XZStream(rewindableStream)))
				{
					rewindableStream.Rewind(stopRecording: true);
					return new TarReader(rewindableStream, options, CompressionType.Xz);
				}
			}
			throw new InvalidOperationException("Cannot determine compressed stream type.  Supported Reader Formats: Zip, GZip, BZip2, Tar, Rar, LZip, XZ");
		}
	}
	public class ReaderOptions : OptionsBase
	{
		public bool LookForHeader { get; set; }

		public string Password { get; set; }
	}
	public class ReaderProgress
	{
		private readonly IEntry _entry;

		public long BytesTransferred { get; }

		public int Iterations { get; }

		public int PercentageRead => (int)Math.Round(PercentageReadExact);

		public double PercentageReadExact => (float)BytesTransferred / (float)_entry.Size * 100f;

		public ReaderProgress(IEntry entry, long bytesTransferred, int iterations)
		{
			_entry = entry;
			BytesTransferred = bytesTransferred;
			Iterations = iterations;
		}
	}
}
namespace SharpCompress.Readers.Zip
{
	public class ZipReader : AbstractReader<ZipEntry, ZipVolume>
	{
		private readonly StreamingZipHeaderFactory _headerFactory;

		public override ZipVolume Volume { get; }

		private ZipReader(Stream stream, ReaderOptions options)
			: base(options, ArchiveType.Zip)
		{
			Volume = new ZipVolume(stream, options);
			_headerFactory = new StreamingZipHeaderFactory(options.Password, options.ArchiveEncoding);
		}

		public static ZipReader Open(Stream stream, ReaderOptions options = null)
		{
			stream.CheckNotNull("stream");
			return new ZipReader(stream, options ?? new ReaderOptions());
		}

		protected override IEnumerable<ZipEntry> GetEntries(Stream stream)
		{
			foreach (ZipHeader item in _headerFactory.ReadStreamHeader(stream))
			{
				if (item != null)
				{
					switch (item.ZipHeaderType)
					{
					case ZipHeaderType.LocalEntry:
						yield return new ZipEntry(new StreamingZipFilePart(item as LocalEntryHeader, stream));
						break;
					case ZipHeaderType.DirectoryEnd:
						yield break;
					}
				}
			}
		}
	}
}
namespace SharpCompress.Readers.Tar
{
	public class TarReader : AbstractReader<TarEntry, TarVolume>
	{
		private readonly CompressionType compressionType;

		public override TarVolume Volume { get; }

		internal TarReader(Stream stream, ReaderOptions options, CompressionType compressionType)
			: base(options, ArchiveType.Tar)
		{
			this.compressionType = compressionType;
			Volume = new TarVolume(stream, options);
		}

		protected override Stream RequestInitialStream()
		{
			Stream stream = base.RequestInitialStream();
			return compressionType switch
			{
				CompressionType.BZip2 => new BZip2Stream(stream, CompressionMode.Decompress, decompressConcatenated: false), 
				CompressionType.GZip => new GZipStream(stream, CompressionMode.Decompress), 
				CompressionType.LZip => new LZipStream(stream, CompressionMode.Decompress), 
				CompressionType.Xz => new XZStream(stream), 
				CompressionType.None => stream, 
				_ => throw new NotSupportedException("Invalid compression type: " + compressionType), 
			};
		}

		public static TarReader Open(Stream stream, ReaderOptions options = null)
		{
			stream.CheckNotNull("stream");
			options = options ?? new ReaderOptions();
			RewindableStream rewindableStream = new RewindableStream(stream);
			rewindableStream.StartRecording();
			if (GZipArchive.IsGZipFile(rewindableStream))
			{
				rewindableStream.Rewind(stopRecording: false);
				if (TarArchive.IsTarFile(new GZipStream(rewindableStream, CompressionMode.Decompress)))
				{
					rewindableStream.Rewind(stopRecording: true);
					return new TarReader(rewindableStream, options, CompressionType.GZip);
				}
				throw new InvalidFormatException("Not a tar file.");
			}
			rewindableStream.Rewind(stopRecording: false);
			if (BZip2Stream.IsBZip2(rewindableStream))
			{
				rewindableStream.Rewind(stopRecording: false);
				if (TarArchive.IsTarFile(new BZip2Stream(rewindableStream, CompressionMode.Decompress, decompressConcatenated: false)))
				{
					rewindableStream.Rewind(stopRecording: true);
					return new TarReader(rewindableStream, options, CompressionType.BZip2);
				}
				throw new InvalidFormatException("Not a tar file.");
			}
			rewindableStream.Rewind(stopRecording: false);
			if (LZipStream.IsLZipFile(rewindableStream))
			{
				rewindableStream.Rewind(stopRecording: false);
				if (TarArchive.IsTarFile(new LZipStream(rewindableStream, CompressionMode.Decompress)))
				{
					rewindableStream.Rewind(stopRecording: true);
					return new TarReader(rewindableStream, options, CompressionType.LZip);
				}
				throw new InvalidFormatException("Not a tar file.");
			}
			rewindableStream.Rewind(stopRecording: true);
			return new TarReader(rewindableStream, options, CompressionType.None);
		}

		protected override IEnumerable<TarEntry> GetEntries(Stream stream)
		{
			return TarEntry.GetEntries(StreamingMode.Streaming, stream, compressionType, base.Options.ArchiveEncoding);
		}
	}
}
namespace SharpCompress.Readers.Rar
{
	internal class MultiVolumeRarReader : RarReader
	{
		private class MultiVolumeStreamEnumerator : IEnumerable<FilePart>, IEnumerable, IEnumerator<FilePart>, IDisposable, IEnumerator
		{
			private readonly MultiVolumeRarReader reader;

			private readonly IEnumerator<Stream> nextReadableStreams;

			private Stream tempStream;

			private bool isFirst = true;

			public FilePart Current { get; private set; }

			object IEnumerator.Current => Current;

			internal MultiVolumeStreamEnumerator(MultiVolumeRarReader r, IEnumerator<Stream> nextReadableStreams, Stream tempStream)
			{
				reader = r;
				this.nextReadableStreams = nextReadableStreams;
				this.tempStream = tempStream;
			}

			public IEnumerator<FilePart> GetEnumerator()
			{
				return this;
			}

			IEnumerator IEnumerable.GetEnumerator()
			{
				return this;
			}

			public void Dispose()
			{
			}

			public bool MoveNext()
			{
				if (isFirst)
				{
					Current = reader.Entry.Parts.First();
					isFirst = false;
					return true;
				}
				if (!reader.Entry.IsSplitAfter)
				{
					return false;
				}
				if (tempStream != null)
				{
					reader.LoadStreamForReading(tempStream);
					tempStream = null;
				}
				else
				{
					if (!nextReadableStreams.MoveNext())
					{
						throw new MultiVolumeExtractionException("No stream provided when requested by MultiVolumeRarReader");
					}
					reader.LoadStreamForReading(nextReadableStreams.Current);
				}
				Current = reader.Entry.Parts.First();
				return true;
			}

			public void Reset()
			{
			}
		}

		private readonly IEnumerator<Stream> streams;

		private Stream tempStream;

		internal MultiVolumeRarReader(IEnumerable<Stream> streams, ReaderOptions options)
			: base(options)
		{
			this.streams = streams.GetEnumerator();
		}

		internal override void ValidateArchive(RarVolume archive)
		{
		}

		protected override Stream RequestInitialStream()
		{
			if (streams.MoveNext())
			{
				return streams.Current;
			}
			throw new MultiVolumeExtractionException("No stream provided when requested by MultiVolumeRarReader");
		}

		internal override bool NextEntryForCurrentStream()
		{
			if (!base.NextEntryForCurrentStream())
			{
				if (streams.MoveNext())
				{
					return LoadStreamForReading(streams.Current);
				}
				return false;
			}
			return true;
		}

		protected override IEnumerable<FilePart> CreateFilePartEnumerableForCurrentEntry()
		{
			MultiVolumeStreamEnumerator result = new MultiVolumeStreamEnumerator(this, streams, tempStream);
			tempStream = null;
			return result;
		}
	}
	internal class NonSeekableStreamFilePart : RarFilePart
	{
		internal override string FilePartName => "Unknown Stream - File Entry: " + base.FileHeader.FileName;

		internal NonSeekableStreamFilePart(MarkHeader mh, FileHeader fh)
			: base(mh, fh)
		{
		}

		internal override Stream GetCompressedStream()
		{
			return base.FileHeader.PackedStream;
		}
	}
	public abstract class RarReader : AbstractReader<RarReaderEntry, RarVolume>
	{
		private RarVolume volume;

		internal Lazy<IRarUnpack> UnpackV2017 { get; } = new Lazy<IRarUnpack>(() => new SharpCompress.Compressors.Rar.UnpackV2017.Unpack());

		internal Lazy<IRarUnpack> UnpackV1 { get; } = new Lazy<IRarUnpack>(() => new SharpCompress.Compressors.Rar.UnpackV1.Unpack());

		public override RarVolume Volume => volume;

		internal RarReader(ReaderOptions options)
			: base(options, ArchiveType.Rar)
		{
		}

		internal abstract void ValidateArchive(RarVolume archive);

		public static RarReader Open(Stream stream, ReaderOptions options = null)
		{
			stream.CheckNotNull("stream");
			return new SingleVolumeRarReader(stream, options ?? new ReaderOptions());
		}

		public static RarReader Open(IEnumerable<Stream> streams, ReaderOptions options = null)
		{
			streams.CheckNotNull("streams");
			return new MultiVolumeRarReader(streams, options ?? new ReaderOptions());
		}

		protected override IEnumerable<RarReaderEntry> GetEntries(Stream stream)
		{
			volume = new RarReaderVolume(stream, base.Options);
			foreach (RarFilePart item in volume.ReadFileParts())
			{
				ValidateArchive(volume);
				yield return new RarReaderEntry(volume.IsSolidArchive, item);
			}
		}

		protected virtual IEnumerable<FilePart> CreateFilePartEnumerableForCurrentEntry()
		{
			return base.Entry.Parts;
		}

		protected override EntryStream GetEntryStream()
		{
			MultiVolumeReadOnlyStream readStream = new MultiVolumeReadOnlyStream(CreateFilePartEnumerableForCurrentEntry().Cast<RarFilePart>(), this);
			if (base.Entry.IsRarV3)
			{
				return CreateEntryStream(new RarCrcStream(UnpackV1.Value, base.Entry.FileHeader, readStream));
			}
			return CreateEntryStream(new RarCrcStream(UnpackV2017.Value, base.Entry.FileHeader, readStream));
		}
	}
	public class RarReaderEntry : RarEntry
	{
		internal RarFilePart Part { get; }

		internal override IEnumerable<FilePart> Parts => ((FilePart)Part).AsEnumerable();

		internal override FileHeader FileHeader => Part.FileHeader;

		public override CompressionType CompressionType => CompressionType.Rar;

		public override long CompressedSize => Part.FileHeader.CompressedSize;

		public override long Size => Part.FileHeader.UncompressedSize;

		internal RarReaderEntry(bool solid, RarFilePart part)
		{
			Part = part;
			base.IsSolid = solid;
		}
	}
	public class RarReaderVolume : RarVolume
	{
		internal RarReaderVolume(Stream stream, ReaderOptions options)
			: base(StreamingMode.Streaming, stream, options)
		{
		}

		internal override RarFilePart CreateFilePart(MarkHeader markHeader, FileHeader fileHeader)
		{
			return new NonSeekableStreamFilePart(markHeader, fileHeader);
		}

		internal override IEnumerable<RarFilePart> ReadFileParts()
		{
			return GetVolumeFileParts();
		}
	}
	internal class SingleVolumeRarReader : RarReader
	{
		private readonly Stream stream;

		internal SingleVolumeRarReader(Stream stream, ReaderOptions options)
			: base(options)
		{
			this.stream = stream;
		}

		internal override void ValidateArchive(RarVolume archive)
		{
			if (archive.IsMultiVolume)
			{
				throw new MultiVolumeExtractionException("Streamed archive is a Multi-volume archive.  Use different RarReader method to extract.");
			}
		}

		protected override Stream RequestInitialStream()
		{
			return stream;
		}
	}
}
namespace SharpCompress.Readers.GZip
{
	public class GZipReader : AbstractReader<GZipEntry, GZipVolume>
	{
		public override GZipVolume Volume { get; }

		internal GZipReader(Stream stream, ReaderOptions options)
			: base(options, ArchiveType.GZip)
		{
			Volume = new GZipVolume(stream, options);
		}

		public static GZipReader Open(Stream stream, ReaderOptions options = null)
		{
			stream.CheckNotNull("stream");
			return new GZipReader(stream, options ?? new ReaderOptions());
		}

		protected override IEnumerable<GZipEntry> GetEntries(Stream stream)
		{
			return GZipEntry.GetEntries(stream, base.Options);
		}
	}
}
namespace SharpCompress.IO
{
	internal class BufferedSubStream : NonDisposingStream
	{
		private long position;

		private int cacheOffset;

		private int cacheLength;

		private readonly byte[] cache;

		private long BytesLeftToRead { get; set; }

		public override bool CanRead => true;

		public override bool CanSeek => false;

		public override bool CanWrite => false;

		public override long Length => BytesLeftToRead;

		public override long Position
		{
			get
			{
				throw new NotSupportedException();
			}
			set
			{
				throw new NotSupportedException();
			}
		}

		public BufferedSubStream(Stream stream, long origin, long bytesToRead)
			: base(stream)
		{
			position = origin;
			BytesLeftToRead = bytesToRead;
			cache = new byte[32768];
		}

		public override void Flush()
		{
			throw new NotSupportedException();
		}

		public override int Read(byte[] buffer, int offset, int count)
		{
			if (count > BytesLeftToRead)
			{
				count = (int)BytesLeftToRead;
			}
			if (count > 0)
			{
				if (cacheLength == 0)
				{
					cacheOffset = 0;
					base.Stream.Position = position;
					cacheLength = base.Stream.Read(cache, 0, cache.Length);
					position += cacheLength;
				}
				if (count > cacheLength)
				{
					count = cacheLength;
				}
				Buffer.BlockCopy(cache, cacheOffset, buffer, offset, count);
				cacheOffset += count;
				cacheLength -= count;
				BytesLeftToRead -= count;
			}
			return count;
		}

		public override long Seek(long offset, SeekOrigin origin)
		{
			throw new NotSupportedException();
		}

		public override void SetLength(long value)
		{
			throw new NotSupportedException();
		}

		public override void Write(byte[] buffer, int offset, int count)
		{
			throw new NotSupportedException();
		}
	}
	internal class CountingWritableSubStream : NonDisposingStream
	{
		public ulong Count { get; private set; }

		public override bool CanRead => false;

		public override bool CanSeek => false;

		public override bool CanWrite => true;

		public override long Length
		{
			get
			{
				throw new NotSupportedException();
			}
		}

		public override long Position
		{
			get
			{
				throw new NotSupportedException();
			}
			set
			{
				throw new NotSupportedException();
			}
		}

		internal CountingWritableSubStream(Stream stream)
			: base(stream)
		{
		}

		public override void Flush()
		{
			base.Stream.Flush();
		}

		public override int Read(byte[] buffer, int offset, int count)
		{
			throw new NotSupportedException();
		}

		public override long Seek(long offset, SeekOrigin origin)
		{
			throw new NotSupportedException();
		}

		public override void SetLength(long value)
		{
			throw new NotSupportedException();
		}

		public override void Write(byte[] buffer, int offset, int count)
		{
			base.Stream.Write(buffer, offset, count);
			Count += (uint)count;
		}

		public override void WriteByte(byte value)
		{
			base.Stream.WriteByte(value);
			ulong count = Count + 1;
			Count = count;
		}
	}
	internal class ListeningStream : Stream
	{
		private long currentEntryTotalReadBytes;

		private readonly IExtractionListener listener;

		public Stream Stream { get; }

		public override bool CanRead => Stream.CanRead;

		public override bool CanSeek => Stream.CanSeek;

		public override bool CanWrite => Stream.CanWrite;

		public override long Length => Stream.Length;

		public override long Position
		{
			get
			{
				return Stream.Position;
			}
			set
			{
				Stream.Position = value;
			}
		}

		public ListeningStream(IExtractionListener listener, Stream stream)
		{
			Stream = stream;
			this.listener = listener;
		}

		protected override void Dispose(bool disposing)
		{
			if (disposing)
			{
				Stream.Dispose();
			}
			base.Dispose(disposing);
		}

		public override void Flush()
		{
			Stream.Flush();
		}

		public override int Read(byte[] buffer, int offset, int count)
		{
			int num = Stream.Read(buffer, offset, count);
			currentEntryTotalReadBytes += num;
			listener.FireCompressedBytesRead(currentEntryTotalReadBytes, currentEntryTotalReadBytes);
			return num;
		}

		public override int ReadByte()
		{
			int num = Stream.ReadByte();
			if (num == -1)
			{
				return -1;
			}
			currentEntryTotalReadBytes++;
			listener.FireCompressedBytesRead(currentEntryTotalReadBytes, currentEntryTotalReadBytes);
			return num;
		}

		public override long Seek(long offset, SeekOrigin origin)
		{
			return Stream.Seek(offset, origin);
		}

		public override void SetLength(long value)
		{
			Stream.SetLength(value);
		}

		public override void Write(byte[] buffer, int offset, int count)
		{
			Stream.Write(buffer, offset, count);
		}
	}
	internal class MarkingBinaryReader : BinaryReader
	{
		public virtual long CurrentReadByteCount { get; protected set; }

		public MarkingBinaryReader(Stream stream)
			: base(stream)
		{
		}

		public virtual void Mark()
		{
			CurrentReadByteCount = 0L;
		}

		public override int Read()
		{
			throw new NotSupportedException();
		}

		public override int Read(byte[] buffer, int index, int count)
		{
			throw new NotSupportedException();
		}

		public override int Read(char[] buffer, int index, int count)
		{
			throw new NotSupportedException();
		}

		public override bool ReadBoolean()
		{
			return ReadByte() != 0;
		}

		public override byte ReadByte()
		{
			CurrentReadByteCount++;
			return base.ReadByte();
		}

		public override byte[] ReadBytes(int count)
		{
			CurrentReadByteCount += count;
			byte[] array = base.ReadBytes(count);
			if (array.Length != count)
			{
				throw new EndOfStreamException($"Could not read the requested amount of bytes.  End of stream reached. Requested: {count} Read: {array.Length}");
			}
			return array;
		}

		public override char ReadChar()
		{
			throw new NotSupportedException();
		}

		public override char[] ReadChars(int count)
		{
			throw new NotSupportedException();
		}

		public override decimal ReadDecimal()
		{
			throw new NotSupportedException();
		}

		public override double ReadDouble()
		{
			throw new NotSupportedException();
		}

		public override short ReadInt16()
		{
			return DataConverter.LittleEndian.GetInt16(ReadBytes(2), 0);
		}

		public override int ReadInt32()
		{
			return DataConverter.LittleEndian.GetInt32(ReadBytes(4), 0);
		}

		public override long ReadInt64()
		{
			return DataConverter.LittleEndian.GetInt64(ReadBytes(8), 0);
		}

		public override sbyte ReadSByte()
		{
			return (sbyte)ReadByte();
		}

		public override float ReadSingle()
		{
			throw new NotSupportedException();
		}

		public override string ReadString()
		{
			throw new NotSupportedException();
		}

		public override ushort ReadUInt16()
		{
			return DataConverter.LittleEndian.GetUInt16(ReadBytes(2), 0);
		}

		public override uint ReadUInt32()
		{
			return DataConverter.LittleEndian.GetUInt32(ReadBytes(4), 0);
		}

		public override ulong ReadUInt64()
		{
			return DataConverter.LittleEndian.GetUInt64(ReadBytes(8), 0);
		}

		public ulong ReadRarVInt(int maxBytes = 10)
		{
			return DoReadRarVInt((maxBytes - 1) * 7);
		}

		private ulong DoReadRarVInt(int maxShift)
		{
			int num = 0;
			ulong num2 = 0uL;
			do
			{
				byte b = ReadByte();
				uint num3 = (uint)(b & 0x7F);
				long num4 = num3;
				ulong num5 = (ulong)(num4 << num);
				if (num4 != (long)(num5 >> num))
				{
					break;
				}
				num2 |= num5;
				if (b == num3)
				{
					return num2;
				}
				num += 7;
			}
			while (num <= maxShift);
			throw new FormatException("malformed vint");
		}

		public uint ReadRarVIntUInt32(int maxBytes = 5)
		{
			return DoReadRarVIntUInt32((maxBytes - 1) * 7);
		}

		public ushort ReadRarVIntUInt16(int maxBytes = 3)
		{
			return checked((ushort)DoReadRarVIntUInt32((maxBytes - 1) * 7));
		}

		public byte ReadRarVIntByte(int maxBytes = 2)
		{
			return checked((byte)DoReadRarVIntUInt32((maxBytes - 1) * 7));
		}

		private uint DoReadRarVIntUInt32(int maxShift)
		{
			int num = 0;
			uint num2 = 0u;
			do
			{
				byte b = ReadByte();
				uint num3 = (uint)(b & 0x7F);
				uint num4 = num3 << num;
				if (num3 != num4 >> num)
				{
					break;
				}
				num2 |= num4;
				if (b == num3)
				{
					return num2;
				}
				num += 7;
			}
			while (num <= maxShift);
			throw new FormatException("malformed vint");
		}
	}
	public class NonDisposingStream : Stream
	{
		public bool ThrowOnDispose { get; set; }

		protected Stream Stream { get; }

		public override bool CanRead => Stream.CanRead;

		public override bool CanSeek => Stream.CanSeek;

		public override bool CanWrite => Stream.CanWrite;

		public override long Length => Stream.Length;

		public override long Position
		{
			get
			{
				return Stream.Position;
			}
			set
			{
				Stream.Position = value;
			}
		}

		public NonDisposingStream(Stream stream, bool throwOnDispose = false)
		{
			Stream = stream;
			ThrowOnDispose = throwOnDispose;
		}

		protected override void Dispose(bool disposing)
		{
			if (ThrowOnDispose)
			{
				throw new InvalidOperationException(string.Format("Attempt to dispose of a {0} when {1} is {2}", "NonDisposingStream", "ThrowOnDispose", ThrowOnDispose));
			}
		}

		public override void Flush()
		{
			Stream.Flush();
		}

		public override int Read(byte[] buffer, int offset, int count)
		{
			return Stream.Read(buffer, offset, count);
		}

		public override long Seek(long offset, SeekOrigin origin)
		{
			return Stream.Seek(offset, origin);
		}

		public override void SetLength(long value)
		{
			Stream.SetLength(value);
		}

		public override void Write(byte[] buffer, int offset, int count)
		{
			Stream.Write(buffer, offset, count);
		}
	}
	internal class ReadOnlySubStream : NonDisposingStream
	{
		private long BytesLeftToRead { get; set; }

		public override bool CanRead => true;

		public override bool CanSeek => false;

		public override bool CanWrite => false;

		public override long Length
		{
			get
			{
				throw new NotSupportedException();
			}
		}

		public override long Position
		{
			get
			{
				throw new NotSupportedException();
			}
			set
			{
				throw new NotSupportedException();
			}
		}

		public ReadOnlySubStream(Stream stream, long bytesToRead)
			: this(stream, null, bytesToRead)
		{
		}

		public ReadOnlySubStream(Stream stream, long? origin, long bytesToRead)
			: base(stream)
		{
			if (origin.HasValue)
			{
				stream.Position = origin.Value;
			}
			BytesLeftToRead = bytesToRead;
		}

		public override void Flush()
		{
			throw new NotSupportedException();
		}

		public override int Read(byte[] buffer, int offset, int count)
		{
			if (BytesLeftToRead < count)
			{
				count = (int)BytesLeftToRead;
			}
			int num = base.Stream.Read(buffer, offset, count);
			if (num > 0)
			{
				BytesLeftToRead -= num;
			}
			return num;
		}

		public override int ReadByte()
		{
			if (BytesLeftToRead <= 0)
			{
				return -1;
			}
			int num = base.Stream.ReadByte();
			if (num != -1)
			{
				long bytesLeftToRead = BytesLeftToRead - 1;
				BytesLeftToRead = bytesLeftToRead;
			}
			return num;
		}

		public override long Seek(long offset, SeekOrigin origin)
		{
			throw new NotSupportedException();
		}

		public override void SetLength(long value)
		{
			throw new NotSupportedException();
		}

		public override void Write(byte[] buffer, int offset, int count)
		{
			throw new NotSupportedException();
		}
	}
	internal class RewindableStream : Stream
	{
		private readonly Stream stream;

		private MemoryStream bufferStream = new MemoryStream();

		private bool isRewound;

		private bool isDisposed;

		internal bool IsRecording { get; private set; }

		public override bool CanRead => true;

		public override bool CanSeek => stream.CanSeek;

		public override bool CanWrite => false;

		public override long Length
		{
			get
			{
				throw new NotSupportedException();
			}
		}

		public override long Position
		{
			get
			{
				return stream.Position + bufferStream.Position - bufferStream.Length;
			}
			set
			{
				if (!isRewound)
				{
					stream.Position = value;
				}
				else if (value < stream.Position - bufferStream.Length || value >= stream.Position)
				{
					stream.Position = value;
					isRewound = false;
					bufferStream.SetLength(0L);
				}
				else
				{
					bufferStream.Position = value - stream.Position + bufferStream.Length;
				}
			}
		}

		public RewindableStream(Stream stream)
		{
			this.stream = stream;
		}

		protected override void Dispose(bool disposing)
		{
			if (!isDisposed)
			{
				isDisposed = true;
				base.Dispose(disposing);
				if (disposing)
				{
					stream.Dispose();
				}
			}
		}

		public void Rewind(bool stopRecording)
		{
			isRewound = true;
			IsRecording = !stopRecording;
			bufferStream.Position = 0L;
		}

		public void Rewind(MemoryStream buffer)
		{
			if (bufferStream.Position >= buffer.Length)
			{
				bufferStream.Position -= buffer.Length;
			}
			else
			{
				bufferStream.TransferTo(buffer);
				bufferStream = new MemoryStream();
				buffer.Position = 0L;
				buffer.TransferTo(bufferStream);
				bufferStream.Position = 0L;
			}
			isRewound = true;
		}

		public void StartRecording()
		{
			if (bufferStream.Position != 0L)
			{
				byte[] array = bufferStream.ToArray();
				long position = bufferStream.Position;
				bufferStream.SetLength(0L);
				bufferStream.Write(array, (int)position, array.Length - (int)position);
				bufferStream.Position = 0L;
			}
			IsRecording = true;
		}

		public override void Flush()
		{
			throw new NotSupportedException();
		}

		public override int Read(byte[] buffer, int offset, int count)
		{
			if (count == 0)
			{
				return 0;
			}
			int num;
			if (isRewound && bufferStream.Position != bufferStream.Length)
			{
				num = bufferStream.Read(buffer, offset, count);
				if (num < count)
				{
					int num2 = stream.Read(buffer, offset + num, count - num);
					if (IsRecording)
					{
						bufferStream.Write(buffer, offset + num, num2);
					}
					num += num2;
				}
				if (bufferStream.Position == bufferStream.Length && !IsRecording)
				{
					isRewound = false;
					bufferStream.SetLength(0L);
				}
				return num;
			}
			num = stream.Read(buffer, offset, count);
			if (IsRecording)
			{
				bufferStream.Write(buffer, offset, num);
			}
			return num;
		}

		public override long Seek(long offset, SeekOrigin origin)
		{
			throw new NotSupportedException();
		}

		public override void SetLength(long value)
		{
			throw new NotSupportedException();
		}

		public override void Write(byte[] buffer, int offset, int count)
		{
			throw new NotSupportedException();
		}
	}
	internal enum StreamingMode
	{
		Streaming,
		Seekable
	}
}
namespace SharpCompress.Crypto
{
	internal sealed class Crc32Stream : Stream
	{
		public const uint DefaultPolynomial = 3988292384u;

		public const uint DefaultSeed = uint.MaxValue;

		private static uint[] defaultTable;

		private readonly uint[] table;

		private uint hash;

		private readonly Stream stream;

		public Stream WrappedStream => stream;

		public override bool CanRead => stream.CanRead;

		public override bool CanSeek => false;

		public override bool CanWrite => stream.CanWrite;

		public override long Length
		{
			get
			{
				throw new NotSupportedException();
			}
		}

		public override long Position
		{
			get
			{
				throw new NotSupportedException();
			}
			set
			{
				throw new NotSupportedException();
			}
		}

		public uint Crc => ~hash;

		public Crc32Stream(Stream stream)
			: this(stream, 3988292384u, uint.MaxValue)
		{
		}

		public Crc32Stream(Stream stream, uint polynomial, uint seed)
		{
			this.stream = stream;
			table = InitializeTable(polynomial);
			hash = seed;
		}

		public override void Flush()
		{
			stream.Flush();
		}

		public override int Read(byte[] buffer, int offset, int count)
		{
			throw new NotSupportedException();
		}

		public override long Seek(long offset, SeekOrigin origin)
		{
			throw new NotSupportedException();
		}

		public override void SetLength(long value)
		{
			throw new NotSupportedException();
		}

		public override void Write(byte[] buffer, int offset, int count)
		{
			stream.Write(buffer, offset, count);
			hash = CalculateCrc(table, hash, buffer, offset, count);
		}

		public override void WriteByte(byte value)
		{
			stream.WriteByte(value);
			hash = CalculateCrc(table, hash, value);
		}

		public static uint Compute(byte[] buffer)
		{
			return Compute(uint.MaxValue, buffer);
		}

		public static uint Compute(uint seed, byte[] buffer)
		{
			return Compute(3988292384u, seed, buffer);
		}

		public static uint Compute(uint polynomial, uint seed, byte[] buffer)
		{
			return ~CalculateCrc(InitializeTable(polynomial), seed, buffer, 0, buffer.Length);
		}

		private static uint[] InitializeTable(uint polynomial)
		{
			if (polynomial == 3988292384u && defaultTable != null)
			{
				return defaultTable;
			}
			uint[] array = new uint[256];
			for (int i = 0; i < 256; i++)
			{
				uint num = (uint)i;
				for (int j = 0; j < 8; j++)
				{
					num = (((num & 1) != 1) ? (num >> 1) : ((num >> 1) ^ polynomial));
				}
				array[i] = num;
			}
			if (polynomial == 3988292384u)
			{
				defaultTable = array;
			}
			return array;
		}

		private static uint CalculateCrc(uint[] table, uint crc, byte[] buffer, int offset, int count)
		{
			int i = offset;
			for (int num = offset + count; i < num; i++)
			{
				crc = CalculateCrc(table, crc, buffer[i]);
			}
			return crc;
		}

		private static uint CalculateCrc(uint[] table, uint crc, byte b)
		{
			return (crc >> 8) ^ table[(crc ^ b) & 0xFF];
		}
	}
	public class CryptoException : Exception
	{
		public CryptoException()
		{
		}

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

		public CryptoException(string message, Exception exception)
			: base(message, exception)
		{
		}
	}
	public class DataLengthException : CryptoException
	{
		public DataLengthException()
		{
		}

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

		public DataLengthException(string message, Exception exception)
			: base(message, exception)
		{
		}
	}
	public interface IBlockCipher
	{
		string AlgorithmName { get; }

		bool IsPartialBlockOkay { get; }

		void Init(bool forEncryption, ICipherParameters parameters);

		int GetBlockSize();

		int ProcessBlock(byte[] inBuf, int inOff, byte[] outBuf, int outOff);

		void Reset();
	}
	public interface ICipherParameters
	{
	}
	public class KeyParameter : ICipherParameters
	{
		private readonly byte[] key;

		public KeyParameter(byte[] key)
		{
			if (key == null)
			{
				throw new ArgumentNullException("key");
			}
			this.key = (byte[])key.Clone();
		}

		public KeyParameter(byte[] key, int keyOff, int keyLen)
		{
			if (key == null)
			{
				throw new ArgumentNullException("key");
			}
			if (keyOff < 0 || keyOff > key.Length)
			{
				throw new ArgumentOutOfRangeException("keyOff");
			}
			if (keyLen < 0 || keyOff + keyLen > key.Length)
			{
				throw new ArgumentOutOfRangeException("keyLen");
			}
			this.key = new byte[keyLen];
			Array.Copy(key, keyOff, this.key, 0, keyLen);
		}

		public byte[] GetKey()
		{
			return (byte[])key.Clone();
		}
	}
	public class RijndaelEngine : IBlockCipher
	{
		private static readonly int MAXROUNDS = 14;

		private static readonly int MAXKC = 64;

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

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

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

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

		private static readonly byte[] rcon = new byte[30]
		{
			1, 2, 4, 8, 16, 32, 64, 128, 27, 54,
			108, 216, 171, 77, 154, 47, 94, 188, 99, 198,
			151, 53, 106, 212, 179, 125, 250, 239, 197, 145
		};

		private static readonly byte[][] shifts0 = new byte[5][]
		{
			new byte[4] { 0, 8, 16, 24 },
			new byte[4] { 0, 8, 16, 24 },
			new byte[4] { 0, 8, 16, 24 },
			new byte[4] { 0, 8, 16, 32 },
			new byte[4] { 0, 8, 24, 32 }
		};

		private static readonly byte[][] shifts1 = new byte[5][]
		{
			new byte[4] { 0, 24, 16, 8 },
			new byte[4] { 0, 32, 24, 16 },
			new byte[4] { 0, 40, 32, 24 },
			new byte[4] { 0, 48, 40, 24 },
			new byte[4] { 0, 56, 40, 32 }
		};

		private readonly int BC;

		private readonly long BC_MASK;

		private int ROUNDS;

		private readonly int blockBits;

		private long[][] workingKey;

		private long A0;

		private long A1;

		private long A2;

		private long A3;

		private bool forEncryption;

		private readonly byte[] shifts0SC;

		private readonly byte[] shifts1SC;

		public string AlgorithmName => "Rijndael";

		public bool IsPartialBlockOkay => false;

		private byte Mul0x2(int b)
		{
			if (b != 0)
			{
				return Alogtable[25 + (Logtable[b] & 0xFF)];
			}
			return 0;
		}

		private byte Mul0x3(int b)
		{
			if (b != 0)
			{
				return Alogtable[1 + (Logtable[b] & 0xFF)];
			}
			return 0;
		}

		private byte Mul0x9(int b)
		{
			if (b >= 0)
			{
				return Alogtable[199 + b];
			}
			return 0;
		}

		private byte Mul0xb(int b)
		{
			if (b >= 0)
			{
				return Alogtable[104 + b];
			}
			return 0;
		}

		private byte Mul0xd(int b)
		{
			if (b >= 0)
			{
				return Alogtable[238 + b];
			}
			return 0;
		}

		private byte Mul0xe(int b)
		{
			if (b >= 0)
			{
				return Alogtable[223 + b];
			}
			return 0;
		}

		private void KeyAddition(long[] rk)
		{
			A0 ^= rk[0];
			A1 ^= rk[1];
			A2 ^= rk[2];
			A3 ^= rk[3];
		}

		private long Shift(long r, int shift)
		{
			ulong num = (ulong)r >> shift;
			if (shift > 31)
			{
				num &= 0xFFFFFFFFu;
			}
			return (long)(num | (ulong)(r << BC - shift)) & BC_MASK;
		}

		private void ShiftRow(byte[] shiftsSC)
		{
			A1 = Shift(A1, shiftsSC[1]);
			A2 = Shift(A2, shiftsSC[2]);
			A3 = Shift(A3, shiftsSC[3]);
		}

		private long ApplyS(long r, byte[] box)
		{
			long num = 0L;
			for (int i = 0; i < BC; i += 8)
			{
				num |= (long)(box[(int)((r >> i) & 0xFF)] & 0xFF) << i;
			}
			return num;
		}

		private void Substitution(byte[] box)
		{
			A0 = ApplyS(A0, box);
			A1 = ApplyS(A1, box);
			A2 = ApplyS(A2, box);
			A3 = ApplyS(A3, box);
		}

		private void MixColumn()
		{
			long num2;
			long num3;
			long num4;
			long num = (num2 = (num3 = (num4 = 0L)));
			for (int i = 0; i < BC; i += 8)
			{
				int num5 = (int)((A0 >> i) & 0xFF);
				int num6 = (int)((A1 >> i) & 0xFF);
				int num7 = (int)((A2 >> i) & 0xFF);
				int num8 = (int)((A3 >> i) & 0xFF);
				num |= (long)((Mul0x2(num5) ^ Mul0x3(num6) ^ num7 ^ num8) & 0xFF) << i;
				num2 |= (long)((Mul0x2(num6) ^ Mul0x3(num7) ^ num8 ^ num5) & 0xFF) << i;
				num3 |= (long)((Mul0x2(num7) ^ Mul0x3(num8) ^ num5 ^ num6) & 0xFF) << i;
				num4 |= (long)((Mul0x2(num8) ^ Mul0x3(num5) ^ num6 ^ num7) & 0xFF) << i;
			}
			A0 = num;
			A1 = num2;
			A2 = num3;
			A3 = num4;
		}

		private void InvMixColumn()
		{
			long num2;
			long num3;
			long num4;
			long num = (num2 = (num3 = (num4 = 0L)));
			for (int i = 0; i < BC; i += 8)
			{
				int num5 = (int)((A0 >> i) & 0xFF);
				int num6 = (int)((A1 >> i) & 0xFF);
				int num7 = (int)((A2 >> i) & 0xFF);
				int num8 = (int)((A3 >> i) & 0xFF);
				num5 = ((num5 != 0) ? (Logtable[num5 & 0xFF] & 0xFF) : (-1));
				num6 = ((num6 != 0) ? (Logtable[num6 & 0xFF] & 0xFF) : (-1));
				num7 = ((num7 != 0) ? (Logtable[num7 & 0xFF] & 0xFF) : (-1));
				num8 = ((num8 != 0) ? (Logtable[num8 & 0xFF] & 0xFF) : (-1));
				num |= (long)((Mul0xe(num5) ^ Mul0xb(num6) ^ Mul0xd(num7) ^ Mul0x9(num8)) & 0xFF) << i;
				num2 |= (long)((Mul0xe(num6) ^ Mul0xb(num7) ^ Mul0xd(num8) ^ Mul0x9(num5)) & 0xFF) << i;
				num3 |= (long)((Mul0xe(num7) ^ Mul0xb(num8) ^ Mul0xd(num5) ^ Mul0x9(num6)) & 0xFF) << i;
				num4 |= (long)((Mul0xe(num8) ^ Mul0xb(num5) ^ Mul0xd(num6) ^ Mul0x9(num7)) & 0xFF) << i;
			}
			A0 = num;
			A1 = num2;
			A2 = num3;
			A3 = num4;
		}

		private long[][] GenerateWorkingKey(byte[] key)
		{
			int num = 0;
			int num2 = key.Length * 8;
			byte[,] array = new byte[4, MAXKC];
			long[][] array2 = new long[MAXROUNDS + 1][];
			for (int i = 0; i < MAXROUNDS + 1; i++)
			{
				array2[i] = new long[4];
			}
			int num3 = num2 switch
			{
				128 => 4, 
				160 => 5, 
				192 => 6, 
				224 => 7, 
				256 => 8, 
				_ => throw new ArgumentException("Key length not 128/160/192/224/256 bits."), 
			};
			if (num2 >= blockBits)
			{
				ROUNDS = num3 + 6;
			}
			else
			{
				ROUNDS = BC / 8 + 6;
			}
			int num4 = 0;
			for (int j = 0; j < key.Length; j++)
			{
				array[j % 4, j / 4] = key[num4++];
			}
			int num5 = 0;
			int num6 = 0;
			while (num6 < num3 && num5 < (ROUNDS + 1) * (BC / 8))
			{
				for (int k = 0; k < 4; k++)
				{
					array2[num5 / (BC / 8)][k] |= (long)(array[k, num6] & 0xFF) << num5 * 8 % BC;
				}
				num6++;
				num5++;
			}
			while (num5 < (ROUNDS + 1) * (BC / 8))
			{
				for (int l = 0; l < 4; l++)
				{
					array[l, 0] ^= S[array[(l + 1) % 4, num3 - 1] & 0xFF];
				}
				array[0, 0] ^= rcon[num++];
				if (num3 <= 6)
				{
					for (int m = 1; m < num3; m++)
					{
						for (int n = 0; n < 4; n++)
						{
							array[n, m] ^= array[n, m - 1];
						}
					}
				}
				else
				{
					for (int num7 = 1; num7 < 4; num7++)
					{
						for (int num8 = 0; num8 < 4; num8++)
						{
							array[num8, num7] ^= array[num8, num7 - 1];
						}
					}
					for (int num9 = 0; num9 < 4; num9++)
					{
						array[num9, 4] ^= S[array[num9, 3] & 0xFF];
					}
					for (int num10 = 5; num10 < num3; num10++)
					{
						for (int num11 = 0; num11 < 4; num11++)
						{
							array[num11, num10] ^= array[num11, num10 - 1];
						}
					}
				}
				int num12 = 0;
				while (num12 < num3 && num5 < (ROUNDS + 1) * (BC / 8))
				{
					for (int num13 = 0; num13 < 4; num13++)
					{
						array2[num5 / (BC / 8)][num13] |= (long)(array[num13, num12] & 0xFF) << num5 * 8 % BC;
					}
					num12++;
					num5++;
				}
			}
			return array2;
		}

		public RijndaelEngine()
			: this(128)
		{
		}

		public RijndaelEngine(int blockBits)
		{
			switch (blockBits)
			{
			case 128:
				BC = 32;
				BC_MASK = 4294967295L;
				shifts0SC = shifts0[0];
				shifts1SC = shifts1[0];
				break;
			case 160:
				BC = 40;
				BC_MASK = 1099511627775L;
				shifts0SC = shifts0[1];
				shifts1SC = shifts1[1];
				break;
			case 192:
				BC = 48;
				BC_MASK = 281474976710655L;
				shifts0SC = shifts0[2];
				shifts1SC = shifts1[2];
				break;
			case 224:
				BC = 56;
				BC_MASK = 72057594037927935L;
				shifts0SC = shifts0[3];
				shifts1SC = shifts1[3];
				break;
			case 256:
				BC = 64;
				BC_MASK = -1L;
				shifts0SC = shifts0[4];
				shifts1SC = shifts1[4];
				break;
			default:
				throw new ArgumentException("unknown blocksize to Rijndael");
			}
			this.blockBits = blockBits;
		}

		public void Init(bool forEncryption, ICipherParameters parameters)
		{
			if (parameters is KeyParameter keyParameter)
			{
				workingKey = GenerateWorkingKey(keyParameter.GetKey());
				this.forEncryption = forEncryption;
				return;
			}
			throw new ArgumentException("invalid parameter passed to Rijndael init - " + parameters.GetType());
		}

		public int GetBlockSize()
		{
			return BC / 2;
		}

		public int ProcessBlock(byte[] input, int inOff, byte[] output, int outOff)
		{
			if (workingKey == null)
			{
				throw new InvalidOperationException("Rijndael engine not initialised");
			}
			if (inOff + BC / 2 > input.Length)
			{
				throw new DataLengthException("input buffer too short");
			}
			if (outOff + BC / 2 > output.Length)
			{
				throw new DataLengthException("output buffer too short");
			}
			UnPackBlock(input, inOff);
			if (forEncryption)
			{
				EncryptBlock(workingKey);
			}
			else
			{
				DecryptBlock(workingKey);
			}
			PackBlock(output, outOff);
			return BC / 2;
		}

		public void Reset()
		{
		}

		private void UnPackBlock(byte[] bytes, int off)
		{
			int num = off;
			A0 = bytes[num++] & 0xFF;
			A1 = bytes[num++] & 0xFF;
			A2 = bytes[num++] & 0xFF;
			A3 = bytes[num++] & 0xFF;
			for (int i = 8; i != BC; i += 8)
			{
				A0 |= (long)(bytes[num++] & 0xFF) << i;
				A1 |= (long)(bytes[num++] & 0xFF) << i;
				A2 |= (long)(bytes[num++] & 0xFF) << i;
				A3 |= (long)(bytes[num++] & 0xFF) << i;
			}
		}

		private void PackBlock(byte[] bytes, int off)
		{
			int num = off;
			for (int i = 0; i != BC; i += 8)
			{
				bytes[num++] = (byte)(A0 >> i);
				bytes[num++] = (byte)(A1 >> i);
				bytes[num++] = (byte)(A2 >> i);
				bytes[num++] = (byte)(A3 >> i);
			}
		}

		private void EncryptBlock(long[][] rk)
		{
			KeyAddition(rk[0]);
			for (int i = 1; i < ROUNDS; i++)
			{
				Substitution(S);
				ShiftRow(shifts0SC);
				MixColumn();
				KeyAddition(rk[i]);
			}
			Substitution(S);
			ShiftRow(shifts0SC);
			KeyAddition(rk[ROUNDS]);
		}

		private void DecryptBlock(long[][] rk)
		{
			KeyAddition(rk[ROUNDS]);
			Substitution(Si);
			ShiftRow(shifts1SC);
			for (int num = ROUNDS - 1; num > 0; num--)
			{
				KeyAddition(rk[num]);
				InvMixColumn();
				Substitution(Si);
				ShiftRow(shifts1SC);
			}
			KeyAddition(rk[0]);
		}
	}
}
namespace SharpCompress.Converters
{
	internal abstract class DataConverter
	{
		private class CopyConverter : DataConverter
		{
			public unsafe override double GetDouble(byte[] data, int index)
			{
				if (data == null)
				{
					throw new ArgumentNullException("data");
				}
				if (data.Length - index < 8)
				{
					throw new ArgumentException("index");
				}
				if (index < 0)
				{
					throw new ArgumentException("index");
				}
				double result = default(double);
				byte* ptr = (byte*)(&result);
				for (int i = 0; i < 8; i++)
				{
					ptr[i] = data[index + i];
				}
				return result;
			}

			public unsafe override ulong GetUInt64(byte[] data, int index)
			{
				if (data == null)
				{
					throw new ArgumentNullException("data");
				}
				if (data.Length - index < 8)
				{
					throw new ArgumentException("index");
				}
				if (index < 0)
				{
					throw new ArgumentException("index");
				}
				ulong result = default(ulong);
				byte* ptr = (byte*)(&result);
				for (int i = 0; i < 8; i++)
				{
					ptr[i] = data[index + i];
				}
				return result;
			}

			public unsafe override long GetInt64(byte[] data, int index)
			{
				if (data == null)
				{
					throw new ArgumentNullException("data");
				}
				if (data.Length - index < 8)
				{
					throw new ArgumentException("index");
				}
				if (index < 0)
				{
					throw new ArgumentException("index");
				}
				long result = default(long);
				byte* ptr = (byte*)(&result);
				for (int i = 0; i < 8; i++)
				{
					ptr[i] = data[index + i];
				}
				return result;
			}

			public unsafe override float GetFloat(byte[] data, int index)
			{
				if (data == null)
				{
					throw new ArgumentNullException("data");
				}
				if (data.Length - index < 4)
				{
					throw new ArgumentException("index");
				}
				if (index < 0)
				{
					throw new ArgumentException("index");
				}
				float result = default(float);
				byte* ptr = (byte*)(&result);
				for (int i =