Decompiled source of OtherLoaderPatched v1.5.1

patchers\Sirdoggy.OldOtherLoaderDisabler.dll

Decompiled a week ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Logging;
using Microsoft.CodeAnalysis;
using Mono.Cecil;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyCompany("Sirdoggy")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("Sirdoggy.OldOtherLoaderDisabler")]
[assembly: AssemblyTitle("OldOtherLoaderDisabler")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

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

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

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace Sirdoggy.OldOtherLoaderDisabler
{
	public static class OldOtherLoaderDisablerPatcher
	{
		private const string OtherLoaderDirectoryName = "devyndamonster-OtherLoader";

		private const string OtherLoaderDllFullName = "OtherLoader.dll";

		private const string OtherLoaderDllFullNameDisabled = "OtherLoader.dll.old";

		private const string ManifestFullNameDisabled = "manifest.json.old";

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

		public static IEnumerable<string> TargetDLLs => Enumerable.Empty<string>();

		internal static void Initialize()
		{
			try
			{
				Log.LogMessage((object)"Attempting to disable original OtherLoader. Looking for BepInEx/plugins/devyndamonster-OtherLoader/OtherLoader.dll");
				string text = Directory.GetDirectories(Paths.PluginPath, "devyndamonster-OtherLoader", SearchOption.TopDirectoryOnly).FirstOrDefault();
				if (text == null)
				{
					Log.LogMessage((object)"Original OtherLoader not found in plugins directory, it's likely not installed, aborting...");
					return;
				}
				string text2 = Path.Combine(text, "OtherLoader.dll");
				string text3 = Path.Combine(text, "OtherLoader.dll.old");
				if (!File.Exists(text2))
				{
					Log.LogMessage((object)"Did not resolve 'OtherLoader.dll', OtherLoader is likely disabled, aborting...");
					return;
				}
				if (File.Exists(text3))
				{
					File.Delete(text3);
				}
				File.Move(text2, text3);
				Log.LogMessage((object)"Successfully disabled original OtherLoader!");
			}
			catch (Exception arg)
			{
				Log.LogError((object)$"Exception when trying to disable original OtherLoader: {arg}");
			}
		}

		public static void RestoreOtherLoaderDll()
		{
			try
			{
				Log.LogMessage((object)"Attempting to restore original OtherLoader dll");
				string text = Directory.GetDirectories(Paths.PluginPath, "devyndamonster-OtherLoader", SearchOption.TopDirectoryOnly).FirstOrDefault();
				if (text == null)
				{
					Log.LogMessage((object)"Original OtherLoader not found in plugins directory, it's likely not installed, aborting...");
					return;
				}
				if (File.Exists(Path.Combine(text, "manifest.json.old")))
				{
					Log.LogMessage((object)"OtherLoader has been disabled in mod manager, aborting...");
					return;
				}
				string text2 = Path.Combine(text, "OtherLoader.dll.old");
				string text3 = Path.Combine(text, "OtherLoader.dll");
				if (!File.Exists(text2))
				{
					Log.LogMessage((object)("Did not resolve 'OtherLoader.dll.old' from path " + text2));
				}
				else if (File.Exists(text3))
				{
					Log.LogWarning((object)"Duplicate dlls exist, this shouldn't happen. Deleting dll.old and exiting...");
					File.Delete(text2);
				}
				else
				{
					File.Move(text2, text3);
					Log.LogMessage((object)"Successfully restored original OtherLoader dll!");
				}
			}
			catch (Exception arg)
			{
				Log.LogError((object)$"Exception when restoring original OtherLoader dll: {arg}");
			}
		}

		public static void Patch(AssemblyDefinition _)
		{
		}
	}
}

OtherLoader.dll

Decompiled a week ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Threading;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using FistVR;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using OtherLoader.Common;
using OtherLoader.Common.FVR;
using OtherLoader.ConsoleLogs;
using OtherLoader.ItemSpawner;
using OtherLoader.ItemSpawner.CustomCategories;
using OtherLoader.ItemSpawner.Patches;
using OtherLoader.ItemSpawner.SecondaryObjectsLinker;
using OtherLoader.ItemSpawner.VanillaCategories;
using OtherLoader.Loading;
using OtherLoader.Loading.AssetLoaders;
using OtherLoader.Loading.AssetLoaders.Implementations;
using OtherLoader.Loading.Model;
using OtherLoader.PortableItemSpawner;
using OtherLoader.QuickbeltPanel;
using OtherLoader.UnlockAllItems;
using Sirdoggy.OldOtherLoaderDisabler;
using Sodalite;
using Sodalite.Api;
using Sodalite.ModPanel;
using Stratum;
using Stratum.Extensions;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyCompany("OtherLoader")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("OtherLoader")]
[assembly: AssemblyTitle("OtherLoader")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class ParamCollectionAttribute : Attribute
	{
	}
	[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 OtherLoader
{
	[CreateAssetMenu(menuName = "MeatKit/Otherloader/SpawnerEntry", fileName = "New Spawner Entry")]
	public class ItemSpawnerEntry : ScriptableObject
	{
		[Header("Item IDs")]
		[Tooltip("ItemID for the main object that will spawn")]
		public string MainObjectID;

		[Tooltip("ItemIDs for items that will spawn alongside the main object")]
		public List<string> SpawnWithIDs = new List<string>();

		[Tooltip("ItemIDs for items that appear in the secondary items section")]
		public List<string> SecondaryObjectIDs = new List<string>();

		[Header("[OPTIONAL] Populate ItemIDs using FVRObjects directly")]
		public FVRObject? MainObjectObj;

		public List<FVRObject> SpawnWithObjs = new List<FVRObject>();

		public List<FVRObject> SecondaryObjs = new List<FVRObject>();

		[Header("Entry Path Properties")]
		[Tooltip("The path for the entry")]
		public string EntryPath;

		public PageMode Page;

		public ESubCategory SubCategory;

		[Header("Display Properties")]
		[Tooltip("The icon that will appear in the spawner for this entry")]
		public Sprite EntryIcon;

		[Tooltip("The name of the entry")]
		public string DisplayName;

		[Tooltip("Decides wether the entry will be visible in the spawner.\n Set to false if you only want the entry visible as a secondary")]
		public bool IsDisplayedInMainEntry;

		[Tooltip("A list modding tags to allow for sorting by mod groups in itemspawner")]
		public List<string> ModTags = new List<string>();

		[Tooltip("A list of tutorial block IDs that will appear when this entry is selected")]
		public List<string> TutorialBlockIDs = new List<string>();

		[Header("Misc Properties")]
		public bool UsesLargeSpawnPad;

		public bool UsesHugeSpawnPad;

		public bool IsReward;

		internal bool IsUncategorized;

		public static ItemSpawnerEntry CreateEmpty(string path)
		{
			ItemSpawnerEntry itemSpawnerEntry = ScriptableObject.CreateInstance<ItemSpawnerEntry>();
			itemSpawnerEntry.EntryPath = path;
			return itemSpawnerEntry;
		}

		public void PopulateIDsFromObj()
		{
			if ((Object)(object)MainObjectObj != (Object)null)
			{
				MainObjectID = MainObjectObj.ItemID;
				OtherLogger.Log("Assigned MainObjectID '" + MainObjectID + "' from MainObjectObj.ItemID", LogTag.Assets);
			}
			foreach (FVRObject spawnWithObj in SpawnWithObjs)
			{
				if (!SpawnWithIDs.Contains(spawnWithObj.ItemID))
				{
					SpawnWithIDs.Add(spawnWithObj.ItemID);
				}
			}
			foreach (FVRObject secondaryObj in SecondaryObjs)
			{
				if (!SecondaryObjectIDs.Contains(secondaryObj.ItemID))
				{
					SecondaryObjectIDs.Add(secondaryObj.ItemID);
				}
			}
		}

		public bool IsCategoryEntry()
		{
			return string.IsNullOrEmpty(MainObjectID);
		}

		internal ESubCategory? GetSpawnerSubcategory()
		{
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			string[] array = (from o in EntryPath.Split(new char[1] { '/' })
				where Enum.IsDefined(typeof(ESubCategory), o)
				select o).ToArray();
			if (array.Length == 0)
			{
				return null;
			}
			return ((IEnumerable<string>)array).Select((Func<string, ESubCategory>)((string o) => (ESubCategory)Enum.Parse(typeof(ESubCategory), o))).FirstOrDefault();
		}

		internal EItemCategory? GetSpawnerCategory()
		{
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			string[] array = (from o in EntryPath.Split(new char[1] { '/' })
				where Enum.IsDefined(typeof(EItemCategory), o)
				select o).ToArray();
			if (array.Length == 0)
			{
				return null;
			}
			return ((IEnumerable<string>)array).Select((Func<string, EItemCategory>)((string o) => (EItemCategory)Enum.Parse(typeof(EItemCategory), o))).FirstOrDefault();
		}
	}
	public delegate void StatusUpdate(float progress);
	internal enum LoadOrderType
	{
		LoadFirst,
		LoadLast,
		LoadUnordered
	}
	internal enum BundleStatus
	{
		Waiting,
		CanLoad,
		Loading,
		Loaded,
		Unloaded
	}
	internal class BundleLoadStatus
	{
		public readonly string BundleId;

		public BundleStatus Status;

		public LoadOrderType LoadOrderType;

		public BundleLoadStatus(string bundleId, LoadOrderType loadOrderType)
		{
			BundleId = bundleId;
			LoadOrderType = loadOrderType;
			Status = BundleStatus.Waiting;
		}
	}
	public static class LoaderStatus
	{
		private class ModLoadOrderContainer
		{
			public List<BundleLoadStatus> loadFirst = new List<BundleLoadStatus>();

			public List<BundleLoadStatus> loadUnordered = new List<BundleLoadStatus>();

			public List<BundleLoadStatus> loadLast = new List<BundleLoadStatus>();

			public Dictionary<string, BundleLoadStatus> bundleLoadStatusDic = new Dictionary<string, BundleLoadStatus>();

			public void AddToLoadOrder(string bundleID, LoadOrderType loadOrderType)
			{
				BundleLoadStatus bundleLoadStatus = new BundleLoadStatus(bundleID, loadOrderType);
				if (bundleLoadStatusDic.ContainsKey(bundleID))
				{
					BundleLoadStatus bundleLoadStatus2 = bundleLoadStatusDic[bundleID];
					bundleLoadStatusDic.Remove(bundleID);
					loadFirst.Remove(bundleLoadStatus2);
					loadUnordered.Remove(bundleLoadStatus2);
					loadLast.Remove(bundleLoadStatus2);
					bundleLoadStatus.Status = BundleStatus.Unloaded;
					bundleLoadStatus.LoadOrderType = bundleLoadStatus2.LoadOrderType;
					if (bundleLoadStatus2.Status != BundleStatus.Loaded && bundleLoadStatus2.Status != BundleStatus.Unloaded)
					{
						OtherLogger.LogError("Tracking a late bundle, but the data bundle isn't already loaded! Data bundle status: " + bundleLoadStatus2.Status);
					}
				}
				else
				{
					if (loadOrderType == LoadOrderType.LoadFirst)
					{
						if (loadFirst.Count == 0 || loadFirst.All((BundleLoadStatus o) => o.Status == BundleStatus.Loaded || o.Status == BundleStatus.Unloaded))
						{
							bundleLoadStatus.Status = BundleStatus.CanLoad;
						}
						if (loadUnordered.Count != 0 || loadLast.Count != 0)
						{
							OtherLogger.LogError("Mod is set to load first, but it looks like unordered or load last mods are already loading! BundleID (" + bundleID + ")");
							loadUnordered.ForEach(delegate(BundleLoadStatus o)
							{
								OtherLogger.LogError("Load Unordered BundleID (" + o.BundleId + ")");
							});
							loadLast.ForEach(delegate(BundleLoadStatus o)
							{
								OtherLogger.LogError("Load Last BundleID (" + o.BundleId + ")");
							});
						}
					}
					if (loadOrderType == LoadOrderType.LoadUnordered)
					{
						if (loadFirst.Count == 0 || loadFirst.All((BundleLoadStatus o) => o.Status == BundleStatus.Loaded || o.Status == BundleStatus.Unloaded))
						{
							bundleLoadStatus.Status = BundleStatus.CanLoad;
						}
						if (loadLast.Count != 0)
						{
							OtherLogger.LogError("Mod is set to load unordered, but it looks like load last mods are already loading! BundleID (" + bundleID + ")");
							loadLast.ForEach(delegate(BundleLoadStatus o)
							{
								OtherLogger.LogError("Load Last BundleID (" + o.BundleId + ")");
							});
						}
					}
					if (loadOrderType == LoadOrderType.LoadLast && ((loadFirst.Count == 0 && loadUnordered.Count == 0 && loadLast.Count == 0) || (loadFirst.All((BundleLoadStatus o) => o.Status == BundleStatus.Loaded || o.Status == BundleStatus.Unloaded) && loadUnordered.All((BundleLoadStatus o) => o.Status == BundleStatus.Loaded || o.Status == BundleStatus.Unloaded) && loadLast.All((BundleLoadStatus o) => o.Status == BundleStatus.Loaded || o.Status == BundleStatus.Unloaded))))
					{
						bundleLoadStatus.Status = BundleStatus.CanLoad;
					}
				}
				bundleLoadStatusDic.Add(bundleID, bundleLoadStatus);
				switch (loadOrderType)
				{
				case LoadOrderType.LoadFirst:
					loadFirst.Add(bundleLoadStatus);
					break;
				case LoadOrderType.LoadLast:
					loadLast.Add(bundleLoadStatus);
					break;
				case LoadOrderType.LoadUnordered:
					loadUnordered.Add(bundleLoadStatus);
					break;
				}
			}

			public BundleStatus? TryGetBundleLoadStatus(string bundleID)
			{
				return bundleLoadStatusDic.GetValueOrNull(bundleID)?.Status;
			}

			public void MarkBundleAsLoaded(string bundleID, bool permanentlyLoaded)
			{
				BundleLoadStatus bundleLoadStatus = bundleLoadStatusDic[bundleID];
				if (permanentlyLoaded)
				{
					bundleLoadStatus.Status = BundleStatus.Loaded;
				}
				else
				{
					bundleLoadStatus.Status = BundleStatus.Unloaded;
				}
				if (bundleLoadStatus.LoadOrderType == LoadOrderType.LoadFirst)
				{
					BundleLoadStatus bundleLoadStatus2 = loadFirst.FirstOrDefault((BundleLoadStatus o) => o.Status == BundleStatus.Waiting);
					if (bundleLoadStatus2 != null)
					{
						bundleLoadStatus2.Status = BundleStatus.CanLoad;
					}
					else if (loadUnordered.Count > 0)
					{
						loadUnordered.ForEach(delegate(BundleLoadStatus o)
						{
							o.Status = BundleStatus.CanLoad;
						});
					}
					else if (loadLast.Count > 0)
					{
						loadLast[0].Status = BundleStatus.CanLoad;
					}
				}
				else if (bundleLoadStatus.LoadOrderType == LoadOrderType.LoadUnordered)
				{
					if (loadUnordered.All((BundleLoadStatus o) => o.Status == BundleStatus.Loaded || o.Status == BundleStatus.Unloaded) && loadLast.Count != 0)
					{
						loadLast[0].Status = BundleStatus.CanLoad;
					}
				}
				else if (bundleLoadStatus.LoadOrderType == LoadOrderType.LoadLast)
				{
					BundleLoadStatus bundleLoadStatus3 = loadLast.FirstOrDefault((BundleLoadStatus o) => o.Status == BundleStatus.Waiting);
					if (bundleLoadStatus3 != null)
					{
						bundleLoadStatus3.Status = BundleStatus.CanLoad;
					}
				}
			}

			public List<BundleLoadStatus> GetBundleDependencies(string bundleID)
			{
				List<BundleLoadStatus> list = new List<BundleLoadStatus>();
				BundleLoadStatus bundleLoadStatus = bundleLoadStatusDic[bundleID];
				if (bundleLoadStatus.LoadOrderType == LoadOrderType.LoadFirst)
				{
					foreach (BundleLoadStatus item in loadFirst)
					{
						if (item.BundleId == bundleID)
						{
							break;
						}
						if (!AnvilManager.m_bundles.m_lookup.ContainsKey(item.BundleId))
						{
							list.Add(item);
						}
					}
				}
				else if (bundleLoadStatus.LoadOrderType == LoadOrderType.LoadUnordered)
				{
					foreach (BundleLoadStatus item2 in loadFirst)
					{
						if (!AnvilManager.m_bundles.m_lookup.ContainsKey(item2.BundleId))
						{
							list.Add(item2);
						}
					}
				}
				else if (bundleLoadStatus.LoadOrderType == LoadOrderType.LoadLast)
				{
					foreach (BundleLoadStatus item3 in loadFirst)
					{
						if (!AnvilManager.m_bundles.m_lookup.ContainsKey(item3.BundleId))
						{
							list.Add(item3);
						}
					}
					foreach (BundleLoadStatus item4 in loadUnordered)
					{
						if (!AnvilManager.m_bundles.m_lookup.ContainsKey(item4.BundleId))
						{
							list.Add(item4);
						}
					}
					foreach (BundleLoadStatus item5 in loadLast)
					{
						if (item5.BundleId == bundleID)
						{
							break;
						}
						if (!AnvilManager.m_bundles.m_lookup.ContainsKey(item5.BundleId))
						{
							list.Add(item5);
						}
					}
				}
				return list;
			}
		}

		internal static float LastLoadEventTime;

		private static float? _lastStatus;

		private static StatusUpdate? _progressUpdatedReplayingListeners;

		private static readonly Dictionary<string, float> TrackedLoaders = new Dictionary<string, float>();

		private static readonly List<string> ActiveLoaders = new List<string>();

		private static readonly Dictionary<string, ModLoadOrderContainer> OrderedLoadingLists = new Dictionary<string, ModLoadOrderContainer>();

		private static float _loadStartTime;

		private const float LoadTimeBuffer = 2f;

		public static event StatusUpdate? ProgressUpdated;

		public static event StatusUpdate? ProgressUpdatedReplaying
		{
			add
			{
				_progressUpdatedReplayingListeners = (StatusUpdate)Delegate.Combine(_progressUpdatedReplayingListeners, value);
				float? lastStatus = _lastStatus;
				if (lastStatus.HasValue)
				{
					value?.Invoke(_lastStatus.Value);
				}
			}
			remove
			{
				_progressUpdatedReplayingListeners = (StatusUpdate)Delegate.Remove(_progressUpdatedReplayingListeners, value);
			}
		}

		private static void DoStatusUpdate(float status)
		{
			_lastStatus = status;
			_progressUpdatedReplayingListeners?.Invoke(status);
			LoaderStatus.ProgressUpdated?.Invoke(status);
		}

		public static float GetLoaderProgress()
		{
			if (TrackedLoaders.Count == 0)
			{
				return 0f;
			}
			float num = 0f;
			foreach (float value in TrackedLoaders.Values)
			{
				num += value;
			}
			if (Time.realtimeSinceStartup - LastLoadEventTime > 2f)
			{
				return num / (float)TrackedLoaders.Count;
			}
			return Mathf.Min(num / (float)TrackedLoaders.Count, 0.99f);
		}

		internal static IEnumerator LoadTimeCoroutine()
		{
			LastLoadEventTime = Time.realtimeSinceStartup;
			float progress;
			for (progress = GetLoaderProgress(); progress < 1f; progress = GetLoaderProgress())
			{
				yield return null;
				DoStatusUpdate(progress);
			}
			DoStatusUpdate(progress);
			OtherLogger.Log($"All items loaded, took {Time.realtimeSinceStartup - _loadStartTime:0.000} seconds!");
		}

		internal static void AddActiveLoader(string bundleID)
		{
			if (!ActiveLoaders.Contains(bundleID))
			{
				ActiveLoaders.Add(bundleID);
			}
		}

		internal static void RemoveActiveLoader(string bundleID, bool permanentlyLoaded)
		{
			if (ActiveLoaders.Contains(bundleID))
			{
				ActiveLoaders.Remove(bundleID);
				string modPathFromUniqueID = GetModPathFromUniqueID(bundleID);
				OrderedLoadingLists[modPathFromUniqueID].MarkBundleAsLoaded(bundleID, permanentlyLoaded);
				LastLoadEventTime = Time.realtimeSinceStartup;
			}
		}

		internal static void TrackLoader(string bundleID, LoadOrderType loadOrderType)
		{
			if (TrackedLoaders.Count == 0)
			{
				_loadStartTime = Time.realtimeSinceStartup;
				OtherLoader.CoroutineStarter.Invoke(LoadTimeCoroutine());
			}
			LastLoadEventTime = Time.realtimeSinceStartup;
			if (!TrackedLoaders.ContainsKey(bundleID))
			{
				TrackedLoaders.Add(bundleID, 0f);
			}
			string modPathFromUniqueID = GetModPathFromUniqueID(bundleID);
			if (!OrderedLoadingLists.ContainsKey(modPathFromUniqueID))
			{
				OtherLogger.Log("Adding new load order entry for mod", LogTag.BundleLoading);
				OrderedLoadingLists.Add(modPathFromUniqueID, new ModLoadOrderContainer());
			}
			OrderedLoadingLists[modPathFromUniqueID].AddToLoadOrder(bundleID, loadOrderType);
			OtherLogger.Log($"Tracking modded bundle ({bundleID}), Load Order ({loadOrderType})", LogTag.BundleLoading);
		}

		internal static bool IsBundleAlreadyTracked(string bundleID)
		{
			string modPathFromUniqueID = GetModPathFromUniqueID(bundleID);
			return (OrderedLoadingLists.GetValueOrNull(modPathFromUniqueID)?.TryGetBundleLoadStatus(bundleID)).HasValue;
		}

		internal static bool CanOrderedModLoad(string bundleID)
		{
			string modPathFromUniqueID = GetModPathFromUniqueID(bundleID);
			BundleStatus? bundleStatus = (OrderedLoadingLists.GetValueOrNull(modPathFromUniqueID) ?? throw new Exception("Mod was not found in load order! BundleID: " + bundleID)).TryGetBundleLoadStatus(bundleID);
			if (!bundleStatus.HasValue)
			{
				throw new Exception("BundleID was not found in mod load order container: " + bundleID);
			}
			if (bundleStatus.GetValueOrDefault() == BundleStatus.Loaded || bundleStatus.GetValueOrDefault() == BundleStatus.Unloaded)
			{
				throw new Exception("BundleID is already loaded/unloaded: " + bundleID);
			}
			bool flag = bundleStatus.GetValueOrDefault() == BundleStatus.CanLoad;
			return (PluginConfig.MaxActiveLoaders <= 0 || ActiveLoaders.Count < PluginConfig.MaxActiveLoaders) && flag;
		}

		internal static void PrintWaitingBundles(string bundleID)
		{
			OtherLogger.Log("Current Active Loaders: " + ActiveLoaders.Count);
			string modPathFromUniqueID = GetModPathFromUniqueID(bundleID);
			foreach (BundleLoadStatus item in (from o in OrderedLoadingLists[modPathFromUniqueID].GetBundleDependencies(bundleID)
				where o.Status != BundleStatus.Loaded && o.Status != BundleStatus.Unloaded
				select o).ToList())
			{
				OtherLogger.Log("Waiting on bundle: " + item.BundleId + ", Status: " + item.Status);
			}
		}

		internal static void UpdateProgress(string bundleID, float progress)
		{
			if (TrackedLoaders.ContainsKey(bundleID))
			{
				TrackedLoaders[bundleID] = progress;
			}
		}

		internal static List<BundleLoadStatus> GetBundleDependencies(string bundleID)
		{
			string modPathFromUniqueID = GetModPathFromUniqueID(bundleID);
			return OrderedLoadingLists[modPathFromUniqueID].GetBundleDependencies(bundleID);
		}

		private static string GetModPathFromUniqueID(string bundleID)
		{
			return bundleID.Split(new string[1] { " : " }, StringSplitOptions.None)[0].Trim();
		}
	}
	[BepInPlugin("h3vr.otherloader", "OtherLoaderPatched", "1.5.1")]
	[BepInDependency("stratum", "1.1.0")]
	[BepInDependency("nrgill28.Sodalite", "1.4.1")]
	public class OtherLoader : StratumPlugin
	{
		private class DirectLoadMod
		{
			public readonly string Path;

			public readonly string LoadFirst;

			public readonly string LoadAny;

			public readonly string LoadLast;

			public DirectLoadMod(string path, string loadFirst, string loadAny, string loadLast)
			{
				Path = path;
				LoadFirst = loadFirst;
				LoadAny = loadAny;
				LoadLast = loadLast;
				base..ctor();
			}
		}

		private const string OtherLoaderVersion = "1.5.1";

		public static readonly Dictionary<string, ItemSpawnerEntry> SpawnerEntriesByID = new Dictionary<string, ItemSpawnerEntry>();

		internal static readonly Dictionary<string, string> ManagedBundles = new Dictionary<string, string>();

		internal static CoroutineStarter CoroutineStarter = null;

		internal static ExceptionCatcher ExceptionCatcher = null;

		private static readonly List<DirectLoadMod> DirectLoadMods = new List<DirectLoadMod>();

		private void Awake()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fa: Expected O, but got Unknown
			//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ff: Expected O, but got Unknown
			CoroutineStarter = new CoroutineStarter(((MonoBehaviour)this).StartCoroutine);
			ExceptionCatcher = new ExceptionCatcher(((BaseUnityPlugin)this).Logger);
			OtherLogger.Initialize(((BaseUnityPlugin)this).Logger);
			PluginConfig.Initialize(((BaseUnityPlugin)this).Info);
			ExceptionCatcher.Run(delegate
			{
				Harmony.CreateAndPatchAll(typeof(LogLevelColorPatcher), (string)null);
			});
			if (PluginConfig.ItemUnlocker != 0)
			{
				ExceptionCatcher.Run(delegate
				{
					Harmony.CreateAndPatchAll(typeof(RewardUnlocksPatchers), (string)null);
				});
			}
			ExceptionCatcher.Run(delegate
			{
				Harmony.CreateAndPatchAll(typeof(PortableSpawnerPatcher), (string)null);
			});
			ExceptionCatcher.Run(delegate
			{
				Harmony.CreateAndPatchAll(typeof(AnvilRuntimeLoadingPatcher), (string)null);
			});
			ExceptionCatcher.Run(delegate
			{
				Harmony.CreateAndPatchAll(typeof(QuickbeltPanelPatcher), (string)null);
			});
			ExceptionCatcher.Run(delegate
			{
				Harmony.CreateAndPatchAll(typeof(ItemSpawnerV2InitialPatcher), (string)null);
			});
			ExceptionCatcher.Run(delegate
			{
				Harmony.CreateAndPatchAll(typeof(ItemSpawnerV2SimpleModePatcher), (string)null);
			});
			ExceptionCatcher.Run(delegate
			{
				Harmony.CreateAndPatchAll(typeof(ItemSpawnerV2SpawningPatcher), (string)null);
			});
			ExceptionCatcher.Run(delegate
			{
				Harmony.CreateAndPatchAll(typeof(ItemSpawnerV2DisplayItemsPatcher), (string)null);
			});
			ExceptionCatcher.Run(delegate
			{
				Harmony.CreateAndPatchAll(typeof(ItemSpawnerV2TagsFromHeldPatcher), (string)null);
			});
			if (PluginConfig.AddUnloadButton)
			{
				WristMenuAPI.Buttons.Add(new WristMenuButton("Unload Bundles", (ButtonClickEvent)delegate
				{
					UnloadAllModdedBundles();
				}));
			}
		}

		private void Start()
		{
			GM.SetRunningModded();
			OldOtherLoaderDisablerPatcher.RestoreOtherLoaderDll();
		}

		public override void OnSetup(IStageContext<Empty> ctx)
		{
			ctx.Loaders.Add("icon", (FileSystemInfo _) => default(Empty));
			ctx.Loaders.Add("assembly", MainLoader.LoadAssembly);
		}

		public override IEnumerator OnRuntime(IStageContext<IEnumerator> ctx)
		{
			ctx.Loaders.Add("item_data", MainLoader.BundlePrepareLate);
			ctx.Loaders.Add("item_first_late", (FileSystemInfo handle) => MainLoader.BundleRegisterLate(handle, LoadOrderType.LoadFirst));
			ctx.Loaders.Add("item_unordered_late", (FileSystemInfo handle) => MainLoader.BundleRegisterLate(handle, LoadOrderType.LoadUnordered));
			ctx.Loaders.Add("item_last_late", (FileSystemInfo handle) => MainLoader.BundleRegisterLate(handle, LoadOrderType.LoadLast));
			ctx.Loaders.Add("item", (FileSystemInfo handle) => MainLoader.BundleLoadImmediate(handle, LoadOrderType.LoadFirst));
			ctx.Loaders.Add("item_unordered", (FileSystemInfo handle) => MainLoader.BundleLoadImmediate(handle, LoadOrderType.LoadUnordered));
			ctx.Loaders.Add("item_last", (FileSystemInfo handle) => MainLoader.BundleLoadImmediate(handle, LoadOrderType.LoadLast));
			MainLoader.LoadLegacyBundles();
			foreach (DirectLoadMod directLoadMod in DirectLoadMods)
			{
				MainLoader.BundleLoadDirectFromDirectory(directLoadMod.Path, directLoadMod.LoadFirst.Split(new char[1] { ',' }), directLoadMod.LoadAny.Split(new char[1] { ',' }), directLoadMod.LoadLast.Split(new char[1] { ',' }));
			}
			DirectLoadMods.Clear();
			LoaderStatus.ProgressUpdated += OnLoaderProgress;
			yield break;
		}

		private static void OnLoaderProgress(float progress)
		{
			if (!(progress < 1f))
			{
				LoaderStatus.ProgressUpdated -= OnLoaderProgress;
				ItemSpawnerIDLinker.LinkQueuedEntries();
				ItemManagerDebugger.TryPrintEntries();
				SpawnerTilesDatabase.TryCreateTestCategories();
			}
		}

		public static void RegisterDirectLoad(string path, string guid, string dependancies, string loadFirst, string loadAny, string loadLast)
		{
			DirectLoadMods.Add(new DirectLoadMod(path, loadFirst, loadAny, loadLast));
		}

		private void UnloadAllModdedBundles()
		{
			foreach (string item in ManagedBundles.Keys.Where((string bundleID) => AnvilManager.m_bundles.m_lookup.ContainsKey(bundleID)))
			{
				OtherLogger.Log("Unloading bundle '" + item + "'");
				AnvilCallback<AssetBundle> val = (AnvilCallback<AssetBundle>)(object)AnvilManager.m_bundles.m_lookup[item];
				AnvilManager.m_bundles.m_loading.Remove((AnvilCallbackBase)(object)val);
				AnvilManager.m_bundles.m_lookup.Remove(item);
				val.Result.Unload(false);
			}
		}
	}
	internal static class PluginAssets
	{
		private const string PluginFolderName = "Sirdoggy-OtherLoaderPatched";

		private static readonly string AssetsRelativePath = Path.Combine("Sirdoggy-OtherLoaderPatched", "assets");

		private static readonly string AssetsFullPath = Path.Combine(Paths.PluginPath, AssetsRelativePath);

		public static readonly Sprite? UnknownFolder = SpriteMaker.CreateFromImage(Path.Combine(AssetsFullPath, "UnknownFolder.png"));

		public static readonly Sprite? Shapes = SpriteMaker.CreateFromImage(Path.Combine(AssetsFullPath, "Shapes.png"));

		public static string CustomCategoriesHeaderLabel => "Modded Categories";

		public static string CustomCategoriesButtonLabel(int? count)
		{
			return $"MODDED CATEGORIES ({count.GetValueOrDefault()})";
		}

		public static string ModsLoadingProgressLabel(int percentage)
		{
			return $"Loading mods | {percentage}%";
		}
	}
	internal static class PluginConfig
	{
		public static bool OptimizeMemory;

		public static int MaxActiveLoaders;

		public static ItemUnlockerMode ItemUnlocker;

		public static ConfigEntry<bool> PreventSelectingModTagsFromHeldObject;

		public static ConfigEntry<bool> ShowSpawnItemButtonInPortableSpawner;

		public static ConfigEntry<ItemSpawnerSortGrouping> ItemSpawnerSortGrouping;

		public static ConfigEntry<ItemSpawnerSortOrder> ItemSpawnerSortOrder;

		public static ConfigEntry<bool> ColoredLogs;

		public static ConfigEntry<LogTag> LogTags;

		public static bool AddUnloadButton;

		public static bool EnableLogTraces;

		public static bool ShowDebugItemSpawnerEntries;

		private static ConfigFile _configFile;

		private const string ConfigFileName = "OtherLoaderPatched.cfg";

		public static void Initialize(PluginInfo pluginInfo)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Expected O, but got Unknown
			_configFile = new ConfigFile(Path.Combine(Paths.ConfigPath, "OtherLoaderPatched.cfg"), true);
			BindFields();
			UniversalModPanel.RegisterPluginSettings(pluginInfo, _configFile);
		}

		public static void BindFields()
		{
			OptimizeMemory = _configFile.Bind<bool>("General", "OptimizeMemory", true, "When true, modded assets will be loaded on-demand instead of kept in memory. Requires game restart.").Value;
			MaxActiveLoaders = _configFile.Bind<int>("General", "MaxActiveLoaders", 6, "Sets the number of mods that can be loading at once when first launching the game. Values less than 1 will result in all mods being loaded at the same time.").Value;
			ItemUnlocker = _configFile.Bind<ItemUnlockerMode>("General", "ItemUnlocker", ItemUnlockerMode.Disabled, "Cheat. Unlocks all reward/hidden items, including ones that can only spawn in T&H. Using this won't affect your H3VR save file. Requires game restart.").Value;
			PreventSelectingModTagsFromHeldObject = _configFile.Bind<bool>("General", "PreventSelectingModTagsFromHeldObject", true, "ModTags will be skipped when using the 'Select Tags From Held Object' button.");
			ShowSpawnItemButtonInPortableSpawner = _configFile.Bind<bool>("General", "ShowSpawnItemButtonInPortableSpawner", true, "Makes the spawn item button visible in the portable item spawner, letting you spawn objects without having to use the stylus.");
			ItemSpawnerSortGrouping = _configFile.Bind<ItemSpawnerSortGrouping>("General", "ItemSpawnerSortGrouping", global::OtherLoader.ItemSpawner.VanillaCategories.ItemSpawnerSortGrouping.ShowModdedItemsFirst, "Changes how items are grouped and displayed in the item spawner.");
			ItemSpawnerSortOrder = _configFile.Bind<ItemSpawnerSortOrder>("General", "ItemSpawnerSortOrder", global::OtherLoader.ItemSpawner.VanillaCategories.ItemSpawnerSortOrder.AlphabeticalByDisplayName, "'Vanilla' orders items alphabetically by their internal ItemIDs. 'AlphabeticalByDisplayName' orders items by their actual visible names. This does not affect how categories are ordered, only items.");
			ColoredLogs = _configFile.Bind<bool>("Logging", "ColoredLogs", true, "When true, logs will change colors depending on their LogTag.");
			LogTags = _configFile.Bind<LogTag>("Logging", "LogTags", LogTag.General, "Controls which types of logs should be enabled. Errors and warnings will always be logged, regardless of this setting.");
			AddUnloadButton = _configFile.Bind<bool>("Debug", "AddUnloadButton", false, "When true, you'll have a wrist menu button that can unload all modded asset bundles for testing purposes. Requires game restart.").Value;
			EnableLogTraces = _configFile.Bind<bool>("Debug", "EnableLogTraces", false, "Affects performance, only enable when debugging. When true, method call traces will be included in logs. Requires game restart.").Value;
			ShowDebugItemSpawnerEntries = _configFile.Bind<bool>("Debug", "ShowDebugItemSpawnerEntries", false, "When true, debug spawner entries will be added to the item spawner's custom categories tab. Requires game restart.").Value;
		}
	}
}
namespace OtherLoader.UnlockAllItems
{
	public enum ItemUnlockerMode
	{
		Disabled,
		UnlockOnlyFirearmsAndAmmo,
		UnlockAllItems
	}
	[HarmonyPriority(600)]
	[HarmonyWrapSafe]
	internal static class RewardUnlocksPatchers
	{
		private static int _activeMethods;

