Decompiled source of AssetHelper v1.0.2

plugins/AssetHelperLib.dll

Decompiled 19 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security.Cryptography;
using System.Text;
using AssetHelperLib.BundleTools;
using AssetHelperLib.PreloadTable;
using AssetHelperLib.Repacking;
using AssetHelperLib.Util;
using AssetsTools.NET;
using AssetsTools.NET.Extra;
using Microsoft.CodeAnalysis;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("AssetHelperLib")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Scene Asset repacking library built upon AssetsTools.NET.")]
[assembly: AssemblyFileVersion("0.10.0.0")]
[assembly: AssemblyInformationalVersion("0.10.0+1cf7c9c01a64364be35f3b4ad53d0fae43901194")]
[assembly: AssemblyProduct("AssetHelperLib")]
[assembly: AssemblyTitle("AssetHelperLib")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/flibber-hk/AssetHelperLib")]
[assembly: AssemblyVersion("0.10.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace System.Runtime.Versioning
{
	[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Module | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Interface | AttributeTargets.Delegate, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class RequiresPreviewFeaturesAttribute : Attribute
	{
		public string? Message { get; }

		public string? Url { get; set; }

		public RequiresPreviewFeaturesAttribute()
		{
		}

		public RequiresPreviewFeaturesAttribute(string? message)
		{
			Message = message;
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class CallerArgumentExpressionAttribute : Attribute
	{
		public string ParameterName { get; }

		public CallerArgumentExpressionAttribute(string parameterName)
		{
			ParameterName = parameterName;
		}
	}
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class CollectionBuilderAttribute : Attribute
	{
		public Type BuilderType { get; }

		public string MethodName { get; }

		public CollectionBuilderAttribute(Type builderType, string methodName)
		{
			BuilderType = builderType;
			MethodName = methodName;
		}
	}
	[AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class CompilerFeatureRequiredAttribute : Attribute
	{
		public const string RefStructs = "RefStructs";

		public const string RequiredMembers = "RequiredMembers";

		public string FeatureName { get; }

		public bool IsOptional { get; set; }

		public CompilerFeatureRequiredAttribute(string featureName)
		{
			FeatureName = featureName;
		}
	}
	[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class InterpolatedStringHandlerArgumentAttribute : Attribute
	{
		public string[] Arguments { get; }

		public InterpolatedStringHandlerArgumentAttribute(string argument)
		{
			Arguments = new string[1] { argument };
		}

		public InterpolatedStringHandlerArgumentAttribute(params string[] arguments)
		{
			Arguments = arguments;
		}
	}
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class InterpolatedStringHandlerAttribute : Attribute
	{
	}
	[EditorBrowsable(EditorBrowsableState.Never)]
	[ExcludeFromCodeCoverage]
	internal static class IsExternalInit
	{
	}
	[AttributeUsage(AttributeTargets.Method, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class ModuleInitializerAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class OverloadResolutionPriorityAttribute : Attribute
	{
		public int Priority { get; }

		public OverloadResolutionPriorityAttribute(int priority)
		{
			Priority = priority;
		}
	}
	[AttributeUsage(AttributeTargets.Parameter, Inherited = true, AllowMultiple = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class ParamCollectionAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class RequiredMemberAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
	[EditorBrowsable(EditorBrowsableState.Never)]
	[ExcludeFromCodeCoverage]
	internal sealed class RequiresLocationAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Module | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Event | AttributeTargets.Interface, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class SkipLocalsInitAttribute : Attribute
	{
	}
}
namespace System.Diagnostics.CodeAnalysis
{
	[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class ConstantExpectedAttribute : Attribute
	{
		public object? Min { get; set; }

		public object? Max { get; set; }
	}
	[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Module | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Interface | AttributeTargets.Delegate, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class ExperimentalAttribute : Attribute
	{
		public string DiagnosticId { get; }

		public string? UrlFormat { get; set; }

		public ExperimentalAttribute(string diagnosticId)
		{
			DiagnosticId = diagnosticId;
		}
	}
	[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)]
	[ExcludeFromCodeCoverage]
	internal sealed class MemberNotNullAttribute : Attribute
	{
		public string[] Members { get; }

		public MemberNotNullAttribute(string member)
		{
			Members = new string[1] { member };
		}

		public MemberNotNullAttribute(params string[] members)
		{
			Members = members;
		}
	}
	[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)]
	[ExcludeFromCodeCoverage]
	internal sealed class MemberNotNullWhenAttribute : Attribute
	{
		public bool ReturnValue { get; }

		public string[] Members { get; }

		public MemberNotNullWhenAttribute(bool returnValue, string member)
		{
			ReturnValue = returnValue;
			Members = new string[1] { member };
		}

		public MemberNotNullWhenAttribute(bool returnValue, params string[] members)
		{
			ReturnValue = returnValue;
			Members = members;
		}
	}
	[AttributeUsage(AttributeTargets.Constructor, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class SetsRequiredMembersAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class StringSyntaxAttribute : Attribute
	{
		public const string CompositeFormat = "CompositeFormat";

		public const string DateOnlyFormat = "DateOnlyFormat";

		public const string DateTimeFormat = "DateTimeFormat";

		public const string EnumFormat = "EnumFormat";

		public const string GuidFormat = "GuidFormat";

		public const string Json = "Json";

		public const string NumericFormat = "NumericFormat";

		public const string Regex = "Regex";

		public const string TimeOnlyFormat = "TimeOnlyFormat";

		public const string TimeSpanFormat = "TimeSpanFormat";

		public const string Uri = "Uri";

		public const string Xml = "Xml";

		public string Syntax { get; }

		public object?[] Arguments { get; }

		public StringSyntaxAttribute(string syntax)
		{
			Syntax = syntax;
			Arguments = new object[0];
		}

		public StringSyntaxAttribute(string syntax, params object?[] arguments)
		{
			Syntax = syntax;
			Arguments = arguments;
		}
	}
	[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class UnscopedRefAttribute : Attribute
	{
	}
}
namespace AssetHelperLib
{
	public static class Logging
	{
		public static event Action<string>? OnLog;

		public static event Action<string>? OnLogWarning;

		public static event Action<string>? OnLogError;

		internal static void LogInfo(string message)
		{
			Logging.OnLog?.Invoke(message);
		}

		internal static void LogWarning(string message)
		{
			Logging.OnLogWarning?.Invoke(message);
		}

		internal static void LogError(string message)
		{
			Logging.OnLogError?.Invoke(message);
		}
	}
}
namespace AssetHelperLib.Util
{
	public static class ObjPathUtil
	{
		public static bool HasPrefix(this string self, string? maybePrefix)
		{
			if (maybePrefix == null)
			{
				return false;
			}
			if (!self.StartsWith(maybePrefix))
			{
				return false;
			}
			if (self == maybePrefix)
			{
				return true;
			}
			if (self[maybePrefix.Length] == '/')
			{
				return true;
			}
			return false;
		}

		public static List<string> GetHighestNodes(this ICollection<string> objPaths)
		{
			List<string> list = new List<string>();
			string maybePrefix = null;
			foreach (string item in objPaths.OrderBy((string x) => x))
			{
				if (!item.HasPrefix(maybePrefix))
				{
					maybePrefix = item;
					list.Add(item);
				}
			}
			return list;
		}

		public static bool TryFindRelativePath(string ancestor, string descendant, out string? relativePath)
		{
			string ancestorPath;
			return TryFindAncestor(new List<string>(1) { ancestor }, descendant, out ancestorPath, out relativePath);
		}

		public static bool TryFindAncestor(List<string>? paths, string objName, [MaybeNullWhen(false)] out string ancestorPath, out string? relativePath)
		{
			foreach (string item in paths ?? Enumerable.Empty<string>())
			{
				if (objName == item)
				{
					ancestorPath = objName;
					relativePath = null;
					return true;
				}
				if (objName.HasPrefix(item))
				{
					ancestorPath = item;
					int num = 1 + item.Length;
					relativePath = objName.Substring(num, objName.Length - num);
					return true;
				}
			}
			ancestorPath = null;
			relativePath = null;
			return false;
		}

		public static bool TryGetParent(this string objName, out string parent)
		{
			int num = objName.LastIndexOf('/');
			if (num == -1)
			{
				parent = string.Empty;
				return false;
			}
			parent = objName.Substring(0, num);
			return true;
		}
	}
}
namespace AssetHelperLib.Repacking
{
	public class RepackedBundleData
	{
		public string? RepackStrategy { get; set; }

		public string? BundleName { get; set; }

		public string? CabName { get; set; }

		public Dictionary<string, string>? GameObjectAssets { get; set; }

		public List<string>? NonRepackedAssets { get; set; }
	}
	public static class RepackedBundleDataExtensions
	{
		public static bool CanLoad(this RepackedBundleData data, string objName, [MaybeNullWhen(false)] out string assetPath, out string? relativePath)
		{
			if (data.GameObjectAssets == null)
			{
				assetPath = null;
				relativePath = null;
				return false;
			}
			foreach (var (text3, ancestor) in data.GameObjectAssets)
			{
				if (ObjPathUtil.TryFindRelativePath(ancestor, objName, out relativePath))
				{
					assetPath = text3;
					return true;
				}
			}
			assetPath = null;
			relativePath = null;
			return false;
		}

		public static bool TriedToRepack(this RepackedBundleData data, string objName)
		{
			if (data.NonRepackedAssets != null && ObjPathUtil.TryFindAncestor(data.NonRepackedAssets, objName, out string relativePath, out string assetPath))
			{
				return true;
			}
			return data.CanLoad(objName, out assetPath, out relativePath);
		}
	}
	public class RepackingContext
	{
		private AssetDependencies? _assetDeps;

		public required AssetsManager SceneAssetsManager { get; init; }

		public required BundleFileInstance SceneBundleFileInstance { get; init; }

		public required AssetsFileInstance SharedAssetsFileInstance { get; init; }

		public required AssetsFileInstance MainAssetsFileInstance { get; init; }

		public required BundleUtils.SceneBundleInfo SceneBundleInfo { get; init; }

		public GameObjectLookup? GameObjLookup { get; set; }

		public AssetDependencies AssetDeps
		{
			get
			{
				if (_assetDeps == null)
				{
					_assetDeps = new AssetDependencies(SceneAssetsManager, MainAssetsFileInstance);
				}
				return _assetDeps;
			}
		}
	}
	public record RepackingParams
	{
		public required string SceneBundlePath { get; set; }

		public required List<string> ObjectNames { get; set; }

		public required string ContainerPrefix { get; set; }

		public required string OutBundlePath { get; set; }

		[CompilerGenerated]
		[SetsRequiredMembers]
		protected RepackingParams(RepackingParams original)
		{
			SceneBundlePath = original.SceneBundlePath;
			ObjectNames = original.ObjectNames;
			ContainerPrefix = original.ContainerPrefix;
			OutBundlePath = original.OutBundlePath;
		}

		public RepackingParams()
		{
		}
	}
	public abstract class SceneRepacker
	{
		protected virtual string RepackStrategy => GetType().Name;

		protected static void GetDefaultBundleNames(RepackingParams repackingParams, out string cabName, out string bundleName)
		{
			using SHA256 sHA = SHA256.Create();
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.AppendLine("AssetHelperSalt\n");
			stringBuilder.AppendLine(repackingParams.SceneBundlePath ?? string.Empty);
			foreach (string objectName in repackingParams.ObjectNames)
			{
				stringBuilder.AppendLine("\n" + objectName);
			}
			stringBuilder.AppendLine(repackingParams.OutBundlePath);
			string s = stringBuilder.ToString();
			byte[] bytes = Encoding.UTF8.GetBytes(s);
			byte[] array = sHA.ComputeHash(bytes);
			StringBuilder stringBuilder2 = new StringBuilder(64);
			byte[] array2 = array;
			foreach (byte b in array2)
			{
				stringBuilder2.Append(b.ToString("x2"));
			}
			string text = stringBuilder2.ToString();
			cabName = "CAB-" + text.Substring(0, 32);
			bundleName = text.Substring(32, 32) + ".bundle";
		}

		public RepackedBundleData Repack(RepackingParams repackingParams)
		{
			RepackedBundleData outData = new RepackedBundleData();
			Repack(repackingParams, ref outData);
			return outData;
		}

		public void Repack(RepackingParams repackingParams, ref RepackedBundleData outData)
		{
			outData.RepackStrategy = RepackStrategy;
			GetDefaultBundleNames(repackingParams, out string cabName, out string bundleName);
			RepackedBundleData repackedBundleData = outData;
			if (repackedBundleData.CabName == null)
			{
				string text2 = (repackedBundleData.CabName = cabName);
			}
			repackedBundleData = outData;
			if (repackedBundleData.BundleName == null)
			{
				string text2 = (repackedBundleData.BundleName = bundleName);
			}
			AssetsManager val = BundleUtils.CreateDefaultManager();
			using MemoryStream memoryStream = new MemoryStream(File.ReadAllBytes(repackingParams.SceneBundlePath));
			BundleFileInstance val2 = val.LoadBundleFile((Stream)memoryStream, repackingParams.SceneBundlePath, true);
			if (!val.TryFindAssetsFiles(val2, out BundleUtils.SceneBundleInfo info))
			{
				throw new NotSupportedException("Could not find assets files for " + repackingParams.SceneBundlePath);
			}
			AssetsFileInstance mainAssetsFileInstance = val.LoadAssetsFileFromBundle(val2, info.mainAfileInstIndex, false);
			AssetsFileInstance sharedAssetsFileInstance = val.LoadAssetsFileFromBundle(val2, info.sharedAssetsAfileIndex, false);
			RepackingContext ctx = new RepackingContext
			{
				SceneAssetsManager = val,
				SceneBundleFileInstance = val2,
				MainAssetsFileInstance = mainAssetsFileInstance,
				SharedAssetsFileInstance = sharedAssetsFileInstance,
				SceneBundleInfo = info
			};
			Run(ctx, repackingParams, outData);
			val.UnloadAll(false);
		}

		protected abstract void Run(RepackingContext ctx, RepackingParams repackingParams, RepackedBundleData outData);
	}
	public class StrippedSceneRepacker : SceneRepacker
	{
		private BasePreloadTableResolver _preloadResolver;

		public StrippedSceneRepacker()
			: this(new DefaultPreloadTableResolver())
		{
		}

		public StrippedSceneRepacker(BasePreloadTableResolver preloadResolver)
		{
			_preloadResolver = preloadResolver;
		}

		protected override void Run(RepackingContext ctx, RepackingParams repackingParams, RepackedBundleData outData)
		{
			List<string> highestNodes = repackingParams.ObjectNames.GetHighestNodes();
			ctx.GameObjLookup = GameObjectLookup.CreateFromFile(ctx.SceneAssetsManager, ctx.MainAssetsFileInstance);
			HashSet<long> hashSet = new HashSet<long>();
			foreach (string item2 in highestNodes)
			{
				if (ctx.GameObjLookup.TryLookupName(item2, out GameObjectLookup.GameObjectInfo info))
				{
					hashSet.Add(info.GameObjectPathId);
					hashSet.UnionWith(ctx.AssetDeps.FindBundleDeps(info.GameObjectPathId).InternalPaths);
				}
				else
				{
					Logging.LogError("Couldn't find game object " + item2);
				}
			}
			List<string> list = new List<string>();
			foreach (long item3 in hashSet)
			{
				if (ctx.GameObjLookup.TryLookupGameObject(item3, out GameObjectLookup.GameObjectInfo info2))
				{
					list.Add(info2.GameObjectName);
				}
			}
			List<string> highestNodes2 = list.GetHighestNodes();
			HashSet<string> hashSet2 = new HashSet<string>();
			List<string> list2 = new List<string>();
			foreach (string item4 in highestNodes)
			{
				if (ObjPathUtil.TryFindAncestor(highestNodes2, item4, out string ancestorPath, out string _))
				{
					hashSet2.Add(ancestorPath);
					continue;
				}
				Logging.LogWarning("Did not find " + item4 + " in bundle");
				list2.Add(item4);
			}
			outData.NonRepackedAssets = list2;
			foreach (AssetFileInfo item5 in ctx.MainAssetsFileInstance.file.AssetInfos.ToList())
			{
				if (!hashSet.Contains(item5.PathId))
				{
					ctx.MainAssetsFileInstance.file.Metadata.RemoveAssetInfo(item5);
				}
			}
			long newOneAssetPathId = 1L;
			if (hashSet.Contains(1L))
			{
				for (newOneAssetPathId = -1L; hashSet.Contains(newOneAssetPathId); newOneAssetPathId--)
				{
				}
			}
			foreach (GameObjectLookup.GameObjectInfo item6 in ctx.GameObjLookup)
			{
				if (hashSet.Contains(item6.TransformPathId) && item6.GameObjectName.TryGetParent(out string parent))
				{
					if (!ctx.GameObjLookup.TryLookupName(parent, out GameObjectLookup.GameObjectInfo info3))
					{
						Logging.LogWarning("Unexpectedly failed to find " + parent + " from " + item6.GameObjectName);
					}
					else if (!hashSet.Contains(info3.TransformPathId))
					{
						AssetFileInfo assetInfo = ctx.MainAssetsFileInstance.file.GetAssetInfo(item6.TransformPathId);
						AssetTypeValueField baseField = ctx.SceneAssetsManager.GetBaseField(ctx.MainAssetsFileInstance, assetInfo, (AssetReadFlags)0);
						baseField["m_Father.m_PathID"].AsLong = 0L;
						assetInfo.SetNewData(baseField);
					}
				}
			}
			AssetFileInfo val = ctx.SharedAssetsFileInstance.file.GetAssetsOfType((AssetClassID)142).First();
			AssetTypeValueField baseField2 = ctx.SceneAssetsManager.GetBaseField(ctx.SharedAssetsFileInstance, val, (AssetReadFlags)0);
			baseField2["m_Name"].AsString = outData.BundleName;
			baseField2["m_AssetBundleName"].AsString = outData.BundleName;
			baseField2["m_IsStreamedSceneAssetBundle"].AsBool = false;
			baseField2["m_SceneHashes.Array"].Children.Clear();
			List<AssetTypeValueField> list3 = new List<AssetTypeValueField>();
			List<AssetTypeValueField> list4 = new List<AssetTypeValueField>();
			Dictionary<string, string> dictionary = new Dictionary<string, string>();
			foreach (string item7 in hashSet2)
			{
				GameObjectLookup.GameObjectInfo gameObjectInfo = ctx.GameObjLookup.LookupName(item7);
				long gameObjectPathId = gameObjectInfo.GameObjectPathId;
				HashSet<(int, long)> tableInfos = new HashSet<(int, long)>();
				_preloadResolver.BuildPreloadTable(gameObjectPathId, ctx, ref tableInfos);
				int count = list3.Count;
				foreach (var item8 in tableInfos)
				{
					AssetTypeValueField val2 = ValueBuilder.DefaultValueFieldFromArrayTemplate(baseField2["m_PreloadTable.Array"]);
					val2["m_FileID"].AsInt = item8.Item1;
					val2["m_PathID"].AsLong = item8.Item2;
					list3.Add(val2);
				}
				int asInt = list3.Count - count;
				string text = repackingParams.ContainerPrefix + "/" + item7 + ".prefab";
				dictionary[text] = item7;
				AssetTypeValueField val3 = ValueBuilder.DefaultValueFieldFromArrayTemplate(baseField2["m_Container.Array"]);
				val3["first"].AsString = text;
				val3["second.preloadIndex"].AsInt = count;
				val3["second.preloadSize"].AsInt = asInt;
				val3["second.asset.m_FileID"].AsInt = 0;
				val3["second.asset.m_PathID"].AsLong = updatedPathId(gameObjectInfo.GameObjectPathId);
				list4.Add(val3);
			}
			baseField2["m_PreloadTable.Array"].Children.Clear();
			baseField2["m_PreloadTable.Array"].Children.AddRange(list3);
			baseField2["m_Container.Array"].Children.Clear();
			baseField2["m_Container.Array"].Children.AddRange(list4);
			outData.GameObjectAssets = dictionary;
			if (newOneAssetPathId != 1)
			{
				int num = 0;
				AssetFileInfo assetInfo2 = ctx.MainAssetsFileInstance.file.GetAssetInfo(1L);
				ctx.MainAssetsFileInstance.file.Metadata.RemoveAssetInfo(assetInfo2);
				assetInfo2.PathId = newOneAssetPathId;
				ctx.MainAssetsFileInstance.file.Metadata.AddAssetInfo(assetInfo2);
				foreach (long item9 in hashSet)
				{
					if (item9 != 1 && ctx.AssetDeps.FindImmediateDeps(item9).InternalPaths.Contains(1L))
					{
						num += ctx.SceneAssetsManager.Redirect(ctx.MainAssetsFileInstance, ctx.MainAssetsFileInstance.file.GetAssetInfo(item9), 1L, newOneAssetPathId);
					}
				}
				int num2 = ctx.SceneAssetsManager.Redirect(ctx.MainAssetsFileInstance, assetInfo2, 1L, newOneAssetPathId);
				Logging.LogInfo($"Redirected {num} references plus {num2} self-references");
			}
			if (!ctx.MainAssetsFileInstance.file.Metadata.TypeTreeTypes.Any((TypeTreeType x) => x.TypeId == 142))
			{
				TypeTreeType item = ctx.SharedAssetsFileInstance.file.Metadata.TypeTreeTypes.First((TypeTreeType x) => x.TypeId == 142);
				ctx.MainAssetsFileInstance.file.Metadata.TypeTreeTypes.Add(item);
			}
			AssetFileInfo val4 = AssetFileInfo.Create(ctx.MainAssetsFileInstance.file, (long)ctx.SceneBundleInfo.mainAfileInstIndex, 142, (ClassDatabaseFile)null, false);
			val4.SetNewData(baseField2);
			ctx.MainAssetsFileInstance.file.Metadata.AddAssetInfo(val4);
			ctx.SceneBundleFileInstance.file.BlockAndDirInfo.DirectoryInfos[ctx.SceneBundleInfo.mainAfileInstIndex].SetNewData(ctx.MainAssetsFileInstance.file);
			ctx.SceneBundleFileInstance.file.BlockAndDirInfo.DirectoryInfos[ctx.SceneBundleInfo.mainAfileInstIndex].Name = outData.CabName;
			int count2 = ctx.SceneBundleFileInstance.file.BlockAndDirInfo.DirectoryInfos.Count;
			for (int i = 0; i < count2; i++)
			{
				if (i != ctx.SceneBundleInfo.mainAfileInstIndex)
				{
					ctx.SceneBundleFileInstance.file.BlockAndDirInfo.DirectoryInfos[i].SetRemoved();
				}
			}
			ctx.SceneBundleFileInstance.file.WriteBundleToFile(repackingParams.OutBundlePath);
			long updatedPathId(long orig)
			{
				if (orig != 1)
				{
					return orig;
				}
				return newOneAssetPathId;
			}
		}
	}
}
namespace AssetHelperLib.PreloadTable
{
	public abstract class BasePreloadTableResolver
	{
		public abstract void BuildPreloadTable(long assetPathId, RepackingContext ctx, ref HashSet<(int fileId, long pathId)> tableInfos);
	}
	public sealed class DefaultPreloadTableResolver : BasePreloadTableResolver
	{
		public override void BuildPreloadTable(long assetPathId, RepackingContext ctx, ref HashSet<(int fileId, long pathId)> tableInfos)
		{
			HashSet<AssetDependencies.PPtrData> externalPaths = ctx.AssetDeps.FindBundleDeps(assetPathId).ExternalPaths;
			tableInfos.UnionWith(externalPaths.Select((AssetDependencies.PPtrData dep) => (dep.FileId, dep.PathId)));
		}
	}
	public sealed class PreloadTableResolver : BasePreloadTableResolver
	{
		private readonly List<BasePreloadTableResolver> _resolvers;

		public PreloadTableResolver(List<BasePreloadTableResolver> resolvers)
		{
			_resolvers = resolvers;
			base..ctor();
		}

		public override void BuildPreloadTable(long assetPathId, RepackingContext ctx, ref HashSet<(int fileId, long pathId)> tableInfos)
		{
			foreach (BasePreloadTableResolver resolver in _resolvers)
			{
				resolver.BuildPreloadTable(assetPathId, ctx, ref tableInfos);
			}
		}
	}
}
namespace AssetHelperLib.BundleTools
{
	public class AssetDependencies
	{
		public class Config
		{
			public bool FollowTransformParent { get; set; }
		}

		public record PPtrData(int FileId, long PathId, string TypeName);

		public record ChildPPtrs(HashSet<long> InternalPaths, HashSet<PPtrData> ExternalPaths)
		{
			public static ChildPPtrs CreateNew()
			{
				return new ChildPPtrs(new HashSet<long>(), new HashSet<PPtrData>());
			}

			public bool Add(int fileId, long pathId, string typeName)
			{
				if (pathId == 0L)
				{
					return false;
				}
				if (fileId == 0)
				{
					return InternalPaths.Add(pathId);
				}
				return ExternalPaths.Add(new PPtrData(fileId, pathId, typeName));
			}

			public bool Add(AssetTypeValueField valueField, string typeName)
			{
				return Add(valueField["m_FileID"].AsInt, valueField["m_PathID"].AsLong, typeName);
			}
		}

		private readonly AssetsManager _mgr;

		private readonly AssetsFileInstance _afileInst;

		private readonly Dictionary<long, ChildPPtrs> _immediateDeps;

		private readonly Dictionary<long, ChildPPtrs> _bundleDeps;

		public Config Settings { get; init; }

		public int Hits { get; private set; }

		public int Misses { get; private set; }

		public AssetDependencies(AssetsManager mgr, AssetsFileInstance afileInst, Config? settings = null)
		{
			_mgr = mgr;
			_afileInst = afileInst;
			Settings = settings ?? new Config();
			_immediateDeps = new Dictionary<long, ChildPPtrs>();
			_bundleDeps = new Dictionary<long, ChildPPtrs>();
			base..ctor();
		}

		public ChildPPtrs FindImmediateDeps(long assetPathId)
		{
			if (_immediateDeps.TryGetValue(assetPathId, out ChildPPtrs value))
			{
				Hits++;
				return value;
			}
			Misses++;
			AssetFileInfo assetInfo = _afileInst.file.GetAssetInfo(assetPathId);
			ChildPPtrs childPPtrs = ChildPPtrs.CreateNew();
			if (!Settings.FollowTransformParent && (assetInfo.TypeId == 4 || assetInfo.TypeId == 224))
			{
				AssetTypeValueField baseField = _mgr.GetBaseField(_afileInst, assetInfo, (AssetReadFlags)0);
				childPPtrs.Add(baseField["m_GameObject"], "PPtr<GameObject>");
				foreach (AssetTypeValueField child in baseField["m_Children.Array"].Children)
				{
					childPPtrs.Add(child, "PPtr<Transform>");
				}
				return _immediateDeps[assetPathId] = childPPtrs;
			}
			AssetTypeValueIterator val = _mgr.CreateIterator(_afileInst, assetInfo);
			while (val.ReadNext())
			{
				string type = val.TempField.Type;
				if (type.StartsWith("PPtr<"))
				{
					AssetTypeValueField valueField = val.ReadValueField();
					childPPtrs.Add(valueField, type);
				}
			}
			return _immediateDeps[assetPathId] = childPPtrs;
		}

		public ChildPPtrs FindBundleDeps(long assetPathId)
		{
			if (_bundleDeps.TryGetValue(assetPathId, out ChildPPtrs value))
			{
				return value;
			}
			HashSet<long> hashSet = new HashSet<long>(new <>z__ReadOnlySingleElementList<long>(assetPathId));
			HashSet<PPtrData> hashSet2 = new HashSet<PPtrData>();
			Queue<long> queue = new Queue<long>();
			queue.Enqueue(assetPathId);
			lock (_afileInst.LockReader)
			{
				long result;
				while (queue.TryDequeue(out result))
				{
					ChildPPtrs childPPtrs = FindImmediateDeps(result);
					hashSet2.UnionWith(childPPtrs.ExternalPaths);
					foreach (long internalPath in childPPtrs.InternalPaths)
					{
						if (hashSet.Add(internalPath))
						{
							queue.Enqueue(internalPath);
						}
					}
				}
			}
			hashSet.Remove(assetPathId);
			return _bundleDeps[assetPathId] = new ChildPPtrs(hashSet, hashSet2);
		}
	}
	public static class BundleUtils
	{
		public record AssetData(AssetFileInfo Info, AssetTypeValueField ValueField);

		public record SceneBundleInfo(int mainAfileInstIndex, int sharedAssetsAfileIndex);

		[CompilerGenerated]
		private sealed class <EnumerateContainer>d__16 : IEnumerable<(string name, int assetTypeId)>, IEnumerable, IEnumerator<(string name, int assetTypeId)>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private (string name, int assetTypeId) <>2__current;

			private int <>l__initialThreadId;

			private AssetsManager mgr;

			public AssetsManager <>3__mgr;

			private AssetsFileInstance afi;

			public AssetsFileInstance <>3__afi;

			private List<AssetTypeValueField>.Enumerator <>7__wrap1;

			(string, int) IEnumerator<(string, int)>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

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

			[DebuggerHidden]
			public <EnumerateContainer>d__16(int <>1__state)
			{
				this.<>1__state = <>1__state;
				<>l__initialThreadId = Environment.CurrentManagedThreadId;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				int num = <>1__state;
				if (num == -3 || num == 1)
				{
					try
					{
					}
					finally
					{
						<>m__Finally1();
					}
				}
				<>7__wrap1 = default(List<AssetTypeValueField>.Enumerator);
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				try
				{
					switch (<>1__state)
					{
					default:
						return false;
					case 0:
					{
						<>1__state = -1;
						AssetTypeValueField baseField = mgr.GetBaseField(afi, 1L, (AssetReadFlags)0);
						<>7__wrap1 = baseField["m_Container.Array"].Children.GetEnumerator();
						<>1__state = -3;
						break;
					}
					case 1:
						<>1__state = -3;
						break;
					}
					if (<>7__wrap1.MoveNext())
					{
						AssetTypeValueField current = <>7__wrap1.Current;
						string asString = current["first"].AsString;
						long asLong = current["second.asset.m_PathID"].AsLong;
						int typeId = afi.file.GetAssetInfo(asLong).TypeId;
						<>2__current = (asString, typeId);
						<>1__state = 1;
						return true;
					}
					<>m__Finally1();
					<>7__wrap1 = default(List<AssetTypeValueField>.Enumerator);
					return false;
				}
				catch
				{
					//try-fault
					((IDisposable)this).Dispose();
					throw;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			private void <>m__Finally1()
			{
				<>1__state = -1;
				((IDisposable)<>7__wrap1).Dispose();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}

			[DebuggerHidden]
			IEnumerator<(string name, int assetTypeId)> IEnumerable<(string, int)>.GetEnumerator()
			{
				<EnumerateContainer>d__16 <EnumerateContainer>d__;
				if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
				{
					<>1__state = 0;
					<EnumerateContainer>d__ = this;
				}
				else
				{
					<EnumerateContainer>d__ = new <EnumerateContainer>d__16(0);
				}
				<EnumerateContainer>d__.mgr = <>3__mgr;
				<EnumerateContainer>d__.afi = <>3__afi;
				return <EnumerateContainer>d__;
			}

			[DebuggerHidden]
			IEnumerator IEnumerable.GetEnumerator()
			{
				return ((IEnumerable<(string, int)>)this).GetEnumerator();
			}
		}

		[CompilerGenerated]
		private sealed class <GetAllTransforms>d__5 : IEnumerable<AssetFileInfo>, IEnumerable, IEnumerator<AssetFileInfo>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private AssetFileInfo <>2__current;

			private int <>l__initialThreadId;

			private AssetsFile afile;

			public AssetsFile <>3__afile;

			private List<AssetClassID>.Enumerator <>7__wrap1;

			private List<AssetFileInfo>.Enumerator <>7__wrap2;

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

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

			[DebuggerHidden]
			public <GetAllTransforms>d__5(int <>1__state)
			{
				this.<>1__state = <>1__state;
				<>l__initialThreadId = Environment.CurrentManagedThreadId;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				int num = <>1__state;
				if ((uint)(num - -4) <= 1u || num == 1)
				{
					try
					{
						if (num == -4 || num == 1)
						{
							try
							{
							}
							finally
							{
								<>m__Finally2();
							}
						}
					}
					finally
					{
						<>m__Finally1();
					}
				}
				<>7__wrap1 = default(List<AssetClassID>.Enumerator);
				<>7__wrap2 = default(List<AssetFileInfo>.Enumerator);
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_003c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0041: 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)
				try
				{
					int num = <>1__state;
					if (num != 0)
					{
						if (num != 1)
						{
							return false;
						}
						<>1__state = -4;
						goto IL_0089;
					}
					<>1__state = -1;
					<>7__wrap1 = TransformClassIds.GetEnumerator();
					<>1__state = -3;
					goto IL_00a8;
					IL_0089:
					if (<>7__wrap2.MoveNext())
					{
						AssetFileInfo current = <>7__wrap2.Current;
						<>2__current = current;
						<>1__state = 1;
						return true;
					}
					<>m__Finally2();
					<>7__wrap2 = default(List<AssetFileInfo>.Enumerator);
					goto IL_00a8;
					IL_00a8:
					if (<>7__wrap1.MoveNext())
					{
						AssetClassID current2 = <>7__wrap1.Current;
						<>7__wrap2 = afile.GetAssetsOfType(current2).GetEnumerator();
						<>1__state = -4;
						goto IL_0089;
					}
					<>m__Finally1();
					<>7__wrap1 = default(List<AssetClassID>.Enumerator);
					return false;
				}
				catch
				{
					//try-fault
					((IDisposable)this).Dispose();
					throw;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			private void <>m__Finally1()
			{
				<>1__state = -1;
				((IDisposable)<>7__wrap1).Dispose();
			}

			private void <>m__Finally2()
			{
				<>1__state = -3;
				((IDisposable)<>7__wrap2).Dispose();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}

			[DebuggerHidden]
			IEnumerator<AssetFileInfo> IEnumerable<AssetFileInfo>.GetEnumerator()
			{
				<GetAllTransforms>d__5 <GetAllTransforms>d__;
				if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
				{
					<>1__state = 0;
					<GetAllTransforms>d__ = this;
				}
				else
				{
					<GetAllTransforms>d__ = new <GetAllTransforms>d__5(0);
				}
				<GetAllTransforms>d__.afile = <>3__afile;
				return <GetAllTransforms>d__;
			}

			[DebuggerHidden]
			IEnumerator IEnumerable.GetEnumerator()
			{
				return ((IEnumerable<AssetFileInfo>)this).GetEnumerator();
			}
		}

		[CompilerGenerated]
		private sealed class <GetRootTransforms>d__6 : IEnumerable<AssetData>, IEnumerable, IEnumerator<AssetData>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private AssetData <>2__current;

			private int <>l__initialThreadId;

			private AssetsFileInstance afileInst;

			public AssetsFileInstance <>3__afileInst;

			private AssetsManager mgr;

			public AssetsManager <>3__mgr;

			private IEnumerator<AssetFileInfo> <>7__wrap1;

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

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

			[DebuggerHidden]
			public <GetRootTransforms>d__6(int <>1__state)
			{
				this.<>1__state = <>1__state;
				<>l__initialThreadId = Environment.CurrentManagedThreadId;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				int num = <>1__state;
				if (num == -3 || num == 1)
				{
					try
					{
					}
					finally
					{
						<>m__Finally1();
					}
				}
				<>7__wrap1 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				try
				{
					switch (<>1__state)
					{
					default:
						return false;
					case 0:
						<>1__state = -1;
						<>7__wrap1 = afileInst.file.GetAllTransforms().GetEnumerator();
						<>1__state = -3;
						break;
					case 1:
						<>1__state = -3;
						break;
					}
					while (<>7__wrap1.MoveNext())
					{
						AssetFileInfo current = <>7__wrap1.Current;
						AssetTypeValueField baseField = mgr.GetBaseField(afileInst, current, (AssetReadFlags)0);
						if (baseField["m_Father"]["m_PathID"].AsLong == 0L)
						{
							<>2__current = new AssetData(current, baseField);
							<>1__state = 1;
							return true;
						}
					}
					<>m__Finally1();
					<>7__wrap1 = null;
					return false;
				}
				catch
				{
					//try-fault
					((IDisposable)this).Dispose();
					throw;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			private void <>m__Finally1()
			{
				<>1__state = -1;
				if (<>7__wrap1 != null)
				{
					<>7__wrap1.Dispose();
				}
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}

			[DebuggerHidden]
			IEnumerator<AssetData> IEnumerable<AssetData>.GetEnumerator()
			{
				<GetRootTransforms>d__6 <GetRootTransforms>d__;
				if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
				{
					<>1__state = 0;
					<GetRootTransforms>d__ = this;
				}
				else
				{
					<GetRootTransforms>d__ = new <GetRootTransforms>d__6(0);
				}
				<GetRootTransforms>d__.mgr = <>3__mgr;
				<GetRootTransforms>d__.afileInst = <>3__afileInst;
				return <GetRootTransforms>d__;
			}

			[DebuggerHidden]
			IEnumerator IEnumerable.GetEnumerator()
			{
				return ((IEnumerable<AssetData>)this).GetEnumerator();
			}
		}

		public static List<AssetClassID> TransformClassIds { get; } = new List<AssetClassID>(2)
		{
			(AssetClassID)4,
			(AssetClassID)224
		};


		public static AssetsManager CreateDefaultManager()
		{
			//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_000c: 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_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			return new AssetsManager
			{
				UseQuickLookup = true,
				UseMonoTemplateFieldCache = true,
				UseRefTypeManagerCache = true,
				UseTemplateFieldCache = true
			};
		}

		[IteratorStateMachine(typeof(<GetAllTransforms>d__5))]
		public static IEnumerable<AssetFileInfo> GetAllTransforms(this AssetsFile afile)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <GetAllTransforms>d__5(-2)
			{
				<>3__afile = afile
			};
		}

		[IteratorStateMachine(typeof(<GetRootTransforms>d__6))]
		public static IEnumerable<AssetData> GetRootTransforms(this AssetsManager mgr, AssetsFileInstance afileInst)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <GetRootTransforms>d__6(-2)
			{
				<>3__mgr = mgr,
				<>3__afileInst = afileInst
			};
		}

		public static Dictionary<string, AssetData> FindRootGameObjects(this AssetsManager mgr, AssetsFileInstance afileInst, List<string> objectNames, out List<string> missingObjects)
		{
			Dictionary<string, AssetData> gameObjects = new Dictionary<string, AssetData>();
			foreach (AssetData rootTransform in mgr.GetRootTransforms(afileInst))
			{
				AssetFileInfo assetInfo = afileInst.file.GetAssetInfo(rootTransform.ValueField["m_GameObject.m_PathID"].AsLong);
				AssetTypeValueField baseField = mgr.GetBaseField(afileInst, assetInfo, (AssetReadFlags)0);
				string asString = baseField["m_Name"].AsString;
				if (objectNames.Contains(asString))
				{
					gameObjects[asString] = new AssetData(assetInfo, baseField);
				}
			}
			missingObjects = objectNames.Where((string x) => !gameObjects.ContainsKey(x)).ToList();
			return gameObjects;
		}

		public static string GetTransformName(this AssetsManager mgr, AssetsFileInstance afileInst, AssetFileInfo info)
		{
			AssetTypeValueField baseField = mgr.GetBaseField(afileInst, info, (AssetReadFlags)0);
			return mgr.GetTransformName(afileInst, baseField);
		}

		public static string GetTransformName(this AssetsManager mgr, AssetsFileInstance afileInst, AssetTypeValueField transform)
		{
			long asLong = transform["m_GameObject.m_PathID"].AsLong;
			return mgr.GetBaseField(afileInst, asLong, (AssetReadFlags)0)["m_Name"].AsString;
		}

		public static AssetData FindTransform(this AssetsManager mgr, AssetsFileInstance afileInst, string name)
		{
			string[] array = name.Split('/');
			string text = array[0];
			string[] subArray = array[1..];
			AssetData assetData = null;
			foreach (AssetData rootTransform in mgr.GetRootTransforms(afileInst))
			{
				if (mgr.GetTransformName(afileInst, rootTransform.ValueField) == text)
				{
					assetData = rootTransform;
					break;
				}
			}
			if (assetData == null)
			{
				throw new Exception("Did not find root game object " + text);
			}
			AssetData assetData2 = assetData;
			string[] array2 = subArray;
			foreach (string text2 in array2)
			{
				bool flag = false;
				foreach (AssetTypeValueField child in assetData2.ValueField["m_Children.Array"].Children)
				{
					long asLong = child["m_PathID"].AsLong;
					AssetFileInfo assetInfo = afileInst.file.GetAssetInfo(asLong);
					AssetTypeValueField baseField = mgr.GetBaseField(afileInst, assetInfo, (AssetReadFlags)0);
					if (mgr.GetTransformName(afileInst, baseField) == text2)
					{
						flag = true;
						assetData2 = new AssetData(assetInfo, baseField);
						break;
					}
				}
				if (!flag)
				{
					throw new Exception("Did not find part " + text2);
				}
			}
			return assetData2;
		}

		public static bool TryFindAssetsFiles(this AssetsManager mgr, BundleFileInstance sceneBun, out SceneBundleInfo info)
		{
			int num = -1;
			int num2 = -1;
			List<string> allFileNames = sceneBun.file.GetAllFileNames();
			for (int i = 0; i < allFileNames.Count; i++)
			{
				if (!allFileNames[i].Contains('.'))
				{
					num = i;
				}
				else if (allFileNames[i].EndsWith(".sharedAssets"))
				{
					num2 = i;
				}
			}
			info = new SceneBundleInfo(num, num2);
			if (num == -1 || num2 == -1)
			{
				return false;
			}
			return true;
		}

		public static AssetTypeValueIterator CreateIterator(this AssetsManager mgr, AssetsFileInstance afileinst, AssetFileInfo info)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected O, but got Unknown
			AssetTypeTemplateField templateBaseField = mgr.GetTemplateBaseField(afileinst, info, (AssetReadFlags)0);
			RefTypeManager refTypeManager = mgr.GetRefTypeManager(afileinst);
			long absoluteByteOffset = info.GetAbsoluteByteOffset(afileinst.file);
			return new AssetTypeValueIterator(templateBaseField, afileinst.file.Reader, absoluteByteOffset, refTypeManager);
		}

		public static int Redirect(this AssetsManager mgr, AssetsFileInstance afileinst, AssetFileInfo info, long source, long target)
		{
			int num = 0;
			lock (afileinst.LockReader)
			{
				byte[] array = mgr.GetBaseField(afileinst, info, (AssetReadFlags)0).WriteToByteArray(false);
				AssetTypeValueIterator val = mgr.CreateIterator(afileinst, info);
				while (val.ReadNext())
				{
					if (val.TempField.Type.StartsWith("PPtr<"))
					{
						AssetTypeValueField val2 = val.ReadValueField();
						if (val2["m_PathID"].AsLong == source && val2["m_FileID"].AsInt == 0)
						{
							val2["m_PathID"].AsLong = target;
							byte[] array2 = val2.WriteToByteArray(false);
							int destinationIndex = val.ReadPosition - array2.Length;
							Array.Copy(array2, 0, array, destinationIndex, array2.Length);
							num++;
						}
					}
				}
				info.SetNewData(array);
				return num;
			}
		}

		public static void WriteBundleToFile(this AssetBundleFile bunFile, string outBundlePath)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Expected O, but got Unknown
			using MemoryStream memoryStream = new MemoryStream();
			AssetsFileWriter val = new AssetsFileWriter(memoryStream);
			try
			{
				bunFile.Write(val, 0L);
				using FileStream fileStream = new FileStream(outBundlePath, FileMode.Create, FileAccess.Write);
				byte[] buffer = memoryStream.GetBuffer();
				fileStream.Write(buffer, 0, (int)memoryStream.Length);
			}
			finally
			{
				((IDisposable)val)?.Dispose();
			}
		}

		[IteratorStateMachine(typeof(<EnumerateContainer>d__16))]
		public static IEnumerable<(string name, int assetTypeId)> EnumerateContainer(this AssetsManager mgr, AssetsFileInstance afi)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <EnumerateContainer>d__16(-2)
			{
				<>3__mgr = mgr,
				<>3__afi = afi
			};
		}
	}
	public class GameObjectLookup : IEnumerable<GameObjectLookup.GameObjectInfo>, IEnumerable
	{
		public record GameObjectInfo(long GameObjectPathId, long TransformPathId, string GameObjectName, long ParentPathId);

		private readonly Dictionary<string, GameObjectInfo> _fromName;

		private readonly Dictionary<long, GameObjectInfo> _fromGameObject;

		private readonly Dictionary<long, GameObjectInfo> _fromTransform;

		private GameObjectLookup(Dictionary<string, GameObjectInfo> fromName, Dictionary<long, GameObjectInfo> fromGameObject, Dictionary<long, GameObjectInfo> fromTransform)
		{
			_fromName = fromName;
			_fromGameObject = fromGameObject;
			_fromTransform = fromTransform;
		}

		public static GameObjectLookup CreateFromInfos(IEnumerable<GameObjectInfo> infos)
		{
			Dictionary<string, GameObjectInfo> dictionary = new Dictionary<string, GameObjectInfo>();
			Dictionary<long, GameObjectInfo> dictionary2 = new Dictionary<long, GameObjectInfo>();
			Dictionary<long, GameObjectInfo> dictionary3 = new Dictionary<long, GameObjectInfo>();
			foreach (GameObjectInfo info in infos)
			{
				dictionary[info.GameObjectName] = info;
				dictionary2[info.GameObjectPathId] = info;
				dictionary3[info.TransformPathId] = info;
			}
			return new GameObjectLookup(dictionary, dictionary2, dictionary3);
		}

		public static GameObjectLookup CreateFromFile(AssetsManager mgr, AssetsFileInstance afileInst)
		{
			Dictionary<long, string> go2name = new Dictionary<long, string>();
			Dictionary<long, long> tf2parent = new Dictionary<long, long>();
			Dictionary<long, long> tf2go = new Dictionary<long, long>();
			foreach (AssetFileInfo assetInfo in afileInst.file.AssetInfos)
			{
				if (assetInfo.TypeId == 1)
				{
					AssetTypeValueField baseField = mgr.GetBaseField(afileInst, assetInfo, (AssetReadFlags)0);
					go2name[assetInfo.PathId] = baseField["m_Name"].AsString;
				}
				else if (assetInfo.TypeId == 4 || assetInfo.TypeId == 224)
				{
					AssetTypeValueField baseField2 = mgr.GetBaseField(afileInst, assetInfo, (AssetReadFlags)0);
					tf2parent[assetInfo.PathId] = baseField2["m_Father.m_PathID"].AsLong;
					tf2go[assetInfo.PathId] = baseField2["m_GameObject.m_PathID"].AsLong;
				}
			}
			Dictionary<long, GameObjectInfo> fromTransformLookup = new Dictionary<long, GameObjectInfo>();
			foreach (long key in tf2parent.Keys)
			{
				DoAdd(key);
			}
			return CreateFromInfos(fromTransformLookup.Values);
			GameObjectInfo DoAdd(long tPathId)
			{
				if (fromTransformLookup.TryGetValue(tPathId, out GameObjectInfo value))
				{
					return value;
				}
				long num = tf2parent[tPathId];
				long num2 = tf2go[tPathId];
				string text = go2name[num2];
				if (num == 0L)
				{
					GameObjectInfo gameObjectInfo = new GameObjectInfo(num2, tPathId, text, 0L);
					fromTransformLookup[tPathId] = gameObjectInfo;
					return gameObjectInfo;
				}
				string gameObjectName = DoAdd(num).GameObjectName;
				GameObjectInfo gameObjectInfo2 = new GameObjectInfo(num2, tPathId, gameObjectName + "/" + text, num);
				fromTransformLookup[tPathId] = gameObjectInfo2;
				return gameObjectInfo2;
			}
		}

		private bool TryGet<T>(T key, Dictionary<T, GameObjectInfo> lookupDict, [MaybeNullWhen(false)] out GameObjectInfo info)
		{
			return lookupDict.TryGetValue(key, out info);
		}

		public GameObjectInfo LookupTransform(long pathId)
		{
			if (!TryGet(pathId, _fromTransform, out GameObjectInfo info))
			{
				throw new KeyNotFoundException($"Did not find transform key {pathId}");
			}
			return info;
		}

		public GameObjectInfo LookupGameObject(long pathId)
		{
			if (!TryGet(pathId, _fromGameObject, out GameObjectInfo info))
			{
				throw new KeyNotFoundException($"Did not find game object key {pathId}");
			}
			return info;
		}

		public GameObjectInfo LookupName(string name)
		{
			if (!TryGet(name, _fromName, out GameObjectInfo info))
			{
				throw new KeyNotFoundException("Did not find name " + name);
			}
			return info;
		}

		public bool TryLookupTransfrom(long pathId, [MaybeNullWhen(false)] out GameObjectInfo info)
		{
			return TryGet(pathId, _fromTransform, out info);
		}

		public bool TryLookupGameObject(long pathId, [MaybeNullWhen(false)] out GameObjectInfo info)
		{
			return TryGet(pathId, _fromGameObject, out info);
		}

		public bool TryLookupName(string name, [MaybeNullWhen(false)] out GameObjectInfo info)
		{
			return TryGet(name, _fromName, out info);
		}

		public IEnumerator<GameObjectInfo> GetEnumerator()
		{
			return _fromGameObject.Values.GetEnumerator();
		}

		IEnumerator IEnumerable.GetEnumerator()
		{
			return GetEnumerator();
		}
	}
	public static class GameObjectLookupExtensions
	{
		[CompilerGenerated]
		private sealed class <>c__DisplayClass0_0
		{
			public Dictionary<long, List<GameObjectLookup.GameObjectInfo>> children;
		}

		public static IEnumerable<GameObjectLookup.GameObjectInfo> TraverseOrdered(this GameObjectLookup self)
		{
			<>c__DisplayClass0_0 CS$<>8__locals0 = new <>c__DisplayClass0_0();
			CS$<>8__locals0.children = new Dictionary<long, List<GameObjectLookup.GameObjectInfo>>();
			foreach (GameObjectLookup.GameObjectInfo item in self)
			{
				if (!CS$<>8__locals0.children.TryGetValue(item.ParentPathId, out List<GameObjectLookup.GameObjectInfo> value))
				{
					value = new List<GameObjectLookup.GameObjectInfo>();
					CS$<>8__locals0.children[item.ParentPathId] = value;
				}
				value.Add(item);
			}
			return InnerTraverse(0L);
			[IteratorStateMachine(typeof(<>c__DisplayClass0_0.<<TraverseOrdered>g__InnerTraverse|0>d))]
			IEnumerable<GameObjectLookup.GameObjectInfo> InnerTraverse(long pathId)
			{
				//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
				return new <>c__DisplayClass0_0.<<TraverseOrdered>g__InnerTraverse|0>d(-2)
				{
					<>4__this = CS$<>8__locals0,
					<>3__pathId = pathId
				};
			}
		}
	}
}
[CompilerGenerated]
internal sealed class <>z__ReadOnlySingleElementList<T> : IEnumerable, ICollection, IList, IEnumerable<T>, IReadOnlyCollection<T>, IReadOnlyList<T>, ICollection<T>, IList<T>
{
	private sealed class Enumerator : IDisposable, IEnumerator, IEnumerator<T>
	{
		object IEnumerator.Current => _item;

		T IEnumerator<T>.Current => _item;

		public Enumerator(T item)
		{
			_item = item;
		}

		bool IEnumerator.MoveNext()
		{
			if (!_moveNextCalled)
			{
				return _moveNextCalled = true;
			}
			return false;
		}

		void IEnumerator.Reset()
		{
			_moveNextCalled = false;
		}

		void IDisposable.Dispose()
		{
		}
	}

	int ICollection.Count => 1;

	bool ICollection.IsSynchronized => false;

	object ICollection.SyncRoot => this;

	object IList.this[int index]
	{
		get
		{
			if (index != 0)
			{
				throw new IndexOutOfRangeException();
			}
			return _item;
		}
		set
		{
			throw new NotSupportedException();
		}
	}

	bool IList.IsFixedSize => true;

	bool IList.IsReadOnly => true;

	int IReadOnlyCollection<T>.Count => 1;

	T IReadOnlyList<T>.this[int index]
	{
		get
		{
			if (index != 0)
			{
				throw new IndexOutOfRangeException();
			}
			return _item;
		}
	}

	int ICollection<T>.Count => 1;

	bool ICollection<T>.IsReadOnly => true;

	T IList<T>.this[int index]
	{
		get
		{
			if (index != 0)
			{
				throw new IndexOutOfRangeException();
			}
			return _item;
		}
		set
		{
			throw new NotSupportedException();
		}
	}

	public <>z__ReadOnlySingleElementList(T item)
	{
		_item = item;
	}

	IEnumerator IEnumerable.GetEnumerator()
	{
		return new Enumerator(_item);
	}

	void ICollection.CopyTo(Array array, int index)
	{
		array.SetValue(_item, index);
	}

	int IList.Add(object value)
	{
		throw new NotSupportedException();
	}

	void IList.Clear()
	{
		throw new NotSupportedException();
	}

	bool IList.Contains(object value)
	{
		return EqualityComparer<T>.Default.Equals(_item, (T)value);
	}

	int IList.IndexOf(object value)
	{
		if (!EqualityComparer<T>.Default.Equals(_item, (T)value))
		{
			return -1;
		}
		return 0;
	}

	void IList.Insert(int index, object value)
	{
		throw new NotSupportedException();
	}

	void IList.Remove(object value)
	{
		throw new NotSupportedException();
	}

	void IList.RemoveAt(int index)
	{
		throw new NotSupportedException();
	}

	IEnumerator<T> IEnumerable<T>.GetEnumerator()
	{
		return new Enumerator(_item);
	}

	void ICollection<T>.Add(T item)
	{
		throw new NotSupportedException();
	}

	void ICollection<T>.Clear()
	{
		throw new NotSupportedException();
	}

	bool ICollection<T>.Contains(T item)
	{
		return EqualityComparer<T>.Default.Equals(_item, item);
	}

	void ICollection<T>.CopyTo(T[] array, int arrayIndex)
	{
		array[arrayIndex] = _item;
	}

	bool ICollection<T>.Remove(T item)
	{
		throw new NotSupportedException();
	}

	int IList<T>.IndexOf(T item)
	{
		if (!EqualityComparer<T>.Default.Equals(_item, item))
		{
			return -1;
		}
		return 0;
	}

	void IList<T>.Insert(int index, T item)
	{
		throw new NotSupportedException();
	}

	void IList<T>.RemoveAt(int index)
	{
		throw new NotSupportedException();
	}
}

plugins/AssetHelper.dll

Decompiled 19 hours ago
using System;
using System.Buffers;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using AssetHelperLib;
using AssetHelperLib.BundleTools;
using AssetHelperLib.Repacking;
using AssetHelperLib.Util;
using AssetsTools.NET;
using AssetsTools.NET.Extra;
using BepInEx;
using BepInEx.Logging;
using DataDrivenConstants.Marker;
using Md.StartManager;
using Microsoft.CodeAnalysis;
using Mono.Cecil.Cil;
using MonoDetour;
using MonoDetour.Cil;
using MonoDetour.DetourTypes;
using MonoDetour.HookGen;
using MonoDetour.Reflection.Unspeakable;
using MonoMod.Cil;
using MonoMod.RuntimeDetour;
using MonoMod.Utils;
using Newtonsoft.Json;
using Silksong.AssetHelper.CatalogTools;
using Silksong.AssetHelper.Core;
using Silksong.AssetHelper.Internal;
using Silksong.AssetHelper.Plugin;
using Silksong.AssetHelper.Plugin.Tasks;
using TeamCherry.Localization;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.AddressableAssets.ResourceLocators;
using UnityEngine.ResourceManagement.AsyncOperations;
using UnityEngine.ResourceManagement.ResourceLocations;
using UnityEngine.ResourceManagement.ResourceProviders;
using UnityEngine.ResourceManagement.Util;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("AssetHelper")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Library for helping with loading vanilla Silksong assets.")]
[assembly: AssemblyFileVersion("1.0.2.0")]
[assembly: AssemblyInformationalVersion("1.0.2+f17467b4df559b03b1fb649efa5f577839c76333")]
[assembly: AssemblyProduct("AssetHelper")]
[assembly: AssemblyTitle("AssetHelper")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/silksong-modding/Silksong.AssetHelper")]
[assembly: NeutralResourcesLanguage("EN")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.2.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
internal class LoadingBar : MonoBehaviour
{
	private RectTransform _fillImageRect;

	private GameObject _canvasObject;

	private CanvasGroup _canvasGroup;

	private Text _statusText;

	public static LoadingBar Create()
	{
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_000a: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = new GameObject("AssetHelper LoadingBar");
		LoadingBar result = val.AddComponent<LoadingBar>();
		val.SetActive(true);
		return result;
	}

	private void Awake()
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_0010: Expected O, but got Unknown
		//IL_0072: Unknown result type (might be due to invalid IL or missing references)
		//IL_0077: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_00ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d8: Expected O, but got Unknown
		//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
		//IL_010f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0124: Unknown result type (might be due to invalid IL or missing references)
		//IL_0139: Unknown result type (might be due to invalid IL or missing references)
		//IL_014e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0158: Unknown result type (might be due to invalid IL or missing references)
		//IL_0167: Unknown result type (might be due to invalid IL or missing references)
		//IL_016d: Expected O, but got Unknown
		//IL_0185: Unknown result type (might be due to invalid IL or missing references)
		//IL_0195: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0211: Unknown result type (might be due to invalid IL or missing references)
		//IL_022b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0245: Unknown result type (might be due to invalid IL or missing references)
		//IL_0255: Unknown result type (might be due to invalid IL or missing references)
		//IL_0265: Unknown result type (might be due to invalid IL or missing references)
		//IL_0274: Unknown result type (might be due to invalid IL or missing references)
		//IL_027a: Expected O, but got Unknown
		//IL_02e0: Unknown result type (might be due to invalid IL or missing references)
		//IL_0300: Unknown result type (might be due to invalid IL or missing references)
		//IL_0315: Unknown result type (might be due to invalid IL or missing references)
		//IL_032a: Unknown result type (might be due to invalid IL or missing references)
		//IL_033f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0353: Unknown result type (might be due to invalid IL or missing references)
		_canvasObject = new GameObject("LoadingCanvas");
		Canvas obj = _canvasObject.AddComponent<Canvas>();
		obj.renderMode = (RenderMode)0;
		obj.sortingOrder = 999;
		_canvasObject.AddComponent<CanvasScaler>();
		_canvasObject.AddComponent<GraphicRaycaster>();
		_canvasGroup = _canvasObject.AddComponent<CanvasGroup>();
		_canvasGroup.interactable = false;
		_canvasGroup.blocksRaycasts = true;
		GameObject val = new GameObject("Background");
		val.transform.SetParent(_canvasObject.transform);
		Image obj2 = val.AddComponent<Image>();
		((Graphic)obj2).color = Color.black;
		RectTransform rectTransform = ((Graphic)obj2).rectTransform;
		rectTransform.anchorMin = Vector2.zero;
		rectTransform.anchorMax = Vector2.one;
		rectTransform.sizeDelta = Vector2.zero;
		rectTransform.anchoredPosition = Vector2.zero;
		GameObject val2 = new GameObject("Outline");
		val2.transform.SetParent(_canvasObject.transform);
		Image obj3 = val2.AddComponent<Image>();
		((Graphic)obj3).color = Color.white;
		RectTransform rectTransform2 = ((Graphic)obj3).rectTransform;
		rectTransform2.anchorMin = new Vector2(0.5f, 0.5f);
		rectTransform2.anchorMax = new Vector2(0.5f, 0.5f);
		rectTransform2.pivot = new Vector2(0.5f, 0.5f);
		rectTransform2.sizeDelta = new Vector2(500f, 66f);
		rectTransform2.anchoredPosition = Vector2.zero;
		GameObject val3 = new GameObject("InnerBG");
		val3.transform.SetParent(val2.transform);
		Image obj4 = val3.AddComponent<Image>();
		((Graphic)obj4).color = Color.black;
		RectTransform rectTransform3 = ((Graphic)obj4).rectTransform;
		rectTransform3.anchorMin = Vector2.zero;
		rectTransform3.anchorMax = Vector2.one;
		rectTransform3.sizeDelta = new Vector2(-4f, -4f);
		rectTransform3.anchoredPosition = Vector2.zero;
		GameObject val4 = new GameObject("Fill");
		val4.transform.SetParent(val3.transform);
		Image val5 = val4.AddComponent<Image>();
		((Graphic)val5).color = Color.white;
		_fillImageRect = ((Graphic)val5).rectTransform;
		_fillImageRect.anchorMin = new Vector2(0f, 0f);
		_fillImageRect.anchorMax = new Vector2(0f, 1f);
		_fillImageRect.pivot = new Vector2(0f, 0.5f);
		_fillImageRect.sizeDelta = Vector2.zero;
		_fillImageRect.anchoredPosition = Vector2.zero;
		GameObject val6 = new GameObject("StatusText");
		val6.transform.SetParent(_canvasObject.transform);
		_statusText = val6.AddComponent<Text>();
		_statusText.font = Resources.GetBuiltinResource<Font>("Arial.ttf");
		_statusText.text = string.Empty;
		_statusText.fontSize = 30;
		_statusText.alignment = (TextAnchor)4;
		((Graphic)_statusText).color = Color.white;
		RectTransform rectTransform4 = ((Graphic)_statusText).rectTransform;
		rectTransform4.anchorMin = new Vector2(0.5f, 0.5f);
		rectTransform4.anchorMax = new Vector2(0.5f, 0.5f);
		rectTransform4.pivot = new Vector2(0.5f, 0f);
		rectTransform4.sizeDelta = new Vector2(800f, 50f);
		rectTransform4.anchoredPosition = new Vector2(0f, 45f);
		_statusText.text = "Loading...";
	}

	public void SetProgress(float progress)
	{
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		progress = Mathf.Clamp01(progress);
		_fillImageRect.anchorMax = new Vector2(progress, 1f);
	}

	public void SetVisible(bool visible)
	{
		_canvasGroup.alpha = (visible ? 1f : 0f);
	}

	public void SetText(string text)
	{
		_statusText.text = text;
	}

	private void OnDestroy()
	{
		if ((Object)(object)_canvasObject != (Object)null)
		{
			Object.Destroy((Object)(object)_canvasObject);
		}
	}
}
namespace Md.StartManager
{
	internal static class Start
	{
		public delegate void PrefixSignature(StartManager self);

		public delegate void PostfixSignature(StartManager self, ref IEnumerator returnValue);

		public delegate void PrefixMoveNextSignature(SpeakableEnumerator<object, StartManager> self);

		public delegate void PostfixMoveNextSignature(SpeakableEnumerator<object, StartManager> self, ref bool continueEnumeration);

		public static MonoDetourHook Prefix(PrefixSignature hook, MonoDetourConfig? config = null, bool applyByDefault = true, MonoDetourManager? manager = null)
		{
			return (manager ?? DefaultMonoDetourManager.Instance).Hook<PrefixDetour>(Target(), (Delegate)hook, config, applyByDefault);
		}

		public static MonoDetourHook Postfix(PostfixSignature hook, MonoDetourConfig? config = null, bool applyByDefault = true, MonoDetourManager? manager = null)
		{
			return (manager ?? DefaultMonoDetourManager.Instance).Hook<PostfixDetour>(Target(), (Delegate)hook, config, applyByDefault);
		}

		public static MonoDetourHook ILHook(Manipulator manipulator, MonoDetourConfig? config = null, bool applyByDefault = true, MonoDetourManager? manager = null)
		{
			return (manager ?? DefaultMonoDetourManager.Instance).ILHook(Target(), manipulator, config, applyByDefault);
		}

		public static MonoDetourHook PrefixMoveNext(PrefixMoveNextSignature hook, MonoDetourConfig? config = null, bool applyByDefault = true, MonoDetourManager? manager = null)
		{
			return (manager ?? DefaultMonoDetourManager.Instance).Hook<PrefixDetour>((MethodBase)StateMachineTarget(), (Delegate)hook, config, applyByDefault);
		}

		public static MonoDetourHook PostfixMoveNext(PostfixMoveNextSignature hook, MonoDetourConfig? config = null, bool applyByDefault = true, MonoDetourManager? manager = null)
		{
			return (manager ?? DefaultMonoDetourManager.Instance).Hook<PostfixDetour>((MethodBase)StateMachineTarget(), (Delegate)hook, config, applyByDefault);
		}

		public static MonoDetourHook ILHookMoveNext(Manipulator manipulator, MonoDetourConfig? config = null, bool applyByDefault = true, MonoDetourManager? manager = null)
		{
			return (manager ?? DefaultMonoDetourManager.Instance).ILHook((MethodBase)StateMachineTarget(), manipulator, config, applyByDefault);
		}

		public static MethodBase Target()
		{
			return typeof(StartManager).GetMethod("Start", (BindingFlags)(-1), null, Array.Empty<Type>(), null) ?? throw new MissingMethodException("StartManager", "Start");
		}

		public static MethodInfo StateMachineTarget()
		{
			return Extensions.GetStateMachineTarget((MethodInfo)Target());
		}
	}
	internal static class _Start_d__8
	{
		internal static class MoveNext
		{
			public delegate void PrefixSignature(object self);

			public delegate void PostfixSignature(object self, ref bool returnValue);

			public static MonoDetourHook Prefix(PrefixSignature hook, MonoDetourConfig? config = null, bool applyByDefault = true, MonoDetourManager? manager = null)
			{
				return (manager ?? DefaultMonoDetourManager.Instance).Hook<PrefixDetour>(Target(), (Delegate)hook, config, applyByDefault);
			}

			public static MonoDetourHook Postfix(PostfixSignature hook, MonoDetourConfig? config = null, bool applyByDefault = true, MonoDetourManager? manager = null)
			{
				return (manager ?? DefaultMonoDetourManager.Instance).Hook<PostfixDetour>(Target(), (Delegate)hook, config, applyByDefault);
			}

			public static MonoDetourHook ILHook(Manipulator manipulator, MonoDetourConfig? config = null, bool applyByDefault = true, MonoDetourManager? manager = null)
			{
				return (manager ?? DefaultMonoDetourManager.Instance).ILHook(Target(), manipulator, config, applyByDefault);
			}

			public static MethodBase Target()
			{
				return (Type.GetType("StartManager+<Start>d__8, Assembly-CSharp") ?? throw new Exception("Missing Type: 'StartManager+<Start>d__8'")).GetMethod("MoveNext", (BindingFlags)(-1), null, Array.Empty<Type>(), null) ?? throw new MissingMethodException("StartManager+<Start>d__8", "MoveNext");
			}
		}
	}
}
namespace MonoDetour.HookGen
{
	internal static class DefaultMonoDetourManager
	{
		internal static MonoDetourManager Instance { get; } = New();


		internal static MonoDetourManager New()
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected O, but got Unknown
			return new MonoDetourManager(typeof(DefaultMonoDetourManager).Assembly.GetName().Name);
		}
	}
	[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class, AllowMultiple = true, Inherited = false)]
	internal class MonoDetourTargetsAttribute : Attribute, IMonoDetourTargets
	{
		public Type? TargetType { get; }

		public bool IncludeNestedTypes { get; set; }

		public string[]? Members { get; set; }

		public string[]? MemberNamePrefixes { get; set; }

		public string[]? MemberNameSuffixes { get; set; }

		public bool GenerateControlFlowVariants { get; set; }

		public MonoDetourTargetsAttribute(Type? targetType = null)
		{
			TargetType = targetType;
			IncludeNestedTypes = true;
			base..ctor();
		}
	}
}
namespace BepInEx
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class BepInAutoPluginAttribute : Attribute
	{
		public BepInAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
		{
		}
	}
}
namespace BepInEx.Preloader.Core.Patching
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class PatcherAutoPluginAttribute : Attribute
	{
		public PatcherAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
		{
		}
	}
}
namespace Microsoft.CodeAnalysis
{
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace DataDrivenConstants.Marker
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	internal sealed class JsonDataAttribute : Attribute
	{
		public string ValuePath { get; }

		public string[] FileGlobs { get; }

		public JsonDataAttribute(string valuePath, params string[] fileGlobs)
		{
			ValuePath = valuePath;
			FileGlobs = (string[])fileGlobs.Clone();
		}
	}
	internal enum ReplacementKind
	{
		Normal,
		Regex
	}
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = true)]
	internal sealed class ReplacementRuleAttribute : Attribute
	{
		public string OldString { get; }

		public string NewString { get; }

		public ReplacementKind ReplacementKind { get; }

		public ReplacementRuleAttribute(string oldString, string newString, ReplacementKind replacementKind = ReplacementKind.Normal)
		{
			OldString = oldString;
			NewString = newString;
			ReplacementKind = replacementKind;
		}
	}
}
namespace Silksong.AssetHelper
{
	[AttributeUsage(AttributeTargets.Class)]
	internal class ModMenuIgnoreAttribute : Attribute
	{
	}
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[ModMenuIgnore]
	[BepInPlugin("org.silksong-modding.assethelper", "AssetHelper", "1.0.2")]
	public class AssetHelperPlugin : BaseUnityPlugin
	{
		[CompilerGenerated]
		private sealed class <Start>d__13 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

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

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

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

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

			private bool MoveNext()
			{
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					AssetRequestAPI.RequestApiAvailable = false;
					<>2__current = null;
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					break;
				case 2:
					<>1__state = -1;
					break;
				}
				if (!AddressablesData.TryLoadBundleKeys())
				{
					<>2__current = null;
					<>1__state = 2;
					return true;
				}
				return false;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		public const string Id = "org.silksong-modding.assethelper";

		public static AssetHelperPlugin Instance { get; private set; }

		internal static ManualLogSource InstanceLogger { get; private set; }

		public static string Name => "AssetHelper";

		public static string Version => "1.0.2";

		public static event Action? OnQuitApplication;

		private void Awake()
		{
			Instance = this;
			InstanceLogger = ((BaseUnityPlugin)this).Logger;
			InitLibLogging();
			AssetsToolsPatch.Init();
			AddressablesData.InvokeAfterAddressablesLoaded(BundleMetadata.Setup);
			StartupOverrideManager.Hook();
			Addressables.ResourceManager.ResourceProviders.Add((IResourceProvider)(object)new ChildGameObjectProvider());
			((BaseUnityPlugin)this).Logger.LogInfo((object)("Silksong version: " + VersionData.SilksongVersion + " // OS String: " + AssetPaths.OSFolderName));
			((BaseUnityPlugin)this).Logger.LogInfo((object)("Plugin " + Name + " (org.silksong-modding.assethelper) has loaded!"));
		}

		private static void InitLibLogging()
		{
			ManualLogSource @object = Logger.CreateLogSource("AssetHelper.Lib");
			Logging.OnLog += @object.LogInfo;
			Logging.OnLogWarning += @object.LogWarning;
			Logging.OnLogError += @object.LogError;
		}

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

		private void OnApplicationQuit()
		{
			Delegate[] array = AssetHelperPlugin.OnQuitApplication?.GetInvocationList() ?? Array.Empty<Action>();
			for (int i = 0; i < array.Length; i++)
			{
				ActionUtil.SafeInvoke((Action)array[i]);
			}
		}
	}
	internal static class AssetsToolsPatch
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static Manipulator <0>__PatchATVI;

			public static Action<Action<Stream, Stream, long, int>, Stream, Stream, long, int> <1>__PatchC2C;
		}

		private static ILHook? _atIteratorHook;

		private static Hook? _atCopyHook;

		public static void Init()
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Expected O, but got Unknown
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Expected O, but got Unknown
			MethodInfo? method = typeof(AssetTypeValueIterator).GetMethod("ReadNext");
			object obj = <>O.<0>__PatchATVI;
			if (obj == null)
			{
				Manipulator val = PatchATVI;
				<>O.<0>__PatchATVI = val;
				obj = (object)val;
			}
			_atIteratorHook = new ILHook((MethodBase)method, (Manipulator)obj);
			_atCopyHook = new Hook((MethodBase)typeof(Net35Polyfill).GetMethod("CopyToCompat"), (Delegate)new Action<Action<Stream, Stream, long, int>, Stream, Stream, long, int>(PatchC2C));
		}

		private static void PatchC2C(Action<Stream, Stream, long, int> orig, Stream input, Stream output, long bytes, int bufferSize)
		{
			byte[] array = ArrayPool<byte>.Shared.Rent(bufferSize);
			if (bytes == -1)
			{
				bytes = long.MaxValue;
			}
			int num;
			while (bytes > 0 && (num = input.Read(array, 0, (int)Math.Min(array.Length, bytes))) > 0)
			{
				output.Write(array, 0, num);
				bytes -= num;
			}
			ArrayPool<byte>.Shared.Return(array);
		}

		private static void PatchATVI(ILContext il)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			ILCursor val = new ILCursor(il);
			int num3 = default(int);
			int num2 = default(int);
			int num = default(int);
			ILLabel[] array2 = default(ILLabel[]);
			if (val.TryGotoNext((MoveType)2, new Func<Instruction, bool>[6]
			{
				(Instruction i) => ILPatternMatchingExt.MatchCallvirt<AssetTypeTemplateField>(i, "get_ValueType"),
				(Instruction i) => ILPatternMatchingExt.MatchStloc(i, ref num3),
				(Instruction i) => ILPatternMatchingExt.MatchLdloc(i, ref num2),
				(Instruction i) => ILPatternMatchingExt.MatchLdcI4(i, ref num),
				(Instruction i) => ILPatternMatchingExt.MatchSub(i),
				(Instruction i) => ILPatternMatchingExt.MatchSwitch(i, ref array2)
			}))
			{
				ILLabel[] array = (ILLabel[])val.Prev.Operand;
				array[10] = array[7];
			}
		}
	}
}
namespace Silksong.AssetHelper.Plugin
{
	public static class AssetRequestAPI
	{
		internal static DelayedAction AfterBundleCreationComplete = new DelayedAction();

		internal static bool RequestApiAvailable { get; set; } = true;


		internal static bool AnyRequestMade
		{
			get
			{
				if (RequestedNonSceneAssets.Count <= 0)
				{
					return SceneAssetRequest.Count > 0;
				}
				return true;
			}
		}

		internal static Dictionary<string, HashSet<string>> SceneAssetRequest { get; } = new Dictionary<string, HashSet<string>>();


		public static IResourceLocator? SceneAssetLocator { get; internal set; }

		public static IResourceLocator? NonSceneAssetLocator { get; internal set; }

		internal static Dictionary<(string bundleName, string assetName), Type> RequestedNonSceneAssets { get; } = new Dictionary<(string, string), Type>();


		private static void VerifyRequest([CallerMemberName] string? caller = null)
		{
			if (!RequestApiAvailable)
			{
				throw new InvalidOperationException("Requests made through " + caller + " should be made during a plugin's Awake method!");
			}
		}

		public static void InvokeAfterBundleCreation(Action a)
		{
			AfterBundleCreationComplete.Subscribe(a);
		}

		public static void RequestSceneAssets(string sceneName, IEnumerable<string> assetPaths)
		{
			VerifyRequest("RequestSceneAssets");
			sceneName = sceneName.ToLowerInvariant();
			HashSet<string> value;
			HashSet<string> hashSet = (SceneAssetRequest.TryGetValue(sceneName, out value) ? value : new HashSet<string>());
			hashSet.UnionWith(assetPaths);
			SceneAssetRequest[sceneName] = hashSet;
		}

		public static void RequestSceneAsset(string sceneName, string assetPath)
		{
			RequestSceneAssets(sceneName, new <>z__ReadOnlySingleElementList<string>(assetPath));
		}

		public static void RequestSceneAssets(Dictionary<string, List<string>> assetData)
		{
			foreach (var (sceneName, assetPaths) in assetData)
			{
				RequestSceneAssets(sceneName, assetPaths);
			}
		}

		public static void RequestNonSceneAsset<T>(string bundleName, string assetName)
		{
			RequestNonSceneAsset(bundleName, assetName, typeof(T));
		}

		public static void RequestNonSceneAsset(string bundleName, string assetName, Type assetType)
		{
			VerifyRequest("RequestNonSceneAsset");
			bundleName = bundleName.ToLowerInvariant();
			if (bundleName.EndsWith(".bundle"))
			{
				string text = bundleName;
				bundleName = text.Substring(0, text.Length - 7);
			}
			if (RequestedNonSceneAssets.TryGetValue((bundleName, assetName), out Type value) && value != assetType)
			{
				AssetHelperPlugin.InstanceLogger.LogError((object)("Asset " + bundleName + " - " + assetName + " requested with both " + value.Name + " and " + assetType.Name));
			}
			RequestedNonSceneAssets[(bundleName, assetName)] = assetType;
		}

		public static void RequestNonSceneAssets<T>(string bundleName, IEnumerable<string> assetNames) where T : Object
		{
			foreach (string assetName in assetNames)
			{
				RequestNonSceneAsset<T>(bundleName, assetName);
			}
		}
	}
	public static class CatalogKeys
	{
		public static string SceneCatalogId => "AssetHelper-RepackedScenes";

		public static string NonSceneCatalogId => "AssetHelper-BundleAssets";

		public static string GetKeyForSceneAsset(string sceneName, string objPath)
		{
			return SceneCatalogId + "/Assets/" + sceneName.ToLowerInvariant() + "/" + objPath;
		}

		public static string GetKeyForNonSceneAsset(string assetName)
		{
			return NonSceneCatalogId + "/" + assetName;
		}
	}
	internal class CatalogMetadata
	{
		public string SilksongVersion { get; set; } = VersionData.SilksongVersion;


		public string PluginVersion { get; set; } = AssetHelperPlugin.Version;

	}
	internal class SceneCatalogMetadata : CatalogMetadata
	{
	}
	internal class NonSceneCatalogMetadata : CatalogMetadata
	{
		[JsonConverter(typeof(DictListConverter<ValueTuple<string, string>, Type>))]
		public Dictionary<(string bundleName, string assetName), Type> CatalogAssets { get; set; } = new Dictionary<(string, string), Type>();

	}
	internal class CustomCatalogBuilder
	{
		private readonly string _primaryKeyPrefix;

		private readonly Dictionary<string, ContentCatalogDataEntry> _baseBundleEntries;

		private readonly HashSet<string> _includedBaseBundles = new HashSet<string>();

		private readonly Dictionary<string, string> _basePrimaryKeys = new Dictionary<string, string>();

		private readonly List<ContentCatalogDataEntry> _addedEntries = new List<ContentCatalogDataEntry>();

		public CustomCatalogBuilder(string primaryKeyPrefix = "AssetHelper")
		{
			_primaryKeyPrefix = primaryKeyPrefix;
			_baseBundleEntries = new Dictionary<string, ContentCatalogDataEntry>();
			foreach (string key in AddressablesData.BundleKeys.Keys)
			{
				if (AddressablesData.TryGetLocation(key, out IResourceLocation location) && !(location.ResourceType != typeof(IAssetBundleResource)) && !location.PrimaryKey.StartsWith("scenes_scenes_scenes") && AddressablesData.TryStrip(location.PrimaryKey, out string stripped))
				{
					string text = _primaryKeyPrefix + "/DependencyBundles/" + stripped;
					ContentCatalogDataEntry value = CatalogEntryUtils.CreateEntryFromLocation(location, text);
					_baseBundleEntries.Add(stripped, value);
					_basePrimaryKeys.Add(stripped, text);
				}
			}
		}

		public bool TryDeclareBundleDep(string bundleName, [NotNullWhen(true)] out string? primaryKey)
		{
			string text = bundleName.ToLowerInvariant().Replace(".bundle", "");
			if (!_basePrimaryKeys.TryGetValue(text, out primaryKey))
			{
				return false;
			}
			_includedBaseBundles.Add(text);
			return true;
		}

		public void AddRepackedSceneData(string sceneName, RepackedBundleData data, string bundlePath)
		{
			string text = _primaryKeyPrefix + "/SceneBundles/" + sceneName;
			ContentCatalogDataEntry item = CatalogEntryUtils.CreateBundleEntry(text, bundlePath, data.BundleName, new List<string>());
			_addedEntries.Add(item);
			List<string> list = new List<string>(1) { text };
			foreach (string item3 in BundleMetadata.DetermineCatalogDeps("scenes_scenes_scenes/" + sceneName + ".bundle"))
			{
				if (!TryDeclareBundleDep(item3, out string primaryKey))
				{
					AssetHelperPlugin.InstanceLogger.LogWarning((object)("Error adding asset from scene " + sceneName + " with alien dep " + item3));
				}
				else
				{
					list.Add(primaryKey);
				}
			}
			foreach (KeyValuePair<string, string> item4 in data.GameObjectAssets ?? new Dictionary<string, string>())
			{
				item4.Deconstruct(out var key, out var value);
				string internalId = key;
				string text2 = value;
				ContentCatalogDataEntry item2 = CatalogEntryUtils.CreateAssetEntry(internalId, typeof(GameObject), list, _primaryKeyPrefix + "/Assets/" + sceneName + "/" + text2);
				_addedEntries.Add(item2);
			}
		}

		public void AddAssets(string bundle, List<(string asset, Type assetType)> data)
		{
			if (!TryDeclareBundleDep(bundle, out string primaryKey))
			{
				throw new ArgumentException("Error adding assets from bundle " + bundle + ": bundle not recognized");
			}
			List<string> list = new List<string>(1) { primaryKey };
			foreach (string item4 in BundleMetadata.DetermineTransitiveDeps(bundle))
			{
				if (!TryDeclareBundleDep(item4, out string primaryKey2))
				{
					AssetHelperPlugin.InstanceLogger.LogWarning((object)("Error adding asset from " + bundle + ": unrecognized T-dep " + item4));
				}
				else
				{
					list.Add(primaryKey2);
				}
			}
			foreach (var datum in data)
			{
				string item = datum.asset;
				Type item2 = datum.assetType;
				ContentCatalogDataEntry item3 = CatalogEntryUtils.CreateAssetEntry(item, item2, list, _primaryKeyPrefix + "/" + item);
				_addedEntries.Add(item3);
			}
		}

		public void AddCatalogEntry(ContentCatalogDataEntry entry)
		{
			_addedEntries.Add(entry);
		}

		public string Build(string? catalogId = null)
		{
			if (catalogId == null)
			{
				catalogId = _primaryKeyPrefix;
			}
			List<ContentCatalogDataEntry> list = new List<ContentCatalogDataEntry>();
			list.AddRange(_includedBaseBundles.Select((string x) => _baseBundleEntries[x]));
			list.AddRange(_addedEntries);
			return CatalogUtils.WriteCatalog(list, catalogId);
		}
	}
	public sealed class RepackedSceneBundleData
	{
		public string SilksongVersion { get; init; } = VersionData.SilksongVersion;


		public string PluginVersion { get; init; } = AssetHelperPlugin.Version;


		public required string SceneName { get; init; }

		public string? BundleHash { get; init; }

		public RepackedBundleData? Data { get; set; }
	}
	[MonoDetourTargets(typeof(StartManager))]
	internal static class StartupOverrideManager
	{
		[CompilerGenerated]
		private sealed class <WrapStartManagerStart>d__4 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public IEnumerator original;

			private LoadingBar <bar>5__2;

			private bool <failed>5__3;

			private List<BaseStartupTask>.Enumerator <>7__wrap3;

			private BaseStartupTask <task>5__5;

			private IEnumerator <enumerator>5__6;

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

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

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

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				int num = <>1__state;
				if (num == -3 || num == 2)
				{
					try
					{
					}
					finally
					{
						<>m__Finally1();
					}
				}
				<bar>5__2 = null;
				<>7__wrap3 = default(List<BaseStartupTask>.Enumerator);
				<task>5__5 = null;
				<enumerator>5__6 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_004f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0059: Expected O, but got Unknown
				try
				{
					bool flag;
					switch (<>1__state)
					{
					default:
						return false;
					case 0:
						<>1__state = -1;
						<>2__current = (object)new WaitUntil((Func<bool>)(() => AddressablesData.IsAddressablesLoaded));
						<>1__state = 1;
						return true;
					case 1:
						<>1__state = -1;
						<bar>5__2 = LoadingBar.Create();
						<failed>5__3 = false;
						<>7__wrap3 = _tasks.GetEnumerator();
						<>1__state = -3;
						goto IL_0151;
					case 2:
						<>1__state = -3;
						goto IL_00c6;
					case 3:
						<>1__state = -1;
						<>2__current = original;
						<>1__state = 4;
						return true;
					case 4:
						{
							<>1__state = -1;
							return false;
						}
						IL_0151:
						if (<>7__wrap3.MoveNext())
						{
							<task>5__5 = <>7__wrap3.Current;
							<enumerator>5__6 = <task>5__5.Run(<bar>5__2);
							goto IL_00c6;
						}
						goto IL_0161;
						IL_00c6:
						try
						{
							flag = <enumerator>5__6.MoveNext();
						}
						catch (Exception ex)
						{
							AssetHelperPlugin.InstanceLogger.LogError((object)($"Error during startup task of type {<task>5__5.GetType()}\n" + ex));
							<failed>5__3 = true;
							goto IL_013b;
						}
						if (flag)
						{
							<>2__current = <enumerator>5__6.Current;
							<>1__state = 2;
							return true;
						}
						goto IL_013b;
						IL_0161:
						<>m__Finally1();
						<>7__wrap3 = default(List<BaseStartupTask>.Enumerator);
						if (!<failed>5__3)
						{
							AssetHelperPlugin.InstanceLogger.LogInfo((object)"AssetHelper prep complete!");
							AssetRequestAPI.AfterBundleCreationComplete.Activate();
							_startupRun = true;
							<bar>5__2.SetProgress(1f);
						}
						else
						{
							AssetHelperPlugin.InstanceLogger.LogWarning((object)"An error occurred during startup, and AssetHelper did not finish.");
						}
						Object.Destroy((Object)(object)<bar>5__2);
						<>2__current = null;
						<>1__state = 3;
						return true;
						IL_013b:
						if (!<failed>5__3)
						{
							<enumerator>5__6 = null;
							<task>5__5 = null;
							goto IL_0151;
						}
						goto IL_0161;
					}
				}
				catch
				{
					//try-fault
					((IDisposable)this).Dispose();
					throw;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			private void <>m__Finally1()
			{
				<>1__state = -1;
				((IDisposable)<>7__wrap3).Dispose();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		private static bool _startupRun = false;

		private static List<BaseStartupTask> _tasks = new List<BaseStartupTask>(3)
		{
			new BundleDepsPrecompute(),
			new SceneRepacking(),
			new NonSceneCatalog()
		};

		internal static void Hook()
		{
			Start.Postfix(PrependStartManagerStart);
		}

		private static void PrependStartManagerStart(StartManager self, ref IEnumerator returnValue)
		{
			if (!_startupRun)
			{
				returnValue = WrapStartManagerStart(self, returnValue);
			}
		}

		[IteratorStateMachine(typeof(<WrapStartManagerStart>d__4))]
		private static IEnumerator WrapStartManagerStart(StartManager self, IEnumerator original)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <WrapStartManagerStart>d__4(0)
			{
				original = original
			};
		}
	}
}
namespace Silksong.AssetHelper.Plugin.Tasks
{
	internal abstract class BaseStartupTask
	{
		public abstract IEnumerator Run(LoadingBar loadingBar);
	}
	internal class BundleDepsPrecompute : BaseStartupTask
	{
		[CompilerGenerated]
		private sealed class <Run>d__0 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public LoadingBar loadingBar;

			private Stopwatch <sw>5__2;

			private List<string> <bundles>5__3;

			private int <ct>5__4;

			private int <misses>5__5;

			private List<string>.Enumerator <>7__wrap5;

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

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

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

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				int num = <>1__state;
				if (num == -3 || num == 2)
				{
					try
					{
					}
					finally
					{
						<>m__Finally1();
					}
				}
				<sw>5__2 = null;
				<bundles>5__3 = null;
				<>7__wrap5 = default(List<string>.Enumerator);
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				try
				{
					switch (<>1__state)
					{
					default:
						return false;
					case 0:
						<>1__state = -1;
						if (AssetRequestAPI.RequestedNonSceneAssets.Count == 0)
						{
							return false;
						}
						loadingBar.SetText("COMPUTING_BUNDLE_DEPS".GetLocalized());
						<>2__current = null;
						<>1__state = 1;
						return true;
					case 1:
						<>1__state = -1;
						AssetHelperPlugin.InstanceLogger.LogInfo((object)"Computing bundle deps");
						<sw>5__2 = Stopwatch.StartNew();
						<bundles>5__3 = AddressablesData.BundleKeys.Keys.Where((string x) => !x.Contains("scenes_scenes_scenes")).ToList();
						loadingBar.SetProgress(0f);
						<ct>5__4 = 0;
						<misses>5__5 = 0;
						<>7__wrap5 = <bundles>5__3.GetEnumerator();
						<>1__state = -3;
						break;
					case 2:
						<>1__state = -3;
						break;
					}
					while (<>7__wrap5.MoveNext())
					{
						BundleMetadata.DetermineDirectDepsInternal(<>7__wrap5.Current, out var cacheHit);
						<ct>5__4++;
						loadingBar.SetProgress((float)<ct>5__4 / (float)<bundles>5__3.Count);
						if (!cacheHit)
						{
							<misses>5__5++;
							if (<misses>5__5 % 5 == 0)
							{
								<>2__current = null;
								<>1__state = 2;
								return true;
							}
						}
					}
					<>m__Finally1();
					<>7__wrap5 = default(List<string>.Enumerator);
					<sw>5__2.Stop();
					AssetHelperPlugin.InstanceLogger.LogInfo((object)$"Computed bundle deps in {<sw>5__2.ElapsedMilliseconds} ms.");
					return false;
				}
				catch
				{
					//try-fault
					((IDisposable)this).Dispose();
					throw;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			private void <>m__Finally1()
			{
				<>1__state = -1;
				((IDisposable)<>7__wrap5).Dispose();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		[IteratorStateMachine(typeof(<Run>d__0))]
		public override IEnumerator Run(LoadingBar loadingBar)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <Run>d__0(0)
			{
				loadingBar = loadingBar
			};
		}
	}
	internal class NonSceneCatalog : BaseStartupTask
	{
		[CompilerGenerated]
		private sealed class <CreateAndLoadCatalog>d__3 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public NonSceneCatalog <>4__this;

			public LoadingBar bar;

			private IEnumerator <nonSceneCatalogCreate>5__2;

			private AsyncOperationHandle<IResourceLocator> <catalogLoadOp>5__3;

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

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

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

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				//IL_000d: Unknown result type (might be due to invalid IL or missing references)
				<nonSceneCatalogCreate>5__2 = null;
				<catalogLoadOp>5__3 = default(AsyncOperationHandle<IResourceLocator>);
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_010f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0114: Unknown result type (might be due to invalid IL or missing references)
				//IL_011b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0150: Unknown result type (might be due to invalid IL or missing references)
				int num = <>1__state;
				NonSceneCatalog nonSceneCatalog = <>4__this;
				switch (num)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<nonSceneCatalogCreate>5__2 = nonSceneCatalog.CreateNonSceneAssetCatalog();
					bar.SetText("BUILDING_NON_SCENE".GetLocalized());
					<>2__current = null;
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					goto IL_008a;
				case 2:
					<>1__state = -1;
					goto IL_008a;
				case 3:
					<>1__state = -1;
					if (File.Exists(NonSceneCatalogPath) && AssetRequestAPI.RequestedNonSceneAssets.Count > 0)
					{
						bar.SetText("LOADING_NON_SCENE".GetLocalized());
						<>2__current = null;
						<>1__state = 4;
						return true;
					}
					goto IL_0156;
				case 4:
					<>1__state = -1;
					AssetHelperPlugin.InstanceLogger.LogInfo((object)"Loading non-scene catalog");
					<catalogLoadOp>5__3 = Addressables.LoadContentCatalogAsync(NonSceneCatalogPath, (string)null);
					<>2__current = <catalogLoadOp>5__3;
					<>1__state = 5;
					return true;
				case 5:
					<>1__state = -1;
					AssetRequestAPI.NonSceneAssetLocator = <catalogLoadOp>5__3.Result;
					<catalogLoadOp>5__3 = default(AsyncOperationHandle<IResourceLocator>);
					goto IL_0156;
				case 6:
					{
						<>1__state = -1;
						return false;
					}
					IL_0156:
					<>2__current = null;
					<>1__state = 6;
					return true;
					IL_008a:
					if (<nonSceneCatalogCreate>5__2.MoveNext())
					{
						<>2__current = null;
						<>1__state = 2;
						return true;
					}
					<>2__current = null;
					<>1__state = 3;
					return true;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

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

			private object <>2__current;

			private string <catalogMetadataPath>5__2;

			private NonSceneCatalogMetadata <metadata>5__3;

			private CustomCatalogBuilder <cbr>5__4;

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

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

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

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<catalogMetadataPath>5__2 = null;
				<metadata>5__3 = null;
				<cbr>5__4 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
				{
					<>1__state = -1;
					<catalogMetadataPath>5__2 = Path.ChangeExtension(NonSceneCatalogPath, ".json");
					AssetHelperPlugin.InstanceLogger.LogInfo((object)"Creating NS catalog");
					Dictionary<(string, string), Type> dictionary = new Dictionary<(string, string), Type>();
					bool flag = false;
					if (JsonExtensions.TryLoadFromFile<NonSceneCatalogMetadata>(<catalogMetadataPath>5__2, out NonSceneCatalogMetadata obj) && obj.SilksongVersion == VersionData.SilksongVersion && VersionData.EarliestAcceptableNonSceneCatalogVersion.AllowCachedData(obj.PluginVersion))
					{
						dictionary = obj.CatalogAssets;
					}
					(string, string) key;
					Type value;
					foreach (KeyValuePair<(string, string), Type> requestedNonSceneAsset in AssetRequestAPI.RequestedNonSceneAssets)
					{
						requestedNonSceneAsset.Deconstruct(out key, out value);
						(string, string) tuple = key;
						Type type = value;
						if (!dictionary.ContainsKey(tuple))
						{
							dictionary.Add(tuple, type);
							flag = true;
						}
						else if (dictionary[tuple] != type)
						{
							AssetHelperPlugin.InstanceLogger.LogInfo((object)$"Replacing {tuple} :: {dictionary[tuple]} -> {type}");
							dictionary[tuple] = type;
							flag = true;
						}
					}
					if (!flag)
					{
						AssetHelperPlugin.InstanceLogger.LogInfo((object)"Not writing non-scene catalog: no new assets added");
						return false;
					}
					<metadata>5__3 = new NonSceneCatalogMetadata();
					<cbr>5__4 = new CustomCatalogBuilder(CatalogKeys.NonSceneCatalogId);
					foreach (KeyValuePair<(string, string), Type> requestedNonSceneAsset2 in AssetRequestAPI.RequestedNonSceneAssets)
					{
						requestedNonSceneAsset2.Deconstruct(out key, out value);
						(string, string) tuple2 = key;
						string item = tuple2.Item1;
						string item2 = tuple2.Item2;
						Type type2 = value;
						<cbr>5__4.AddAssets(item, new List<(string, Type)>(1) { (item2, type2) });
						<metadata>5__3.CatalogAssets.Add((item, item2), type2);
					}
					<>2__current = null;
					<>1__state = 1;
					return true;
				}
				case 1:
					<>1__state = -1;
					AssetHelperPlugin.InstanceLogger.LogInfo((object)"Writing catalog");
					<cbr>5__4.Build();
					<metadata>5__3.SerializeToFile(<catalogMetadataPath>5__2);
					return false;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		private static string NonSceneCatalogPath => Path.Combine(AssetPaths.CatalogFolder, CatalogKeys.NonSceneCatalogId + ".bin");

		public override IEnumerator Run(LoadingBar loadingBar)
		{
			return CreateAndLoadCatalog(loadingBar);
		}

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

		[IteratorStateMachine(typeof(<CreateNonSceneAssetCatalog>d__4))]
		private IEnumerator CreateNonSceneAssetCatalog()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <CreateNonSceneAssetCatalog>d__4(0);
		}
	}
	internal class SceneRepacking : BaseStartupTask
	{
		[CompilerGenerated]
		private sealed class <CreateSceneAssetCatalog>d__13 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public SceneRepacking <>4__this;

			public Dictionary<string, RepackedSceneBundleData> data;

			private string <catalogMetadataPath>5__2;

			private CustomCatalogBuilder <cbr>5__3;

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

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

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

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<catalogMetadataPath>5__2 = null;
				<cbr>5__3 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				int num = <>1__state;
				SceneRepacking sceneRepacking = <>4__this;
				switch (num)
				{
				default:
					return false;
				case 0:
				{
					<>1__state = -1;
					<catalogMetadataPath>5__2 = Path.ChangeExtension(SceneCatalogPath, ".json");
					if (!sceneRepacking._didRepack && JsonExtensions.TryLoadFromFile<SceneCatalogMetadata>(<catalogMetadataPath>5__2, out SceneCatalogMetadata obj) && obj.SilksongVersion == VersionData.SilksongVersion && VersionData.EarliestAcceptableSceneRepackVersion.AllowCachedData(obj.PluginVersion))
					{
						return false;
					}
					AssetHelperPlugin.InstanceLogger.LogInfo((object)"Creating catalog");
					Stopwatch stopwatch = Stopwatch.StartNew();
					<cbr>5__3 = new CustomCatalogBuilder(CatalogKeys.SceneCatalogId);
					string objPath = default(string);
					string text3 = default(string);
					foreach (var (text2, repackedSceneBundleData2) in data)
					{
						if (repackedSceneBundleData2.Data == null)
						{
							continue;
						}
						string bundlePathForScene = GetBundlePathForScene(text2);
						<cbr>5__3.AddRepackedSceneData(text2, repackedSceneBundleData2.Data, bundlePathForScene);
						if (!AssetRequestAPI.SceneAssetRequest.TryGetValue(text2, out HashSet<string> value))
						{
							continue;
						}
						foreach (string item in value)
						{
							if (!ObjPathUtil.TryFindAncestor(repackedSceneBundleData2.Data.GameObjectAssets?.Values.ToList(), item, ref objPath, ref text3))
							{
								AssetHelperPlugin.InstanceLogger.LogWarning((object)("Failed to find " + item + " in bundle for " + text2 + " as loadable"));
							}
							else if (!string.IsNullOrEmpty(text3))
							{
								ContentCatalogDataEntry entry = CatalogEntryUtils.CreateChildGameObjectEntry(CatalogKeys.GetKeyForSceneAsset(text2, objPath), primaryKey: CatalogKeys.GetKeyForSceneAsset(text2, item), relativePath: text3);
								<cbr>5__3.AddCatalogEntry(entry);
							}
						}
					}
					stopwatch.Stop();
					AssetHelperPlugin.InstanceLogger.LogInfo((object)$"Prepared catalog in {stopwatch.ElapsedMilliseconds} ms");
					<>2__current = null;
					<>1__state = 1;
					return true;
				}
				case 1:
				{
					<>1__state = -1;
					Stopwatch stopwatch = Stopwatch.StartNew();
					<cbr>5__3.Build();
					stopwatch.Stop();
					AssetHelperPlugin.InstanceLogger.LogInfo((object)$"Finished writing catalog in {stopwatch.ElapsedMilliseconds} ms");
					new SceneCatalogMetadata().SerializeToFile(<catalogMetadataPath>5__2);
					<>2__current = null;
					<>1__state = 2;
					return true;
				}
				case 2:
					<>1__state = -1;
					return false;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

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

			private object <>2__current;

			public SceneRepacking <>4__this;

			public LoadingBar bar;

			private IEnumerator <repack>5__2;

			private IEnumerator <catalogCreate>5__3;

			private AsyncOperationHandle<IResourceLocator> <catalogLoadOp>5__4;

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

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

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

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				//IL_0014: Unknown result type (might be due to invalid IL or missing references)
				<repack>5__2 = null;
				<catalogCreate>5__3 = null;
				<catalogLoadOp>5__4 = default(AsyncOperationHandle<IResourceLocator>);
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0183: Unknown result type (might be due to invalid IL or missing references)
				//IL_0188: Unknown result type (might be due to invalid IL or missing references)
				//IL_018f: Unknown result type (might be due to invalid IL or missing references)
				//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
				int num = <>1__state;
				SceneRepacking sceneRepacking = <>4__this;
				switch (num)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<repack>5__2 = sceneRepacking.PrepareAndRun(bar);
					bar.SetText("REPACKING_SCENE".GetLocalized());
					<>2__current = null;
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					goto IL_0098;
				case 2:
					<>1__state = -1;
					goto IL_0098;
				case 3:
					<>1__state = -1;
					<catalogCreate>5__3 = sceneRepacking.CreateSceneAssetCatalog(sceneRepacking._repackData);
					goto IL_010c;
				case 4:
					<>1__state = -1;
					goto IL_010c;
				case 5:
					<>1__state = -1;
					if (sceneRepacking._repackData.Count > 0)
					{
						bar.SetText("LOADING_SCENE".GetLocalized());
						<>2__current = null;
						<>1__state = 6;
						return true;
					}
					goto IL_01ca;
				case 6:
					<>1__state = -1;
					AssetHelperPlugin.InstanceLogger.LogInfo((object)"Loading scene catalog");
					<catalogLoadOp>5__4 = Addressables.LoadContentCatalogAsync(SceneCatalogPath, (string)null);
					<>2__current = <catalogLoadOp>5__4;
					<>1__state = 7;
					return true;
				case 7:
					<>1__state = -1;
					AssetRequestAPI.SceneAssetLocator = <catalogLoadOp>5__4.Result;
					<catalogLoadOp>5__4 = default(AsyncOperationHandle<IResourceLocator>);
					goto IL_01ca;
				case 8:
					{
						<>1__state = -1;
						return false;
					}
					IL_0098:
					if (<repack>5__2.MoveNext())
					{
						<>2__current = null;
						<>1__state = 2;
						return true;
					}
					bar.SetProgress(1f);
					bar.SetText("BULDING_SCENE".GetLocalized());
					<>2__current = null;
					<>1__state = 3;
					return true;
					IL_01ca:
					<>2__current = null;
					<>1__state = 8;
					return true;
					IL_010c:
					if (<catalogCreate>5__3.MoveNext())
					{
						<>2__current = null;
						<>1__state = 4;
						return true;
					}
					<>2__current = null;
					<>1__state = 5;
					return true;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

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

			private object <>2__current;

			public SceneRepacking <>4__this;

			public LoadingBar bar;

			private SceneRepacker <repacker>5__2;

			private int <total>5__3;

			private int <count>5__4;

			private Dictionary<string, HashSet<string>>.Enumerator <>7__wrap4;

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

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

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

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				int num = <>1__state;
				if (num == -3 || num == 1)
				{
					try
					{
					}
					finally
					{
						<>m__Finally1();
					}
				}
				<repacker>5__2 = null;
				<>7__wrap4 = default(Dictionary<string, HashSet<string>>.Enumerator);
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0027: Unknown result type (might be due to invalid IL or missing references)
				//IL_0031: Expected O, but got Unknown
				//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
				//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
				//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
				//IL_0101: Unknown result type (might be due to invalid IL or missing references)
				//IL_010f: Expected O, but got Unknown
				try
				{
					int num = <>1__state;
					SceneRepacking sceneRepacking = <>4__this;
					switch (num)
					{
					default:
						return false;
					case 0:
						<>1__state = -1;
						<repacker>5__2 = (SceneRepacker)new StrippedSceneRepacker();
						<total>5__3 = sceneRepacking._toRepack.Count;
						<count>5__4 = 0;
						AssetHelperPlugin.InstanceLogger.LogInfo((object)$"Repacking {sceneRepacking._toRepack.Count} scenes");
						<>7__wrap4 = sceneRepacking._toRepack.GetEnumerator();
						<>1__state = -3;
						break;
					case 1:
						<>1__state = -3;
						break;
					}
					if (<>7__wrap4.MoveNext())
					{
						<>7__wrap4.Current.Deconstruct(out string key, out HashSet<string> value);
						string text = key;
						HashSet<string> hashSet = value;
						Stopwatch stopwatch = Stopwatch.StartNew();
						AssetHelperPlugin.InstanceLogger.LogInfo((object)$"Repacking {hashSet.Count} objects in scene {text}");
						RepackingParams val = new RepackingParams
						{
							SceneBundlePath = AssetPaths.GetScenePath(text),
							ObjectNames = hashSet.ToList(),
							ContainerPrefix = "AssetHelper/" + text,
							OutBundlePath = GetBundlePathForScene(text)
						};
						RepackedBundleData data = <repacker>5__2.Repack(val);
						string bundleHash = null;
						if (AddressablesData.TryGetLocationForScene(text, out IResourceLocation location))
						{
							object data2 = location.Data;
							AssetBundleRequestOptions val2 = (AssetBundleRequestOptions)((data2 is AssetBundleRequestOptions) ? data2 : null);
							if (val2 != null)
							{
								bundleHash = val2.Hash;
							}
						}
						RepackedSceneBundleData value2 = new RepackedSceneBundleData
						{
							SceneName = text,
							BundleHash = bundleHash,
							Data = data
						};
						sceneRepacking._repackData[text] = value2;
						sceneRepacking._repackData.SerializeToFile(_repackDataPath);
						AssetHelperPlugin.InstanceLogger.LogInfo((object)$"Repacked {text} in {stopwatch.ElapsedMilliseconds} ms");
						<count>5__4++;
						bar.SetProgress((float)<count>5__4 / (float)<total>5__3);
						<>2__current = null;
						<>1__state = 1;
						return true;
					}
					<>m__Finally1();
					<>7__wrap4 = default(Dictionary<string, HashSet<string>>.Enumerator);
					return false;
				}
				catch
				{
					//try-fault
					((IDisposable)this).Dispose();
					throw;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			private void <>m__Finally1()
			{
				<>1__state = -1;
				((IDisposable)<>7__wrap4).Dispose();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		private static string _repackDataPath = Path.Combine(AssetPaths.RepackedSceneBundleDir, "repack_data.json");

		private Dictionary<string, HashSet<string>> _toRepack = new Dictionary<string, HashSet<string>>();

		private Dictionary<string, RepackedSceneBundleData> _repackData = new Dictionary<string, RepackedSceneBundleData>();

		private bool _didRepack;

		private static string SceneCatalogPath => Path.Combine(AssetPaths.CatalogFolder, CatalogKeys.SceneCatalogId + ".bin");

		public override IEnumerator Run(LoadingBar loadingBar)
		{
			return RepackAndCatalogScenes(loadingBar);
		}

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

		private IEnumerator PrepareAndRun(LoadingBar bar)
		{
			Prepare();
			if (_toRepack.Count > 0)
			{
				_didRepack = true;
				return RunRepacking(bar);
			}
			return Enumerable.Empty<object>().GetEnumerator();
		}

		private void Prepare()
		{
			if (JsonExtensions.TryLoadFromFile<Dictionary<string, RepackedSceneBundleData>>(_repackDataPath, out Dictionary<string, RepackedSceneBundleData> obj))
			{
				_repackData = obj;
			}
			else
			{
				_repackData = new Dictionary<string, RepackedSceneBundleData>();
			}
			_repackData = _repackData.Where<KeyValuePair<string, RepackedSceneBundleData>>((KeyValuePair<string, RepackedSceneBundleData> kvp) => !MetadataMismatch(kvp.Key, kvp.Value) && File.Exists(GetBundlePathForScene(kvp.Key))).ToDictionary((KeyValuePair<string, RepackedSceneBundleData> kvp) => kvp.Key, (KeyValuePair<string, RepackedSceneBundleData> kvp) => kvp.Value);
			_toRepack = new Dictionary<string, HashSet<string>>();
			foreach (KeyValuePair<string, HashSet<string>> item in AssetRequestAPI.SceneAssetRequest)
			{
				item.Deconstruct(out var key, out var value);
				string key2 = key;
				HashSet<string> hashSet = value;
				if (!_repackData.TryGetValue(key2, out RepackedSceneBundleData existingBundleData))
				{
					_toRepack[key2] = hashSet;
				}
				else if (existingBundleData.Data == null)
				{
					_toRepack[key2] = hashSet;
				}
				else if (!hashSet.All((string x) => RepackedBundleDataExtensions.TriedToRepack(existingBundleData.Data, x)))
				{
					Dictionary<string, HashSet<string>> toRepack = _toRepack;
					IEnumerable<string> enumerable = existingBundleData.Data.GameObjectAssets?.Values;
					toRepack[key2] = new HashSet<string>(hashSet.Union(enumerable ?? Enumerable.Empty<string>()));
				}
			}
		}

		private static string GetBundlePathForScene(string sceneName)
		{
			return Path.Combine(AssetPaths.RepackedSceneBundleDir, "repacked_" + sceneName + ".bundle");
		}

		private static bool MetadataMismatch(string scene, RepackedSceneBundleData existingData)
		{
			if (!VersionData.EarliestAcceptableSceneRepackVersion.AllowCachedData(existingData.PluginVersion))
			{
				return true;
			}
			if (existingData.SilksongVersion == VersionData.SilksongVersion)
			{
				return false;
			}
			if (AddressablesData.TryGetLocationForScene(scene, out IResourceLocation location))
			{
				object data = location.Data;
				AssetBundleRequestOptions val = (AssetBundleRequestOptions)((data is AssetBundleRequestOptions) ? data : null);
				if (val != null && !string.IsNullOrEmpty(val.Hash) && !string.IsNullOrEmpty(existingData.BundleHash) && val.Hash == existingData.BundleHash)
				{
					return false;
				}
			}
			return true;
		}

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

		[IteratorStateMachine(typeof(<CreateSceneAssetCatalog>d__13))]
		private IEnumerator CreateSceneAssetCatalog(Dictionary<string, RepackedSceneBundleData> data)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <CreateSceneAssetCatalog>d__13(0)
			{
				<>4__this = this,
				data = data
			};
		}
	}
}
namespace Silksong.AssetHelper.ManagedAssets
{
	public interface IManagedAsset
	{
		object? Load();

		void Unload();
	}
	public class ManagedAsset<T> : IManagedAsset
	{
		private AsyncOperationHandle<T>? _handle;

		public string Key { get; }

		public AsyncOperationHandle<T> Handle
		{
			get
			{
				//IL_002e: Unknown result type (might be due to invalid IL or missing references)
				if (!_handle.HasValue)
				{
					throw new InvalidOperationException("Addressable asset with key " + Key + " must be loaded before accessing the handle!");
				}
				return _handle.Value;
			}
		}

		public bool IsLoaded
		{
			get
			{
				//IL_0009: Unknown result type (might be due to invalid IL or missing references)
				//IL_000e: Unknown result type (might be due to invalid IL or missing references)
				if (HasBeenLoaded)
				{
					return Handle.IsDone;
				}
				return false;
			}
		}

		public bool HasBeenLoaded => _handle.HasValue;

		public ManagedAsset(string key)
		{
			Key = key;
			base..ctor();
		}

		public static ManagedAsset<T> FromSceneAsset(string sceneName, string objPath)
		{
			if (typeof(T) != typeof(GameObject))
			{
				AssetHelperPlugin.InstanceLogger.LogWarning((object)"ManagedAsset instances for scene assets should have GameObject as the type argument!");
			}
			if (AssetRequestAPI.RequestApiAvailable)
			{
				AssetRequestAPI.RequestSceneAsset(sceneName, objPath);
			}
			return new ManagedAsset<T>(CatalogKeys.GetKeyForSceneAsset(sceneName, objPath));
		}

		public static ManagedAsset<T> FromNonSceneAsset(string assetName, string? bundleName = null)
		{
			if (AssetRequestAPI.RequestApiAvailable && !string.IsNullOrEmpty(bundleName))
			{
				AssetRequestAPI.RequestNonSceneAsset<T>(bundleName, assetName);
			}
			return new ManagedAsset<T>(CatalogKeys.GetKeyForNonSceneAsset(assetName));
		}

		public AsyncOperationHandle<T> Load()
		{
			//IL_0024: 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)
			if (!_handle.HasValue)
			{
				_handle = Addressables.LoadAssetAsync<T>((object)Key);
			}
			return Handle;
		}

		object? IManagedAsset.Load()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			return Load();
		}

		public void Unload()
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			if (_handle.HasValue)
			{
				Addressables.Release<T>(_handle.Value);
				_handle = null;
			}
		}
	}
	public static class ManagedAssetExtensions
	{
		public static T InstantiateAsset<T>(this ManagedAsset<T> asset) where T : Object
		{
			//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 (!asset.IsLoaded)
			{
				throw new InvalidOperationException("The asset has not finished loading!");
			}
			return Object.Instantiate<T>(asset.Handle.Result);
		}

		public static T InstantiateAsset<T>(this ManagedAssetGroup<T> group, string key) where T : Object
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			if (!group.IsLoaded)
			{
				throw new InvalidOperationException("The group has not finished loading!");
			}
			return Object.Instantiate<T>(group[key].Result);
		}
	}
	public class ManagedAssetGroup<T> : IManagedAsset
	{
		public record SceneAssetInfo(string SceneName, string ObjPath);

		public record NonSceneAssetInfo(string BundleName, string AssetName);

		private Dictionary<string, string> _keyLookup;

		private Dictionary<string, AsyncOperationHandle<T>>? _handles;

		public AsyncOperationHandle<T> this[string name]
		{
			get
			{
				//IL_001a: Unknown result type (might be due to invalid IL or missing references)
				if (_handles == null)
				{
					throw new InvalidOperationException("Handles can not be accessed until this instance has started loading");
				}
				return _handles[name];
			}
		}

		public bool IsLoaded
		{
			get
			{
				if (HasBeenLoaded)
				{
					return _handles.Values.All((AsyncOperationHandle<T> x) => x.IsDone);
				}
				return false;
			}
		}

		public bool HasBeenLoaded => _handles != null;

		public ManagedAssetGroup(Dictionary<string, string> keyLookup)
		{
			_keyLookup = keyLookup;
		}

		public static ManagedAssetGroup<T> RequestAndCreate(Dictionary<string, SceneAssetInfo>? sceneAssets = null, Dictionary<string, NonSceneAssetInfo>? nonSceneAssets = null)
		{
			if (!AssetRequestAPI.RequestApiAvailable)
			{
				throw new InvalidOperationException("Asset requests should be made during or before a plugin's Awake method!");
			}
			Dictionary<string, string> dictionary = new Dictionary<string, string>();
			string key;
			if (sceneAssets != null)
			{
				if (typeof(T) != typeof(GameObject))
				{
					AssetHelperPlugin.InstanceLogger.LogWarning((object)"ManagedAssetGroup instances for scene assets should have GameObject as the type argument!");
				}
				foreach (KeyValuePair<string, SceneAssetInfo> sceneAsset in sceneAssets)
				{
					sceneAsset.Deconstruct(out key, out var value);
					string key2 = key;
					SceneAssetInfo sceneAssetInfo = value;
					AssetRequestAPI.RequestSceneAsset(sceneAssetInfo.SceneName, sceneAssetInfo.ObjPath);
					dictionary.Add(key2, CatalogKeys.GetKeyForSceneAsset(sceneAssetInfo.SceneName, sceneAssetInfo.ObjPath));
				}
			}
			if (nonSceneAssets != null)
			{
				foreach (KeyValuePair<string, NonSceneAssetInfo> nonSceneAsset in nonSceneAssets)
				{
					nonSceneAsset.Deconstruct(out key, out var value2);
					string key3 = key;
					NonSceneAssetInfo nonSceneAssetInfo = value2;
					AssetRequestAPI.RequestNonSceneAsset<T>(nonSceneAssetInfo.BundleName, nonSceneAssetInfo.AssetName);
					dictionary.Add(key3, CatalogKeys.GetKeyForNonSceneAsset(nonSceneAssetInfo.AssetName));
				}
			}
			return new ManagedAssetGroup<T>(dictionary);
		}

		public CustomYieldInstruction GetYieldInstruction()
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected O, but got Unknown
			if (_handles == null)
			{
				throw new InvalidOperationException("This ManagedAssetGroup must be loaded before awaiting!");
			}
			return (CustomYieldInstruction)new WaitUntil((Func<bool>)(() => IsLoaded));
		}

		public CustomYieldInstruction Load()
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			if (_handles != null)
			{
				return GetYieldInstruction();
			}
			_handles = new Dictionary<string, AsyncOperationHandle<T>>();
			foreach (var (key, text3) in _keyLookup)
			{
				_handles[key] = Addressables.LoadAssetAsync<T>((object)text3);
			}
			return GetYieldInstruction();
		}

		object? IManagedAsset.Load()
		{
			return Load();
		}

		public Task GetTask()
		{
			if (_handles == null)
			{
				throw new InvalidOperationException("This ManagedAssetGroup must be loaded before awaiting!");
			}
			return Task.WhenAll(_handles.Values.Select((AsyncOperationHandle<T> x) => x.Task));
		}

		public void Unload()
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			if (_handles == null)
			{
				return;
			}
			foreach (AsyncOperationHandle<T> value in _handles.Values)
			{
				Addressables.Release<T>(value);
			}
			_handles = null;
		}
	}
	public class ManagedResourceLocation<T> : IManagedAsset
	{
		private AsyncOperationHandle<T>? _handle;

		public IResourceLocation Location { get; }

		public AsyncOperationHandle<T> Handle
		{
			get
			{
				//IL_0033: Unknown result type (might be due to invalid IL or missing references)
				if (!_handle.HasValue)
				{
					throw new InvalidOperationException("Addressable asset with location " + Location.InternalId + " must be loaded before accessing the handle!");
				}
				return _handle.Value;
			}
		}

		public bool IsLoaded
		{
			get
			{
				//IL_0009: Unknown result type (might be due to invalid IL or missing references)
				//IL_000e: Unknown result type (might be due to invalid IL or missing references)
				if (HasBeenLoaded)
				{
					return Handle.IsDone;
				}
				return false;
			}
		}

		public bool HasBeenLoaded => _handle.HasValue;

		public ManagedResourceLocation(IResourceLocation location)
		{
			Location = location;
			base..ctor();
		}

		public AsyncOperationHandle<T> Load()
		{
			//IL_0024: 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)
			if (!_handle.HasValue)
			{
				_handle = Addressables.LoadAssetAsync<T>(Location);
			}
			return Handle;
		}

		object? IManagedAsset.Load()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			return Load();
		}

		public void Unload()
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			if (_handle.HasValue)
			{
				Addressables.Release<T>(_handle.Value);
				_handle = null;
			}
		}
	}
}
namespace Silksong.AssetHelper.Internal
{
	internal static class ActionUtil
	{
		private static readonly ManualLogSource Log = Logger.CreateLogSource("AssetHelper.ActionUtil");