		[HarmonyPostfix]
		[HarmonyPatch(typeof(RewardUnlocks), "IsRewardUnlocked", new Type[] { typeof(ItemSpawnerID) })]
		private static void IsRewardUnlocked_Postfix(ItemSpawnerID ID, ref bool __result)
		{
			if (_activeMethods == 0)
			{
				return;
			}
			if (!__result)
			{
				if (PluginConfig.ItemUnlocker == ItemUnlockerMode.UnlockOnlyFirearmsAndAmmo && !ID.IsFirearm() && !ID.IsAmmo())
				{
					OtherLogger.Log("Reward item '" + ID.DisplayName + "' is not firearm or ammo, skipping...", LogTag.ItemUnlocker);
					return;
				}
				OtherLogger.Log("Game checked if '" + ID.DisplayName + "' is unlocked, returning true!", LogTag.ItemUnlocker);
				if (!ID.ModTags.Contains("GrantedByItemUnlocker"))
				{
					ID.ModTags = ID.ModTags.Concat(new <>z__ReadOnlySingleElementList<string>("GrantedByItemUnlocker")).ToList();
				}
			}
			__result = true;
		}

		private static void AddActiveMethod()
		{
			Interlocked.Increment(ref _activeMethods);
		}

		private static void RemoveActiveMethod()
		{
			if (Interlocked.Decrement(ref _activeMethods) < 0)
			{
				Interlocked.Exchange(ref _activeMethods, 0);
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(IM), "GenerateItemDBs")]
		private static void GenerateItemDBs_Prefix()
		{
			AddActiveMethod();
		}

		[HarmonyFinalizer]
		[HarmonyPatch(typeof(IM), "GenerateItemDBs")]
		private static Exception GenerateItemDBs_Finalizer(Exception __exception)
		{
			RemoveActiveMethod();
			return __exception;
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(ItemSpawnerV2), "RedrawDetailsCanvas")]
		private static void RedrawDetailsCanvas_Prefix()
		{
			AddActiveMethod();
		}

		[HarmonyFinalizer]
		[HarmonyPatch(typeof(ItemSpawnerV2), "RedrawDetailsCanvas")]
		private static Exception RedrawDetailsCanvas_Finalizer(Exception __exception)
		{
			RemoveActiveMethod();
			return __exception;
		}
	}
}
namespace OtherLoader.QuickbeltPanel
{
	internal class QBslotPageController : MonoBehaviour
	{
		public const int QbsPerPage = 14;

		public OptionsPanel_ButtonSet QBslotButtonSet;

		public GameObject ButtonNextPage;

		public GameObject ButtonPreviousPage;

		public int currentPage;

		public void Start()
		{
			SetVisibility();
		}

		public void SetButtons()
		{
			ButtonNextPage.SetActive(true);
			ButtonPreviousPage.SetActive(true);
			if (currentPage <= 0)
			{
				ButtonPreviousPage.SetActive(false);
			}
			int num = Mathf.CeilToInt((float)(QBslotButtonSet.ButtonsInSet.Length / 14));
			if (currentPage >= num)
			{
				ButtonNextPage.SetActive(false);
			}
		}

		public void SetVisibility()
		{
			SetButtons();
			FVRPointableButton[] buttonsInSet = QBslotButtonSet.ButtonsInSet;
			for (int i = 0; i < buttonsInSet.Length; i++)
			{
				((Component)buttonsInSet[i]).gameObject.SetActive(false);
			}
			int num = currentPage * 14;
			int num2 = num + 14;
			for (int j = num; j < num2 && j < QBslotButtonSet.ButtonsInSet.Length; j++)
			{
				((Component)QBslotButtonSet.ButtonsInSet[j]).gameObject.SetActive(true);
			}
		}

		public void GotoPreviousPage()
		{
			currentPage--;
			SetVisibility();
		}