		public static void SafeInvoke(Action? a)
		{
			if (a == null)
			{
				return;
			}
			try
			{
				a();
			}
			catch (Exception ex)
			{
				Log.LogError((object)("Error invoking action " + a.Method.Name + "\n" + ex));
			}
		}

		public static void SafeInvoke<T>(Action<T>? a, T arg)
		{
			if (a == null)
			{
				return;
			}
			try
			{
				a(arg);
			}
			catch (Exception ex)
			{
				Log.LogError((object)("Error invoking action " + a.Method.Name + "\n" + ex));
			}
		}
	}
	internal class CachedObject<T> where T : class
	{
		[JsonProperty]
		public required string SilksongVersion { get; init; }

		[JsonProperty]
		public required string PluginVersion { get; init; }

		[JsonProperty]
		public required T Value { get; set; }

		private CachedObject()
		{
		}

		private bool IsValid()
		{
			if (SilksongVersion == null || PluginVersion == null)
			{
				return false;
			}
			if (VersionData.SilksongVersion != SilksongVersion)
			{
				return false;
			}
			if (!VersionData.EarliestAcceptableGeneralVersion.AllowCachedData(PluginVersion))
			{
				return false;
			}
			return true;
		}

		public static CachedObject<T> CreateSynced(string filename, Func<T> createDefault, bool mutable = true)
		{
			string filePath = Path.Combine(AssetPaths.CacheDirectory, filename);
			if (JsonExtensions.TryLoadFromFile<CachedObject<T>>(filePath, out CachedObject<T> fromCache) && fromCache.Value != null && fromCache.IsValid())
			{
				AssetHelperPlugin.OnQuitApplication += delegate
				{
					fromCache.SerializeToFile(filePath);
				};
				return fromCache;
			}
			CachedObject<T> created = new CachedObject<T>
			{
				SilksongVersion = VersionData.SilksongVersion,
				PluginVersion = AssetHelperPlugin.Version,
				Value = createDefault()
			};
			created.SerializeToFile(filePath);
			if (mutable)
			{
				AssetHelperPlugin.OnQuitApplication += delegate
				{
					created.SerializeToFile(filePath);
				};
			}
			return created;
		}
	}
	internal class DelayedAction
	{
		private List<Action> _subscribers = new List<Action>();