		public void GotoNextPage()
		{
			currentPage++;
			SetVisibility();
		}
	}
	[HarmonyWrapSafe]
	internal static class QuickbeltPanelPatcher
	{
		[HarmonyPrefix]
		[HarmonyPatch(typeof(OptionsScreen_Quickbelt), "Awake")]
		private static bool Awake_Prefix_AddScreens(OptionsScreen_Quickbelt __instance)
		{
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Expected O, but got Unknown
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b1: Expected O, but got Unknown
			//IL_0201: Unknown result type (might be due to invalid IL or missing references)
			//IL_020b: Expected O, but got Unknown
			//IL_024d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0257: Expected O, but got Unknown
			OptionsScreen_Quickbelt __instance2 = __instance;
			QBslotPageController pageController = ((Component)__instance2).gameObject.AddComponent<QBslotPageController>();
			pageController.QBslotButtonSet = __instance2.OBS_SlotStyle;
			GameObject gameObject = ((Component)__instance2.OBS_Handedness.ButtonsInSet[0]).gameObject;
			FVRPointableButton[] buttonsInSet = __instance2.OBS_SlotStyle.ButtonsInSet;
			for (int i = 0; i < buttonsInSet.Length; i++)
			{
				Object.Destroy((Object)(object)((Component)buttonsInSet[i]).gameObject);
			}
			__instance2.OBS_SlotStyle.ButtonsInSet = (FVRPointableButton[])(object)new FVRPointableButton[ManagerSingleton<GM>.Instance.QuickbeltConfigurations.Length];
			for (int j = 0; j < __instance2.OBS_SlotStyle.ButtonsInSet.Length; j++)
			{
				int num = j % 14;
				int column = num % 4;
				int row = (int)Mathf.Floor((float)num / 4f);
				OtherLogger.Log("Adding QB " + ((Object)ManagerSingleton<GM>.Instance.QuickbeltConfigurations[j]).name, LogTag.BundleLoading);
				GameObject val = Object.Instantiate<GameObject>(gameObject, ((Component)__instance2.OBS_SlotStyle).transform, true);
				FVRPointableButton component = val.GetComponent<FVRPointableButton>();
				__instance2.OBS_SlotStyle.ButtonsInSet[j] = component;
				string text = ((Object)ManagerSingleton<GM>.Instance.QuickbeltConfigurations[j]).name.Split(new char[1] { '_' }).Last();
				Button uiButton = SetQBSlotOptionsPanelButton(val, row, column, text);
				((UnityEvent)uiButton.onClick).AddListener((UnityAction)delegate
				{
					__instance2.SetSlotStyle(((Component)uiButton).transform.GetSiblingIndex());
				});
				((UnityEvent)uiButton.onClick).AddListener((UnityAction)delegate
				{
					__instance2.OBS_SlotStyle.SetSelectedButton(((Component)uiButton).transform.GetSiblingIndex());
				});
			}
			Button val2 = SetQBSlotOptionsPanelButton(Object.Instantiate<GameObject>(gameObject, ((Component)__instance2.OBS_SlotStyle).transform, true), 3, 2, "Previous Page");
			((UnityEvent)val2.onClick).AddListener((UnityAction)delegate
			{
				pageController.GotoPreviousPage();
			});
			pageController.ButtonPreviousPage = ((Component)val2).gameObject;
			val2 = SetQBSlotOptionsPanelButton(Object.Instantiate<GameObject>(gameObject, ((Component)__instance2.OBS_SlotStyle).transform, true), 3, 3, "Next Page");
			((UnityEvent)val2.onClick).AddListener((UnityAction)delegate
			{
				pageController.GotoNextPage();
			});
			pageController.ButtonNextPage = ((Component)val2).gameObject;
			return true;
		}

		public static Button SetQBSlotOptionsPanelButton(GameObject button, int row, int column, string text)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			float num = -100 + 125 * column;
			float num2 = -40 + -45 * row;
			button.transform.localPosition = new Vector3(num, num2, button.transform.localPosition.z);
			((Component)button.gameObject.transform.GetChild(0)).GetComponent<Text>().text = text;
			Button component = button.GetComponent<Button>();
			((UnityEventBase)component.onClick).RemoveAllListeners();
			return component;
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(FVRPlayerBody), "ConfigureQuickbelt")]
		private static bool ConfigureQuickbelt_Prefix_PreventIndexOutOfRange(ref int index)
		{
			index = Mathf.Clamp(index, 0, ManagerSingleton<GM>.Instance.QuickbeltConfigurations.Length - 1);
			return true;
		}
	}
}
namespace OtherLoader.PortableItemSpawner
{
	[HarmonyWrapSafe]
	[HarmonyPatch(typeof(ItemSpawnerV2))]
	internal static class PortableSpawnerPatcher
	{
		[HarmonyPostfix]
		[HarmonyPatch("RedrawDetailsCanvas")]
		private static void RedrawDetailsCanvas_Postfix_EnableSpawnButton(ItemSpawnerV2 __instance)
		{
			if (PluginConfig.ShowSpawnItemButtonInPortableSpawner.Value && __instance.IsInPortableMode && !string.IsNullOrEmpty(__instance.m_selectedID))
			{
				GameObject bTN_SpawnSelectedObject = __instance.BTN_SpawnSelectedObject;
				if (bTN_SpawnSelectedObject != null)
				{
					bTN_SpawnSelectedObject.SetActive(true);
				}
			}
		}
	}
}
namespace OtherLoader.Loading
{
	[HarmonyWrapSafe]
	internal static class AnvilRuntimeLoadingPatcher
	{
		[HarmonyPrefix]
		[HarmonyPatch(typeof(AnvilManager), "GetAssetBundleAsyncInternal")]
		private static bool GetAssetBundleAsyncInternal_Prefix(string bundle, ref AnvilCallback<AssetBundle> __result)
		{
			if (OtherLoader.ManagedBundles.TryGetValue(bundle, out string value))
			{
				AnvilCallbackBase val = default(AnvilCallbackBase);
				if (AnvilManager.m_bundles.TryGetValue(bundle, ref val))
				{
					OtherLogger.Log("Tried to load modded asset bundle, and it's already loaded: " + bundle, LogTag.BundleLoading);
					__result = val as AnvilCallback<AssetBundle>;
					return false;
				}
				OtherLogger.Log("Tried to load modded asset bundle, and it's not yet loaded: " + bundle, LogTag.BundleLoading);
				AnvilCallback<AssetBundle> val2 = UnityAssetBundleLoader.LoadAssetsFromBundlePatch(value);
				List<BundleLoadStatus> bundleDependencies = LoaderStatus.GetBundleDependencies(bundle);
				if (bundleDependencies.Count > 0)
				{
					OtherLogger.Log("Dependencies:", LogTag.BundleLoading);
					bundleDependencies.ForEach(delegate(BundleLoadStatus o)
					{
						OtherLogger.Log(OtherLoader.ManagedBundles[o.BundleId], LogTag.BundleLoading);
					});
					AnvilCallback<AssetBundle> val3 = (val2.m_dependancy = UnityAssetBundleLoader.LoadAssetsFromBundlePatch(OtherLoader.ManagedBundles[bundleDependencies.Last().BundleId]));
					AnvilManager.m_bundles.Add(bundleDependencies.Last().BundleId, (AnvilCallbackBase)(object)val3);
					for (int num = bundleDependencies.Count - 2; num >= 0; num--)
					{
						val3.m_dependancy = UnityAssetBundleLoader.LoadAssetsFromBundlePatch(OtherLoader.ManagedBundles[bundleDependencies[num].BundleId]);
						val3 = val3.m_dependancy;
						AnvilManager.m_bundles.Add(bundleDependencies[num].BundleId, (AnvilCallbackBase)(object)val3);
					}
				}
				__result = val2;
				AnvilManager.m_bundles.Add(bundle, (AnvilCallbackBase)(object)__result);
				return false;
			}
			return true;
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(AnvilAsset), "GetGameObject")]
		[HarmonyPatch(typeof(AnvilAsset), "GetGameObjectAsync")]
		private static bool GetGameObject_Prefix_SetBundlePatch(AnvilAsset __instance)
		{
			if (string.IsNullOrEmpty(__instance.m_anvilPrefab.Bundle))
			{
				FVRObject val = (FVRObject)(object)((__instance is FVRObject) ? __instance : null);
				if ((Object)(object)val != (Object)null && IM.OD.TryGetValue(val.ItemID, out var value))
				{
					__instance.m_anvilPrefab.Bundle = ((AnvilAsset)value).m_anvilPrefab.Bundle;
				}
			}
			return true;
		}
	}
	internal static class MainLoader
	{
		private static readonly IAssetBundleLoader[] AssetLoaders = new IAssetBundleLoader[13]
		{
			new MechanicalAccuracyChartLoader(),
			new FVRObjectLoader(),
			new RoundDisplayDataLoader(),
			new ItemSpawnerCategoryLoader(),
			new ItemSpawnerIDLoader(),
			new ItemSpawnerEntryLoader(),
			new HandlingGrabSetLoader(),
			new HandlingReleaseSetLoader(),
			new HandlingSlotSetLoader(),
			new BulletImpactSetLoader(),
			new AudioImpactSetLoader(),
			new TutorialBlockLoader(),
			new QuickBeltLoader()
		};

		public static Empty LoadAssembly(FileSystemInfo handle)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			OtherLogger.Log("Loading assembly file: $" + handle.FullName, LogTag.BundleLoading);
			Assembly.LoadFile(handle.FullName);
			return default(Empty);
		}

		public static IEnumerator BundleLoadImmediate(FileSystemInfo handle, LoadOrderType loadOrder)
		{
			return LoadBundle(new TL("BundleLoadImmediate", LogTag.BundleLoading), handle, loadOrder, allowUnload: true);
		}

		public static IEnumerator BundlePrepareLate(FileSystemInfo handle)
		{
			return LoadBundle(new TL("BundlePrepareLate", LogTag.BundleLoading), handle, LoadOrderType.LoadFirst, allowUnload: false);
		}

		public static IEnumerator BundleRegisterLate(FileSystemInfo handle, LoadOrderType loadOrder)
		{
			TL oldTL = new TL("BundleRegisterLate", LogTag.BundleLoading);
			FileInfo fileInfo = ExtFileSystemInfo.ConsumeFile(handle);
			return RegisterLateBundle(oldTL, fileInfo.Name, fileInfo.FullName, loadOrder);
		}

		public static void BundleLoadDirectFromDirectory(string directoryNameFull, string[] loadFirst, string[] loadAny, string[] loadLast)
		{
			TL oldTL = new TL("BundleLoadDirectFromDirectory", LogTag.BundleLoading);
			foreach (KeyValuePair<string, LoadOrderType> item in loadFirst.Select((string bundle) => new KeyValuePair<string, LoadOrderType>(bundle, LoadOrderType.LoadFirst)).Concat(loadAny.Select((string bundle) => new KeyValuePair<string, LoadOrderType>(bundle, LoadOrderType.LoadUnordered))).Concat(loadLast.Select((string bundle) => new KeyValuePair<string, LoadOrderType>(bundle, LoadOrderType.LoadLast))))
			{
				if (!string.IsNullOrEmpty(item.Key))
				{
					OtherLoader.CoroutineStarter.Invoke(LoadBundleDirect(oldTL, directoryNameFull, item.Key, item.Value));
				}
			}
		}

		public static void LoadLegacyBundles()
		{
			string text = Application.dataPath.Replace("/h3vr_Data", "/LegacyVirtualObjects");
			if (!Directory.Exists(text))
			{
				Directory.CreateDirectory(text);
			}
			TL newTL = new TL("LoadLegacyBundles", LogTag.BundleLoading);
			newTL.Log("Loading bundles from legacy directory (" + text + ")");
			List<string> list = Directory.GetDirectories(Paths.PluginPath, "LegacyVirtualObjects", SearchOption.AllDirectories).ToList();
			list.Add(text);
			foreach (string item in list)
			{
				newTL.Log("Legacy folder found '" + item + "'");
				string[] files = Directory.GetFiles(item, "*", SearchOption.AllDirectories);
				foreach (string text2 in files)
				{
					if (!(Path.GetFileName(text2) != Path.GetFileNameWithoutExtension(text2)))
					{
						BundleInfo bundleInfo = new BundleInfo(text2);
						IEnumerator enumerator2 = ExtIEnumerator.TryCatch<Exception>(TrackLoadAssetsFromBundle(newTL, bundleInfo, LoadOrderType.LoadUnordered, allowUnload: true), (Action<Exception>)delegate(Exception exception)
						{
							newTL.LogError("Exception when loading legacy bundle '" + bundleInfo.Name + "'\n- " + exception.Message);
							LoaderStatus.UpdateProgress(bundleInfo.ID, 1f);
							LoaderStatus.RemoveActiveLoader(bundleInfo.ID, permanentlyLoaded: true);
						});
						OtherLoader.CoroutineStarter.Invoke(enumerator2);
					}
				}
			}
		}

		private static IEnumerator LoadBundle(TL oldTL, FileSystemInfo handle, LoadOrderType loadOrder, bool allowUnload)
		{
			TL newTL = oldTL.New("LoadBundle");
			BundleInfo bundleInfo = new BundleInfo(ExtFileSystemInfo.ConsumeFile(handle));
			newTL.Log($"Loading '{bundleInfo.Name}' with: loadOrder '{loadOrder}', allowUnload '{allowUnload}'");
			return ExtIEnumerator.TryCatch(TrackLoadAssetsFromBundle(newTL, bundleInfo, loadOrder, allowUnload), (Action<Exception>)delegate(Exception exception)
			{
				newTL.LogError("Exception when loading bundle '" + bundleInfo.Name + "'\n- " + exception.Message);
				LoaderStatus.UpdateProgress(bundleInfo.ID, 1f);
				LoaderStatus.RemoveActiveLoader(bundleInfo.ID, permanentlyLoaded: true);
			});
		}

		private static IEnumerator RegisterLateBundle(TL oldTL, string lateBundleName, string lateBundleFullPath, LoadOrderType loadOrder)
		{
			TL tL = oldTL.New("RegisterLateBundle");
			string text = lateBundleName.Replace("late_", "");
			BundleInfo bundleInfo = new BundleInfo(Path.Combine(Path.GetDirectoryName(lateBundleFullPath), text), lateBundleFullPath);
			OtherLoader.ManagedBundles[bundleInfo.ID] = bundleInfo.ContentFullPath;
			LoaderStatus.TrackLoader(bundleInfo.ID, loadOrder);
			AnvilCallbackBase item = default(AnvilCallbackBase);
			if (AnvilManager.m_bundles.TryGetValue(bundleInfo.ID, ref item))
			{
				AnvilManager.m_bundles.m_lookup.Remove(bundleInfo.ID);
				AnvilManager.m_bundles.m_loading.Remove(item);
				tL.Log("Finished registering late bundle '" + lateBundleName + "'\n- This bundle will replace prepared bundle '" + text + "'");
			}
			else
			{
				tL.LogError("Failed to register late bundle '" + lateBundleName + "', there is no prepared bundle it can replace.\n- There should have been a prepared bundle '" + text + "'");
			}
			yield return null;
		}

		private static IEnumerator LoadBundleDirect(TL oldTL, string directoryNameFull, string bundleName, LoadOrderType loadOrder)
		{
			TL newTL = oldTL.New("LoadBundleDirect");
			BundleInfo bundleInfo = new BundleInfo(Path.Combine(directoryNameFull, bundleName));
			newTL.Log("Starting direct load bundle '" + bundleInfo.Name + "'");
			string text = "late_" + bundleName;
			string text2 = Path.Combine(directoryNameFull, text);
			IEnumerator onAfterLoadAsync = null;
			if (File.Exists(text2))
			{
				onAfterLoadAsync = RegisterLateBundle(newTL, text, text2, loadOrder);
			}
			return ExtIEnumerator.TryCatch(TrackLoadAssetsFromBundle(newTL, bundleInfo, loadOrder, allowUnload: false, onAfterLoadAsync), (Action<Exception>)delegate(Exception exception)
			{
				newTL.LogError("Exception when direct loading bundle '" + bundleInfo.Name + "'\n- " + exception.Message);
				LoaderStatus.UpdateProgress(bundleInfo.ID, 1f);
				LoaderStatus.RemoveActiveLoader(bundleInfo.ID, permanentlyLoaded: true);
			});
		}

		private static IEnumerator TrackLoadAssetsFromBundle(TL oldTL, BundleInfo bundleInfo, LoadOrderType loadOrder, bool allowUnload, IEnumerator? onAfterLoadAsync = null)
		{
			TL newTL = oldTL.New("TrackLoadAssetsFromBundle");
			if (LoaderStatus.IsBundleAlreadyTracked(bundleInfo.ID))
			{
				newTL.LogWarning("BundleID '" + bundleInfo.Name + "' is already tracked! Returning...");
				yield break;
			}
			LoaderStatus.TrackLoader(bundleInfo.ID, loadOrder);
			newTL.Log("Began tracking bundle '" + bundleInfo.Name + "', yielding to track others...");
			yield return null;
			newTL.Log("Waiting until bundle '" + bundleInfo.Name + "' can load...");
			yield return WaitUntilBundleCanLoad(newTL, bundleInfo);
			float loadingTime = Time.realtimeSinceStartup;
			LoaderStatus.AddActiveLoader(bundleInfo.ID);
			LoaderStatus.UpdateProgress(bundleInfo.ID, Random.Range(0.1f, 0.3f));
			newTL.Log("Beginning async load of bundle '" + bundleInfo.Name + "'");
			AnvilCallback<AssetBundle> anvilCallback = UnityAssetBundleLoader.LoadAssetsFromBundlePatch(bundleInfo.ContentFullPath);
			yield return anvilCallback;
			if ((Object)(object)anvilCallback?.Result == (Object)null)
			{
				OtherLogger.LogFatal("Asset bundle '" + bundleInfo.Name + "' is null! Cannot load assets from mod '" + bundleInfo.PluginName + "'. Most likely a different mod has already loaded a bundle with the same internal name!");
				LoaderStatus.UpdateProgress(bundleInfo.ID, 1f);
				LoaderStatus.RemoveActiveLoader(bundleInfo.ID, permanentlyLoaded: true);
			}
			else
			{
				yield return RunAssetLoadersOnAssetBundle(newTL, anvilCallback, bundleInfo);
				FinishBundleLoading(newTL, anvilCallback, bundleInfo, allowUnload, loadingTime);
				if (onAfterLoadAsync != null)
				{
					yield return onAfterLoadAsync;
				}
			}
		}

		private static IEnumerator WaitUntilBundleCanLoad(TL oldTL, BundleInfo bundleInfo)
		{
			TL newTL = oldTL.New("WaitUntilBundleCanLoad");
			bool overTime = false;
			while (!LoaderStatus.CanOrderedModLoad(bundleInfo.ID))
			{
				if (!overTime && Time.realtimeSinceStartup - LoaderStatus.LastLoadEventTime > 30f)
				{
					newTL.Log("Bundle '" + bundleInfo.Name + "' has been waiting a long time to load!");
					LoaderStatus.PrintWaitingBundles(bundleInfo.ID);
					overTime = true;
				}
				yield return null;
			}
		}

		private static IEnumerator RunAssetLoadersOnAssetBundle(TL oldTL, AnvilCallback<AssetBundle> anvilCallback, BundleInfo bundleInfo)
		{
			BundleInfo bundleInfo2 = bundleInfo;
			TL newTL = oldTL.New("RunAssetLoadersOnAssetBundle");
			IAssetBundleLoader[] assetLoaders = AssetLoaders;
			foreach (IAssetBundleLoader loader in assetLoaders)
			{
				yield return ExtIEnumerator.TryCatch(loader.LoadAssetsFromBundle(anvilCallback.Result, bundleInfo2), (Action<Exception>)delegate(Exception e)
				{
					newTL.LogError("Exception when loader '" + loader.GetType().Name + "' was loading assets from " + $"bundle '{bundleInfo2.Name}' from mod '{bundleInfo2.PluginName}'! {e}");
				});
			}
		}

		private static void FinishBundleLoading(TL oldTL, AnvilCallback<AssetBundle> anvilCallback, BundleInfo bundleInfo, bool allowUnload, float loadingTime)
		{
			TL tL = oldTL.New("FinishBundleLoading");
			bool flag = PluginConfig.OptimizeMemory && allowUnload;
			string text = $"Completed loading bundle '{bundleInfo.Name}' in {Time.realtimeSinceStartup - loadingTime:0.000} seconds!";
			string message = (flag ? (text + " Optimizing memory!") : text);
			tL.Log(message, LogTag.General);
			if (flag)
			{
				anvilCallback.Result.Unload(false);
			}
			else
			{
				AnvilManager.m_bundles.Add(bundleInfo.ID, (AnvilCallbackBase)(object)anvilCallback);
			}
			OtherLoader.ManagedBundles.Add(bundleInfo.ID, bundleInfo.ContentFullPath);
			LoaderStatus.UpdateProgress(bundleInfo.ID, 1f);
			LoaderStatus.RemoveActiveLoader(bundleInfo.ID, !flag);
		}
	}
	internal static class UnityAssetBundleLoader
	{
		public static AnvilCallback<AssetBundle> LoadAssetsFromBundlePatch(string fullBundlePath)
		{
			return new AnvilCallback<AssetBundle>((AsyncOperation)(object)AssetBundle.LoadFromFileAsync(fullBundlePath), (AnvilCallback<AssetBundle>)null);
		}
	}
}
namespace OtherLoader.Loading.Model
{
	internal class BundleInfo
	{
		public readonly string Name;

		public readonly string ContentFullPath;

		public readonly string PluginName;

		public readonly string FullDirectoryName;

		public string ID => FullDirectoryName + "\\ : " + Name;

		public BundleInfo(FileInfo fileInfo)
		{
			Name = fileInfo.Name;
			FullDirectoryName = fileInfo.DirectoryName;
			PluginName = RetrievePluginNameFromFullDirectoryName() ?? "UnknownPlugin";
			ContentFullPath = fileInfo.FullName;
		}

		public BundleInfo(string bundleFullPath, string? bundleContentFullPathOverride = null)
		{
			Name = Path.GetFileName(bundleFullPath);
			FullDirectoryName = Path.GetDirectoryName(bundleFullPath);
			PluginName = RetrievePluginNameFromFullDirectoryName() ?? "UnknownPlugin";
			ContentFullPath = bundleContentFullPathOverride ?? bundleFullPath;
		}

		private string? RetrievePluginNameFromFullDirectoryName()
		{
			string path = Path.Combine(Paths.BepInExRootPath, "plugins");
			string text = Path.GetFullPath(FullDirectoryName).Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
			string text2 = Path.GetFullPath(path).Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
			if (!text.StartsWith(text2, StringComparison.OrdinalIgnoreCase))
			{
				return null;
			}
			string[] array = text.Substring(text2.Length).TrimStart(new char[1] { Path.DirectorySeparatorChar }).Split(new char[1] { Path.DirectorySeparatorChar });
			if (array.Length == 0)
			{
				return null;
			}
			return array[0];
		}
	}
}
namespace OtherLoader.Loading.AssetLoaders
{
	internal abstract class AssetBundleLoaderBase<T> : IAssetBundleLoader where T : Object
	{
		public IEnumerator LoadAssetsFromBundle(AssetBundle assetBundle, BundleInfo bundleInfo)
		{
			AssetBundleRequest bundleRequest = assetBundle.LoadAllAssetsAsync<T>();
			yield return bundleRequest;
			Object[] allAssets = bundleRequest.allAssets;
			foreach (Object val in allAssets)
			{
				try
				{
					T asset = ((T)(object)((val is T) ? val : null)) ?? throw new InvalidOperationException("CastAsset is null");
					LoadAssetFromBundle(asset, bundleInfo);
				}
				catch (Exception arg)
				{
					OtherLogger.LogError($"Failed to load asset from mod '{bundleInfo.PluginName}'! Exception: {arg}");
				}
			}
		}

		protected abstract void LoadAssetFromBundle(T asset, BundleInfo bundleInfo);
	}
	internal interface IAssetBundleLoader
	{
		IEnumerator LoadAssetsFromBundle(AssetBundle assetBundle, BundleInfo bundleInfo);
	}
}
namespace OtherLoader.Loading.AssetLoaders.Implementations
{
	internal class AudioImpactSetLoader : AssetBundleLoaderBase<AudioImpactSet>
	{
		protected override void LoadAssetFromBundle(AudioImpactSet asset, BundleInfo bundleInfo)
		{
			OtherLogger.Log("Loading new AudioImpactSet: " + ((Object)asset).name, LogTag.Assets);
			ManagerSingleton<SM>.Instance.AudioImpactSets = ManagerSingleton<SM>.Instance.AudioImpactSets.Concat(new <>z__ReadOnlySingleElementList<AudioImpactSet>(asset)).ToArray();
			ManagerSingleton<SM>.Instance.m_impactDic = new Dictionary<ImpactType, Dictionary<MatSoundType, Dictionary<AudioImpactIntensity, AudioEvent>>>();
			ManagerSingleton<SM>.Instance.generateImpactDictionary();
		}
	}
	internal class BulletImpactSetLoader : AssetBundleLoaderBase<AudioBulletImpactSet>
	{
		protected override void LoadAssetFromBundle(AudioBulletImpactSet asset, BundleInfo bundleInfo)
		{
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			OtherLogger.Log("Loading new bullet impact set entry: " + ((Object)asset).name, LogTag.Assets);
			ManagerSingleton<SM>.Instance.AudioBulletImpactSets = ManagerSingleton<SM>.Instance.AudioBulletImpactSets.Concat(new <>z__ReadOnlySingleElementList<AudioBulletImpactSet>(asset)).ToArray();
			ManagerSingleton<SM>.Instance.m_bulletHitDic.Add(asset.Type, asset);
		}
	}
	internal class FVRObjectLoader : AssetBundleLoaderBase<FVRObject>
	{
		protected override void LoadAssetFromBundle(FVRObject fvrObject, BundleInfo bundleInfo)
		{
			OtherLogger.Log("Loading FVRObject with ID '" + fvrObject.ItemID + "'", LogTag.Assets);
			if (IM.OD.ContainsKey(fvrObject.ItemID))
			{
				OtherLogger.LogError("The ItemID '" + fvrObject.ItemID + "' of FVRObject is already used! Item will not be loaded!");
				return;
			}
			((AnvilAsset)fvrObject).m_anvilPrefab.Bundle = bundleInfo.ID;
			LoadIntoObjectDatabase(fvrObject);
			fvrObject.IsModContent = true;
			OtherLogger.Log("Loaded FVRObject with ID '" + fvrObject.ItemID + "'", LogTag.Assets);
		}