		public bool Activated { get; private set; }

		public void Activate()
		{
			if (Activated)
			{
				return;
			}
			Activated = true;
			foreach (Action subscriber in _subscribers)
			{
				ActionUtil.SafeInvoke(subscriber);
			}
			_subscribers.Clear();
		}

		public void Subscribe(Action toInvoke)
		{
			if (Activated)
			{
				ActionUtil.SafeInvoke(toInvoke);
			}
			else
			{
				_subscribers.Add(toInvoke);
			}
		}
	}
	internal class DictListConverter<T, U> : JsonConverter<Dictionary<T, U>>
	{
		public override Dictionary<T, U>? ReadJson(JsonReader reader, Type objectType, Dictionary<T, U>? existingValue, bool hasExistingValue, JsonSerializer serializer)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Invalid comparison between Unknown and I4
			if ((int)reader.TokenType == 11)
			{
				return null;
			}
			return serializer.Deserialize<List<(T, U)>>(reader)?.ToDictionary(((T, U) x) => x.Item1, ((T, U) x) => x.Item2);
		}

		public override void WriteJson(JsonWriter writer, Dictionary<T, U>? value, JsonSerializer serializer)
		{
			if (value == null)
			{
				writer.WriteNull();
				return;
			}
			List<(T, U)> list = value.Select<KeyValuePair<T, U>, (T, U)>((KeyValuePair<T, U> kvp) => (kvp.Key, kvp.Value)).ToList();
			serializer.Serialize(writer, (object)list);
		}