		private void LoadIntoObjectDatabase(FVRObject fvrObject)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			FVRObject fvrObject2 = fvrObject;
			IM.OD.Add(fvrObject2.ItemID, fvrObject2);
			ManagerSingleton<IM>.Instance.odicTagCategory.GetOrCreateDefault(fvrObject2.Category).Add(fvrObject2);
			ManagerSingleton<IM>.Instance.odicTagFirearmEra.GetOrCreateDefault(fvrObject2.TagEra).Add(fvrObject2);
			ManagerSingleton<IM>.Instance.odicTagFirearmSize.GetOrCreateDefault(fvrObject2.TagFirearmSize).Add(fvrObject2);
			ManagerSingleton<IM>.Instance.odicTagFirearmAction.GetOrCreateDefault(fvrObject2.TagFirearmAction).Add(fvrObject2);
			ManagerSingleton<IM>.Instance.odicTagAttachmentMount.GetOrCreateDefault(fvrObject2.TagAttachmentMount).Add(fvrObject2);
			ManagerSingleton<IM>.Instance.odicTagAttachmentFeature.GetOrCreateDefault(fvrObject2.TagAttachmentFeature).Add(fvrObject2);
			fvrObject2.TagFirearmFeedOption.ForEach(delegate(OTagFirearmFeedOption o)
			{
				//IL_000a: Unknown result type (might be due to invalid IL or missing references)
				ManagerSingleton<IM>.Instance.odicTagFirearmFeedOption.GetOrCreateDefault(o).Add(fvrObject2);
			});
			fvrObject2.TagFirearmFiringModes.ForEach(delegate(OTagFirearmFiringMode o)
			{
				//IL_000a: Unknown result type (might be due to invalid IL or missing references)
				ManagerSingleton<IM>.Instance.odicTagFirearmFiringMode.GetOrCreateDefault(o).Add(fvrObject2);
			});
			fvrObject2.TagFirearmMounts.ForEach(delegate(OTagFirearmMount o)
			{
				//IL_000a: Unknown result type (might be due to invalid IL or missing references)
				ManagerSingleton<IM>.Instance.odicTagFirearmMount.GetOrCreateDefault(o).Add(fvrObject2);
			});
		}
	}
	internal class HandlingGrabSetLoader : AssetBundleLoaderBase<HandlingGrabSet>
	{
		protected override void LoadAssetFromBundle(HandlingGrabSet asset, BundleInfo bundleInfo)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			OtherLogger.Log("Loading new handling grab set entry: " + ((Object)asset).name, LogTag.Assets);
			ManagerSingleton<SM>.Instance.m_handlingGrabDic.Add(asset.Type, asset);
		}
	}
	internal class HandlingReleaseSetLoader : AssetBundleLoaderBase<HandlingReleaseSet>
	{
		protected override void LoadAssetFromBundle(HandlingReleaseSet asset, BundleInfo bundleInfo)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			OtherLogger.Log("Loading new handling release set entry: " + ((Object)asset).name, LogTag.Assets);
			ManagerSingleton<SM>.Instance.m_handlingReleaseDic.Add(asset.Type, asset);
		}
	}
	internal class HandlingSlotSetLoader : AssetBundleLoaderBase<HandlingReleaseIntoSlotSet>
	{
		protected override void LoadAssetFromBundle(HandlingReleaseIntoSlotSet asset, BundleInfo bundleInfo)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			OtherLogger.Log("Loading new handling QB slot set entry: " + ((Object)asset).name, LogTag.Assets);
			ManagerSingleton<SM>.Instance.m_handlingReleaseIntoSlotDic.Add(asset.Type, asset);
		}
	}
	internal class ItemSpawnerCategoryLoader : AssetBundleLoaderBase<ItemSpawnerCategoryDefinitions>
	{
		protected override void LoadAssetFromBundle(ItemSpawnerCategoryDefinitions categoryDefinitions, BundleInfo bundleInfo)
		{
			new TL("LoadAssetFromBundle", LogTag.Assets).Log("Loading legacy ItemSpawnerCategoryDefinitions from plugin '" + bundleInfo.PluginName + "'");
			SpawnerTilesDatabase.RegisterLegacyCategories(categoryDefinitions);
		}
	}
	internal class ItemSpawnerEntryLoader : AssetBundleLoaderBase<ItemSpawnerEntry>
	{
		protected override void LoadAssetFromBundle(ItemSpawnerEntry entry, BundleInfo bundleInfo)
		{
			TL tL = new TL("LoadAssetFromBundle", LogTag.Assets);
			bool isDisplayedInMainEntry = entry.IsDisplayedInMainEntry;
			tL.Log("Loading ItemSpawnerEntry from plugin '" + bundleInfo.PluginName + "'\n- MainObjectID '" + (entry.MainObjectID ?? "null") + "'\n- MainObjectObj.ItemID '" + (entry.MainObjectObj?.ItemID ?? "null") + "'\n- EntryPath '" + (entry.EntryPath ?? "null") + "'\n- DisplayName '" + (entry.DisplayName ?? "null") + "'");
			entry.PopulateIDsFromObj();
			bool flag = entry.IsCategoryEntry();
			tL.Log($"Is a category entry: {flag}");
			if ((Object)(object)entry.MainObjectObj == (Object)null && !flag)
			{
				FVRObject valueOrNull = IM.OD.GetValueOrNull(entry.MainObjectID);
				if ((Object)(object)valueOrNull == (Object)null)
				{
					tL.LogWarning("ItemSpawnerEntry is not a custom category, but has no specified FVRObject! Attempted to resolve MainObjectID '" + entry.MainObjectID + "', but there is no FVRObject with such ID! Attempting to load this entry regardless...");
				}
				entry.MainObjectObj = valueOrNull;
			}
			if (!flag)
			{
				ItemSpawnerID itemSpawnerID = SpawnerEntryToSpawnerIDConverter.Convert(tL, entry);
				ItemSpawnerIDRegisterer.Register(tL, itemSpawnerID, registerInTilesDatabase: false, unifyItemIDs: false, blockDuplicateIDs: false, bundleInfo.PluginName);
				OtherLoader.SpawnerEntriesByID[entry.MainObjectID] = entry;
			}
			if (isDisplayedInMainEntry)
			{
				SpawnerTilesDatabase.TryRegister(entry);
			}
			else if (flag)
			{
				OtherLogger.LogWarning("CategoryEntry has IsDisplayedInMainEntry set to false, it will not be displayed!");
			}
		}
	}
	internal class ItemSpawnerIDLoader : AssetBundleLoaderBase<ItemSpawnerID>
	{
		protected override void LoadAssetFromBundle(ItemSpawnerID itemSpawnerID, BundleInfo bundleInfo)
		{
			TL tL = new TL("LoadAssetFromBundle", LogTag.Assets);
			tL.Log("Loading ItemSpawnerID from plugin '" + bundleInfo.PluginName + "'\n- ItemID '" + (itemSpawnerID.ItemID ?? "null") + "'\n- MainObject.ItemID '" + (itemSpawnerID.MainObject?.ItemID ?? "null") + "'\n- DisplayName '" + (itemSpawnerID.DisplayName ?? "null") + "'");
			if (itemSpawnerID.SecondObject?.ItemID != null)
			{
				ItemSpawnerIDLinker.QueueEntryToLink(new EntryToLink(itemSpawnerID, new List<string>(1) { itemSpawnerID.SecondObject.ItemID }, new List<string>()));
			}
			bool flag;
			switch (bundleInfo.PluginName)
			{
			case "Meat_banono-Meats_ASh12":
			case "Meat_banono-Meats_ModulSIG":
			case "Phoenix-NikiFoxsCSGOBenelliNova":
			case "Potatoes-Potatoes_SMGs":
			case "Potatoes-Potatoes_Rifles":
			case "Potatoes-Potatoes_NonRepeaters":
			case "Potatoes-Potatoes_Pistols":
				flag = true;
				break;
			default:
				flag = false;
				break;
			}
			bool num = flag;
			bool flag2 = itemSpawnerID.ItemID?.All(char.IsWhiteSpace) ?? false;
			bool unifyItemIDs = num || flag2;
			bool blockDuplicateIDs = bundleInfo.PluginName == "Andrew_FTW-FTW_Arms_Edged_Weapons_Pack";
			ItemSpawnerIDRegisterer.Register(tL, itemSpawnerID, registerInTilesDatabase: true, unifyItemIDs, blockDuplicateIDs, bundleInfo.PluginName);
		}
	}
	internal class MechanicalAccuracyChartLoader : AssetBundleLoaderBase<FVRFireArmMechanicalAccuracyChart>
	{
		protected override void LoadAssetFromBundle(FVRFireArmMechanicalAccuracyChart asset, BundleInfo bundleInfo)
		{
			foreach (MechanicalAccuracyEntry entry in asset.Entries)
			{
				LoadMechanicalAccuracyEntry(entry);
			}
		}

		private void LoadMechanicalAccuracyEntry(MechanicalAccuracyEntry entry)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			if (AM.SMechanicalAccuracyDic.ContainsKey(entry.Class))
			{
				OtherLogger.LogError("Duplicate mechanical accuracy class found, will not use one of them! Make sure you're using unique mechanical accuracy classes!");
				return;
			}
			AM.SMechanicalAccuracyDic.Add(entry.Class, entry);
			OtherLogger.Log("Loaded new mechanical accuracy entry: " + ((object)(FVRFireArmMechanicalAccuracyClass)(ref entry.Class)).ToString(), LogTag.Assets);
		}
	}
	internal class QuickBeltLoader : AssetBundleLoaderBase<GameObject>
	{
		protected override void LoadAssetFromBundle(GameObject asset, BundleInfo bundleInfo)
		{
			if (IsPrefabAQuickBelt(asset))
			{
				OtherLogger.Log("Adding QuickBelt " + ((Object)asset).name, LogTag.Assets);
				ManagerSingleton<GM>.Instance.QuickbeltConfigurations = ManagerSingleton<GM>.Instance.QuickbeltConfigurations.Concat(new <>z__ReadOnlySingleElementList<GameObject>(asset)).ToArray();
			}
		}

		private static bool IsPrefabAQuickBelt(GameObject prefab)
		{
			string[] array = ((Object)prefab).name.Split(new char[1] { '_' });
			if (array.Length > 1)
			{
				return array[^2] == "QuickBelt";
			}
			return false;
		}
	}
	internal class RoundDisplayDataLoader : AssetBundleLoaderBase<FVRFireArmRoundDisplayData>
	{
		protected override void LoadAssetFromBundle(FVRFireArmRoundDisplayData asset, BundleInfo bundleInfo)
		{
			AddRoundTypeIfNotExist(asset);
			AddRoundClassIfNotExist(asset);
			AddRoundDisplayData(asset);
			OtherLogger.Log("Loaded ammo type: " + ((object)(FireArmRoundType)(ref asset.Type)).ToString(), LogTag.Assets);
		}

		private void AddRoundTypeIfNotExist(FVRFireArmRoundDisplayData displayData)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			AM.STypeDic.GetOrCreateDefault(displayData.Type);
			AM.STypeList.AddIfUnique(displayData.Type);
		}

		private void AddRoundClassIfNotExist(FVRFireArmRoundDisplayData displayData)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			AM.STypeClassLists.GetOrCreateDefault(displayData.Type);
			DisplayDataClass[] classes = displayData.Classes;
			foreach (DisplayDataClass val in classes)
			{
				OtherLogger.Log("Loading ammo class: " + ((object)(FireArmRoundClass)(ref val.Class)).ToString(), LogTag.Assets);
				AM.STypeDic[displayData.Type][val.Class] = val;
				AM.STypeClassLists[displayData.Type].AddIfUnique(val.Class);
			}
		}

		private void AddRoundDisplayData(FVRFireArmRoundDisplayData displayData)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			if (!AM.SRoundDisplayDataDic.ContainsKey(displayData.Type))
			{
				AM.SRoundDisplayDataDic[displayData.Type] = displayData;
				return;
			}
			List<DisplayDataClass> list = AM.SRoundDisplayDataDic[displayData.Type].Classes.ToList();
			list.AddRange(displayData.Classes);
			AM.SRoundDisplayDataDic[displayData.Type].Classes = list.ToArray();
		}
	}
	internal class TutorialBlockLoader : AssetBundleLoaderBase<TutorialBlock>
	{
		protected override void LoadAssetFromBundle(TutorialBlock tutorialBlock, BundleInfo bundleInfo)
		{
			if (string.IsNullOrEmpty(tutorialBlock.MediaRef.MediaPath.Path))
			{
				LinkVideoToTutorialBlockByID(tutorialBlock, bundleInfo);
			}
			IM.TutorialBlockDic[tutorialBlock.ID] = tutorialBlock;
			OtherLogger.Log("Loaded tutorial block with media path: " + tutorialBlock.MediaRef.MediaPath.Path, LogTag.Assets);
		}

		private void LinkVideoToTutorialBlockByID(TutorialBlock tutorialBlock, BundleInfo bundleInfo)
		{
			string text = Path.Combine(bundleInfo.FullDirectoryName, tutorialBlock.ID + ".mp4");
			if (!File.Exists(text))
			{
				throw new FileNotFoundException("Tutorial block had no assigned path. Attempted to find MP4 file by its ID, but failed: " + text);
			}
			tutorialBlock.MediaRef.MediaPath.Path = text;
		}
	}
}
namespace OtherLoader.ItemSpawner
{
	internal static class ItemSpawnerIDRegisterer
	{
		public static void Register(TL oldTL, ItemSpawnerID itemSpawnerID, bool registerInTilesDatabase, bool unifyItemIDs, bool blockDuplicateIDs, string pluginName)
		{
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0233: Unknown result type (might be due to invalid IL or missing references)
			//IL_024f: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0324: Unknown result type (might be due to invalid IL or missing references)
			//IL_0339: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d5: Unknown result type (might be due to invalid IL or missing references)
			TL tL = oldTL.New("Register", LogTag.Assets);
			EnsureMainObjectIsNotNull(tL, itemSpawnerID);
			itemSpawnerID.FromMod = pluginName;
			if (unifyItemIDs && itemSpawnerID.MainObject?.ItemID != null)
			{
				itemSpawnerID.ItemID = itemSpawnerID.MainObject.ItemID;
				itemSpawnerID.MainObject.SpawnedFromId = itemSpawnerID.MainObject.ItemID;
				tL.Log("Unified spawner IDs");
			}
			if (itemSpawnerID.ItemID == null)
			{
				tL.LogError("ItemSpawnerID.ItemID is null, can't register ItemSpawnerID!");
				return;
			}
			tL.Log("Registering new ItemSpawnerID\n- DisplayName '" + itemSpawnerID.DisplayName + "'\n- ItemID '" + itemSpawnerID.ItemID + "'\n- MainObject.ItemID '" + (itemSpawnerID.MainObject?.ItemID ?? "null") + "'" + $"\n- Category '{itemSpawnerID.Category}'" + $"\n- SubCategory '{itemSpawnerID.SubCategory}'" + $"\n- IsDisplayedInMainEntry '{itemSpawnerID.IsDisplayedInMainEntry}'" + $"\n- SecondObject '{itemSpawnerID.SecondObject}'" + "\n- Secondaries: " + (itemSpawnerID.Secondaries?.JoinToString() ?? "null") + "\n- SecondariesByStringID: " + (itemSpawnerID.Secondaries_ByStringID?.JoinToString() ?? "null"));
			if (IM.HasSpawnedID(itemSpawnerID.ItemID))
			{
				if (blockDuplicateIDs)
				{
					tL.LogWarning("Warning! Duplicates are specifically disabled for this mod! Skipping ItemSpawnerID with ID '" + itemSpawnerID.ItemID + "' because a spawner entry with the same ID is already registered!");
					return;
				}
				tL.LogWarning("Warning! Registering ItemSpawnerID with ID '" + itemSpawnerID.ItemID + "' even though a spawner entry with the same ID is already registered!");
				if (itemSpawnerID.IsDisplayedInMainEntry)
				{
					ManagerSingleton<IM>.Instance.SpawnerIDDic[itemSpawnerID.ItemID] = itemSpawnerID;
				}
			}
			else
			{
				ManagerSingleton<IM>.Instance.SpawnerIDDic[itemSpawnerID.ItemID] = itemSpawnerID;
			}
			ItemSpawnerIDTagger.RegisterSpawnerIDIntoTagSystem(itemSpawnerID);
			IM.CD.GetValueOrNull(itemSpawnerID.Category)?.Add(itemSpawnerID);
			IM.SCD.GetValueOrNull(itemSpawnerID.SubCategory)?.Add(itemSpawnerID);
			if (itemSpawnerID.IsDisplayedInMainEntry)
			{
				RegisteredItemSpawnerIDsDatabase.RegisteredVisibleIDs.Add(itemSpawnerID.ItemID);
				if (!registerInTilesDatabase)
				{
					return;
				}
				if (Enum.IsDefined(typeof(EItemCategory), itemSpawnerID.Category))
				{
					if (!Enum.IsDefined(typeof(ESubCategory), itemSpawnerID.SubCategory))
					{
						ItemSpawnerEntry itemSpawnerEntry = ItemSpawnerEntry.CreateEmpty($"{itemSpawnerID.SubCategory}/" + itemSpawnerID.ItemID);
						itemSpawnerEntry.DisplayName = itemSpawnerID.DisplayName;
						itemSpawnerEntry.MainObjectID = itemSpawnerID.ItemID;
						itemSpawnerEntry.EntryIcon = itemSpawnerID.Sprite;
						SpawnerTilesDatabase.TryRegister(itemSpawnerEntry);
					}
				}
				else
				{
					ItemSpawnerEntry itemSpawnerEntry2 = ItemSpawnerEntry.CreateEmpty($"{itemSpawnerID.Category}/" + $"{itemSpawnerID.SubCategory}/" + itemSpawnerID.ItemID);
					itemSpawnerEntry2.DisplayName = itemSpawnerID.DisplayName;
					itemSpawnerEntry2.MainObjectID = itemSpawnerID.ItemID;
					itemSpawnerEntry2.EntryIcon = itemSpawnerID.Sprite;
					SpawnerTilesDatabase.TryRegister(itemSpawnerEntry2);
				}
			}
			else
			{
				RegisteredItemSpawnerIDsDatabase.RegisteredHiddenIDs.Add(itemSpawnerID.ItemID);
			}
		}