		public DictListConverter()
		{
			((JsonConverter<Dictionary<Dictionary<T, U>, ?>>)(object)this)..ctor();
		}
	}
	internal static class JsonExtensions
	{
		public static void SerializeToFile<T>(this T self, string filePath)
		{
			string contents = JsonConvert.SerializeObject((object)self, (Formatting)1);
			File.WriteAllText(filePath, contents);
		}

		public static void SerializeToFileInBackground<T>(this T self, string filePath)
		{
			T self2 = self;
			string filePath2 = filePath;
			Task.Run(delegate
			{
				self2.SerializeToFile(filePath2);
			});
		}

		public static bool TryLoadFromFile<T>(string filePath, [NotNullWhen(true)] out T? obj)
		{
			obj = default(T);
			if (string.IsNullOrEmpty(filePath) || !File.Exists(filePath))
			{
				return false;
			}
			try
			{
				string text = File.ReadAllText(filePath);
				obj = JsonConvert.DeserializeObject<T>(text);
				return obj != null;
			}
			catch (Exception)
			{
				return false;
			}
		}
	}
	[JsonData("$.*~", new string[] { "**/languages/en.json" })]
	internal static class LanguageKeys
	{
		public const string BUILDING_NON_SCENE = "BUILDING_NON_SCENE";

		public const string BULDING_SCENE = "BULDING_SCENE";

		public const string COMPUTING_BUNDLE_DEPS = "COMPUTING_BUNDLE_DEPS";

		public const string LOADING_NON_SCENE = "LOADING_NON_SCENE";

		public const string LOADING_SCENE = "LOADING_SCENE";

		public const string REPACKING_SCENE = "REPACKING_SCENE";

		public static string GetLocalized(this string key)
		{
			return Language.Get(key, "Mods.org.silksong-modding.assethelper");
		}
	}
	internal static class VersionData
	{
		private static string? _silksongVersion;

		public static string SilksongVersion
		{
			get
			{
				if (_silksongVersion == null)
				{
					_silksongVersion = GetSilksongVersion();
				}
				return _silksongVersion;
			}
		}

		internal static Version EarliestAcceptableGeneralVersion { get; } = Version.Parse("0.1.0");


		internal static Version EarliestAcceptableSceneRepackVersion { get; } = Version.Parse("1.0.1");


		internal static Version EarliestAcceptableNonSceneCatalogVersion { get; } = Version.Parse("1.0.1");


		private static string GetSilksongVersion()
		{
			return (typeof(Constants).GetField("GAME_VERSION", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)?.GetRawConstantValue() as string) ?? "UNKNOWN";
		}

		internal static bool AllowCachedData(this Version earliest, string cachedPluginVersion)
		{
			if (!Version.TryParse(cachedPluginVersion, out Version result))
			{
				return false;
			}
			if (result > Version.Parse(AssetHelperPlugin.Version))
			{
				return false;
			}
			if (result < earliest)
			{
				return false;
			}
			return true;
		}
	}
}
namespace Silksong.AssetHelper.Dev
{
	public static class DebugTools
	{
		private class LocatorInfo
		{
			public string? LocatorID { get; init; }

			public Dictionary<string, List<AddressablesAssetInfo>> Infos { get; init; } = new Dictionary<string, List<AddressablesAssetInfo>>();

		}

		private class AddressablesAssetInfo
		{
			public string? InternalId { get; init; }

			public string? ProviderId { get; init; }

			public int DependencyCount { get; init; }

			public List<string>? Dependencies { get; init; }

			public string? PrimaryKey { get; init; }

			public Type? ResourceType { get; init; }

			public Type? AuxDataType { get; init; }

			public static AddressablesAssetInfo FromLocation(IResourceLocation loc, bool includeDependencyNames)
			{
				List<string> dependencies = ((!includeDependencyNames) ? null : (loc.Dependencies?.Select((IResourceLocation x) => "[" + ((x != null) ? x.PrimaryKey : null) + " | " + ((x != null) ? x.InternalId : null) + "]").ToList() ?? new List<string>()));
				return new AddressablesAssetInfo
				{
					InternalId = loc.InternalId,
					ProviderId = loc.ProviderId,
					DependencyCount = (loc.Dependencies?.Count ?? 0),
					Dependencies = dependencies,
					PrimaryKey = loc.PrimaryKey,
					ResourceType = loc.ResourceType,
					AuxDataType = loc.Data?.GetType()
				};
			}
		}

		public class LoadedBundleNames
		{
			public List<string> VanillaBundleNames;

			public List<string> Unknown;

			public LoadedBundleNames(List<string> names, List<string> unknown)
			{
				VanillaBundleNames = names;
				Unknown = unknown;
				base..ctor();
			}
		}

		private static readonly ManualLogSource Log = Logger.CreateLogSource("AssetHelper.DebugTools");

		private static string _debugDataDir = Path.Combine(AssetPaths.AssemblyFolder, "DebugData");

		private static Dictionary<string, string>? _bundleNameLookup;

		public static string DebugDataDir
		{
			get
			{
				if (!Directory.Exists(_debugDataDir))
				{
					Directory.CreateDirectory(_debugDataDir);
				}
				return _debugDataDir;
			}
		}

		public static void DumpAddressablesKeys()
		{
			string dumpFile = Path.Combine(DebugDataDir, "bundle_keys.json");
			AddressablesData.InvokeAfterAddressablesLoaded(delegate
			{
				AddressablesData.BundleKeys.SerializeToFileInBackground(dumpFile);
			});
		}

		public static void DumpAllAssetNames()
		{
			AddressablesData.InvokeAfterAddressablesLoaded(DumpAllAssetNamesInternal);
		}

		private static void DumpAllAssetNamesInternal()
		{
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			string filePath = Path.Combine(DebugDataDir, "asset_names.json");
			Dictionary<string, List<string>> dictionary = new Dictionary<string, List<string>>();
			Dictionary<string, List<string>> dictionary2 = new Dictionary<string, List<string>>();
			Stopwatch stopwatch = Stopwatch.StartNew();
			foreach (KeyValuePair<string, string> bundleKey in AddressablesData.BundleKeys)
			{
				bundleKey.Deconstruct(out var key, out var value);
				string key2 = key;
				AsyncOperationHandle<IAssetBundleResource> val = Addressables.LoadAssetAsync<IAssetBundleResource>((object)value);
				AssetBundle assetBundle = val.WaitForCompletion().GetAssetBundle();
				string[] allScenePaths = assetBundle.GetAllScenePaths();
				if (allScenePaths.Length != 0)
				{
					dictionary2[key2] = allScenePaths.ToList();
				}
				string[] allAssetNames = assetBundle.GetAllAssetNames();
				if (allAssetNames.Length != 0)
				{
					dictionary[key2] = allAssetNames.ToList();
				}
				Addressables.Release<IAssetBundleResource>(val);
			}
			stopwatch.Stop();
			Log.LogInfo((object)$"Determined asset names in {stopwatch.ElapsedMilliseconds} ms");
			new Dictionary<string, Dictionary<string, List<string>>>
			{
				["assets"] = dictionary,
				["scenes"] = dictionary2
			}.SerializeToFileInBackground(filePath);
		}

		public static void DumpAllAddressableAssets()
		{
			AddressablesData.InvokeAfterAddressablesLoaded(DumpAllAddressableAssetsInternal);
		}

		private static void DumpAllAddressableAssetsInternal()
		{
			if (AddressablesData.MainLocator != null)
			{
				DumpAllAddressableAssets(AddressablesData.MainLocator, "addressables_main.json");
			}
		}

		public static void DumpAllAddressableAssets(IResourceLocator locator, string fileName, bool includeDependencyNames = false)
		{
			Dictionary<string, List<AddressablesAssetInfo>> dictionary = new Dictionary<string, List<AddressablesAssetInfo>>();
			IList<IResourceLocation> source = default(IList<IResourceLocation>);
			foreach (string item in locator.Keys.OfType<string>())
			{
				if (locator.Locate((object)item, (Type)null, ref source))
				{
					dictionary[item] = source.Select((IResourceLocation x) => AddressablesAssetInfo.FromLocation(x, includeDependencyNames)).ToList();
				}
			}
			new LocatorInfo
			{
				LocatorID = locator.LocatorId,
				Infos = dictionary
			}.SerializeToFileInBackground(Path.Combine(DebugDataDir, fileName));
		}

		private static Dictionary<string, string> GenerateBundleNameLookup()
		{
			//IL_002a: 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_0051: Unknown result type (might be due to invalid IL or missing references)
			Dictionary<string, string> dictionary = new Dictionary<string, string>();
			foreach (KeyValuePair<string, string> bundleKey in AddressablesData.BundleKeys)
			{
				bundleKey.Deconstruct(out var key, out var value);
				string value2 = key;
				AsyncOperationHandle<IAssetBundleResource> val = Addressables.LoadAssetAsync<IAssetBundleResource>((object)value);
				val.WaitForCompletion();
				dictionary[((Object)val.Result.GetAssetBundle()).name] = value2;
				Addressables.Release<IAssetBundleResource>(val);
			}
			return dictionary;
		}

		public static LoadedBundleNames GetLoadedBundleNames()
		{
			if (!AddressablesData.IsAddressablesLoaded)
			{
				throw new InvalidOperationException("GetLoadedBundleNames cannot be called until Addressables is loaded!");
			}
			if (_bundleNameLookup == null)
			{
				_bundleNameLookup = CachedObject<Dictionary<string, string>>.CreateSynced("bundle_name_lookup.json", GenerateBundleNameLookup, mutable: false).Value;
			}
			List<string> list = new List<string>();
			List<string> list2 = new List<string>();
			foreach (string item in from b in AssetBundle.GetAllLoadedAssetBundles()
				select ((Object)b).name)
			{
				if (_bundleNameLookup.TryGetValue(item, out string value))
				{
					list.Add(value);
				}
				else
				{
					list2.Add(item);
				}
			}
			return new LoadedBundleNames(list, list2);
		}

		public static void DumpGameObjectPaths(string sceneName, bool compressed)
		{
			string path = "paths_" + sceneName + (compressed ? "_compressed.json" : ".json");
			string filePath = Path.Combine(DebugDataDir, path);
			AssetsManager val = BundleUtils.CreateDefaultManager();
			BundleFileInstance val2 = val.LoadBundleFile(AssetPaths.GetScenePath(sceneName), true);
			SceneBundleInfo val3 = default(SceneBundleInfo);
			if (!BundleUtils.TryFindAssetsFiles(val, val2, ref val3))
			{
				return;
			}
			AssetsFileInstance val4 = val.LoadAssetsFileFromBundle(val2, val3.mainAfileInstIndex, false);
			List<GameObjectInfo> list = GameObjectLookupExtensions.TraverseOrdered(GameObjectLookup.CreateFromFile(val, val4)).ToList();
			if (!compressed)
			{
				list.SerializeToFile(filePath);
				return;
			}
			list.Select((GameObjectInfo x) => $"{x.GameObjectName} [{x.GameObjectPathId}, {x.TransformPathId}]").ToList().SerializeToFile(filePath);
			val.UnloadAll(false);
		}
	}
}
namespace Silksong.AssetHelper.Core
{
	public static class AddressablesData
	{
		private static readonly ManualLogSource Log = Logger.CreateLogSource("AssetHelper.AddressablesData");

		private static Dictionary<string, string>? _bundleKeys;

		private static DelayedAction _afterAddressablesLoaded = new DelayedAction();

		private static readonly string BundleSuffix = "_[0-9a-fA-F]{32}\\.bundle+$";

		private static readonly Regex BundleSuffixRegex = new Regex(BundleSuffix, RegexOptions.Compiled);

		public static IResourceLocator? MainLocator { get; private set; }

		public static IReadOnlyDictionary<string, string>? BundleKeys
		{
			get
			{
				if (_bundleKeys != null)
				{
					return new ReadOnlyDictionary<string, string>(_bundleKeys);
				}
				return null;
			}
		}

		public static bool IsAddressablesLoaded => _bundleKeys != null;

		public static bool TryGetLocation(string bundleName, [NotNullWhen(true)] out IResourceLocation? location)
		{
			string text = ToBundleKey(bundleName);
			IList<IResourceLocation> source = Array.Empty<IResourceLocation>();
			IResourceLocator? mainLocator = MainLocator;
			if (mainLocator != null && !mainLocator.Locate((object)text, typeof(IAssetBundleResource), ref source))
			{
				location = null;
				return false;
			}
			location = source.FirstOrDefault();
			return location != null;
		}

		public static bool TryGetLocationForScene(string sceneName, [NotNullWhen(true)] out IResourceLocation? location)
		{
			return TryGetLocation("scenes_scenes_scenes/" + sceneName.ToLowerInvariant(), out location);
		}

		public static void InvokeAfterAddressablesLoaded(Action a)
		{
			_afterAddressablesLoaded.Subscribe(a);
		}

		internal static bool TryStrip(string key, [MaybeNullWhen(false)] out string stripped)
		{
			if (BundleSuffixRegex.IsMatch(key))
			{
				stripped = BundleSuffixRegex.Replace(key, "");
				return true;
			}
			stripped = key;
			return false;
		}

		internal static bool TryLoadBundleKeys()
		{
			Dictionary<string, string> dictionary = new Dictionary<string, string>();
			Stopwatch stopwatch = Stopwatch.StartNew();
			MainLocator = Addressables.ResourceLocators.FirstOrDefault((Func<IResourceLocator, bool>)((IResourceLocator x) => x.Keys.Any()));
			if (MainLocator == null)
			{
				Log.LogWarning((object)"Addressables not loaded yet");
				return false;
			}
			foreach (string item in MainLocator.Keys.OfType<string>())
			{
				if (TryStrip(item, out string stripped))
				{
					dictionary[stripped] = item;
				}
			}
			stopwatch.Stop();
			Log.LogInfo((object)$"Loaded {dictionary.Count} bundle locations in {stopwatch.ElapsedMilliseconds} ms");
			if (dictionary.Count == 0)
			{
				return false;
			}
			_bundleKeys = dictionary;
			_afterAddressablesLoaded.Activate();
			return true;
		}

		public static string ToBundleKey(string name)
		{
			if (_bundleKeys == null)
			{
				Log.LogWarning((object)"ToBundleKey called before addressables loaded");
				return name;
			}
			if (TryStrip(name, out string stripped))
			{
				name = stripped;
			}
			else if (name.EndsWith(".bundle"))
			{
				string text = name;
				name = text.Substring(0, text.Length - 7);
			}
			if (_bundleKeys.TryGetValue(name, out string value))
			{
				return value;
			}
			throw new Exception("Bundle " + name + " not found in lookup.");
		}
	}
	public static class AssetPaths
	{
		public static string OSFolderName
		{
			get
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				//IL_0005: Unknown result type (might be due to invalid IL or missing references)
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				//IL_0008: Invalid comparison between Unknown and I4
				//IL_000a: Unknown result type (might be due to invalid IL or missing references)
				//IL_000c: Invalid comparison between Unknown and I4
				//IL_000e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0011: Invalid comparison between Unknown and I4
				RuntimePlatform platform = Application.platform;
				if ((int)platform != 1)
				{
					if ((int)platform != 2)
					{
						if ((int)platform == 13)
						{
							return "StandaloneLinux64";
						}
						return "";
					}
					return "StandaloneWindows64";
				}
				return "StandaloneOSX";
			}
		}

		public static string BundleFolder => Path.Combine(Application.streamingAssetsPath, "aa", OSFolderName);

		private static string CacheSubfolder => "AssetHelper";

		internal static string CacheDirectory => Path.Combine(Paths.CachePath, CacheSubfolder).CreateIfNeeded();

		internal static string RepackedSceneBundleDir => Path.Combine(CacheDirectory, "repacked_scenes").CreateIfNeeded();

		internal static string CatalogFolder => Path.Combine(CacheDirectory, "Catalogs").CreateIfNeeded();

		internal static string AssemblyFolder => Directory.GetParent(typeof(AssetPaths).Assembly.Location).FullName;

		private static string CreateIfNeeded(this string path)
		{
			Directory.CreateDirectory(path);
			return path;
		}

		public static string GetScenePath(string sceneName)
		{
			return Path.Combine(BundleFolder, "scenes_scenes_scenes", sceneName.ToLowerInvariant() + ".bundle");
		}
	}
	public static class BundleMetadata
	{
		public static IReadOnlyDictionary<string, string> CabLookup { get; private set; }

		private static CachedObject<Dictionary<string, List<string>>> DirectDependencyLookup { get; set; }

		internal static void Setup()
		{
			CabLookup = CachedObject<IReadOnlyDictionary<string, string>>.CreateSynced("cabs.json", GenerateCabLookup, mutable: false).Value;
			DirectDependencyLookup = CachedObject<Dictionary<string, List<string>>>.CreateSynced("direct_deps.json", () => new Dictionary<string, List<string>>());
		}

		private static Dictionary<string, string> GenerateCabLookup()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			Stopwatch stopwatch = Stopwatch.StartNew();
			AssetsManager val = new AssetsManager();
			string bundleFolder = AssetPaths.BundleFolder;
			Dictionary<string, string> dictionary = new Dictionary<string, string>();
			foreach (string key in AddressablesData.BundleKeys.Keys)
			{
				string text = key.Replace("\\", "/");
				if (!text.EndsWith(".bundle"))
				{
					text += ".bundle";
				}
				string text2 = Path.Combine(bundleFolder, text);
				string text3 = val.LoadBundleFile(text2, true).file.GetFileName(0).Split(".")[0].ToLowerInvariant();
				if (dictionary.ContainsKey(text3))
				{
					AssetHelperPlugin.InstanceLogger.LogWarning((object)("Duplicate cab detected! " + text3 + ": " + dictionary[text3] + " -> " + text));
				}
				else
				{
					dictionary[text3] = text;
				}
				val.UnloadAll(false);
			}
			stopwatch.Stop();
			AssetHelperPlugin.InstanceLogger.LogInfo((object)$"Generated CAB lookup in {stopwatch.ElapsedMilliseconds} ms");
			return dictionary;
		}

		public static List<string> DetermineDirectDeps(string bundleName)
		{
			bool cacheHit;
			return DetermineDirectDepsInternal(bundleName, out cacheHit);
		}

		internal static List<string> DetermineDirectDepsInternal(string bundleName, out bool cacheHit)
		{
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Expected O, but got Unknown
			string text = bundleName;
			if (!text.EndsWith(".bundle"))
			{
				text += ".bundle";
			}
			if (DirectDependencyLookup.Value.TryGetValue(text, out List<string> value))
			{
				cacheHit = true;
				return value.ToList();
			}
			cacheHit = false;
			AssetsManager val = new AssetsManager();
			string text2 = Path.Combine(AssetPaths.BundleFolder, text);
			using MemoryStream memoryStream = new MemoryStream(File.ReadAllBytes(text2));
			BundleFileInstance val2 = val.LoadBundleFile((Stream)memoryStream, text2, true);
			AssetsFile file = val.LoadAssetsFileFromBundle(val2, 0, false).file;
			List<string> list = new List<string>();
			foreach (AssetsFileExternal external in file.Metadata.Externals)
			{
				string key = external.OriginalPathName.Split('/')[^1].Split(".")[0].ToLowerInvariant();
				if (CabLookup.TryGetValue(key, out string value2))
				{
					list.Add(value2);
				}
			}
			DirectDependencyLookup.Value[text] = list.ToList();
			val.UnloadAll(false);
			return list;
		}

		public static List<string> DetermineTransitiveDeps(string bundleName)
		{
			string text = bundleName;
			if (!text.EndsWith(".bundle"))
			{
				text += ".bundle";
			}
			HashSet<string> hashSet = new HashSet<string> { text };
			Queue<string> queue = new Queue<string>();
			queue.Enqueue(text);
			string result;
			while (queue.TryDequeue(out result))
			{
				foreach (string item in DetermineDirectDeps(result))
				{
					if (hashSet.Add(item))
					{
						queue.Enqueue(item);
					}
				}
			}
			hashSet.Remove(text);
			return hashSet.ToList();
		}

		public static List<string> DetermineCatalogDeps(string sceneBundle)
		{
			sceneBundle = sceneBundle.Replace(".bundle", "");
			if (!sceneBundle.StartsWith("scenes_scenes_scenes/"))
			{
				sceneBundle = "scenes_scenes_scenes/" + sceneBundle;
			}
			string sceneName = sceneBundle.Substring("scenes_scenes_scenes/".Length);
			if (AddressablesData.MainLocator == null)
			{
				throw new InvalidOperationException("Cannot inspect catalog until after Addressables has loaded");
			}
			string text = (from s in AddressablesData.MainLocator.Keys.OfType<string>()
				where s.StartsWith("Scenes/") && s.Substring(7).Equals(sceneName, StringComparison.InvariantCultureIgnoreCase)
				select s).First();
			IList<IResourceLocation> source = default(IList<IResourceLocation>);
			AddressablesData.MainLocator.Locate((object)text, typeof(SceneInstance), ref source);
			IResourceLocation obj = source.First();
			List<string> list = new List<string>();
			foreach (IResourceLocation dependency in obj.Dependencies)
			{
				AddressablesData.TryStrip(dependency.PrimaryKey, out string stripped);
				if (!(stripped == sceneBundle))
				{
					list.Add(stripped + ".bundle");
				}
			}
			return list;
		}
	}
}
namespace Silksong.AssetHelper.CatalogTools
{
	internal static class CatalogEntryUtils
	{
		public static ContentCatalogDataEntry CreateBundleEntry(string primaryKey, string bundlePath, string internalBundleName, List<string> dependencyKeys)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Expected O, but got Unknown
			AssetBundleRequestOptions val = new AssetBundleRequestOptions();
			val.AssetLoadMode = (AssetLoadMode)0;
			val.BundleName = internalBundleName;
			val.ChunkedTransfer = false;
			val.RetryCount = 0;
			val.RedirectLimit = 32;
			val.Timeout = 0;
			val.BundleSize = 0L;
			val.ClearOtherCachedVersionsWhenLoaded = false;
			val.Crc = 0u;
			val.UseCrcForCachedBundle = true;
			val.BundleSize = new FileInfo(bundlePath).Length;
			return new ContentCatalogDataEntry(typeof(IAssetBundleResource), bundlePath, "UnityEngine.ResourceManagement.ResourceProviders.AssetBundleProvider", (IEnumerable<object>)new object[1] { primaryKey }, (IEnumerable<object>)dependencyKeys, (object)val);
		}

		public static ContentCatalogDataEntry CreateAssetEntry(string internalId, Type assetType, List<string> dependencyKeys, out string primaryKey)
		{
			primaryKey = internalId;
			return CreateAssetEntry(internalId, assetType, dependencyKeys, primaryKey);
		}