		private static void EnsureMainObjectIsNotNull(TL oldTL, ItemSpawnerID spawnerId)
		{
			TL tL = oldTL.New("EnsureMainObjectIsNotNull");
			if (!((Object)(object)spawnerId.MainObject != (Object)null))
			{
				spawnerId.MainObject = spawnerId.Secondaries.Select((ItemSpawnerID obj) => obj.MainObject).FirstOrDefault((Func<FVRObject, bool>)((FVRObject obj) => (Object)(object)obj != (Object)null));
				if ((Object)(object)spawnerId.MainObject == (Object)null)
				{
					throw new NullReferenceException("ItemSpawnerID.MainObject is null, and there are no secondary objects to use as the main object");
				}
				spawnerId.ItemID = spawnerId.MainObject.ItemID;
				tL.Log("Assigned ItemID '" + spawnerId.ItemID + "' from secondary object");
			}
		}
	}
	internal static class ItemSpawnerIDTagger
	{
		public static void RegisterSpawnerIDIntoTagSystem(ItemSpawnerID spawnerID)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Invalid comparison between Unknown and I4
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Invalid comparison between Unknown and I4
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Invalid comparison between Unknown and I4
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			TL tL = new TL("RegisterSpawnerIDIntoTagSystem", LogTag.ItemSpawnerTagging);
			tL.Log("Attempting to tag '" + spawnerID.ItemID + "'");
			PageMode spawnerPageForSpawnerId = GetSpawnerPageForSpawnerId(spawnerID);
			tL.Log($"Assigning item to spawner page '{spawnerPageForSpawnerId}'");
			RegisterModTags(spawnerID, spawnerPageForSpawnerId);
			RegisterCategoryTags(spawnerID, spawnerPageForSpawnerId);
			if ((int)spawnerPageForSpawnerId == 1)
			{
				RegisterFirearmIntoMetaTagSystem(spawnerID, spawnerPageForSpawnerId);
			}
			else if ((int)spawnerPageForSpawnerId == 3)
			{
				RegisterAttachmentIntoMetaTagSystem(spawnerID, spawnerPageForSpawnerId);
			}
			else if ((int)spawnerPageForSpawnerId == 2)
			{
				RegisterAmmoIntoMetaTagSystem(spawnerID, spawnerPageForSpawnerId);
			}
		}