		public static ContentCatalogDataEntry CreateAssetEntry(string internalId, Type assetType, List<string> dependencyKeys, string primaryKey)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected O, but got Unknown
			object[] array = dependencyKeys.Cast<object>().ToArray();
			return new ContentCatalogDataEntry(assetType, internalId, "UnityEngine.ResourceManagement.ResourceProviders.BundledAssetProvider", (IEnumerable<object>)new object[1] { primaryKey }, (IEnumerable<object>)array, (object)null);
		}

		public static ContentCatalogDataEntry CreateChildGameObjectEntry(string parentPrimaryKey, string relativePath, out string primaryKey)
		{
			int num = parentPrimaryKey.LastIndexOf('.');
			int num2 = parentPrimaryKey.LastIndexOf('/');
			if (num != -1 && num > num2)
			{
				string text = parentPrimaryKey.Substring(0, num);
				string text2 = parentPrimaryKey.Substring(num);
				primaryKey = text + "/" + relativePath + text2;
			}
			else if (parentPrimaryKey.EndsWith('/'))
			{
				primaryKey = parentPrimaryKey + relativePath;
			}
			else
			{
				primaryKey = parentPrimaryKey + "/" + relativePath;
			}
			return CreateChildGameObjectEntry(parentPrimaryKey, relativePath, primaryKey);
		}

		public static ContentCatalogDataEntry CreateChildGameObjectEntry(string parentPrimaryKey, string relativePath, string primaryKey)
		{
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Expected O, but got Unknown
			object[] array = new object[1] { parentPrimaryKey };
			return new ContentCatalogDataEntry(typeof(GameObject), relativePath + "/" + ChildGameObjectProvider.InternalIdSeparator + "/" + parentPrimaryKey, ChildGameObjectProvider.ClassProviderId, (IEnumerable<object>)new object[1] { primaryKey }, (IEnumerable<object>)array, (object)null);
		}

		public static ContentCatalogDataEntry CreateEntryFromLocation(IResourceLocation location, out string primaryKey)
		{
			primaryKey = "AssetHelper:" + location.PrimaryKey;
			return CreateEntryFromLocation(location, primaryKey);
		}

		public static ContentCatalogDataEntry CreateEntryFromLocation(IResourceLocation location, string primaryKey)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Expected O, but got Unknown
			return new ContentCatalogDataEntry(location.ResourceType, location.InternalId, location.ProviderId, (IEnumerable<object>)new object[1] { primaryKey }, (IEnumerable<object>)null, locati

plugins/AssetsTools.NET.dll

Decompiled 19 hours ago
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Text;
using System.Text.RegularExpressions;
using AssetsTools.NET.Extra;
using AssetsTools.NET.Extra.Decompressors.LZ4;
using LZ4ps;
using SevenZip;
using SevenZip.Compression.LZ;
using SevenZip.Compression.LZMA;
using SevenZip.Compression.RangeCoder;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("AssetsTools.NET")]
[assembly: AssemblyDescription("A remake and port of SeriousCache's AssetTools")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("nesrak1")]
[assembly: AssemblyProduct("AssetsTools.NET")]
[assembly: AssemblyCopyright("Written by nes")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("e09d5ac2-1a2e-4ec1-94ad-3f5e22f17658")]
[assembly: AssemblyFileVersion("3.0.0.0")]
[assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")]
[assembly: AssemblyVersion("3.0.0.0")]
namespace SevenZip
{
	internal class CRC
	{
		public static readonly uint[] Table;

		private uint _value = uint.MaxValue;

		static CRC()
		{
			Table = new uint[256];
			for (uint num = 0u; num < 256; num++)
			{
				uint num2 = num;
				for (int i = 0; i < 8; i++)
				{
					num2 = (((num2 & 1) == 0) ? (num2 >> 1) : ((num2 >> 1) ^ 0xEDB88320u));
				}
				Table[num] = num2;
			}
		}

		public void Init()
		{
			_value = uint.MaxValue;
		}

		public void UpdateByte(byte b)
		{
			_value = Table[(byte)_value ^ b] ^ (_value >> 8);
		}

		public void Update(byte[] data, uint offset, uint size)
		{
			for (uint num = 0u; num < size; num++)
			{
				_value = Table[(byte)_value ^ data[offset + num]] ^ (_value >> 8);
			}
		}

		public uint GetDigest()
		{
			return _value ^ 0xFFFFFFFFu;
		}

		private static uint CalculateDigest(byte[] data, uint offset, uint size)
		{
			CRC cRC = new CRC();
			cRC.Update(data, offset, size);
			return cRC.GetDigest();
		}

		private static bool VerifyDigest(uint digest, byte[] data, uint offset, uint size)
		{
			return CalculateDigest(data, offset, size) == digest;
		}
	}
	internal class DataErrorException : ApplicationException
	{
		public DataErrorException()
			: base("Data Error")
		{
		}
	}
	internal class InvalidParamException : ApplicationException
	{
		public InvalidParamException()
			: base("Invalid Parameter")
		{
		}
	}
	public interface ICodeProgress
	{
		void SetProgress(long inSize, long outSize);
	}
	public interface ICoder
	{
		void Code(Stream inStream, Stream outStream, long inSize, long outSize, ICodeProgress progress);
	}
	public enum CoderPropID
	{
		DefaultProp,
		DictionarySize,
		UsedMemorySize,
		Order,
		BlockSize,
		PosStateBits,
		LitContextBits,
		LitPosBits,
		NumFastBytes,
		MatchFinder,
		MatchFinderCycles,
		NumPasses,
		Algorithm,
		NumThreads,
		EndMarker
	}
	public interface ISetCoderProperties
	{
		void SetCoderProperties(CoderPropID[] propIDs, object[] properties);
	}
	public interface IWriteCoderProperties
	{
		void WriteCoderProperties(Stream outStream);
	}
	public interface ISetDecoderProperties
	{
		void SetDecoderProperties(byte[] properties);
	}
}
namespace SevenZip.Compression.RangeCoder
{
	internal class Encoder
	{
		public const uint kTopValue = 16777216u;

		private Stream Stream;

		public ulong Low;

		public uint Range;

		private uint _cacheSize;

		private byte _cache;

		private long StartPosition;

		public void SetStream(Stream stream)
		{
			Stream = stream;
		}

		public void ReleaseStream()
		{
			Stream = null;
		}

		public void Init()
		{
			StartPosition = Stream.Position;
			Low = 0uL;
			Range = uint.MaxValue;
			_cacheSize = 1u;
			_cache = 0;
		}

		public void FlushData()
		{
			for (int i = 0; i < 5; i++)
			{
				ShiftLow();
			}
		}

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

		public void CloseStream()
		{
			Stream.Close();
		}

		public void Encode(uint start, uint size, uint total)
		{
			Low += start * (Range /= total);
			Range *= size;
			while (Range < 16777216)
			{
				Range <<= 8;
				ShiftLow();
			}
		}

		public void ShiftLow()
		{
			if ((uint)Low < 4278190080u || (int)(Low >> 32) == 1)
			{
				byte b = _cache;
				do
				{
					Stream.WriteByte((byte)(b + (Low >> 32)));
					b = byte.MaxValue;
				}
				while (--_cacheSize != 0);
				_cache = (byte)((uint)Low >> 24);
			}
			_cacheSize++;
			Low = (uint)((int)Low << 8);
		}

		public void EncodeDirectBits(uint v, int numTotalBits)
		{
			for (int num = numTotalBits - 1; num >= 0; num--)
			{
				Range >>= 1;
				if (((v >> num) & 1) == 1)
				{
					Low += Range;
				}
				if (Range < 16777216)
				{
					Range <<= 8;
					ShiftLow();
				}
			}
		}

		public void EncodeBit(uint size0, int numTotalBits, uint symbol)
		{
			uint num = (Range >> numTotalBits) * size0;
			if (symbol == 0)
			{
				Range = num;
			}
			else
			{
				Low += num;
				Range -= num;
			}
			while (Range < 16777216)
			{
				Range <<= 8;
				ShiftLow();
			}
		}

		public long GetProcessedSizeAdd()
		{
			return _cacheSize + Stream.Position - StartPosition + 4;
		}
	}
	internal class Decoder
	{
		public const uint kTopValue = 16777216u;

		public uint Range;

		public uint Code;

		public Stream Stream;

		public void Init(Stream stream)
		{
			Stream = stream;
			Code = 0u;
			Range = uint.MaxValue;
			for (int i = 0; i < 5; i++)
			{
				Code = (Code << 8) | (byte)Stream.ReadByte();
			}
		}

		public void ReleaseStream()
		{
			Stream = null;
		}

		public void CloseStream()
		{
			Stream.Close();
		}

		public void Normalize()
		{
			while (Range < 16777216)
			{
				Code = (Code << 8) | (byte)Stream.ReadByte();
				Range <<= 8;
			}
		}

		public void Normalize2()
		{
			if (Range < 16777216)
			{
				Code = (Code << 8) | (byte)Stream.ReadByte();
				Range <<= 8;
			}
		}

		public uint GetThreshold(uint total)
		{
			return Code / (Range /= total);
		}

		public void Decode(uint start, uint size, uint total)
		{
			Code -= start * Range;
			Range *= size;
			Normalize();
		}

		public uint DecodeDirectBits(int numTotalBits)
		{
			uint num = Range;
			uint num2 = Code;
			uint num3 = 0u;
			for (int num4 = numTotalBits; num4 > 0; num4--)
			{
				num >>= 1;
				uint num5 = num2 - num >> 31;
				num2 -= num & (num5 - 1);
				num3 = (num3 << 1) | (1 - num5);
				if (num < 16777216)
				{
					num2 = (num2 << 8) | (byte)Stream.ReadByte();
					num <<= 8;
				}
			}
			Range = num;
			Code = num2;
			return num3;
		}

		public uint DecodeBit(uint size0, int numTotalBits)
		{
			uint num = (Range >> numTotalBits) * size0;
			uint result;
			if (Code < num)
			{
				result = 0u;
				Range = num;
			}
			else
			{
				result = 1u;
				Code -= num;
				Range -= num;
			}
			Normalize();
			return result;
		}
	}
	internal struct BitEncoder
	{
		public const int kNumBitModelTotalBits = 11;

		public const uint kBitModelTotal = 2048u;

		private const int kNumMoveBits = 5;

		private const int kNumMoveReducingBits = 2;

		public const int kNumBitPriceShiftBits = 6;

		private uint Prob;

		private static uint[] ProbPrices;

		public void Init()
		{
			Prob = 1024u;
		}

		public void UpdateModel(uint symbol)
		{
			if (symbol == 0)
			{
				Prob += 2048 - Prob >> 5;
			}
			else
			{
				Prob -= Prob >> 5;
			}
		}

		public void Encode(Encoder encoder, uint symbol)
		{
			uint num = (encoder.Range >> 11) * Prob;
			if (symbol == 0)
			{
				encoder.Range = num;
				Prob += 2048 - Prob >> 5;
			}
			else
			{
				encoder.Low += num;
				encoder.Range -= num;
				Prob -= Prob >> 5;
			}
			if (encoder.Range < 16777216)
			{
				encoder.Range <<= 8;
				encoder.ShiftLow();
			}
		}

		static BitEncoder()
		{
			ProbPrices = new uint[512];
			for (int num = 8; num >= 0; num--)
			{
				int num2 = 1 << 9 - num - 1;
				uint num3 = (uint)(1 << 9 - num);
				for (uint num4 = (uint)num2; num4 < num3; num4++)
				{
					ProbPrices[num4] = (uint)(num << 6) + (num3 - num4 << 6 >> 9 - num - 1);
				}
			}
		}

		public uint GetPrice(uint symbol)
		{
			return ProbPrices[(((Prob - symbol) ^ (int)(0 - symbol)) & 0x7FF) >> 2];
		}

		public uint GetPrice0()
		{
			return ProbPrices[Prob >> 2];
		}

		public uint GetPrice1()
		{
			return ProbPrices[2048 - Prob >> 2];
		}
	}
	internal struct BitDecoder
	{
		public const int kNumBitModelTotalBits = 11;

		public const uint kBitModelTotal = 2048u;

		private const int kNumMoveBits = 5;

		private uint Prob;

		public void UpdateModel(int numMoveBits, uint symbol)
		{
			if (symbol == 0)
			{
				Prob += 2048 - Prob >> numMoveBits;
			}
			else
			{
				Prob -= Prob >> numMoveBits;
			}
		}

		public void Init()
		{
			Prob = 1024u;
		}

		public uint Decode(Decoder rangeDecoder)
		{
			uint num = (rangeDecoder.Range >> 11) * Prob;
			if (rangeDecoder.Code < num)
			{
				rangeDecoder.Range = num;
				Prob += 2048 - Prob >> 5;
				if (rangeDecoder.Range < 16777216)
				{
					rangeDecoder.Code = (rangeDecoder.Code << 8) | (byte)rangeDecoder.Stream.ReadByte();
					rangeDecoder.Range <<= 8;
				}
				return 0u;
			}
			rangeDecoder.Range -= num;
			rangeDecoder.Code -= num;
			Prob -= Prob >> 5;
			if (rangeDecoder.Range < 16777216)
			{
				rangeDecoder.Code = (rangeDecoder.Code << 8) | (byte)rangeDecoder.Stream.ReadByte();
				rangeDecoder.Range <<= 8;
			}
			return 1u;
		}
	}
	internal struct BitTreeEncoder
	{
		private BitEncoder[] Models;

		private int NumBitLevels;

		public BitTreeEncoder(int numBitLevels)
		{
			NumBitLevels = numBitLevels;
			Models = new BitEncoder[1 << numBitLevels];
		}

		public void Init()
		{
			for (uint num = 1u; num < 1 << NumBitLevels; num++)
			{
				Models[num].Init();
			}
		}

		public void Encode(Encoder rangeEncoder, uint symbol)
		{
			uint num = 1u;
			int num2 = NumBitLevels;
			while (num2 > 0)
			{
				num2--;
				uint num3 = (symbol >> num2) & 1u;
				Models[num].Encode(rangeEncoder, num3);
				num = (num << 1) | num3;
			}
		}

		public void ReverseEncode(Encoder rangeEncoder, uint symbol)
		{
			uint num = 1u;
			for (uint num2 = 0u; num2 < NumBitLevels; num2++)
			{
				uint num3 = symbol & 1u;
				Models[num].Encode(rangeEncoder, num3);
				num = (num << 1) | num3;
				symbol >>= 1;
			}
		}

		public uint GetPrice(uint symbol)
		{
			uint num = 0u;
			uint num2 = 1u;
			int num3 = NumBitLevels;
			while (num3 > 0)
			{
				num3--;
				uint num4 = (symbol >> num3) & 1u;
				num += Models[num2].GetPrice(num4);
				num2 = (num2 << 1) + num4;
			}
			return num;
		}

		public uint ReverseGetPrice(uint symbol)
		{
			uint num = 0u;
			uint num2 = 1u;
			for (int num3 = NumBitLevels; num3 > 0; num3--)
			{
				uint num4 = symbol & 1u;
				symbol >>= 1;
				num += Models[num2].GetPrice(num4);
				num2 = (num2 << 1) | num4;
			}
			return num;
		}

		public static uint ReverseGetPrice(BitEncoder[] Models, uint startIndex, int NumBitLevels, uint symbol)
		{
			uint num = 0u;
			uint num2 = 1u;
			for (int num3 = NumBitLevels; num3 > 0; num3--)
			{
				uint num4 = symbol & 1u;
				symbol >>= 1;
				num += Models[startIndex + num2].GetPrice(num4);
				num2 = (num2 << 1) | num4;
			}
			return num;
		}

		public static void ReverseEncode(BitEncoder[] Models, uint startIndex, Encoder rangeEncoder, int NumBitLevels, uint symbol)
		{
			uint num = 1u;
			for (int i = 0; i < NumBitLevels; i++)
			{
				uint num2 = symbol & 1u;
				Models[startIndex + num].Encode(rangeEncoder, num2);
				num = (num << 1) | num2;
				symbol >>= 1;
			}
		}
	}
	internal struct BitTreeDecoder
	{
		private BitDecoder[] Models;

		private int NumBitLevels;

		public BitTreeDecoder(int numBitLevels)
		{
			NumBitLevels = numBitLevels;
			Models = new BitDecoder[1 << numBitLevels];
		}

		public void Init()
		{
			for (uint num = 1u; num < 1 << NumBitLevels; num++)
			{
				Models[num].Init();
			}
		}

		public uint Decode(Decoder rangeDecoder)
		{
			uint num = 1u;
			for (int num2 = NumBitLevels; num2 > 0; num2--)
			{
				num = (num << 1) + Models[num].Decode(rangeDecoder);
			}
			return num - (uint)(1 << NumBitLevels);
		}

		public uint ReverseDecode(Decoder rangeDecoder)
		{
			uint num = 1u;
			uint num2 = 0u;
			for (int i = 0; i < NumBitLevels; i++)
			{
				uint num3 = Models[num].Decode(rangeDecoder);
				num <<= 1;
				num += num3;
				num2 |= num3 << i;
			}
			return num2;
		}

		public static uint ReverseDecode(BitDecoder[] Models, uint startIndex, Decoder rangeDecoder, int NumBitLevels)
		{
			uint num = 1u;
			uint num2 = 0u;
			for (int i = 0; i < NumBitLevels; i++)
			{
				uint num3 = Models[startIndex + num].Decode(rangeDecoder);
				num <<= 1;
				num += num3;
				num2 |= num3 << i;
			}
			return num2;
		}
	}
}
namespace SevenZip.Compression.LZ
{
	internal interface IInWindowStream
	{
		void SetStream(Stream inStream);

		void Init();

		void ReleaseStream();

		byte GetIndexByte(int index);

		uint GetMatchLen(int index, uint distance, uint limit);

		uint GetNumAvailableBytes();
	}
	internal interface IMatchFinder : IInWindowStream
	{
		void Create(uint historySize, uint keepAddBufferBefore, uint matchMaxLen, uint keepAddBufferAfter);

		uint GetMatches(uint[] distances);

		void Skip(uint num);
	}
	public class BinTree : InWindow, IMatchFinder, IInWindowStream
	{
		private uint _cyclicBufferPos;

		private uint _cyclicBufferSize;

		private uint _matchMaxLen;

		private uint[] _son;

		private uint[] _hash;

		private uint _cutValue = 255u;

		private uint _hashMask;

		private uint _hashSizeSum;

		private bool HASH_ARRAY = true;

		private const uint kHash2Size = 1024u;

		private const uint kHash3Size = 65536u;

		private const uint kBT2HashSize = 65536u;

		private const uint kStartMaxLen = 1u;

		private const uint kHash3Offset = 1024u;

		private const uint kEmptyHashValue = 0u;

		private const uint kMaxValForNormalize = 2147483647u;

		private uint kNumHashDirectBytes;

		private uint kMinMatchCheck = 4u;

		private uint kFixHashSize = 66560u;

		public void SetType(int numHashBytes)
		{
			HASH_ARRAY = numHashBytes > 2;
			if (HASH_ARRAY)
			{
				kNumHashDirectBytes = 0u;
				kMinMatchCheck = 4u;
				kFixHashSize = 66560u;
			}
			else
			{
				kNumHashDirectBytes = 2u;
				kMinMatchCheck = 3u;
				kFixHashSize = 0u;
			}
		}

		public new void SetStream(Stream stream)
		{
			base.SetStream(stream);
		}

		public new void ReleaseStream()
		{
			base.ReleaseStream();
		}

		public new void Init()
		{
			base.Init();
			for (uint num = 0u; num < _hashSizeSum; num++)
			{
				_hash[num] = 0u;
			}
			_cyclicBufferPos = 0u;
			ReduceOffsets(-1);
		}

		public new void MovePos()
		{
			if (++_cyclicBufferPos >= _cyclicBufferSize)
			{
				_cyclicBufferPos = 0u;
			}
			base.MovePos();
			if (_pos == int.MaxValue)
			{
				Normalize();
			}
		}

		public new byte GetIndexByte(int index)
		{
			return base.GetIndexByte(index);
		}

		public new uint GetMatchLen(int index, uint distance, uint limit)
		{
			return base.GetMatchLen(index, distance, limit);
		}

		public new uint GetNumAvailableBytes()
		{
			return base.GetNumAvailableBytes();
		}

		public void Create(uint historySize, uint keepAddBufferBefore, uint matchMaxLen, uint keepAddBufferAfter)
		{
			if (historySize > 2147483391)
			{
				throw new Exception();
			}
			_cutValue = 16 + (matchMaxLen >> 1);
			uint keepSizeReserv = (historySize + keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + 256;
			Create(historySize + keepAddBufferBefore, matchMaxLen + keepAddBufferAfter, keepSizeReserv);
			_matchMaxLen = matchMaxLen;
			uint num = historySize + 1;
			if (_cyclicBufferSize != num)
			{
				_son = new uint[(_cyclicBufferSize = num) * 2];
			}
			uint num2 = 65536u;
			if (HASH_ARRAY)
			{
				num2 = historySize - 1;
				num2 |= num2 >> 1;
				num2 |= num2 >> 2;
				num2 |= num2 >> 4;
				num2 |= num2 >> 8;
				num2 >>= 1;
				num2 |= 0xFFFFu;
				if (num2 > 16777216)
				{
					num2 >>= 1;
				}
				_hashMask = num2;
				num2++;
				num2 += kFixHashSize;
			}
			if (num2 != _hashSizeSum)
			{
				_hash = new uint[_hashSizeSum = num2];
			}
		}

		public uint GetMatches(uint[] distances)
		{
			uint num;
			if (_pos + _matchMaxLen <= _streamPos)
			{
				num = _matchMaxLen;
			}
			else
			{
				num = _streamPos - _pos;
				if (num < kMinMatchCheck)
				{
					MovePos();
					return 0u;
				}
			}
			uint num2 = 0u;
			uint num3 = ((_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0u);
			uint num4 = _bufferOffset + _pos;
			uint num5 = 1u;
			uint num6 = 0u;
			uint num7 = 0u;
			uint num10;
			if (HASH_ARRAY)
			{
				uint num8 = CRC.Table[_bufferBase[num4]] ^ _bufferBase[num4 + 1];
				num6 = num8 & 0x3FFu;
				int num9 = (int)num8 ^ (_bufferBase[num4 + 2] << 8);
				num7 = (uint)num9 & 0xFFFFu;
				num10 = ((uint)num9 ^ (CRC.Table[_bufferBase[num4 + 3]] << 5)) & _hashMask;
			}
			else
			{
				num10 = (uint)(_bufferBase[num4] ^ (_bufferBase[num4 + 1] << 8));
			}
			uint num11 = _hash[kFixHashSize + num10];
			if (HASH_ARRAY)
			{
				uint num12 = _hash[num6];
				uint num13 = _hash[1024 + num7];
				_hash[num6] = _pos;
				_hash[1024 + num7] = _pos;
				if (num12 > num3 && _bufferBase[_bufferOffset + num12] == _bufferBase[num4])
				{
					num5 = (distances[num2++] = 2u);
					distances[num2++] = _pos - num12 - 1;
				}
				if (num13 > num3 && _bufferBase[_bufferOffset + num13] == _bufferBase[num4])
				{
					if (num13 == num12)
					{
						num2 -= 2;
					}
					num5 = (distances[num2++] = 3u);
					distances[num2++] = _pos - num13 - 1;
					num12 = num13;
				}
				if (num2 != 0 && num12 == num11)
				{
					num2 -= 2;
					num5 = 1u;
				}
			}
			_hash[kFixHashSize + num10] = _pos;
			uint num14 = (_cyclicBufferPos << 1) + 1;
			uint num15 = _cyclicBufferPos << 1;
			uint val;
			uint val2 = (val = kNumHashDirectBytes);
			if (kNumHashDirectBytes != 0 && num11 > num3 && _bufferBase[_bufferOffset + num11 + kNumHashDirectBytes] != _bufferBase[num4 + kNumHashDirectBytes])
			{
				num5 = (distances[num2++] = kNumHashDirectBytes);
				distances[num2++] = _pos - num11 - 1;
			}
			uint cutValue = _cutValue;
			while (true)
			{
				if (num11 <= num3 || cutValue-- == 0)
				{
					_son[num14] = (_son[num15] = 0u);
					break;
				}
				uint num16 = _pos - num11;
				uint num17 = ((num16 <= _cyclicBufferPos) ? (_cyclicBufferPos - num16) : (_cyclicBufferPos - num16 + _cyclicBufferSize)) << 1;
				uint num18 = _bufferOffset + num11;
				uint num19 = Math.Min(val2, val);
				if (_bufferBase[num18 + num19] == _bufferBase[num4 + num19])
				{
					while (++num19 != num && _bufferBase[num18 + num19] == _bufferBase[num4 + num19])
					{
					}
					if (num5 < num19)
					{
						num5 = (distances[num2++] = num19);
						distances[num2++] = num16 - 1;
						if (num19 == num)
						{
							_son[num15] = _son[num17];
							_son[num14] = _son[num17 + 1];
							break;
						}
					}
				}
				if (_bufferBase[num18 + num19] < _bufferBase[num4 + num19])
				{
					_son[num15] = num11;
					num15 = num17 + 1;
					num11 = _son[num15];
					val = num19;
				}
				else
				{
					_son[num14] = num11;
					num14 = num17;
					num11 = _son[num14];
					val2 = num19;
				}
			}
			MovePos();
			return num2;
		}

		public void Skip(uint num)
		{
			do
			{
				uint num2;
				if (_pos + _matchMaxLen <= _streamPos)
				{
					num2 = _matchMaxLen;
				}
				else
				{
					num2 = _streamPos - _pos;
					if (num2 < kMinMatchCheck)
					{
						MovePos();
						continue;
					}
				}
				uint num3 = ((_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0u);
				uint num4 = _bufferOffset + _pos;
				uint num9;
				if (HASH_ARRAY)
				{
					uint num5 = CRC.Table[_bufferBase[num4]] ^ _bufferBase[num4 + 1];
					uint num6 = num5 & 0x3FFu;
					_hash[num6] = _pos;
					int num7 = (int)num5 ^ (_bufferBase[num4 + 2] << 8);
					uint num8 = (uint)num7 & 0xFFFFu;
					_hash[1024 + num8] = _pos;
					num9 = ((uint)num7 ^ (CRC.Table[_bufferBase[num4 + 3]] << 5)) & _hashMask;
				}
				else
				{
					num9 = (uint)(_bufferBase[num4] ^ (_bufferBase[num4 + 1] << 8));
				}
				uint num10 = _hash[kFixHashSize + num9];
				_hash[kFixHashSize + num9] = _pos;
				uint num11 = (_cyclicBufferPos << 1) + 1;
				uint num12 = _cyclicBufferPos << 1;
				uint val;
				uint val2 = (val = kNumHashDirectBytes);
				uint cutValue = _cutValue;
				while (true)
				{
					if (num10 <= num3 || cutValue-- == 0)
					{
						_son[num11] = (_son[num12] = 0u);
						break;
					}
					uint num13 = _pos - num10;
					uint num14 = ((num13 <= _cyclicBufferPos) ? (_cyclicBufferPos - num13) : (_cyclicBufferPos - num13 + _cyclicBufferSize)) << 1;
					uint num15 = _bufferOffset + num10;
					uint num16 = Math.Min(val2, val);
					if (_bufferBase[num15 + num16] == _bufferBase[num4 + num16])
					{
						while (++num16 != num2 && _bufferBase[num15 + num16] == _bufferBase[num4 + num16])
						{
						}
						if (num16 == num2)
						{
							_son[num12] = _son[num14];
							_son[num11] = _son[num14 + 1];
							break;
						}
					}
					if (_bufferBase[num15 + num16] < _bufferBase[num4 + num16])
					{
						_son[num12] = num10;
						num12 = num14 + 1;
						num10 = _son[num12];
						val = num16;
					}
					else
					{
						_son[num11] = num10;
						num11 = num14;
						num10 = _son[num11];
						val2 = num16;
					}
				}
				MovePos();
			}
			while (--num != 0);
		}

		private void NormalizeLinks(uint[] items, uint numItems, uint subValue)
		{
			for (uint num = 0u; num < numItems; num++)
			{
				uint num2 = items[num];
				num2 = ((num2 > subValue) ? (num2 - subValue) : 0u);
				items[num] = num2;
			}
		}

		private void Normalize()
		{
			uint subValue = _pos - _cyclicBufferSize;
			NormalizeLinks(_son, _cyclicBufferSize * 2, subValue);
			NormalizeLinks(_hash, _hashSizeSum, subValue);
			ReduceOffsets((int)subValue);
		}

		public void SetCutValue(uint cutValue)
		{
			_cutValue = cutValue;
		}
	}
	public class InWindow
	{
		public byte[] _bufferBase;

		private Stream _stream;

		private uint _posLimit;

		private bool _streamEndWasReached;

		private uint _pointerToLastSafePosition;

		public uint _bufferOffset;

		public uint _blockSize;

		public uint _pos;

		private uint _keepSizeBefore;

		private uint _keepSizeAfter;

		public uint _streamPos;

		public void MoveBlock()
		{
			uint num = _bufferOffset + _pos - _keepSizeBefore;
			if (num != 0)
			{
				num--;
			}
			uint num2 = _bufferOffset + _streamPos - num;
			for (uint num3 = 0u; num3 < num2; num3++)
			{
				_bufferBase[num3] = _bufferBase[num + num3];
			}
			_bufferOffset -= num;
		}

		public virtual void ReadBlock()
		{
			if (_streamEndWasReached)
			{
				return;
			}
			while (true)
			{
				int num = (int)(0 - _bufferOffset + _blockSize - _streamPos);
				if (num == 0)
				{
					return;
				}
				int num2 = _stream.Read(_bufferBase, (int)(_bufferOffset + _streamPos), num);
				if (num2 == 0)
				{
					break;
				}
				_streamPos += (uint)num2;
				if (_streamPos >= _pos + _keepSizeAfter)
				{
					_posLimit = _streamPos - _keepSizeAfter;
				}
			}
			_posLimit = _streamPos;
			if (_bufferOffset + _posLimit > _pointerToLastSafePosition)
			{
				_posLimit = _pointerToLastSafePosition - _bufferOffset;
			}
			_streamEndWasReached = true;
		}

		private void Free()
		{
			_bufferBase = null;
		}

		public void Create(uint keepSizeBefore, uint keepSizeAfter, uint keepSizeReserv)
		{
			_keepSizeBefore = keepSizeBefore;
			_keepSizeAfter = keepSizeAfter;
			uint num = keepSizeBefore + keepSizeAfter + keepSizeReserv;
			if (_bufferBase == null || _blockSize != num)
			{
				Free();
				_blockSize = num;
				_bufferBase = new byte[_blockSize];
			}
			_pointerToLastSafePosition = _blockSize - keepSizeAfter;
		}

		public void SetStream(Stream stream)
		{
			_stream = stream;
		}

		public void ReleaseStream()
		{
			_stream = null;
		}

		public void Init()
		{
			_bufferOffset = 0u;
			_pos = 0u;
			_streamPos = 0u;
			_streamEndWasReached = false;
			ReadBlock();
		}

		public void MovePos()
		{
			_pos++;
			if (_pos > _posLimit)
			{
				if (_bufferOffset + _pos > _pointerToLastSafePosition)
				{
					MoveBlock();
				}
				ReadBlock();
			}
		}

		public byte GetIndexByte(int index)
		{
			return _bufferBase[_bufferOffset + _pos + index];
		}

		public uint GetMatchLen(int index, uint distance, uint limit)
		{
			if (_streamEndWasReached && _pos + index + limit > _streamPos)
			{
				limit = _streamPos - (uint)(int)(_pos + index);
			}
			distance++;
			uint num = _bufferOffset + _pos + (uint)index;
			uint num2;
			for (num2 = 0u; num2 < limit && _bufferBase[num + num2] == _bufferBase[num + num2 - distance]; num2++)
			{
			}
			return num2;
		}

		public uint GetNumAvailableBytes()
		{
			return _streamPos - _pos;
		}

		public void ReduceOffsets(int subValue)
		{
			_bufferOffset += (uint)subValue;
			_posLimit -= (uint)subValue;
			_pos -= (uint)subValue;
			_streamPos -= (uint)subValue;
		}
	}
	public class OutWindow
	{
		private byte[] _buffer;

		private uint _pos;

		private uint _windowSize;

		private uint _streamPos;

		private Stream _stream;

		public uint TrainSize;

		public void Create(uint windowSize)
		{
			if (_windowSize != windowSize)
			{
				_buffer = new byte[windowSize];
			}
			_windowSize = windowSize;
			_pos = 0u;
			_streamPos = 0u;
		}

		public void Init(Stream stream, bool solid)
		{
			ReleaseStream();
			_stream = stream;
			if (!solid)
			{
				_streamPos = 0u;
				_pos = 0u;
				TrainSize = 0u;
			}
		}

		public bool Train(Stream stream)
		{
			long length = stream.Length;
			uint num = (TrainSize = (uint)((length < _windowSize) ? length : _windowSize));
			stream.Position = length - num;
			_streamPos = (_pos = 0u);
			while (num != 0)
			{
				uint num2 = _windowSize - _pos;
				if (num < num2)
				{
					num2 = num;
				}
				int num3 = stream.Read(_buffer, (int)_pos, (int)num2);
				if (num3 == 0)
				{
					return false;
				}
				num -= (uint)num3;
				_pos += (uint)num3;
				_streamPos += (uint)num3;
				if (_pos == _windowSize)
				{
					_streamPos = (_pos = 0u);
				}
			}
			return true;
		}

		public void ReleaseStream()
		{
			Flush();
			_stream = null;
		}

		public void Flush()
		{
			uint num = _pos - _streamPos;
			if (num != 0)
			{
				_stream.Write(_buffer, (int)_streamPos, (int)num);
				if (_pos >= _windowSize)
				{
					_pos = 0u;
				}
				_streamPos = _pos;
			}
		}

		public void CopyBlock(uint distance, uint len)
		{
			uint num = _pos - distance - 1;
			if (num >= _windowSize)
			{
				num += _windowSize;
			}
			while (len != 0)
			{
				if (num >= _windowSize)
				{
					num = 0u;
				}
				_buffer[_pos++] = _buffer[num++];
				if (_pos >= _windowSize)
				{
					Flush();
				}
				len--;
			}
		}

		public void PutByte(byte b)
		{
			_buffer[_pos++] = b;
			if (_pos >= _windowSize)
			{
				Flush();
			}
		}

		public byte GetByte(uint distance)
		{
			uint num = _pos - distance - 1;
			if (num >= _windowSize)
			{
				num += _windowSize;
			}
			return _buffer[num];
		}
	}
}
namespace SevenZip.Compression.LZMA
{
	internal abstract class Base
	{
		public struct State
		{
			public uint Index;

			public void Init()
			{
				Index = 0u;
			}

			public void UpdateChar()
			{
				if (Index < 4)
				{
					Index = 0u;
				}
				else if (Index < 10)
				{
					Index -= 3u;
				}
				else
				{
					Index -= 6u;
				}
			}

			public void UpdateMatch()
			{
				Index = ((Index < 7) ? 7u : 10u);
			}

			public void UpdateRep()
			{
				Index = ((Index < 7) ? 8u : 11u);
			}

			public void UpdateShortRep()
			{
				Index = ((Index < 7) ? 9u : 11u);
			}

			public bool IsCharState()
			{
				return Index < 7;
			}
		}

		public const uint kNumRepDistances = 4u;

		public const uint kNumStates = 12u;

		public const int kNumPosSlotBits = 6;

		public const int kDicLogSizeMin = 0;

		public const int kNumLenToPosStatesBits = 2;

		public const uint kNumLenToPosStates = 4u;

		public const uint kMatchMinLen = 2u;

		public const int kNumAlignBits = 4;

		public const uint kAlignTableSize = 16u;

		public const uint kAlignMask = 15u;

		public const uint kStartPosModelIndex = 4u;

		public const uint kEndPosModelIndex = 14u;

		public const uint kNumPosModels = 10u;

		public const uint kNumFullDistances = 128u;

		public const uint kNumLitPosStatesBitsEncodingMax = 4u;

		public const uint kNumLitContextBitsMax = 8u;

		public const int kNumPosStatesBitsMax = 4;

		public const uint kNumPosStatesMax = 16u;

		public const int kNumPosStatesBitsEncodingMax = 4;

		public const uint kNumPosStatesEncodingMax = 16u;

		public const int kNumLowLenBits = 3;

		public const int kNumMidLenBits = 3;

		public const int kNumHighLenBits = 8;

		public const uint kNumLowLenSymbols = 8u;

		public const uint kNumMidLenSymbols = 8u;

		public const uint kNumLenSymbols = 272u;

		public const uint kMatchMaxLen = 273u;

		public static uint GetLenToPosState(uint len)
		{
			len -= 2;
			if (len < 4)
			{
				return len;
			}
			return 3u;
		}
	}
	public class Decoder : ICoder, ISetDecoderProperties
	{
		private class LenDecoder
		{
			private BitDecoder m_Choice;

			private BitDecoder m_Choice2;

			private BitTreeDecoder[] m_LowCoder = new BitTreeDecoder[16];

			private BitTreeDecoder[] m_MidCoder = new BitTreeDecoder[16];

			private BitTreeDecoder m_HighCoder = new BitTreeDecoder(8);

			private uint m_NumPosStates;

			public void Create(uint numPosStates)
			{
				for (uint num = m_NumPosStates; num < numPosStates; num++)
				{
					m_LowCoder[num] = new BitTreeDecoder(3);
					m_MidCoder[num] = new BitTreeDecoder(3);
				}
				m_NumPosStates = numPosStates;
			}

			public void Init()
			{
				m_Choice.Init();
				for (uint num = 0u; num < m_NumPosStates; num++)
				{
					m_LowCoder[num].Init();
					m_MidCoder[num].Init();
				}
				m_Choice2.Init();
				m_HighCoder.Init();
			}

			public uint Decode(SevenZip.Compression.RangeCoder.Decoder rangeDecoder, uint posState)
			{
				if (m_Choice.Decode(rangeDecoder) == 0)
				{
					return m_LowCoder[posState].Decode(rangeDecoder);
				}
				uint num = 8u;
				if (m_Choice2.Decode(rangeDecoder) == 0)
				{
					return num + m_MidCoder[posState].Decode(rangeDecoder);
				}
				num += 8;
				return num + m_HighCoder.Decode(rangeDecoder);
			}
		}

		private class LiteralDecoder
		{
			private struct Decoder2
			{
				private BitDecoder[] m_Decoders;

				public void Create()
				{
					m_Decoders = new BitDecoder[768];
				}

				public void Init()
				{
					for (int i = 0; i < 768; i++)
					{
						m_Decoders[i].Init();
					}
				}

				public byte DecodeNormal(SevenZip.Compression.RangeCoder.Decoder rangeDecoder)
				{
					uint num = 1u;
					do
					{
						num = (num << 1) | m_Decoders[num].Decode(rangeDecoder);
					}
					while (num < 256);
					return (byte)num;
				}

				public byte DecodeWithMatchByte(SevenZip.Compression.RangeCoder.Decoder rangeDecoder, byte matchByte)
				{
					uint num = 1u;
					do
					{
						uint num2 = (uint)(matchByte >> 7) & 1u;
						matchByte <<= 1;
						uint num3 = m_Decoders[(1 + num2 << 8) + num].Decode(rangeDecoder);
						num = (num << 1) | num3;
						if (num2 != num3)
						{
							while (num < 256)
							{
								num = (num << 1) | m_Decoders[num].Decode(rangeDecoder);
							}
							break;
						}
					}
					while (num < 256);
					return (byte)num;
				}
			}

			private Decoder2[] m_Coders;

			private int m_NumPrevBits;

			private int m_NumPosBits;

			private uint m_PosMask;

			public void Create(int numPosBits, int numPrevBits)
			{
				if (m_Coders == null || m_NumPrevBits != numPrevBits || m_NumPosBits != numPosBits)
				{
					m_NumPosBits = numPosBits;
					m_PosMask = (uint)((1 << numPosBits) - 1);
					m_NumPrevBits = numPrevBits;
					uint num = (uint)(1 << m_NumPrevBits + m_NumPosBits);
					m_Coders = new Decoder2[num];
					for (uint num2 = 0u; num2 < num; num2++)
					{
						m_Coders[num2].Create();
					}
				}
			}

			public void Init()
			{
				uint num = (uint)(1 << m_NumPrevBits + m_NumPosBits);
				for (uint num2 = 0u; num2 < num; num2++)
				{
					m_Coders[num2].Init();
				}
			}

			private uint GetState(uint pos, byte prevByte)
			{
				return ((pos & m_PosMask) << m_NumPrevBits) + (uint)(prevByte >> 8 - m_NumPrevBits);
			}

			public byte DecodeNormal(SevenZip.Compression.RangeCoder.Decoder rangeDecoder, uint pos, byte prevByte)
			{
				return m_Coders[GetState(pos, prevByte)].DecodeNormal(rangeDecoder);
			}

			public byte DecodeWithMatchByte(SevenZip.Compression.RangeCoder.Decoder rangeDecoder, uint pos, byte prevByte, byte matchByte)
			{
				return m_Coders[GetState(pos, prevByte)].DecodeWithMatchByte(rangeDecoder, matchByte);
			}
		}

		private OutWindow m_OutWindow = new OutWindow();

		private SevenZip.Compression.RangeCoder.Decoder m_RangeDecoder = new SevenZip.Compression.RangeCoder.Decoder();

		private BitDecoder[] m_IsMatchDecoders = new BitDecoder[192];

		private BitDecoder[] m_IsRepDecoders = new BitDecoder[12];

		private BitDecoder[] m_IsRepG0Decoders = new BitDecoder[12];

		private BitDecoder[] m_IsRepG1Decoders = new BitDecoder[12];

		private BitDecoder[] m_IsRepG2Decoders = new BitDecoder[12];

		private BitDecoder[] m_IsRep0LongDecoders = new BitDecoder[192];

		private BitTreeDecoder[] m_PosSlotDecoder = new BitTreeDecoder[4];

		private BitDecoder[] m_PosDecoders = new BitDecoder[114];

		private BitTreeDecoder m_PosAlignDecoder = new BitTreeDecoder(4);

		private LenDecoder m_LenDecoder = new LenDecoder();

		private LenDecoder m_RepLenDecoder = new LenDecoder();

		private LiteralDecoder m_LiteralDecoder = new LiteralDecoder();

		private uint m_DictionarySize;

		private uint m_DictionarySizeCheck;

		private uint m_PosStateMask;

		private bool _solid;

		public Decoder()
		{
			m_DictionarySize = uint.MaxValue;
			for (int i = 0; (long)i < 4L; i++)
			{
				m_PosSlotDecoder[i] = new BitTreeDecoder(6);
			}
		}

		private void SetDictionarySize(uint dictionarySize)
		{
			if (m_DictionarySize != dictionarySize)
			{
				m_DictionarySize = dictionarySize;
				m_DictionarySizeCheck = Math.Max(m_DictionarySize, 1u);
				uint windowSize = Math.Max(m_DictionarySizeCheck, 4096u);
				m_OutWindow.Create(windowSize);
			}
		}

		private void SetLiteralProperties(int lp, int lc)
		{
			if (lp > 8)
			{
				throw new InvalidParamException();
			}
			if (lc > 8)
			{
				throw new InvalidParamException();
			}
			m_LiteralDecoder.Create(lp, lc);
		}

		private void SetPosBitsProperties(int pb)
		{
			if (pb > 4)
			{
				throw new InvalidParamException();
			}
			uint num = (uint)(1 << pb);
			m_LenDecoder.Create(num);
			m_RepLenDecoder.Create(num);
			m_PosStateMask = num - 1;
		}

		private void Init(Stream inStream, Stream outStream)
		{
			m_RangeDecoder.Init(inStream);
			m_OutWindow.Init(outStream, _solid);
			for (uint num = 0u; num < 12; num++)
			{
				for (uint num2 = 0u; num2 <= m_PosStateMask; num2++)
				{
					uint num3 = (num << 4) + num2;
					m_IsMatchDecoders[num3].Init();
					m_IsRep0LongDecoders[num3].Init();
				}
				m_IsRepDecoders[num].Init();
				m_IsRepG0Decoders[num].Init();
				m_IsRepG1Decoders[num].Init();
				m_IsRepG2Decoders[num].Init();
			}
			m_LiteralDecoder.Init();
			for (uint num = 0u; num < 4; num++)
			{
				m_PosSlotDecoder[num].Init();
			}
			for (uint num = 0u; num < 114; num++)
			{
				m_PosDecoders[num].Init();
			}
			m_LenDecoder.Init();
			m_RepLenDecoder.Init();
			m_PosAlignDecoder.Init();
		}

		public void Code(Stream inStream, Stream outStream, long inSize, long outSize, ICodeProgress progress)
		{
			Init(inStream, outStream);
			Base.State state = default(Base.State);
			state.Init();
			uint num = 0u;
			uint num2 = 0u;
			uint num3 = 0u;
			uint num4 = 0u;
			ulong num5 = 0uL;
			if (num5 < (ulong)outSize)
			{
				if (m_IsMatchDecoders[state.Index << 4].Decode(m_RangeDecoder) != 0)
				{
					throw new DataErrorException();
				}
				state.UpdateChar();
				byte b = m_LiteralDecoder.DecodeNormal(m_RangeDecoder, 0u, 0);
				m_OutWindow.PutByte(b);
				num5++;
			}
			while (num5 < (ulong)outSize)
			{
				uint num6 = (uint)(int)num5 & m_PosStateMask;
				if (m_IsMatchDecoders[(state.Index << 4) + num6].Decode(m_RangeDecoder) == 0)
				{
					byte @byte = m_OutWindow.GetByte(0u);
					byte b2 = (state.IsCharState() ? m_LiteralDecoder.DecodeNormal(m_RangeDecoder, (uint)num5, @byte) : m_LiteralDecoder.DecodeWithMatchByte(m_RangeDecoder, (uint)num5, @byte, m_OutWindow.GetByte(num)));
					m_OutWindow.PutByte(b2);
					state.UpdateChar();
					num5++;
					continue;
				}
				uint num8;
				if (m_IsRepDecoders[state.Index].Decode(m_RangeDecoder) == 1)
				{
					if (m_IsRepG0Decoders[state.Index].Decode(m_RangeDecoder) == 0)
					{
						if (m_IsRep0LongDecoders[(state.Index << 4) + num6].Decode(m_RangeDecoder) == 0)
						{
							state.UpdateShortRep();
							m_OutWindow.PutByte(m_OutWindow.GetByte(num));
							num5++;
							continue;
						}
					}
					else
					{
						uint num7;
						if (m_IsRepG1Decoders[state.Index].Decode(m_RangeDecoder) == 0)
						{
							num7 = num2;
						}
						else
						{
							if (m_IsRepG2Decoders[state.Index].Decode(m_RangeDecoder) == 0)
							{
								num7 = num3;
							}
							else
							{
								num7 = num4;
								num4 = num3;
							}
							num3 = num2;
						}
						num2 = num;
						num = num7;
					}
					num8 = m_RepLenDecoder.Decode(m_RangeDecoder, num6) + 2;
					state.UpdateRep();
				}
				else
				{
					num4 = num3;
					num3 = num2;
					num2 = num;
					num8 = 2 + m_LenDecoder.Decode(m_RangeDecoder, num6);
					state.UpdateMatch();
					uint num9 = m_PosSlotDecoder[Base.GetLenToPosState(num8)].Decode(m_RangeDecoder);
					if (num9 >= 4)
					{
						int num10 = (int)((num9 >> 1) - 1);
						num = (2 | (num9 & 1)) << num10;
						if (num9 < 14)
						{
							num += BitTreeDecoder.ReverseDecode(m_PosDecoders, num - num9 - 1, m_RangeDecoder, num10);
						}
						else
						{
							num += m_RangeDecoder.DecodeDirectBits(num10 - 4) << 4;
							num += m_PosAlignDecoder.ReverseDecode(m_RangeDecoder);
						}
					}
					else
					{
						num = num9;
					}
				}
				if (num >= m_OutWindow.TrainSize + num5 || num >= m_DictionarySizeCheck)
				{
					if (num == uint.MaxValue)
					{
						break;
					}
					throw new DataErrorException();
				}
				m_OutWindow.CopyBlock(num, num8);
				num5 += num8;
			}
			m_OutWindow.Flush();
			m_OutWindow.ReleaseStream();
			m_RangeDecoder.ReleaseStream();
		}

		public void SetDecoderProperties(byte[] properties)
		{
			if (properties.Length < 5)
			{
				throw new InvalidParamException();
			}
			int lc = properties[0] % 9;
			int num = properties[0] / 9;
			int lp = num % 5;
			int num2 = num / 5;
			if (num2 > 4)
			{
				throw new InvalidParamException();
			}
			uint num3 = 0u;
			for (int i = 0; i < 4; i++)
			{
				num3 += (uint)(properties[1 + i] << i * 8);
			}
			SetDictionarySize(num3);
			SetLiteralProperties(lp, lc);
			SetPosBitsProperties(num2);
		}

		public bool Train(Stream stream)
		{
			_solid = true;
			return m_OutWindow.Train(stream);
		}
	}
	public class Encoder : ICoder, ISetCoderProperties, IWriteCoderProperties
	{
		private enum EMatchFinderType
		{
			BT2,
			BT4
		}

		private class LiteralEncoder
		{
			public struct Encoder2
			{
				private BitEncoder[] m_Encoders;

				public void Create()
				{
					m_Encoders = new BitEncoder[768];
				}

				public void Init()
				{
					for (int i = 0; i < 768; i++)
					{
						m_Encoders[i].Init();
					}
				}

				public void Encode(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, byte symbol)
				{
					uint num = 1u;
					for (int num2 = 7; num2 >= 0; num2--)
					{
						uint num3 = (uint)(symbol >> num2) & 1u;
						m_Encoders[num].Encode(rangeEncoder, num3);
						num = (num << 1) | num3;
					}
				}

				public void EncodeMatched(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, byte matchByte, byte symbol)
				{
					uint num = 1u;
					bool flag = true;
					for (int num2 = 7; num2 >= 0; num2--)
					{
						uint num3 = (uint)(symbol >> num2) & 1u;
						uint num4 = num;
						if (flag)
						{
							uint num5 = (uint)(matchByte >> num2) & 1u;
							num4 += 1 + num5 << 8;
							flag = num5 == num3;
						}
						m_Encoders[num4].Encode(rangeEncoder, num3);
						num = (num << 1) | num3;
					}
				}

				public uint GetPrice(bool matchMode, byte matchByte, byte symbol)
				{
					uint num = 0u;
					uint num2 = 1u;
					int num3 = 7;
					if (matchMode)
					{
						while (num3 >= 0)
						{
							uint num4 = (uint)(matchByte >> num3) & 1u;
							uint num5 = (uint)(symbol >> num3) & 1u;
							num += m_Encoders[(1 + num4 << 8) + num2].GetPrice(num5);
							num2 = (num2 << 1) | num5;
							if (num4 != num5)
							{
								num3--;
								break;
							}
							num3--;
						}
					}
					while (num3 >= 0)
					{
						uint num6 = (uint)(symbol >> num3) & 1u;
						num += m_Encoders[num2].GetPrice(num6);
						num2 = (num2 << 1) | num6;
						num3--;
					}
					return num;
				}
			}

			private Encoder2[] m_Coders;

			private int m_NumPrevBits;

			private int m_NumPosBits;

			private uint m_PosMask;

			public void Create(int numPosBits, int numPrevBits)
			{
				if (m_Coders == null || m_NumPrevBits != numPrevBits || m_NumPosBits != numPosBits)
				{
					m_NumPosBits = numPosBits;
					m_PosMask = (uint)((1 << numPosBits) - 1);
					m_NumPrevBits = numPrevBits;
					uint num = (uint)(1 << m_NumPrevBits + m_NumPosBits);
					m_Coders = new Encoder2[num];
					for (uint num2 = 0u; num2 < num; num2++)
					{
						m_Coders[num2].Create();
					}
				}
			}

			public void Init()
			{
				uint num = (uint)(1 << m_NumPrevBits + m_NumPosBits);
				for (uint num2 = 0u; num2 < num; num2++)
				{
					m_Coders[num2].Init();
				}
			}

			public Encoder2 GetSubCoder(uint pos, byte prevByte)
			{
				return m_Coders[(int)((pos & m_PosMask) << m_NumPrevBits) + (prevByte >> 8 - m_NumPrevBits)];
			}
		}

		private class LenEncoder
		{
			private BitEncoder _choice;

			private BitEncoder _choice2;

			private BitTreeEncoder[] _lowCoder = new BitTreeEncoder[16];

			private BitTreeEncoder[] _midCoder = new BitTreeEncoder[16];

			private BitTreeEncoder _highCoder = new BitTreeEncoder(8);

			public LenEncoder()
			{
				for (uint num = 0u; num < 16; num++)
				{
					_lowCoder[num] = new BitTreeEncoder(3);
					_midCoder[num] = new BitTreeEncoder(3);
				}
			}

			public void Init(uint numPosStates)
			{
				_choice.Init();
				_choice2.Init();
				for (uint num = 0u; num < numPosStates; num++)
				{
					_lowCoder[num].Init();
					_midCoder[num].Init();
				}
				_highCoder.Init();
			}

			public void Encode(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, uint symbol, uint posState)
			{
				if (symbol < 8)
				{
					_choice.Encode(rangeEncoder, 0u);
					_lowCoder[posState].Encode(rangeEncoder, symbol);
					return;
				}
				symbol -= 8;
				_choice.Encode(rangeEncoder, 1u);
				if (symbol < 8)
				{
					_choice2.Encode(rangeEncoder, 0u);
					_midCoder[posState].Encode(rangeEncoder, symbol);
				}
				else
				{
					_choice2.Encode(rangeEncoder, 1u);
					_highCoder.Encode(rangeEncoder, symbol - 8);
				}
			}

			public void SetPrices(uint posState, uint numSymbols, uint[] prices, uint st)
			{
				uint price = _choice.GetPrice0();
				uint price2 = _choice.GetPrice1();
				uint num = price2 + _choice2.GetPrice0();
				uint num2 = price2 + _choice2.GetPrice1();
				uint num3 = 0u;
				for (num3 = 0u; num3 < 8; num3++)
				{
					if (num3 >= numSymbols)
					{
						return;
					}
					prices[st + num3] = price + _lowCoder[posState].GetPrice(num3);
				}
				for (; num3 < 16; num3++)
				{
					if (num3 >= numSymbols)
					{
						return;
					}
					prices[st + num3] = num + _midCoder[posState].GetPrice(num3 - 8);
				}
				for (; num3 < numSymbols; num3++)
				{
					prices[st + num3] = num2 + _highCoder.GetPrice(num3 - 8 - 8);
				}
			}
		}

		private class LenPriceTableEncoder : LenEncoder
		{
			private uint[] _prices = new uint[4352];

			private uint _tableSize;

			private uint[] _counters = new uint[16];

			public void SetTableSize(uint tableSize)
			{
				_tableSize = tableSize;
			}

			public uint GetPrice(uint symbol, uint posState)
			{
				return _prices[posState * 272 + symbol];
			}

			private void UpdateTable(uint posState)
			{
				SetPrices(posState, _tableSize, _prices, posState * 272);
				_counters[posState] = _tableSize;
			}

			public void UpdateTables(uint numPosStates)
			{
				for (uint num = 0u; num < numPosStates; num++)
				{
					UpdateTable(num);
				}
			}

			public new void Encode(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, uint symbol, uint posState)
			{
				base.Encode(rangeEncoder, symbol, posState);
				if (--_counters[posState] == 0)
				{
					UpdateTable(posState);
				}
			}
		}

		private class Optimal
		{
			public Base.State State;

			public bool Prev1IsChar;

			public bool Prev2;

			public uint PosPrev2;

			public uint BackPrev2;

			public uint Price;

			public uint PosPrev;

			public uint BackPrev;

			public uint Backs0;

			public uint Backs1;

			public uint Backs2;

			public uint Backs3;

			public void MakeAsChar()
			{
				BackPrev = uint.MaxValue;
				Prev1IsChar = false;
			}

			public void MakeAsShortRep()
			{
				BackPrev = 0u;
				Prev1IsChar = false;
			}

			public bool IsShortRep()
			{
				return BackPrev == 0;
			}
		}

		private const uint kIfinityPrice = 268435455u;

		private static byte[] g_FastPos;

		private Base.State _state;

		private byte _previousByte;

		private uint[] _repDistances = new uint[4];

		private const int kDefaultDictionaryLogSize = 22;

		private const uint kNumFastBytesDefault = 32u;

		private const uint kNumLenSpecSymbols = 16u;

		private const uint kNumOpts = 4096u;

		private Optimal[] _optimum = new Optimal[4096];

		private IMatchFinder _matchFinder;

		private SevenZip.Compression.RangeCoder.Encoder _rangeEncoder = new SevenZip.Compression.RangeCoder.Encoder();

		private BitEncoder[] _isMatch = new BitEncoder[192];

		private BitEncoder[] _isRep = new BitEncoder[12];

		private BitEncoder[] _isRepG0 = new BitEncoder[12];

		private BitEncoder[] _isRepG1 = new BitEncoder[12];

		private BitEncoder[] _isRepG2 = new BitEncoder[12];

		private BitEncoder[] _isRep0Long = new BitEncoder[192];

		private BitTreeEncoder[] _posSlotEncoder = new BitTreeEncoder[4];

		private BitEncoder[] _posEncoders = new BitEncoder[114];

		private BitTreeEncoder _posAlignEncoder = new BitTreeEncoder(4);

		private LenPriceTableEncoder _lenEncoder = new LenPriceTableEncoder();

		private LenPriceTableEncoder _repMatchLenEncoder = new LenPriceTableEncoder();

		private LiteralEncoder _literalEncoder = new LiteralEncoder();

		private uint[] _matchDistances = new uint[548];

		private uint _numFastBytes = 32u;

		private uint _longestMatchLength;

		private uint _numDistancePairs;

		private uint _additionalOffset;

		private uint _optimumEndIndex;

		private uint _optimumCurrentIndex;

		private bool _longestMatchWasFound;

		private uint[] _posSlotPrices = new uint[256];

		private uint[] _distancesPrices = new uint[512];

		private uint[] _alignPrices = new uint[16];

		private uint _alignPriceCount;

		private uint _distTableSize = 44u;

		private int _posStateBits = 2;

		private uint _posStateMask = 3u;

		private int _numLiteralPosStateBits;

		private int _numLiteralContextBits = 3;

		private uint _dictionarySize = 4194304u;

		private uint _dictionarySizePrev = uint.MaxValue;

		private uint _numFastBytesPrev = uint.MaxValue;

		private long nowPos64;

		private bool _finished;

		private Stream _inStream;

		private EMatchFinderType _matchFinderType = EMatchFinderType.BT4;

		private bool _writeEndMark;

		private bool _needReleaseMFStream;

		private uint[] reps = new uint[4];

		private uint[] repLens = new uint[4];

		private const int kPropSize = 5;

		private byte[] properties = new byte[5];

		private uint[] tempPrices = new uint[128];

		private uint _matchPriceCount;

		private static string[] kMatchFinderIDs;

		private uint _trainSize;

		static Encoder()
		{
			g_FastPos = new byte[2048];
			kMatchFinderIDs = new string[2] { "BT2", "BT4" };
			int num = 2;
			g_FastPos[0] = 0;
			g_FastPos[1] = 1;
			for (byte b = 2; b < 22; b++)
			{
				uint num2 = (uint)(1 << (b >> 1) - 1);
				uint num3 = 0u;
				while (num3 < num2)
				{
					g_FastPos[num] = b;
					num3++;
					num++;
				}
			}
		}

		private static uint GetPosSlot(uint pos)
		{
			if (pos < 2048)
			{
				return g_FastPos[pos];
			}
			if (pos < 2097152)
			{
				return (uint)(g_FastPos[pos >> 10] + 20);
			}
			return (uint)(g_FastPos[pos >> 20] + 40);
		}

		private static uint GetPosSlot2(uint pos)
		{
			if (pos < 131072)
			{
				return (uint)(g_FastPos[pos >> 6] + 12);
			}
			if (pos < 134217728)
			{
				return (uint)(g_FastPos[pos >> 16] + 32);
			}
			return (uint)(g_FastPos[pos >> 26] + 52);
		}

		private void BaseInit()
		{
			_state.Init();
			_previousByte = 0;
			for (uint num = 0u; num < 4; num++)
			{
				_repDistances[num] = 0u;
			}
		}

		private void Create()
		{
			if (_matchFinder == null)
			{
				BinTree binTree = new BinTree();
				int type = 4;
				if (_matchFinderType == EMatchFinderType.BT2)
				{
					type = 2;
				}
				binTree.SetType(type);
				_matchFinder = binTree;
			}
			_literalEncoder.Create(_numLiteralPosStateBits, _numLiteralContextBits);
			if (_dictionarySize != _dictionarySizePrev || _numFastBytesPrev != _numFastBytes)
			{
				_matchFinder.Create(_dictionarySize, 4096u, _numFastBytes, 274u);
				_dictionarySizePrev = _dictionarySize;
				_numFastBytesPrev = _numFastBytes;
			}
		}

		public Encoder()
		{
			for (int i = 0; (long)i < 4096L; i++)
			{
				_optimum[i] = new Optimal();
			}
			for (int j = 0; (long)j < 4L; j++)
			{
				_posSlotEncoder[j] = new BitTreeEncoder(6);
			}
		}

		private void SetWriteEndMarkerMode(bool writeEndMarker)
		{
			_writeEndMark = writeEndMarker;
		}

		private void Init()
		{
			BaseInit();
			_rangeEncoder.Init();
			for (uint num = 0u; num < 12; num++)
			{
				for (uint num2 = 0u; num2 <= _posStateMask; num2++)
				{
					uint num3 = (num << 4) + num2;
					_isMatch[num3].Init();
					_isRep0Long[num3].Init();
				}
				_isRep[num].Init();
				_isRepG0[num].Init();
				_isRepG1[num].Init();
				_isRepG2[num].Init();
			}
			_literalEncoder.Init();
			for (uint num = 0u; num < 4; num++)
			{
				_posSlotEncoder[num].Init();
			}
			for (uint num = 0u; num < 114; num++)
			{
				_posEncoders[num].Init();
			}
			_lenEncoder.Init((uint)(1 << _posStateBits));
			_repMatchLenEncoder.Init((uint)(1 << _posStateBits));
			_posAlignEncoder.Init();
			_longestMatchWasFound = false;
			_optimumEndIndex = 0u;
			_optimumCurrentIndex = 0u;
			_additionalOffset = 0u;
		}

		private void ReadMatchDistances(out uint lenRes, out uint numDistancePairs)
		{
			lenRes = 0u;
			numDistancePairs = _matchFinder.GetMatches(_matchDistances);
			if (numDistancePairs != 0)
			{
				lenRes = _matchDistances[numDistancePairs - 2];
				if (lenRes == _numFastBytes)
				{
					lenRes += _matchFinder.GetMatchLen((int)(lenRes - 1), _matchDistances[numDistancePairs - 1], 273 - lenRes);
				}
			}
			_additionalOffset++;
		}

		private void MovePos(uint num)
		{
			if (num != 0)
			{
				_matchFinder.Skip(num);
				_additionalOffset += num;
			}
		}

		private uint GetRepLen1Price(Base.State state, uint posState)
		{
			return _isRepG0[state.Index].GetPrice0() + _isRep0Long[(state.Index << 4) + posState].GetPrice0();
		}

		private uint GetPureRepPrice(uint repIndex, Base.State state, uint posState)
		{
			uint price;
			if (repIndex == 0)
			{
				price = _isRepG0[state.Index].GetPrice0();
				return price + _isRep0Long[(state.Index << 4) + posState].GetPrice1();
			}
			price = _isRepG0[state.Index].GetPrice1();
			if (repIndex == 1)
			{
				return price + _isRepG1[state.Index].GetPrice0();
			}
			price += _isRepG1[state.Index].GetPrice1();
			return price + _isRepG2[state.Index].GetPrice(repIndex - 2);
		}

		private uint GetRepPrice(uint repIndex, uint len, Base.State state, uint posState)
		{
			return _repMatchLenEncoder.GetPrice(len - 2, posState) + GetPureRepPrice(repIndex, state, posState);
		}

		private uint GetPosLenPrice(uint pos, uint len, uint posState)
		{
			uint lenToPosState = Base.GetLenToPosState(len);
			uint num = ((pos >= 128) ? (_posSlotPrices[(lenToPosState << 6) + GetPosSlot2(pos)] + _alignPrices[pos & 0xF]) : _distancesPrices[lenToPosState * 128 + pos]);
			return num + _lenEncoder.GetPrice(len - 2, posState);
		}

		private uint Backward(out uint backRes, uint cur)
		{
			_optimumEndIndex = cur;
			uint posPrev = _optimum[cur].PosPrev;
			uint backPrev = _optimum[cur].BackPrev;
			do
			{
				if (_optimum[cur].Prev1IsChar)
				{
					_optimum[posPrev].MakeAsChar();
					_optimum[posPrev].PosPrev = posPrev - 1;
					if (_optimum[cur].Prev2)
					{
						_optimum[posPrev - 1].Prev1IsChar = false;
						_optimum[posPrev - 1].PosPrev = _optimum[cur].PosPrev2;
						_optimum[posPrev - 1].BackPrev = _optimum[cur].BackPrev2;
					}
				}
				uint num = posPrev;
				uint backPrev2 = backPrev;
				backPrev = _optimum[num].BackPrev;
				posPrev = _optimum[num].PosPrev;
				_optimum[num].BackPrev = backPrev2;
				_optimum[num].PosPrev = cur;
				cur = num;
			}
			while (cur != 0);
			backRes = _optimum[0].BackPrev;
			_optimumCurrentIndex = _optimum[0].PosPrev;
			return _optimumCurrentIndex;
		}

		private uint GetOptimum(uint position, out uint backRes)
		{
			if (_optimumEndIndex != _optimumCurrentIndex)
			{
				uint result = _optimum[_optimumCurrentIndex].PosPrev - _optimumCurrentIndex;
				backRes = _optimum[_optimumCurrentIndex].BackPrev;
				_optimumCurrentIndex = _optimum[_optimumCurrentIndex].PosPrev;
				return result;
			}
			_optimumCurrentIndex = (_optimumEndIndex = 0u);
			uint lenRes;
			uint numDistancePairs;
			if (!_longestMatchWasFound)
			{
				ReadMatchDistances(out lenRes, out numDistancePairs);
			}
			else
			{
				lenRes = _longestMatchLength;
				numDistancePairs = _numDistancePairs;
				_longestMatchWasFound = false;
			}
			uint num = _matchFinder.GetNumAvailableBytes() + 1;
			if (num < 2)
			{
				backRes = uint.MaxValue;
				return 1u;
			}
			if (num > 273)
			{
				num = 273u;
			}
			uint num2 = 0u;
			for (uint num3 = 0u; num3 < 4; num3++)
			{
				reps[num3] = _repDistances[num3];
				repLens[num3] = _matchFinder.GetMatchLen(-1, reps[num3], 273u);
				if (repLens[num3] > repLens[num2])
				{
					num2 = num3;
				}
			}
			if (repLens[num2] >= _numFastBytes)
			{
				backRes = num2;
				uint num4 = repLens[num2];
				MovePos(num4 - 1);
				return num4;
			}
			if (lenRes >= _numFastBytes)
			{
				backRes = _matchDistances[numDistancePairs - 1] + 4;
				MovePos(lenRes - 1);
				return lenRes;
			}
			byte indexByte = _matchFinder.GetIndexByte(-1);
			byte indexByte2 = _matchFinder.GetIndexByte((int)(0 - _repDistances[0] - 1 - 1));
			if (lenRes < 2 && indexByte != indexByte2 && repLens[num2] < 2)
			{
				backRes = uint.MaxValue;
				return 1u;
			}
			_optimum[0].State = _state;
			uint num5 = position & _posStateMask;
			_optimum[1].Price = _isMatch[(_state.Index << 4) + num5].GetPrice0() + _literalEncoder.GetSubCoder(position, _previousByte).GetPrice(!_state.IsCharState(), indexByte2, indexByte);
			_optimum[1].MakeAsChar();
			uint price = _isMatch[(_state.Index << 4) + num5].GetPrice1();
			uint num6 = price + _isRep[_state.Index].GetPrice1();
			if (indexByte2 == indexByte)
			{
				uint num7 = num6 + GetRepLen1Price(_state, num5);
				if (num7 < _optimum[1].Price)
				{
					_optimum[1].Price = num7;
					_optimum[1].MakeAsShortRep();
				}
			}
			uint num8 = ((lenRes >= repLens[num2]) ? lenRes : repLens[num2]);
			if (num8 < 2)
			{
				backRes = _optimum[1].BackPrev;
				return 1u;
			}
			_optimum[1].PosPrev = 0u;
			_optimum[0].Backs0 = reps[0];
			_optimum[0].Backs1 = reps[1];
			_optimum[0].Backs2 = reps[2];
			_optimum[0].Backs3 = reps[3];
			uint num9 = num8;
			do
			{
				_optimum[num9--].Price = 268435455u;
			}
			while (num9 >= 2);
			for (uint num3 = 0u; num3 < 4; num3++)
			{
				uint num10 = repLens[num3];
				if (num10 < 2)
				{
					continue;
				}
				uint num11 = num6 + GetPureRepPrice(num3, _state, num5);
				do
				{
					uint num12 = num11 + _repMatchLenEncoder.GetPrice(num10 - 2, num5);
					Optimal optimal = _optimum[num10];
					if (num12 < optimal.Price)
					{
						optimal.Price = num12;
						optimal.PosPrev = 0u;
						optimal.BackPrev = num3;
						optimal.Prev1IsChar = false;
					}
				}
				while (--num10 >= 2);
			}
			uint num13 = price + _isRep[_state.Index].GetPrice0();
			num9 = ((repLens[0] >= 2) ? (repLens[0] + 1) : 2u);
			if (num9 <= lenRes)
			{
				uint num14;
				for (num14 = 0u; num9 > _matchDistances[num14]; num14 += 2)
				{
				}
				while (true)
				{
					uint num15 = _matchDistances[num14 + 1];
					uint num16 = num13 + GetPosLenPrice(num15, num9, num5);
					Optimal optimal2 = _optimum[num9];
					if (num16 < optimal2.Price)
					{
						optimal2.Price = num16;
						optimal2.PosPrev = 0u;
						optimal2.BackPrev = num15 + 4;
						optimal2.Prev1IsChar = false;
					}
					if (num9 == _matchDistances[num14])
					{
						num14 += 2;
						if (num14 == numDistancePairs)
						{
							break;
						}
					}
					num9++;
				}
			}
			uint num17 = 0u;
			uint lenRes2;
			while (true)
			{
				num17++;
				if (num17 == num8)
				{
					return Backward(out backRes, num17);
				}
				ReadMatchDistances(out lenRes2, out numDistancePairs);
				if (lenRes2 >= _numFastBytes)
				{
					break;
				}
				position++;
				uint num18 = _optimum[num17].PosPrev;
				Base.State state;
				if (_optimum[num17].Prev1IsChar)
				{
					num18--;
					if (_optimum[num17].Prev2)
					{
						state = _optimum[_optimum[num17].PosPrev2].State;
						if (_optimum[num17].BackPrev2 < 4)
						{
							state.UpdateRep();
						}
						else
						{
							state.UpdateMatch();
						}
					}
					else
					{
						state = _optimum[num18].State;
					}
					state.UpdateChar();
				}
				else
				{
					state = _optimum[num18].State;
				}
				if (num18 == num17 - 1)
				{
					if (_optimum[num17].IsShortRep())
					{
						state.UpdateShortRep();
					}
					else
					{
						state.UpdateChar();
					}
				}
				else
				{
					uint num19;
					if (_optimum[num17].Prev1IsChar && _optimum[num17].Prev2)
					{
						num18 = _optimum[num17].PosPrev2;
						num19 = _optimum[num17].BackPrev2;
						state.UpdateRep();
					}
					else
					{
						num19 = _optimum[num17].BackPrev;
						if (num19 < 4)
						{
							state.UpdateRep();
						}
						else
						{
							state.UpdateMatch();
						}
					}
					Optimal optimal3 = _optimum[num18];
					switch (num19)
					{
					case 0u:
						reps[0] = optimal3.Backs0;
						reps[1] = optimal3.Backs1;
						reps[2] = optimal3.Backs2;
						reps[3] = optimal3.Backs3;
						break;
					case 1u:
						reps[0] = optimal3.Backs1;
						reps[1] = optimal3.Backs0;
						reps[2] = optimal3.Backs2;
						reps[3] = optimal3.Backs3;
						break;
					case 2u:
						reps[0] = optimal3.Backs2;
						reps[1] = optimal3.Backs0;
						reps[2] = optimal3.Backs1;
						reps[3] = optimal3.Backs3;
						break;
					case 3u:
						reps[0] = optimal3.Backs3;
						reps[1] = optimal3.Backs0;
						reps[2] = optimal3.Backs1;
						reps[3] = optimal3.Backs2;
						break;
					default:
						reps[0] = num19 - 4;
						reps[1] = optimal3.Backs0;
						reps[2] = optimal3.Backs1;
						reps[3] = optimal3.Backs2;
						break;
					}
				}
				_optimum[num17].State = state;
				_optimum[num17].Backs0 = reps[0];
				_optimum[num17].Backs1 = reps[1];
				_optimum[num17].Backs2 = reps[2];
				_optimum[num17].Backs3 = reps[3];
				uint price2 = _optimum[num17].Price;
				indexByte = _matchFinder.GetIndexByte(-1);
				indexByte2 = _matchFinder.GetIndexByte((int)(0 - reps[0] - 1 - 1));
				num5 = position & _posStateMask;
				uint num20 = price2 + _isMatch[(state.Index << 4) + num5].GetPrice0() + _literalEncoder.GetSubCoder(position, _matchFinder.GetIndexByte(-2)).GetPrice(!state.IsCharState(), indexByte2, indexByte);
				Optimal optimal4 = _optimum[num17 + 1];
				bool flag = false;
				if (num20 < optimal4.Price)
				{
					optimal4.Price = num20;
					optimal4.PosPrev = num17;
					optimal4.MakeAsChar();
					flag = true;
				}
				price = price2 + _isMatch[(state.Index << 4) + num5].GetPrice1();
				num6 = price + _isRep[state.Index].GetPrice1();
				if (indexByte2 == indexByte && (optimal4.PosPrev >= num17 || optimal4.BackPrev != 0))
				{
					uint num21 = num6 + GetRepLen1Price(state, num5);
					if (num21 <= optimal4.Price)
					{
						optimal4.Price = num21;
						optimal4.PosPrev = num17;
						optimal4.MakeAsShortRep();
						flag = true;
					}
				}
				uint val = _matchFinder.GetNumAvailableBytes() + 1;
				val = Math.Min(4095 - num17, val);
				num = val;
				if (num < 2)
				{
					continue;
				}
				if (num > _numFastBytes)
				{
					num = _numFastBytes;
				}
				if (!flag && indexByte2 != indexByte)
				{
					uint limit = Math.Min(val - 1, _numFastBytes);
					uint matchLen = _matchFinder.GetMatchLen(0, reps[0], limit);
					if (matchLen >= 2)
					{
						Base.State state2 = state;
						state2.UpdateChar();
						uint num22 = (position + 1) & _posStateMask;
						uint num23 = num20 + _isMatch[(state2.Index << 4) + num22].GetPrice1() + _isRep[state2.Index].GetPrice1();
						uint num24 = num17 + 1 + matchLen;
						while (num8 < num24)
						{
							_optimum[++num8].Price = 268435455u;
						}
						uint num25 = num23 + GetRepPrice(0u, matchLen, state2, num22);
						Optimal optimal5 = _optimum[num24];
						if (num25 < optimal5.Price)
						{
							optimal5.Price = num25;
							optimal5.PosPrev = num17 + 1;
							optimal5.BackPrev = 0u;
							optimal5.Prev1IsChar = true;
							optimal5.Prev2 = false;
						}
					}
				}
				uint num26 = 2u;
				for (uint num27 = 0u; num27 < 4; num27++)
				{
					uint num28 = _matchFinder.GetMatchLen(-1, reps[num27], num);
					if (num28 < 2)
					{
						continue;
					}
					uint num29 = num28;
					while (true)
					{
						if (num8 < num17 + num28)
						{
							_optimum[++num8].Price = 268435455u;
							continue;
						}
						uint num30 = num6 + GetRepPrice(num27, num28, state, num5);
						Optimal optimal6 = _optimum[num17 + num28];
						if (num30 < optimal6.Price)
						{
							optimal6.Price = num30;
							optimal6.PosPrev = num17;
							optimal6.BackPrev = num27;
							optimal6.Prev1IsChar = false;
						}
						if (--num28 < 2)
						{
							break;
						}
					}
					num28 = num29;
					if (num27 == 0)
					{
						num26 = num28 + 1;
					}
					if (num28 >= val)
					{
						continue;
					}
					uint limit2 = Math.Min(val - 1 - num28, _numFastBytes);
					uint matchLen2 = _matchFinder.GetMatchLen((int)num28, reps[num27], limit2);
					if (matchLen2 >= 2)
					{
						Base.State state3 = state;
						state3.UpdateRep();
						uint num31 = (position + num28) & _posStateMask;
						uint num32 = num6 + GetRepPrice(num27, num28, state, num5) + _isMatch[(state3.Index << 4) + num31].GetPrice0() + _literalEncoder.GetSubCoder(position + num28, _matchFinder.GetIndexByte((int)(num28 - 1 - 1))).GetPrice(matchMode: true, _matchFinder.GetIndexByte((int)(num28 - 1 - (reps[num27] + 1))), _matchFinder.GetIndexByte((int)(num28 - 1)));
						state3.UpdateChar();
						num31 = (position + num28 + 1) & _posStateMask;
						uint num33 = num32 + _isMatch[(state3.Index << 4) + num31].GetPrice1() + _isRep[state3.Index].GetPrice1();
						uint num34 = num28 + 1 + matchLen2;
						while (num8 < num17 + num34)
						{
							_optimum[++num8].Price = 268435455u;
						}
						uint num35 = num33 + GetRepPrice(0u, matchLen2, state3, num31);
						Optimal optimal7 = _optimum[num17 + num34];
						if (num35 < optimal7.Price)
						{
							optimal7.Price = num35;
							optimal7.PosPrev = num17 + num28 + 1;
							optimal7.BackPrev = 0u;
							optimal7.Prev1IsChar = true;
							optimal7.Prev2 = true;
							optimal7.PosPrev2 = num17;
							optimal7.BackPrev2 = num27;
						}
					}
				}
				if (lenRes2 > num)
				{
					lenRes2 = num;
					for (numDistancePairs = 0u; lenRes2 > _matchDistances[numDistancePairs]; numDistancePairs += 2)
					{
					}
					_matchDistances[numDistancePairs] = lenRes2;
					numDistancePairs += 2;
				}
				if (lenRes2 < num26)
				{
					continue;
				}
				num13 = price + _isRep[state.Index].GetPrice0();
				while (num8 < num17 + lenRes2)
				{
					_optimum[++num8].Price = 268435455u;
				}
				uint num36;
				for (num36 = 0u; num26 > _matchDistances[num36]; num36 += 2)
				{
				}
				uint num37 = num26;
				while (true)
				{
					uint num38 = _matchDistances[num36 + 1];
					uint num39 = num13 + GetPosLenPrice(num38, num37, num5);
					Optimal optimal8 = _optimum[num17 + num37];
					if (num39 < optimal8.Price)
					{
						optimal8.Price = num39;
						optimal8.PosPrev = num17;
						optimal8.BackPrev = num38 + 4;
						optimal8.Prev1IsChar = false;
					}
					if (num37 == _matchDistances[num36])
					{
						if (num37 < val)
						{
							uint limit3 = Math.Min(val - 1 - num37, _numFastBytes);
							uint matchLen3 = _matchFinder.GetMatchLen((int)num37, num38, limit3);
							if (matchLen3 >= 2)
							{
								Base.State state4 = state;
								state4.UpdateMatch();
								uint num40 = (position + num37) & _posStateMask;
								uint num41 = num39 + _isMatch[(state4.Index << 4) + num40].GetPrice0() + _literalEncoder.GetSubCoder(position + num37, _matchFinder.GetIndexByte((int)(num37 - 1 - 1))).GetPrice(matchMode: true, _matchFinder.GetIndexByte((int)(num37 - (num38 + 1) - 1)), _matchFinder.GetIndexByte((int)(num37 - 1)));
								state4.UpdateChar();
								num40 = (position + num37 + 1) & _posStateMask;
								uint num42 = num41 + _isMatch[(state4.Index << 4) + num40].GetPrice1() + _isRep[state4.Index].GetPrice1();
								uint num43 = num37 + 1 + matchLen3;
								while (num8 < num17 + num43)
								{
									_optimum[++num8].Price = 268435455u;
								}
								num39 = num42 + GetRepPrice(0u, matchLen3, state4, num40);
								optimal8 = _optimum[num17 + num43];
								if (num39 < optimal8.Price)
								{
									optimal8.Price = num39;
									optimal8.PosPrev = num17 + num37 + 1;
									optimal8.BackPrev = 0u;
									optimal8.Prev1IsChar = true;
									optimal8.Prev2 = true;
									optimal8.PosPrev2 = num17;
									optimal8.BackPrev2 = num38 + 4;
								}
							}
						}
						num36 += 2;
						if (num36 == numDistancePairs)
						{
							break;
						}
					}
					num37++;
				}
			}
			_numDistancePairs = numDistancePairs;
			_longestMatchLength = lenRes2;
			_longestMatchWasFound = true;
			return Backward(out backRes, num17);
		}

		private bool ChangePair(uint smallDist, uint bigDist)
		{
			if (smallDist < 33554432)
			{
				return bigDist >= smallDist << 7;
			}
			return false;
		}

		private void WriteEndMarker(uint posState)
		{
			if (_writeEndMark)
			{
				_isMatch[(_state.Index << 4) + posState].Encode(_rangeEncoder, 1u);
				_isRep[_state.Index].Encode(_rangeEncoder, 0u);
				_state.UpdateMatch();
				uint num = 2u;
				_lenEncoder.Encode(_rangeEncoder, num - 2, posState);
				uint symbol = 63u;
				uint lenToPosState = Base.GetLenToPosState(num);
				_posSlotEncoder[lenToPosState].Encode(_rangeEncoder, symbol);
				int num2 = 30;
				uint num3 = (uint)((1 << num2) - 1);
				_rangeEncoder.EncodeDirectBits(num3 >> 4, num2 - 4);
				_posAlignEncoder.ReverseEncode(_rangeEncoder, num3 & 0xFu);
			}
		}

		private void Flush(uint nowPos)
		{
			ReleaseMFStream();
			WriteEndMarker(nowPos & _posStateMask);
			_rangeEncoder.FlushData();
			_rangeEncoder.FlushStream();
		}

		public void CodeOneBlock(out long inSize, out long outSize, out bool finished)
		{
			inSize = 0L;
			outSize = 0L;
			finished = true;
			if (_inStream != null)
			{
				_matchFinder.SetStream(_inStream);
				_matchFinder.Init();
				_needReleaseMFStream = true;
				_inStream = null;
				if (_trainSize != 0)
				{
					_matchFinder.Skip(_trainSize);
				}
			}
			if (_finished)
			{
				return;
			}
			_finished = true;
			long num = nowPos64;
			if (nowPos64 == 0L)
			{
				if (_matchFinder.GetNumAvailableBytes() == 0)
				{
					Flush((uint)nowPos64);
					return;
				}
				ReadMatchDistances(out var _, out var _);
				uint num2 = (uint)(int)nowPos64 & _posStateMask;
				_isMatch[(_state.Index << 4) + num2].Encode(_rangeEncoder, 0u);
				_state.UpdateChar();
				byte indexByte = _matchFinder.GetIndexByte((int)(0 - _additionalOffset));
				_literalEncoder.GetSubCoder((uint)nowPos64, _previousByte).Encode(_rangeEncoder, indexByte);
				_previousByte = indexByte;
				_additionalOffset--;
				nowPos64++;
			}
			if (_matchFinder.GetNumAvailableBytes() == 0)
			{
				Flush((uint)nowPos64);
				return;
			}
			while (true)
			{
				uint backRes;
				uint optimum = GetOptimum((uint)nowPos64, out backRes);
				uint num3 = (uint)(int)nowPos64 & _posStateMask;
				uint num4 = (_state.Index << 4) + num3;
				if (optimum == 1 && backRes == uint.MaxValue)
				{
					_isMatch[num4].Encode(_rangeEncoder, 0u);
					byte indexByte2 = _matchFinder.GetIndexByte((int)(0 - _additionalOffset));
					LiteralEncoder.Encoder2 subCoder = _literalEncoder.GetSubCoder((uint)nowPos64, _previousByte);
					if (!_state.IsCharState())
					{
						byte indexByte3 = _matchFinder.GetIndexByte((int)(0 - _repDistances[0] - 1 - _additionalOffset));
						subCoder.EncodeMatched(_rangeEncoder, indexByte3, indexByte2);
					}
					else
					{
						subCoder.Encode(_rangeEncoder, indexByte2);
					}
					_previousByte = indexByte2;
					_state.UpdateChar();
				}
				else
				{
					_isMatch[num4].Encode(_rangeEncoder, 1u);
					if (backRes < 4)
					{
						_isRep[_state.Index].Encode(_rangeEncoder, 1u);
						if (backRes == 0)
						{
							_isRepG0[_state.Index].Encode(_rangeEncoder, 0u);
							if (optimum == 1)
							{
								_isRep0Long[num4].Encode(_rangeEncoder, 0u);
							}
							else
							{
								_isRep0Long[num4].Encode(_rangeEncoder, 1u);
							}
						}
						else
						{
							_isRepG0[_state.Index].Encode(_rangeEncoder, 1u);
							if (backRes == 1)
							{
								_isRepG1[_state.Index].Encode(_rangeEncoder, 0u);
							}
							else
							{
								_isRepG1[_state.Index].Encode(_rangeEncoder, 1u);
								_isRepG2[_state.Index].Encode(_rangeEncoder, backRes - 2);
							}
						}
						if (optimum == 1)
						{
							_state.UpdateShortRep();
						}
						else
						{
							_repMatchLenEncoder.Encode(_rangeEncoder, optimum - 2, num3);
							_state.UpdateRep();
						}
						uint num5 = _repDistances[backRes];
						if (backRes != 0)
						{
							for (uint num6 = backRes; num6 >= 1; num6--)
							{
								_repDistances[num6] = _repDistances[num6 - 1];
							}
							_repDistances[0] = num5;
						}
					}
					else
					{
						_isRep[_state.Index].Encode(_rangeEncoder, 0u);
						_state.UpdateMatch();
						_lenEncoder.Encode(_rangeEncoder, optimum - 2, num3);
						backRes -= 4;
						uint posSlot = GetPosSlot(backRes);
						uint lenToPosState = Base.GetLenToPosState(optimum);
						_posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot);
						if (posSlot >= 4)
						{
							int num7 = (int)((posSlot >> 1) - 1);
							uint num8 = (2 | (posSlot & 1)) << num7;
							uint num9 = backRes - num8;
							if (posSlot < 14)
							{
								BitTreeEncoder.ReverseEncode(_posEncoders, num8 - posSlot - 1, _rangeEncoder, num7, num9);
							}
							else
							{
								_rangeEncoder.EncodeDirectBits(num9 >> 4, num7 - 4);
								_posAlignEncoder.ReverseEncode(_rangeEncoder, num9 & 0xFu);
								_alignPriceCount++;
							}
						}
						uint num10 = backRes;
						for (uint num11 = 3u; num11 >= 1; num11--)
						{
							_repDistances[num11] = _repDistances[num11 - 1];
						}
						_repDistances[0] = num10;
						_matchPriceCount++;
					}
					_previousByte = _matchFinder.GetIndexByte((int)(optimum - 1 - _additionalOffset));
				}
				_additionalOffset -= optimum;
				nowPos64 += optimum;
				if (_additionalOffset == 0)
				{
					if (_matchPriceCount >= 128)
					{
						FillDistancesPrices();
					}
					if (_alignPriceCount >= 16)
					{
						FillAlignPrices();
					}
					inSize = nowPos64;
					outSize = _rangeEncoder.GetProcessedSizeAdd();
					if (_matchFinder.GetNumAvailableBytes() == 0)
					{
						Flush((uint)nowPos64);
						return;
					}
					if (nowPos64 - num >= 4096)
					{
						break;
					}
				}
			}
			_finished = false;
			finished = false;
		}

		private void ReleaseMFStream()
		{
			if (_matchFinder != null && _needReleaseMFStream)
			{
				_matchFinder.ReleaseStream();
				_needReleaseMFStream = false;
			}
		}

		private void SetOutStream(Stream outStream)
		{
			_rangeEncoder.SetStream(outStream);
		}

		private void ReleaseOutStream()
		{
			_rangeEncoder.ReleaseStream();
		}

		private void ReleaseStreams()
		{
			ReleaseMFStream();
			ReleaseOutStream();
		}

		private void SetStreams(Stream inStream, Stream outStream, long inSize, long outSize)
		{
			_inStream = inStream;
			_finished = false;
			Create();
			SetOutStream(outStream);
			Init();
			FillDistancesPrices();
			FillAlignPrices();
			_lenEncoder.SetTableSize(_numFastBytes + 1 - 2);
			_lenEncoder.UpdateTables((uint)(1 << _posStateBits));
			_repMatchLenEncoder.SetTableSize(_numFastBytes + 1 - 2);
			_repMatchLenEncoder.UpdateTables((uint)(1 << _posStateBits));
			nowPos64 = 0L;
		}

		public void Code(Stream inStream, Stream outStream, long inSize, long outSize, ICodeProgress progress)
		{
			_needReleaseMFStream = false;
			try
			{
				SetStreams(inStream, outStream, inSize, outSize);
				while (true)
				{
					CodeOneBlock(out var inSize2, out var outSize2, out var finished);
					if (finished)
					{
						break;
					}
					progress?.SetProgress(inSize2, outSize2);
				}
			}
			finally
			{
				ReleaseStreams();
			}
		}

		public void WriteCoderProperties(Stream outStream)
		{
			properties[0] = (byte)((_posStateBits * 5 + _numLiteralPosStateBits) * 9 + _numLiteralContextBits);
			for (int i = 0; i < 4; i++)
			{
				properties[1 + i] = (byte)((_dictionarySize >> 8 * i) & 0xFFu);
			}
			outStream.Write(properties, 0, 5);
		}

		private void FillDistancesPrices()
		{
			for (uint num = 4u; num < 128; num++)
			{
				uint posSlot = GetPosSlot(num);
				int num2 = (int)((posSlot >> 1) - 1);
				uint num3 = (2 | (posSlot & 1)) << num2;
				tempPrices[num] = BitTreeEncoder.ReverseGetPrice(_posEncoders, num3 - posSlot - 1, num2, num - num3);
			}
			for (uint num4 = 0u; num4 < 4; num4++)
			{
				BitTreeEncoder bitTreeEncoder = _posSlotEncoder[num4];
				uint num5 = num4 << 6;
				for (uint num6 = 0u; num6 < _distTableSize; num6++)
				{
					_posSlotPrices[num5 + num6] = bitTreeEncoder.GetPrice(num6);
				}
				for (uint num6 = 14u; num6 < _distTableSize; num6++)
				{
					_posSlotPrices[num5 + num6] += (num6 >> 1) - 1 - 4 << 6;
				}
				uint num7 = num4 * 128;
				uint num8;
				for (num8 = 0u; num8 < 4; num8++)
				{
					_distancesPrices[num7 + num8] = _posSlotPrices[num5 + num8];
				}
				for (; num8 < 128; num8++)
				{
					_distancesPrices[num7 + num8] = _posSlotPrices[num5 + GetPosSlot(num8)] + tempPrices[num8];
				}
			}
			_matchPriceCount = 0u;
		}

		private void FillAlignPrices()
		{
			for (uint num = 0u; num < 16; num++)
			{
				_alignPrices[num] = _posAlignEncoder.ReverseGetPrice(num);
			}
			_alignPriceCount = 0u;
		}

		private static int FindMatchFinder(string s)
		{
			for (int i = 0; i < kMatchFinderIDs.Length; i++)
			{
				if (s == kMatchFinderIDs[i])
				{
					return i;
				}
			}
			return -1;
		}

		public void SetCoderProperties(CoderPropID[] propIDs, object[] properties)
		{
			for (uint num = 0u; num < properties.Length; num++)
			{
				object obj = properties[num];
				switch (propIDs[num])
				{
				case CoderPropID.NumFastBytes:
					if (!(obj is int num2))
					{
						throw new InvalidParamException();
					}
					if (num2 < 5 || (long)num2 > 273L)
					{
						throw new InvalidParamException();
					}
					_numFastBytes = (uint)num2;
					break;
				case CoderPropID.MatchFinder:
				{
					if (!(obj is string))
					{
						throw new InvalidParamException();
					}
					EMatchFinderType matchFinderType = _matchFinderType;
					int num6 = FindMatchFinder(((string)obj).ToUpper());
					if (num6 < 0)
					{
						throw new InvalidParamException();
					}
					_matchFinderType = (EMatchFinderType)num6;
					if (_matchFinder != null && matchFinderType != _matchFinderType)
					{
						_dictionarySizePrev = uint.MaxValue;
						_matchFinder = null;
					}
					break;
				}
				case CoderPropID.DictionarySize:
				{
					if (!(obj is int num7))
					{
						throw new InvalidParamException();
					}
					if ((long)num7 < 1L || (long)num7 > 1073741824L)
					{
						throw new InvalidParamException();
					}
					_dictionarySize = (uint)num7;
					int i;
					for (i = 0; (long)i < 30L && num7 > (uint)(1 << i); i++)
					{
					}
					_distTableSize = (uint)(i * 2);
					break;
				}
				case CoderPropID.PosStateBits:
					if (!(obj is int num3))
					{
						throw new InvalidParamException();
					}
					if (num3 < 0 || (long)num3 > 4L)
					{
						throw new InvalidParamException();
					}
					_posStateBits = num3;
					_posStateMask = (uint)((1 << _posStateBits) - 1);
					break;
				case CoderPropID.LitPosBits:
					if (!(obj is int num5))
					{
						throw new InvalidParamException();
					}
					if (num5 < 0 || (long)num5 > 4L)
					{
						throw new InvalidParamException();
					}
					_numLiteralPosStateBits = num5;
					break;
				case CoderPropID.LitContextBits:
					if (!(obj is int num4))
					{
						throw new InvalidParamException();
					}
					if (num4 < 0 || (long)num4 > 8L)
					{
						throw new InvalidParamException();
					}
					_numLiteralContextBits = num4;
					break;
				case CoderPropID.EndMarker:
					if (!(obj is bool))
					{
						throw new InvalidParamException();
					}
					SetWriteEndMarkerMode((bool)obj);
					break;
				default:
					throw new InvalidParamException();
				case CoderPropID.Algorithm:
					break;
				}
			}
		}

		public void SetTrainSize(uint trainSize)
		{
			_trainSize = trainSize;
		}
	}
	public static class SevenZipHelper
	{
		private static CoderPropID[] propIDs = new CoderPropID[8]
		{
			CoderPropID.DictionarySize,
			CoderPropID.PosStateBits,
			CoderPropID.LitContextBits,
			CoderPropID.LitPosBits,
			CoderPropID.Algorithm,
			CoderPropID.NumFastBytes,
			CoderPropID.MatchFinder,
			CoderPropID.EndMarker
		};

		private static object[] properties = new object[8] { 2097152, 2, 3, 0, 2, 32, "bt4", false };

		public static byte[] Compress(byte[] inputBytes, ICodeProgress progress = null)
		{
			MemoryStream inStream = new MemoryStream(inputBytes);
			MemoryStream memoryStream = new MemoryStream();
			Compress(inStream, memoryStream, progress);
			return memoryStream.ToArray();
		}

		public static void Compress(Stream inStream, Stream outStream, ICodeProgress progress = null)
		{
			Encoder encoder = new Encoder();
			encoder.SetCoderProperties(propIDs, properties);
			encoder.WriteCoderProperties(outStream);
			encoder.Code(inStream, outStream, -1L, -1L, progress);
		}

		public static byte[] Decompress(byte[] inputBytes)
		{
			MemoryStream memoryStream = new MemoryStream(inputBytes);
			Decoder decoder = new Decoder();
			memoryStream.Seek(0L, SeekOrigin.Begin);
			MemoryStream memoryStream2 = new MemoryStream();
			byte[] array = new byte[5];
			if (memoryStream.Read(array, 0, 5) != 5)
			{
				throw new Exception("input .lzma is too short");
			}
			long num = 0L;
			for (int i = 0; i < 8; i++)
			{
				int num2 = memoryStream.ReadByte();
				if (num2 < 0)
				{
					throw new Exception("Can't Read 1");
				}
				num |= (long)((ulong)(byte)num2 << 8 * i);
			}
			decoder.SetDecoderProperties(array);
			long inSize = memoryStream.Length - memoryStream.Position;
			decoder.Code(memoryStream, memoryStream2, inSize, num, null);
			return memoryStream2.ToArray();
		}

		public static MemoryStream StreamDecompress(MemoryStream newInStream)
		{
			Decoder decoder = new Decoder();
			newInStream.Seek(0L, SeekOrigin.Begin);
			MemoryStream memoryStream = new MemoryStream();
			byte[] array = new byte[5];
			if (newInStream.Read(array, 0, 5) != 5)
			{
				throw new Exception("input .lzma is too short");
			}
			long num = 0L;
			for (int i = 0; i < 8; i++)
			{
				int num2 = newInStream.ReadByte();
				if (num2 < 0)
				{
					throw new Exception("Can't Read 1");
				}
				num |= (long)((ulong)(byte)num2 << 8 * i);
			}
			decoder.SetDecoderProperties(array);
			long inSize = newInStream.Length - newInStream.Position;
			decoder.Code(newInStream, memoryStream, inSize, num, null);
			memoryStream.Position = 0L;
			return memoryStream;
		}

		public static MemoryStream StreamDecompress(MemoryStream newInStream, long outSize)
		{
			Decoder decoder = new Decoder();
			newInStream.Seek(0L, SeekOrigin.Begin);
			MemoryStream memoryStream = new MemoryStream();
			byte[] array = new byte[5];
			if (newInStream.Read(array, 0, 5) != 5)
			{
				throw new Exception("input .lzma is too short");
			}
			decoder.SetDecoderProperties(array);
			long inSize = newInStream.Length - newInStream.Position;
			decoder.Code(newInStream, memoryStream, inSize, outSize, null);
			memoryStream.Position = 0L;
			return memoryStream;
		}

		public static void StreamDecompress(Stream compressedStream, Stream decompressedStream, long compressedSize, long decompressedSize)
		{
			long position = compressedStream.Position;
			Decoder decoder = new Decoder();
			byte[] array = new byte[5];
			if (compressedStream.Read(array, 0, 5) != 5)
			{
				throw new Exception("input .lzma is too short");
			}
			decoder.SetDecoderProperties(array);
			decoder.Code(compressedStream, decompressedStream, compressedSize - 5, decompressedSize, null);
			compressedStream.Position = position + compressedSize;
		}
	}
}
namespace SevenZip.Buffer
{
	public class InBuffer
	{
		private byte[] m_Buffer;

		private uint m_Pos;

		private uint m_Limit;

		private uint m_BufferSize;

		private Stream m_Stream;

		private bool m_StreamWasExhausted;

		private ulong m_ProcessedSize;

		public InBuffer(uint bufferSize)
		{
			m_Buffer = new byte[bufferSize];
			m_BufferSize = bufferSize;
		}

		public void Init(Stream stream)
		{
			m_Stream = stream;
			m_ProcessedSize = 0uL;
			m_Limit = 0u;
			m_Pos = 0u;
			m_StreamWasExhausted = false;
		}

		public bool ReadBlock()
		{
			if (m_StreamWasExhausted)
			{
				return false;
			}
			m_ProcessedSize += m_Pos;
			int num = m_Stream.Read(m_Buffer, 0, (int)m_BufferSize);
			m_Pos = 0u;
			m_Limit = (uint)num;
			m_StreamWasExhausted = num == 0;
			return !m_StreamWasExhausted;
		}

		public void ReleaseStream()
		{
			m_Stream = null;
		}

		public bool ReadByte(byte b)
		{
			if (m_Pos >= m_Limit && !ReadBlock())
			{
				return false;
			}
			b = m_Buffer[m_Pos++];
			return true;
		}

		public byte ReadByte()
		{
			if (m_Pos >= m_Limit && !ReadBlock())
			{
				return byte.MaxValue;
			}
			return m_Buffer[m_Pos++];
		}

		public ulong GetProcessedSize()
		{
			return m_ProcessedSize + m_Pos;
		}
	}
	public class OutBuffer
	{
		private byte[] m_Buffer;

		private uint m_Pos;

		private uint m_BufferSize;

		private Stream m_Stream;

		private ulong m_ProcessedSize;

		public OutBuffer(uint bufferSize)
		{
			m_Buffer = new byte[bufferSize];
			m_BufferSize = bufferSize;
		}

		public void SetStream(Stream stream)
		{
			m_Stream = stream;
		}

		public void FlushStream()
		{
			m_Stream.Flush();
		}

		public void CloseStream()
		{
			m_Stream.Close();
		}

		public void ReleaseStream()
		{
			m_Stream = null;
		}

		public void Init()
		{
			m_ProcessedSize = 0uL;
			m_Pos = 0u;
		}

		public void WriteByte(byte b)
		{
			m_Buffer[m_Pos++] = b;
			if (m_Pos >= m_BufferSize)
			{
				FlushData();
			}
		}

		public void FlushData()
		{
			if (m_Pos != 0)
			{
				m_Stream.Write(m_Buffer, 0, (int)m_Pos);
				m_Pos = 0u;
			}
		}

		public ulong GetProcessedSize()
		{
			return m_ProcessedSize + m_Pos;
		}
	}
}
namespace SevenZip.CommandLineParser
{
	public enum SwitchType
	{
		Simple,
		PostMinus,
		LimitedPostString,
		UnLimitedPostString,
		PostChar
	}
	public class SwitchForm
	{
		public string IDString;

		public SwitchType Type;

		public bool Multi;

		public int MinLen;

		public int MaxLen;

		public string PostCharSet;

		public SwitchForm(string idString, SwitchType type, bool multi, int minLen, int maxLen, string postCharSet)
		{
			IDString = idString;
			Type = type;
			Multi = multi;
			MinLen = minLen;
			MaxLen = maxLen;
			PostCharSet = postCharSet;
		}

		public SwitchForm(string idString, SwitchType type, bool multi, int minLen)
			: this(idString, type, multi, minLen, 0, "")
		{
		}

		public SwitchForm(string idString, SwitchType type, bool multi)
			: this(idString, type, multi, 0)
		{
		}
	}
	public class SwitchResult
	{
		public bool ThereIs;

		public bool WithMinus;

		public ArrayList PostStrings = new ArrayList();

		public int PostCharIndex;

		public SwitchResult()
		{
			ThereIs = false;
		}
	}
	public class Parser
	{
		public ArrayList NonSwitchStrings = new ArrayList();

		private SwitchResult[] _switches;

		private const char kSwitchID1 = '-';

		private const char kSwitchID2 = '/';

		private const char kSwitchMinus = '-';

		private const string kStopSwitchParsing = "--";

		public SwitchResult this[int index] => _switches[index];

		public Parser(int numSwitches)
		{
			_switches = new SwitchResult[numSwitches];
			for (int i = 0; i < numSwitches; i++)
			{
				_switches[i] = new SwitchResult();
			}
		}

		private bool ParseString(string srcString, SwitchForm[] switchForms)
		{
			int length = srcString.Length;
			if (length == 0)
			{
				return false;
			}
			int num = 0;
			if (!IsItSwitchChar(srcString[num]))
			{
				return false;
			}
			while (num < length)
			{
				if (IsItSwitchChar(srcString[num]))
				{
					num++;
				}
				int num2 = 0;
				int num3 = -1;
				for (int i = 0; i < _switches.Length; i++)
				{
					int length2 = switchForms[i].IDString.Length;
					if (length2 > num3 && num + length2 <= length && string.Compare(switchForms[i].IDString, 0, srcString, num, length2, ignoreCase: true) == 0)
					{
						num2 = i;
						num3 = length2;
					}
				}
				if (num3 == -1)
				{
					throw new Exception("maxLen == kNoLen");
				}
				SwitchResult switchResult = _switches[num2];
				SwitchForm switchForm = switchForms[num2];
				if (!switchForm.Multi && switchResult.ThereIs)
				{
					throw new Exception("switch must be single");
				}
				switchResult.ThereIs = true;
				num += num3;
				int num4 = length - num;
				SwitchType type = switchForm.Type;
				switch (type)
				{
				case SwitchType.PostMinus:
					if (num4 == 0)
					{
						switchResult.WithMinus = false;
						break;
					}
					switchResult.WithMinus = srcString[num] == '-';
					if (switchResult.WithMinus)
					{
						num++;
					}
					break;
				case SwitchType.PostChar:
				{
					if (num4 < switchForm.MinLen)
					{
						throw new Exception("switch is not full");
					}
					string postCharSet = switchForm.PostCharSet;
					if (num4 == 0)
					{
						switchResult.PostCharIndex = -1;
						break;
					}
					int num6 = postCharSet.IndexOf(srcString[num]);
					if (num6 < 0)
					{
						switchResult.PostCharIndex = -1;
						break;
					}
					switchResult.PostCharIndex = num6;
					num++;
					break;
				}
				case SwitchType.LimitedPostString:
				case SwitchType.UnLimitedPostString:
				{
					int minLen = switchForm.MinLen;
					if (num4 < minLen)
					{
						throw new Exception("switch is not full");
					}
					if (type == SwitchType.UnLimitedPostString)
					{
						switchResult.PostStrings.Add(srcString.Substring(num));
						return true;
					}
					string text = srcString.Substring(num, minLen);
					num += minLen;
					int num5 = minLen;
					while (num5 < switchForm.MaxLen && num < length)
					{
						char c = srcString[num];
						if (IsItSwitchChar(c))
						{
							break;
						}
						text += c;
						num5++;
						num++;
					}
					switchResult.PostStrings.Add(text);
					break;
				}
				}
			}
			return true;
		}

		public void ParseStrings(SwitchForm[] switchForms, string[] commandStrings)
		{
			int num = commandStrings.Length;
			bool flag = false;
			for (int i = 0; i < num; i++)
			{
				string text = commandStrings[i];
				if (flag)
				{
					NonSwitchStrings.Add(text);
				}
				else if (text == "--")
				{
					flag = true;
				}
				else if (!ParseString(text, switchForms))
				{
					NonSwitchStrings.Add(text);
				}
			}
		}

		public static int ParseCommand(CommandForm[] commandForms, string commandString, out string postString)
		{
			for (int i = 0; i < commandForms.Length; i++)
			{
				string iDString = commandForms[i].IDString;
				if (commandForms[i].PostStringMode)
				{
					if (commandString.IndexOf(iDString) == 0)
					{
						postString = commandString.Substring(iDString.Length);
						return i;
					}
				}
				else if (commandString == iDString)
				{
					postString = "";
					return i;
				}
			}
			postString = "";
			return -1;
		}

		private static bool ParseSubCharsCommand(int numForms, CommandSubCharsSet[] forms, string commandString, ArrayList indices)
		{
			indices.Clear();
			int num = 0;
			for (int i = 0; i < numForms; i++)
			{
				CommandSubCharsSet commandSubCharsSet = forms[i];
				int num2 = -1;
				int length = commandSubCharsSet.Chars.Length;
				for (int j = 0; j < length; j++)
				{
					char value = commandSubCharsSet.Chars[j];
					int num3 = commandString.IndexOf(value);
					if (num3 >= 0)
					{
						if (num2 >= 0)
						{
							return false;
						}
						if (commandString.IndexOf(value, num3 + 1) >= 0)
						{
							return false;
						}
						num2 = j;
						num++;
					}
				}
				if (num2 == -1 && !commandSubCharsSet.EmptyAllowed)
				{
					return false;
				}
				indices.Add(num2);
			}
			return num == commandString.Length;
		}

		private static bool IsItSwitchChar(char c)
		{
			if (c != '-')
			{
				return c == '/';
			}
			return true;
		}
	}
	public class CommandForm
	{
		public string IDString = "";

		public bool PostStringMode;

		public CommandForm(string idString, bool postStringMode)
		{
			IDString = idString;
			PostStringMode = postStringMode;
		}
	}
	internal class CommandSubCharsSet
	{
		public string Chars = "";

		public bool EmptyAllowed;
	}
}
namespace LZ4ps
{
	public static class LZ4Codec
	{
		private class LZ4HC_Data_Structure
		{
			public byte[] src;

			public int src_base;

			public int src_end;

			public int src_LASTLITERALS;

			public byte[] dst;

			public int dst_base;

			public int dst_len;

			public int dst_end;

			public int[] hashTable;

			public ushort[] chainTable;

			public int nextToUpdate;
		}

		private const int MEMORY_USAGE = 14;

		private const int NOTCOMPRESSIBLE_DETECTIONLEVEL = 6;

		private const int BLOCK_COPY_LIMIT = 16;

		private const int MINMATCH = 4;

		private const int SKIPSTRENGTH = 6;

		private const int COPYLENGTH = 8;

		private const int LASTLITERALS = 5;

		private const int MFLIMIT = 12;

		private const int MINLENGTH = 13;

		private const int MAXD_LOG = 16;

		private const int MAXD = 65536;

		private const int MAXD_MASK = 65535;

		private const int MAX_DISTANCE = 65535;

		private const int ML_BITS = 4;

		private const int ML_MASK = 15;

		private const int RUN_BITS = 4;

		private const int RUN_MASK = 15;

		private const int STEPSIZE_64 = 8;

		private const int STEPSIZE_32 = 4;

		private const int LZ4_64KLIMIT = 65547;

		private const int HASH_LOG = 12;

		private const int HASH_TABLESIZE = 4096;

		private const int HASH_ADJUST = 20;

		private const int HASH64K_LOG = 13;

		private const int HASH64K_TABLESIZE = 8192;

		private const int HASH64K_ADJUST = 19;

		private const int HASHHC_LOG = 15;

		private const int HASHHC_TABLESIZE = 32768;

		private const int HASHHC_ADJUST = 17;

		private static readonly int[] DECODER_TABLE_32 = new int[8] { 0, 3, 2, 3, 0, 0, 0, 0 };

		private static readonly int[] DECODER_TABLE_64 = new int[8] { 0, 0, 0, -1, 0, 1, 2, 3 };

		private static readonly int[] DEBRUIJN_TABLE_32 = new int[32]
		{
			0, 0, 3, 0, 3, 1, 3, 0, 3, 2,
			2, 1, 3, 2, 0, 1, 3, 3, 1, 2,
			2, 2, 2, 0, 3, 1, 2, 0, 1, 0,
			1, 1
		};

		private static readonly int[] DEBRUIJN_TABLE_64 = new int[64]
		{
			0, 0, 0, 0, 0, 1, 1, 2, 0, 3,
			1, 3, 1, 4, 2, 7, 0, 2, 3, 6,
			1, 5, 3, 5, 1, 3, 4, 4, 2, 5,
			6, 7, 7, 0, 1, 2, 3, 3, 4, 6,
			2, 6, 5, 5, 3, 4, 5, 6, 7, 1,
			2, 4, 6, 4, 4, 5, 7, 2, 6, 5,
			7, 6, 7, 7
		};

		private const int MAX_NB_ATTEMPTS = 256;

		private const int OPTIMAL_ML = 18;

		public static int MaximumOutputLength(int inputLength)
		{
			return inputLength + inputLength / 255 + 16;
		}

		internal static void CheckArguments(byte[] input, int inputOffset, ref int inputLength, byte[] output, int outputOffset, ref int outputLength)
		{
			if (inputLength < 0)
			{
				inputLength = input.Length - inputOffset;
			}
			if (inputLength == 0)
			{
				outputLength = 0;
				return;
			}
			if (input == null)
			{
				throw new ArgumentNullException("input");
			}
			if (inputOffset < 0 || inputOffset + inputLength > input.Length)
			{
				throw new ArgumentException("inputOffset and inputLength are invalid for given input");
			}
			if (outputLength < 0)
			{
				outputLength = output.Length - outputOffset;
			}
			if (output == null)
			{
				throw new ArgumentNullException("output");
			}
			if (outputOffset >= 0 && outputOffset + outputLength <= output.Length)
			{
				return;
			}
			throw new ArgumentException("outputOffset and outputLength are invalid for given output");
		}

		[Conditional("DEBUG")]
		private static void Assert(bool condition, string errorMessage)
		{
			if (!condition)
			{
				throw new ArgumentException(errorMessage);
			}
		}

		internal static void Poke2(byte[] buffer, int offset, ushort value)
		{
			buffer[offset] = (byte)value;
			buffer[offset + 1] = (byte)(value >> 8);
		}

		internal static ushort Peek2(byte[] buffer, int offset)
		{
			return (ushort)(buffer[offset] | (buffer[offset + 1] << 8));
		}

		internal static uint Peek4(byte[] buffer, int offset)
		{
			return (uint)(buffer[offset] | (buffer[offset + 1] << 8) | (buffer[offset + 2] << 16) | (buffer[offset + 3] << 24));
		}

		private static uint Xor4(byte[] buffer, int offset1, int offset2)
		{
			int num = buffer[offset1] | (buffer[offset1 + 1] << 8) | (buffer[offset1 + 2] << 16) | (buffer[offset1 + 3] << 24);
			uint num2 = (uint)(buffer[offset2] | (buffer[offset2 + 1] << 8) | (buffer[offset2 + 2] << 16) | (buffer[offset2 + 3] << 24));
			return (uint)num ^ num2;
		}

		private static ulong Xor8(byte[] buffer, int offset1, int offset2)
		{
			ulong num = buffer[offset1] | ((ulong)buffer[offset1 + 1] << 8) | ((ulong)buffer[offset1 + 2] << 16) | ((ulong)buffer[offset1 + 3] << 24) | ((ulong)buffer[offset1 + 4] << 32) | ((ulong)buffer[offset1 + 5] << 40) | ((ulong)buffer[offset1 + 6] << 48) | ((ulong)buffer[offset1 + 7] << 56);
			ulong num2 = buffer[offset2] | ((ulong)buffer[offset2 + 1] << 8) | ((ulong)buffer[offset2 + 2] << 16) | ((ulong)buffer[offset2 + 3] << 24) | ((ulong)buffer[offset2 + 4] << 32) | ((ulong)buffer[offset2 + 5] << 40) | ((ulong)buffer[offset2 + 6] << 48) | ((ulong)buffer[offset2 + 7] << 56);
			return num ^ num2;
		}

		private static bool Equal2(byte[] buffer, int offset1, int offset2)
		{
			if (buffer[offset1] != buffer[offset2])
			{
				return false;
			}
			return buffer[offset1 + 1] == buffer[offset2 + 1];
		}

		private static bool Equal4(byte[] buffer, int offset1, int offset2)
		{
			if (buffer[offset1] != buffer[offset2])
			{
				return false;
			}
			if (buffer[offset1 + 1] != buffer[offset2 + 1])
			{
				return false;
			}
			if (buffer[offset1 + 2] != buffer[offset2 + 2])
			{
				return false;
			}
			return buffer[offset1 + 3] == buffer[offset2 + 3];
		}

		private static void Copy4(byte[] buf, int src, int dst)
		{
			buf[dst + 3] = buf[src + 3];
			buf[dst + 2] = buf[src + 2];
			buf[dst + 1] = buf[src + 1];
			buf[dst] = buf[src];
		}

		private static void Copy8(byte[] buf, int src, int dst)
		{
			buf[dst + 7] = buf[src + 7];
			buf[dst + 6] = buf[src + 6];
			buf[dst + 5] = buf[src + 5];
			buf[dst + 4] = buf[src + 4];
			buf[dst + 3] = buf[src + 3];
			buf[dst + 2] = buf[src + 2];
			buf[dst + 1] = buf[src + 1];
			buf[dst] = buf[src];
		}

		private static void BlockCopy(byte[] src, int src_0, byte[] dst, int dst_0, int len)
		{
			if (len >= 16)
			{
				Buffer.BlockCopy(src, src_0, dst, dst_0, len);
				return;
			}
			while (len >= 8)
			{
				dst[dst_0] = src[src_0];
				dst[dst_0 + 1] = src[src_0 + 1];
				dst[dst_0 + 2] = src[src_0 + 2];
				dst[dst_0 + 3] = src[src_0 + 3];
				dst[dst_0 + 4] = src[src_0 + 4];
				dst[dst_0 + 5] = src[src_0 + 5];
				dst[dst_0 + 6] = src[src_0 + 6];
				dst[dst_0 + 7] = src[src_0 + 7];
				len -= 8;
				src_0 += 8;
				dst_0 += 8;
			}
			while (len >= 4)
			{
				dst[dst_0] = src[src_0];
				dst[dst_0 + 1] = src[src_0 + 1];
				dst[dst_0 + 2] = src[src_0 + 2];
				dst[dst_0 + 3] = src[src_0 + 3];
				len -= 4;
				src_0 += 4;
				dst_0 += 4;
			}
			while (len-- > 0)
			{
				dst[dst_0++] = src[src_0++];
			}
		}

		private static int WildCopy(byte[] src, int src_0, byte[] dst, int dst_0, int dst_end)
		{
			int num = dst_end - dst_0;
			if (num >= 16)
			{
				Buffer.BlockCopy(src, src_0, dst, dst_0, num);
			}
			else
			{
				while (num >= 4)
				{
					dst[dst_0] = src[src_0];
					dst[dst_0 + 1] = src[src_0 + 1];
					dst[dst_0 + 2] = src[src_0 + 2];
					dst[dst_0 + 3] = src[src_0 + 3];
					num -= 4;
					src_0 += 4;
					dst_0 += 4;
				}
				while (num-- > 0)
				{
					dst[dst_0++] = src[src_0++];
				}
			}
			return num;
		}

		private static int SecureCopy(byte[] buffer, int src, int dst, int dst_end)
		{
			int num = dst - src;
			int num2 = dst_end - dst;
			int num3 = num2;
			if (num >= 16)
			{
				if (num >= num2)
				{
					Buffer.BlockCopy(buffer, src, buffer, dst, num2);
					return num2;
				}
				do
				{
					Buffer.BlockCopy(buffer, src, buffer, dst, num);
					src += num;
					dst += num;
					num3 -= num;
				}
				while (num3 >= num);
			}
			while (num3 >= 4)
			{
				buffer[dst] = buffer[src];
				buffer[dst + 1] = buffer[src + 1];
				buffer[dst + 2] = buffer[src + 2];
				buffer[dst + 3] = buffer[src + 3];
				dst += 4;
				src += 4;
				num3 -= 4;
			}
			while (num3-- > 0)
			{
				buffer[dst++] = buffer[src++];
			}
			return num2;
		}

		public static int Encode32(byte[] input, int inputOffset, int inputLength, byte[] output, int outputOffset, int outputLength)
		{
			CheckArguments(input, inputOffset, ref inputLength, output, outputOffset, ref outputLength);
			if (outputLength == 0)
			{
				return 0;
			}
			if (inputLength < 65547)
			{
				return LZ4_compress64kCtx_safe32(new ushort[8192], input, output, inputOffset, outputOffset, inputLength, outputLength);
			}
			return LZ4_compressCtx_safe32(new int[4096], input, output, inputOffset, outputOffset, inputLength, outputLength);
		}

		public static byte[] Encode32(byte[] input, int inputOffset, int inputLength)
		{
			if (inputLength < 0)
			{
				inputLength = input.Length - inputOffset;
			}
			if (input == null)
			{
				throw new ArgumentNullException("input");
			}
			if (inputOffset < 0 || inputOffset + inputLength > input.Length)
			{
				throw new ArgumentException("inputOffset and inputLength are invalid for given input");
			}
			byte[] array = new byte[MaximumOutputLength(inputLength)];
			int num = Encode32(input, inputOffset, inputLength, array, 0, array.Length);
			if (num != array.Length)
			{
				if (num < 0)
				{
					throw new InvalidOperationException("Compression has been corrupted");
				}
				byte[] array2 = new byte[num];
				Buffer.BlockCopy(array, 0, array2, 0, num);
				return array2;
			}
			return array;
		}

		public static int Encode64(byte[] input, int inputOffset, int inputLength, byte[] output, int outputOffset, int outputLength)
		{
			CheckArguments(input, inputOffset, ref inputLength, output, outputOffset, ref outputLength);
			if (outputLength == 0)
			{
				return 0;
			}
			if (inputLength < 65547)
			{
				return LZ4_compress64kCtx_safe64(new ushort[8192], input, output, inputOffset, outputOffset, inputLength, outputLength);
			}
			return LZ4_compressCtx_safe64(new int[4096], input, output, inputOffset, outputOffset, inputLength, outputLength);
		}

		public static byte[] Encode64(byte[] input, int inputOffset, int inputLength)
		{
			if (inputLength < 0)
			{
				inputLength = input.Length - inputOffset;
			}
			if (input == null)
			{
				throw new ArgumentNullException("input");
			}
			if (inputOffset < 0 || inputOffset + inputLength > input.Length)
			{
				throw new ArgumentException("inputOffset and inputLength are invalid for given input");
			}
			byte[] array = new byte[MaximumOutputLength(inputLength)];
			int num = Encode64(input, inputOffset, inputLength, array, 0, array.Length);
			if (num != array.Length)
			{
				if (num < 0)
				{
					throw new InvalidOperationException("Compression has been corrupted");
				}
				byte[] array2 = new byte[num];
				Buffer.BlockCopy(array, 0, array2, 0, num);
				return array2;
			}
			return array;
		}

		public static int Decode32(byte[] input, int inputOffset, int inputLength, byte[] output, int outputOffset, int outputLength, bool knownOutputLength)
		{
			CheckArguments(input, inputOffset, ref inputLength, output, outputOffset, ref outputLength);
			if (outp