		private static PageMode GetSpawnerPageForSpawnerId(ItemSpawnerID spawnerId)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Invalid comparison between Unknown and I4
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Invalid comparison between Unknown and I4
			//IL_0053: 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_0054: Unknown result type (might be due to invalid IL or missing references)
			if (ShouldItemBeTaggedAsToolsToys(spawnerId))
			{
				return (PageMode)5;
			}
			if (ShouldItemBeTaggedAsMelee(spawnerId))
			{
				return (PageMode)4;
			}
			if (ShouldItemBeTaggedAsAmmo(spawnerId))
			{
				return (PageMode)2;
			}
			if ((int)ItemSubCategoryMapper.InferCategoryFrom(spawnerId.SubCategory).GetValueOrDefault() == 4)
			{
				return (PageMode)3;
			}
			if (spawnerId.IsFirearm())
			{
				return (PageMode)1;
			}
			if ((int)spawnerId.MainObject.Category == 5)
			{
				return (PageMode)3;
			}
			return (PageMode)1;
		}

		private static void RegisterCategoryTags(ItemSpawnerID spawnerId, PageMode page)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			IM.AddMetaTag(((object)(EItemCategory)(ref spawnerId.Category)).ToString(), (TagType)2, spawnerId.ItemID, page);
			if ((int)spawnerId.SubCategory != 0)
			{
				IM.AddMetaTag(((object)(ESubCategory)(ref spawnerId.SubCategory)).ToString(), (TagType)3, spawnerId.ItemID, page);
			}
		}

		private static void RegisterModTags(ItemSpawnerID spawnerId, PageMode page)
		{
			//IL_001d: 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)
			foreach (string modTag in spawnerId.ModTags)
			{
				IM.AddMetaTag(modTag, (TagType)50, spawnerId.ItemID, page);
			}
			IM.AddMetaTag("OtherLoader", (TagType)50, spawnerId.ItemID, page);
		}

		private static void RegisterFirearmIntoMetaTagSystem(ItemSpawnerID itemSpawnerID, PageMode page)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
			ItemSpawnerID itemSpawnerID2 = itemSpawnerID;
			FVRObject mainObject = itemSpawnerID2.MainObject;
			IM.AddMetaTag(((object)(OTagSet)(ref mainObject.TagSet)).ToString(), (TagType)4, itemSpawnerID2.ItemID, page);
			if ((int)mainObject.TagEra != 0)
			{
				IM.AddMetaTag(((object)(OTagEra)(ref mainObject.TagEra)).ToString(), (TagType)6, itemSpawnerID2.ItemID, page);
			}
			if ((int)mainObject.TagFirearmSize != 0)
			{
				IM.AddMetaTag(((object)(OTagFirearmSize)(ref mainObject.TagFirearmSize)).ToString(), (TagType)5, itemSpawnerID2.ItemID, page);
			}
			if ((int)mainObject.TagFirearmAction != 0)
			{
				IM.AddMetaTag(((object)(OTagFirearmAction)(ref mainObject.TagFirearmAction)).ToString(), (TagType)7, itemSpawnerID2.ItemID, page);
			}
			if ((int)mainObject.TagFirearmRoundPower != 0)
			{
				IM.AddMetaTag(((object)(OTagFirearmRoundPower)(ref mainObject.TagFirearmRoundPower)).ToString(), (TagType)8, itemSpawnerID2.ItemID, page);
			}
			if ((int)mainObject.TagFirearmCountryOfOrigin != 0)
			{
				IM.AddMetaTag(((object)(OTagFirearmCountryOfOrigin)(ref mainObject.TagFirearmCountryOfOrigin)).ToString(), (TagType)10, itemSpawnerID2.ItemID, page);
			}
			if (mainObject.TagFirearmFirstYear != 0)
			{
				IM.AddMetaTag(mainObject.TagFirearmFirstYear.ToString(), (TagType)11, itemSpawnerID2.ItemID, page);
			}
			if ((int)mainObject.MagazineType != 0)
			{
				IM.AddMetaTag(((object)(FireArmMagazineType)(ref mainObject.MagazineType)).ToString(), (TagType)14, itemSpawnerID2.ItemID, page);
			}
			if (mainObject.UsesRoundTypeFlag)
			{
				IM.AddMetaTag(((object)(FireArmRoundType)(ref mainObject.RoundType)).ToString(), (TagType)9, itemSpawnerID2.ItemID, page);
			}
			mainObject.TagFirearmFiringModes.ForEach(delegate(OTagFirearmFiringMode tag)
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				//IL_001e: Unknown result type (might be due to invalid IL or missing references)
				if ((int)tag != 0)
				{
					IM.AddMetaTag(((object)(OTagFirearmFiringMode)(ref tag)).ToString(), (TagType)12, itemSpawnerID2.ItemID, page);
				}
			});
			mainObject.TagFirearmFeedOption.ForEach(delegate(OTagFirearmFeedOption tag)
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				//IL_001e: Unknown result type (might be due to invalid IL or missing references)
				if ((int)tag != 0)
				{
					IM.AddMetaTag(((object)(OTagFirearmFeedOption)(ref tag)).ToString(), (TagType)13, itemSpawnerID2.ItemID, page);
				}
			});
			mainObject.TagFirearmMounts.ForEach(delegate(OTagFirearmMount tag)
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				//IL_001e: Unknown result type (might be due to invalid IL or missing references)
				if ((int)tag != 0)
				{
					IM.AddMetaTag(((object)(OTagFirearmMount)(ref tag)).ToString(), (TagType)15, itemSpawnerID2.ItemID, page);
				}
			});
		}

		private static void RegisterAttachmentIntoMetaTagSystem(ItemSpawnerID itemSpawnerID, PageMode page)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: 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)
			FVRObject mainObject = itemSpawnerID.MainObject;
			IM.AddMetaTag(((object)(OTagSet)(ref mainObject.TagSet)).ToString(), (TagType)4, itemSpawnerID.ItemID, page);
			if ((int)mainObject.TagEra != 0)
			{
				IM.AddMetaTag(((object)(OTagEra)(ref mainObject.TagEra)).ToString(), (TagType)6, itemSpawnerID.ItemID, page);
			}
			if ((int)mainObject.TagAttachmentFeature != 0)
			{
				IM.AddMetaTag(((object)(OTagAttachmentFeature)(ref mainObject.TagAttachmentFeature)).ToString(), (TagType)16, itemSpawnerID.ItemID, page);
			}
			if ((int)mainObject.TagAttachmentMount != 0)
			{
				IM.AddMetaTag(((object)(OTagFirearmMount)(ref mainObject.TagAttachmentMount)).ToString(), (TagType)15, itemSpawnerID.ItemID, page);
			}
		}

		private static void RegisterAmmoIntoMetaTagSystem(ItemSpawnerID itemSpawnerID, PageMode page)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			FVRObject mainObject = itemSpawnerID.MainObject;
			IM.AddMetaTag(((object)(OTagSet)(ref mainObject.TagSet)).ToString(), (TagType)4, itemSpawnerID.ItemID, page);
			if ((int)mainObject.TagEra != 0)
			{
				IM.AddMetaTag(((object)(OTagEra)(ref mainObject.TagEra)).ToString(), (TagType)6, itemSpawnerID.ItemID, page);
			}
			if ((int)mainObject.MagazineType != 0)
			{
				IM.AddMetaTag(((object)(FireArmMagazineType)(ref mainObject.MagazineType)).ToString(), (TagType)14, itemSpawnerID.ItemID, page);
			}
			if (mainObject.UsesRoundTypeFlag)
			{
				IM.AddMetaTag(((object)(FireArmRoundType)(ref mainObject.RoundType)).ToString(), (TagType)9, itemSpawnerID.ItemID, page);
			}
		}

		private static bool ShouldItemBeTaggedAsToolsToys(ItemSpawnerID spawnerId)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Invalid comparison between Unknown and I4
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Invalid comparison between Unknown and I4
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Invalid comparison between Unknown and I4
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Invalid comparison between Unknown and I4
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Invalid comparison between Unknown and I4
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Invalid comparison between Unknown and I4
			if ((int)spawnerId.MainObject.Category != 20 && (int)spawnerId.MainObject.Category != 7 && (int)spawnerId.SubCategory != 15 && (int)spawnerId.SubCategory != 61 && (int)spawnerId.Category != 6)
			{
				return (int)ItemSubCategoryMapper.InferCategoryFrom(spawnerId.SubCategory).GetValueOrDefault() == 6;
			}
			return true;
		}

		private static bool ShouldItemBeTaggedAsMelee(ItemSpawnerID spawnerId)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Invalid comparison between Unknown and I4
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Invalid comparison between Unknown and I4
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Invalid comparison between Unknown and I4
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Invalid comparison between Unknown and I4
			if ((int)spawnerId.MainObject.Category != 10 && (int)spawnerId.Category != 5 && (int)spawnerId.SubCategory != 46)
			{
				return (int)ItemSubCategoryMapper.InferCategoryFrom(spawnerId.SubCategory).GetValueOrDefault() == 5;
			}
			return true;
		}

		private static bool ShouldItemBeTaggedAsAmmo(ItemSpawnerID spawnerId)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Invalid comparison between Unknown and I4
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Invalid comparison between Unknown and I4
			EItemCategory category = spawnerId.Category;
			if (category - 7 <= 1 || category - 10 <= 1)
			{
				return true;
			}
			return false;
		}
	}
	internal static class RegisteredItemSpawnerIDsDatabase
	{
		public static readonly HashSet<string> RegisteredVisibleIDs = new HashSet<string>();

		public static readonly HashSet<string> RegisteredHiddenIDs = new HashSet<string>();

		public static readonly HashSet<string> RegisteredInCustomCategoryIDs = new HashSet<string>();
	}
	internal static class SpawnerEntryToSpawnerIDConverter
	{
		public static ItemSpawnerID Convert(TL oldTL, ItemSpawnerEntry entry)
		{
			TL newTL = oldTL.New("Convert");
			ItemSpawnerID val = ScriptableObject.CreateInstance<ItemSpawnerID>();
			AssignCategoriesForSpawnerID(newTL, val, entry);
			val.DisplayName = entry.DisplayName;
			val.IsDisplayedInMainEntry = entry.IsDisplayedInMainEntry;
			val.ItemID = entry.MainObjectID;
			val.ModTags = entry.ModTags;
			val.MainObject = entry.MainObjectObj;
			ItemSpawnerIDLinker.QueueEntryToLink(new EntryToLink(val, entry.SpawnWithIDs, entry.SecondaryObjectIDs));
			FVRObject val2 = ItemSpawnerIDLinker.ResolveObjectIDsToFVRObjects(entry.SpawnWithIDs).FirstOrDefault();
			if ((Object)(object)val2 != (Object)null)
			{
				val.SecondObject = val2;
			}
			val.Secondaries_ByStringID = ItemSpawnerIDLinker.ResolveObjectIDsToSpawnerIDs(entry.SecondaryObjectIDs).ToList();
			val.Secondaries = (ItemSpawnerID[])(object)new ItemSpawnerID[0];
			val.Sprite = entry.EntryIcon;
			val.UsesLargeSpawnPad = entry.UsesLargeSpawnPad;
			val.UsesHugeSpawnPad = entry.UsesHugeSpawnPad;
			val.IsReward = entry.IsReward;
			val.TutorialBlocks = entry.TutorialBlockIDs;
			return val;
		}

		private static void AssignCategoriesForSpawnerID(TL newTL, ItemSpawnerID itemSpawnerID, ItemSpawnerEntry entry)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0203: Unknown result type (might be due to invalid IL or missing references)
			//IL_020a: Unknown result type (might be due to invalid IL or missing references)
			//IL_021b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0230: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: 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_00a8: 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_00ce: 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_01a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: 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_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			PageMode? vanillaSpawnerPage = entry.GetVanillaSpawnerPage();
			EItemCategory? vanillaSpawnerCategory = entry.GetVanillaSpawnerCategory();
			ESubCategory? vanillaSpawnerSubCategory = entry.GetVanillaSpawnerSubCategory();
			if (vanillaSpawnerCategory.HasValue)
			{
				itemSpawnerID.Category = vanillaSpawnerCategory.Value;
				itemSpawnerID.SubCategory = (ESubCategory)0;
				newTL.Log("Updated item categories:" + $"\n- Category '{itemSpawnerID.Category}' read from EntryPath" + $"\n- SubCategory '{itemSpawnerID.SubCategory}'");
			}
			else if (vanillaSpawnerSubCategory.HasValue)
			{
				EItemCategory? val = ItemSubCategoryMapper.InferCategoryFrom(vanillaSpawnerSubCategory.Value);
				if (!val.HasValue)
				{
					itemSpawnerID.Category = (EItemCategory)0;
					itemSpawnerID.SubCategory = vanillaSpawnerSubCategory.Value;
					newTL.Log("Updated item categories:" + $"\n- Category '{itemSpawnerID.Category}' (failed to infer from SubCategory)" + $"\n- SubCategory '{itemSpawnerID.SubCategory}' read from EntryPath");
					return;
				}
				PageMode? val2 = ItemSubCategoryMapper.InferPageFrom(val.Value);
				if (val2.HasValue && vanillaSpawnerPage.HasValue && vanillaSpawnerPage != val2)
				{
					entry.IsUncategorized = true;
					itemSpawnerID.Category = (EItemCategory)621113382;
					itemSpawnerID.SubCategory = (ESubCategory)0;
					newTL.Log("Updated item categories:" + $"\n- Category '{621113382}' (Miscellaneous category)" + $"\n- SubCategory '{itemSpawnerID.SubCategory}'");
				}
				else
				{
					itemSpawnerID.Category = val.Value;
					itemSpawnerID.SubCategory = vanillaSpawnerSubCategory.Value;
					newTL.Log("Updated item categories:" + $"\n- Category '{itemSpawnerID.Category}' inferred from SubCategory" + $"\n- SubCategory '{itemSpawnerID.SubCategory}' read from EntryPath");
				}
			}
			else
			{
				itemSpawnerID.Category = (EItemCategory)CreateCustomEItemCategoryInt(newTL, entry);
				itemSpawnerID.SubCategory = (ESubCategory)0;
				newTL.Log("Updated item categories:" + $"\n- Category '{itemSpawnerID.Category}' (custom category)" + $"\n- SubCategory '{itemSpawnerID.SubCategory}'");
			}
		}

		private static int CreateCustomEItemCategoryInt(TL oldTL, ItemSpawnerEntry entry)
		{
			if (string.IsNullOrEmpty(entry.EntryPath))
			{
				return 0;
			}
			TL tL = oldTL.New("CreateCustomEItemCategoryInt");
			string[] array = entry.EntryPath.Split(new char[1] { '/' });
			IEnumerable<string> values;
			if (!entry.IsCategoryEntry())
			{
				values = array.Take(array.Length - 1);
			}
			else
			{
				IEnumerable<string> enumerable = array;
				values = enumerable;
			}
			string text = values.JoinToString("/");
			int num = Hasher.HashStringToInt(text);
			tL.Log($"Hashed '{text}' to custom EItemCategory integer: {num}");
			return num;
		}

		private static PageMode? GetVanillaSpawnerPage(this ItemSpawnerEntry entry)
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			string[] array = entry.EntryPath.Split(new char[1] { '/' });
			if (array.Length < 1)
			{
				return null;
			}
			string value = array[0];
			if (Enum.IsDefined(typeof(PageMode), value))
			{
				return (PageMode)Enum.Parse(typeof(PageMode), value);
			}
			return null;
		}

		private static EItemCategory? GetVanillaSpawnerCategory(this ItemSpawnerEntry entry)
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			string[] array = entry.EntryPath.Split(new char[1] { '/' });
			if (array.Length < 2)
			{
				return null;
			}
			string value = array[1];
			if (Enum.IsDefined(typeof(EItemCategory), value))
			{
				return (EItemCategory)Enum.Parse(typeof(EItemCategory), value);
			}
			return null;
		}

		private static ESubCategory? GetVanillaSpawnerSubCategory(this ItemSpawnerEntry entry)
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			string[] array = entry.EntryPath.Split(new char[1] { '/' });
			if (array.Length < 2)
			{
				return null;
			}
			string value = array[1];
			if (Enum.IsDefined(typeof(ESubCategory), value))
			{
				return (ESubCategory)Enum.Parse(typeof(ESubCategory), value);
			}
			return null;
		}
	}
}
namespace OtherLoader.ItemSpawner.VanillaCategories
{
	internal enum ItemSpawnerSortGrouping
	{
		ShowModdedItemsFirst,
		ShowModdedItemsLast,
		NoGrouping
	}
	internal enum ItemSpawnerSortOrder
	{
		Vanilla,
		AlphabeticalByDisplayName
	}
	internal static class ItemSpawnerV2DisplayItemsPatcher
	{
		[HarmonyTranspiler]
		[HarmonyPatch(typeof(ItemSpawnerV2), "RedrawSimpleCanvas")]
		private static IEnumerable<CodeInstruction> RedrawSimpleCanvas_Transpiler_ApplyCustomSorting(IEnumerable<CodeInstruction> instructions)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			List<CodeInstruction> list = instructions.ToList();
			try
			{
				return new CodeMatcher((IEnumerable<CodeInstruction>)list, (ILGenerator)null).SearchForward((Func<CodeInstruction, bool>)((CodeInstruction code) => code.opcode == OpCodes.Callvirt && code.operand == AccessTools.Method(typeof(List<string>), "Sort", (Type[])null, (Type[])null))).SetAndAdvance(OpCodes.Call, (object)AccessTools.Method(typeof(SpawnerIDSorter), "FilterAndSortItemsSimpleMode", (Type[])null, (Type[])null)).InstructionEnumeration();
			}
			catch (Exception arg)
			{
				OtherLogger.LogError($"Exception in RedrawSimpleCanvas transpiler: {arg}");
				return list;
			}
		}

		[HarmonyTranspiler]
		[HarmonyPatch(typeof(ItemSpawnerV2), "RedrawListCanvas")]
		private static IEnumerable<CodeInstruction> RedrawListCanvas_Transpiler_ApplyCustomSorting(IEnumerable<CodeInstruction> instructions)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			List<CodeInstruction> list = instructions.ToList();
			try
			{
				return new CodeMatcher((IEnumerable<CodeInstruction>)list, (ILGenerator)null).SearchForward((Func<CodeInstruction, bool>)((CodeInstruction code) => code.opcode == OpCodes.Callvirt && code.operand == AccessTools.Method(typeof(List<string>), "Sort", (Type[])null, (Type[])null))).SetAndAdvance(OpCodes.Call, (object)AccessTools.Method(typeof(SpawnerIDSorter), "FilterAndSortItemsTagMode", (Type[])null, (Type[])null)).InstructionEnumeration();
			}
			catch (Exception arg)
			{
				OtherLogger.LogError($"Exception in RedrawListCanvas transpiler: {arg}");
				return list;
			}
		}
	}
	internal static class SpawnerIDSorter
	{
		public static void FilterAndSortItemsSimpleMode(List<string> workingItemSpawnerIDs)
		{
			FilterAndSortItems(workingItemSpawnerIDs, includeHiddenIDs: false);
		}

		public static void FilterAndSortItemsTagMode(List<string> workingItemSpawnerIDs)
		{
			FilterAndSortItems(workingItemSpawnerIDs, includeHiddenIDs: true);
		}

		private static void FilterAndSortItems(List<string> workingItemSpawnerIDs, bool includeHiddenIDs)
		{
			List<string> list = workingItemSpawnerIDs.ToList();
			workingItemSpawnerIDs.Clear();
			List<string> list2 = new List<string>();
			List<string> list3 = new List<string>();
			foreach (string item in list)
			{
				if (RegisteredItemSpawnerIDsDatabase.RegisteredInCustomCategoryIDs.Contains(item))
				{
					if (includeHiddenIDs)
					{
						list3.Add(item);
					}
				}
				else if (RegisteredItemSpawnerIDsDatabase.RegisteredVisibleIDs.Contains(item))
				{
					list3.Add(item);
				}
				else if (RegisteredItemSpawnerIDsDatabase.RegisteredHiddenIDs.Contains(item))
				{
					if (includeHiddenIDs)
					{
						list3.Add(item);
					}
				}
				else
				{
					list2.Add(item);
				}
			}
			OtherLogger.Log($"Sorting tiles: {list2.Count} vanilla, {list3.Count} modded. " + $"Showing hidden: {includeHiddenIDs}", LogTag.ItemSpawnerPatches);
			switch (PluginConfig.ItemSpawnerSortGrouping.Value)
			{
			default:
				SortListCustom(list2);
				SortListCustom(list3);
				workingItemSpawnerIDs.AddRange(list3);
				workingItemSpawnerIDs.AddRange(list2);
				break;
			case ItemSpawnerSortGrouping.ShowModdedItemsLast:
				SortListCustom(list2);
				SortListCustom(list3);
				workingItemSpawnerIDs.AddRange(list2);
				workingItemSpawnerIDs.AddRange(list3);
				break;
			case ItemSpawnerSortGrouping.NoGrouping:
				workingItemSpawnerIDs.AddRange(list2);
				workingItemSpawnerIDs.AddRange(list3);
				SortListCustom(workingItemSpawnerIDs);
				break;
			}
		}

		private static void SortListCustom(List<string> list)
		{
			ItemSpawnerSortOrder value = PluginConfig.ItemSpawnerSortOrder.Value;
			if (value == ItemSpawnerSortOrder.Vanilla || value != ItemSpawnerSortOrder.AlphabeticalByDisplayN