Decompiled source of CustomRunEx v0.2.2

plugins/com.github.LengSword.CustomRunEx.dll

Decompiled 2 days ago
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using ExitGames.Client.Photon;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Peak;
using Photon.Pun;
using Photon.Realtime;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;
using Zorro.Core;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("com.github.LengSword.CustomRunEx")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.2.2.0")]
[assembly: AssemblyInformationalVersion("0.2.2+de3540a9b0ef78397db67dd1835576708df6aa1b")]
[assembly: AssemblyProduct("com.github.LengSword.CustomRunEx")]
[assembly: AssemblyTitle("CustomRunEx")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://codeberg.org/yls-peak-mods/CustomRunEx")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.2.2.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class 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]
	[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]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace BepInEx
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	[Embedded]
	internal sealed class BepInAutoPluginAttribute : Attribute
	{
		public BepInAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
		{
		}
	}
}
namespace BepInEx.Preloader.Core.Patching
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	[Embedded]
	internal sealed class PatcherAutoPluginAttribute : Attribute
	{
		public PatcherAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
		{
		}
	}
}
namespace Microsoft.CodeAnalysis
{
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace CustomRunEx
{
	internal static class AscentPresetHandler
	{
		internal static bool CanUsePreservedAscent(BoardingPass boardingPass)
		{
			if ((Object)(object)boardingPass != (Object)null && CustomSettingsHandler.ShouldUseSelectedAscentInCustomRun && PhotonNetwork.IsMasterClient && (Object)(object)Character.localCharacter != (Object)null && Character.localCharacter.inAirport && RunSettings.IsCustomRun)
			{
				int ascentIndex = boardingPass.ascentIndex;
				if (ascentIndex >= -1)
				{
					return ascentIndex <= 8;
				}
				return false;
			}
			return false;
		}

		internal static void ApplySelectedPreset(BoardingPass boardingPass)
		{
			if (!((Object)(object)boardingPass == (Object)null) && CanUsePreservedAscent(boardingPass))
			{
				int ascentIndex = boardingPass.ascentIndex;
				bool flag = ascentIndex == -1;
				RunSettings.SetValue((SETTINGTYPE)100, (!flag) ? 1 : 0);
				RunSettings.SetValue((SETTINGTYPE)1400, (!flag) ? 1 : 0);
				RunSettings.SetValue((SETTINGTYPE)2700, (!flag) ? 1 : 0);
				RunSettings.SetValue((SETTINGTYPE)200, flag ? 1 : ((ascentIndex >= 2) ? 3 : 2));
				RunSettings.SetValue((SETTINGTYPE)300, (ascentIndex >= 1) ? 3 : 2);
				RunSettings.SetValue((SETTINGTYPE)600, (ascentIndex < 3) ? 1 : 2);
				RunSettings.SetValue((SETTINGTYPE)700, (ascentIndex < 4) ? 1 : 0);
				RunSettings.SetValue((SETTINGTYPE)500, (ascentIndex >= 5) ? 1 : 0);
				RunSettings.SetValue((SETTINGTYPE)800, flag ? 1 : ((ascentIndex >= 6) ? 3 : 2));
			}
		}
	}
	internal static class CustomSettingsHandler
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static UnityAction <0>__NextItemPage;
		}

		private static CustomOptionsWindow cachedCustomOptionsWindow = null;

		private static Button nextPageButton = null;

		private static TextMeshProUGUI nextPageButtonText = null;

		private static List<Item> sessionModifiableItems = new List<Item>();

		private static int currentModifiableItemPage;

		private const int ItemsPerPage = 32;

		private static bool sessionShowHiddenSettings;

		private static bool sessionShowMoreNatureItems;

		private static bool sessionUseSelectedAscentInCustomRun;

		private static bool sessionAllowProgressionInCustomRun;

		internal static bool IsWindowSessionActive { get; private set; }

		internal static bool IsSessionEnabled { get; private set; }

		internal static bool ShouldUseSelectedAscentInCustomRun
		{
			get
			{
				if (IsSessionEnabled)
				{
					return sessionUseSelectedAscentInCustomRun;
				}
				return false;
			}
		}

		internal static bool ShouldAllowProgressionInCustomRun
		{
			get
			{
				if (IsSessionEnabled && sessionAllowProgressionInCustomRun)
				{
					return RunSettings.IsCustomRun;
				}
				return false;
			}
		}

		internal static void InitializeRuntimeConfigSnapshot()
		{
			IsSessionEnabled = PluginConfig.Enable.Value;
			sessionUseSelectedAscentInCustomRun = PluginConfig.UseSelectedAscentInCustomRun.Value;
			sessionAllowProgressionInCustomRun = PluginConfig.AllowProgressionInCustomRun.Value;
		}

		public static void InitializeCache(CustomOptionsWindow window)
		{
			if (!((Object)(object)window == (Object)null))
			{
				if ((Object)(object)cachedCustomOptionsWindow != (Object)(object)window)
				{
					nextPageButton = null;
					nextPageButtonText = null;
				}
				cachedCustomOptionsWindow = window;
				EnsureNextPageButton();
			}
		}

		public static void BeginWindowSession(bool isMasterClient)
		{
			if (Object.op_Implicit((Object)(object)cachedCustomOptionsWindow))
			{
				bool shouldUseSelectedAscentInCustomRun = ShouldUseSelectedAscentInCustomRun;
				IsWindowSessionActive = true;
				IsSessionEnabled = PluginConfig.Enable.Value;
				sessionShowHiddenSettings = PluginConfig.ShowHiddenSettings.Value;
				sessionShowMoreNatureItems = PluginConfig.ShowMoreNatureItems.Value;
				sessionUseSelectedAscentInCustomRun = PluginConfig.UseSelectedAscentInCustomRun.Value;
				sessionAllowProgressionInCustomRun = PluginConfig.AllowProgressionInCustomRun.Value;
				currentModifiableItemPage = 0;
				if (!shouldUseSelectedAscentInCustomRun && ShouldUseSelectedAscentInCustomRun && isMasterClient && RunSettings.IsCustomRun && (Object)(object)Character.localCharacter != (Object)null && Character.localCharacter.inAirport)
				{
					AscentPresetHandler.ApplySelectedPreset(cachedCustomOptionsWindow.boardingPass);
				}
				ApplyHiddenSettings();
				BuildSessionItemList();
				SpawnCurrentItemPage();
				RefreshControlValues();
				SetControlsInteractable(!IsSessionEnabled || isMasterClient);
			}
		}

		public static void EndWindowSession()
		{
			IsWindowSessionActive = false;
		}

		private static void ApplyHiddenSettings()
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)cachedCustomOptionsWindow))
			{
				return;
			}
			bool flag = IsSessionEnabled && sessionShowHiddenSettings;
			CustomOptionToggle[] componentsInChildren = ((Component)cachedCustomOptionsWindow).GetComponentsInChildren<CustomOptionToggle>(true);
			foreach (CustomOptionToggle val in componentsInChildren)
			{
				if (PluginConfig.DisabledSettings.Contains(val.settingType) && ((Component)val).gameObject.activeSelf != flag)
				{
					((Component)val).gameObject.SetActive(flag);
				}
			}
		}

		public static void SetControlsInteractable(bool interactable)
		{
			if (Object.op_Implicit((Object)(object)cachedCustomOptionsWindow))
			{
				CustomOptionToggle[] componentsInChildren = ((Component)cachedCustomOptionsWindow).GetComponentsInChildren<CustomOptionToggle>(true);
				foreach (CustomOptionToggle val in componentsInChildren)
				{
					((Selectable)val.toggle).interactable = interactable;
				}
				CustomOptionItemToggle[] componentsInChildren2 = ((Component)cachedCustomOptionsWindow).GetComponentsInChildren<CustomOptionItemToggle>(true);
				foreach (CustomOptionItemToggle val2 in componentsInChildren2)
				{
					((Selectable)val2.toggle).interactable = interactable;
				}
				CustomOptionMulti[] componentsInChildren3 = ((Component)cachedCustomOptionsWindow).GetComponentsInChildren<CustomOptionMulti>(true);
				foreach (CustomOptionMulti val3 in componentsInChildren3)
				{
					((Selectable)val3.button).interactable = interactable;
				}
				((Selectable)cachedCustomOptionsWindow.restoreDefaultsButton).interactable = interactable;
			}
		}

		private static void BuildSessionItemList()
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			sessionModifiableItems = new List<Item>();
			HashSet<Item> hashSet = new HashSet<Item>();
			foreach (Item modifiableItemPrefab in RunSettings.ModifiableItemPrefabs)
			{
				if (Object.op_Implicit((Object)(object)modifiableItemPrefab) && !((Enum)modifiableItemPrefab.itemTags).HasFlag((Enum)(object)(ItemTags)1) && hashSet.Add(modifiableItemPrefab))
				{
					sessionModifiableItems.Add(modifiableItemPrefab);
				}
			}
			if (!IsSessionEnabled || !sessionShowMoreNatureItems)
			{
				return;
			}
			LootData lootData = default(LootData);
			foreach (Item value in SingletonAsset<ItemDatabase>.Instance.itemLookup.Values)
			{
				if (Object.op_Implicit((Object)(object)value) && !hashSet.Contains(value) && !((Enum)value.itemTags).HasFlag((Enum)(object)(ItemTags)1) && ((Component)value).TryGetComponent<LootData>(ref lootData) && !lootData.excludeFromCustomRunSelection && PluginConfig.NaturePools.Any((SpawnPool spawnPool) => ((Enum)lootData.spawnLocations).HasFlag((Enum)(object)spawnPool)))
				{
					hashSet.Add(value);
					sessionModifiableItems.Add(value);
				}
			}
		}

		private static void SpawnCurrentItemPage()
		{
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Expected O, but got Unknown
			if (!Object.op_Implicit((Object)(object)cachedCustomOptionsWindow))
			{
				return;
			}
			int totalPages = GetTotalPages();
			currentModifiableItemPage = Mathf.Clamp(currentModifiableItemPage, 0, totalPages - 1);
			List<Item> list = sessionModifiableItems.Skip(currentModifiableItemPage * 32).Take(32).ToList();
			foreach (Transform spawnPool in cachedCustomOptionsWindow.spawnPoolList)
			{
				Transform val = spawnPool;
				((Component)val).gameObject.SetActive(false);
				Object.Destroy((Object)(object)((Component)val).gameObject);
			}
			foreach (Item item in list)
			{
				Object.Instantiate<CustomOptionItemToggle>(cachedCustomOptionsWindow.customOptionItemTogglePrefab, cachedCustomOptionsWindow.spawnPoolList).Init(item);
			}
			bool active = IsSessionEnabled && sessionShowMoreNatureItems && totalPages > 1;
			if (Object.op_Implicit((Object)(object)nextPageButton))
			{
				((Component)nextPageButton).gameObject.SetActive(active);
			}
			UpdateNextPageButtonText(totalPages);
		}

		public static void NextItemPage()
		{
			int totalPages = GetTotalPages();
			if (totalPages > 1)
			{
				currentModifiableItemPage = (currentModifiableItemPage + 1) % totalPages;
				SpawnCurrentItemPage();
				SetControlsInteractable(!IsSessionEnabled || PhotonNetwork.IsMasterClient);
			}
		}

		public static void RefreshControlValues()
		{
			if (Object.op_Implicit((Object)(object)cachedCustomOptionsWindow) && IsWindowSessionActive)
			{
				CustomOptionToggle[] componentsInChildren = ((Component)cachedCustomOptionsWindow).GetComponentsInChildren<CustomOptionToggle>(true);
				foreach (CustomOptionToggle val in componentsInChildren)
				{
					((CustomOptionBase)val).RestoreDefault();
				}
				CustomOptionItemToggle[] componentsInChildren2 = ((Component)cachedCustomOptionsWindow).GetComponentsInChildren<CustomOptionItemToggle>(true);
				foreach (CustomOptionItemToggle val2 in componentsInChildren2)
				{
					val2.Refresh();
				}
				CustomOptionMulti[] componentsInChildren3 = ((Component)cachedCustomOptionsWindow).GetComponentsInChildren<CustomOptionMulti>(true);
				foreach (CustomOptionMulti val3 in componentsInChildren3)
				{
					((CustomOptionBase)val3).RestoreDefault();
				}
				cachedCustomOptionsWindow.miniRunOptions.SetActive(RunSettings.GetValue((SETTINGTYPE)10000, true) != RunSettings.GetDefaultValue((SETTINGTYPE)10000));
				if (IsSessionEnabled)
				{
					SetControlsInteractable(PhotonNetwork.IsMasterClient);
				}
			}
		}

		internal static bool ShouldHandlePhotonCallbacks()
		{
			return IsSessionEnabled;
		}

		internal static bool ShouldFilterItemSpawns()
		{
			if (IsSessionEnabled)
			{
				return RunSettings.IsCustomRun;
			}
			return false;
		}

		private static int GetTotalPages()
		{
			return Mathf.Max(1, Mathf.CeilToInt((float)sessionModifiableItems.Count / 32f));
		}

		private static void EnsureNextPageButton()
		{
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Expected O, but got Unknown
			if (!Object.op_Implicit((Object)(object)nextPageButton) && Object.op_Implicit((Object)(object)cachedCustomOptionsWindow) && Object.op_Implicit((Object)(object)cachedCustomOptionsWindow.restoreDefaultsButton))
			{
				GameObject val = Object.Instantiate<GameObject>(((Component)cachedCustomOptionsWindow.restoreDefaultsButton).gameObject, ((Component)cachedCustomOptionsWindow.restoreDefaultsButton).transform.parent, false);
				((Object)val).name = "Button_NextItemPage";
				RectTransform component = val.GetComponent<RectTransform>();
				component.sizeDelta = new Vector2(170f, 45f);
				component.anchoredPosition = new Vector2(-64f, -135f);
				LocalizedText componentInChildren = val.GetComponentInChildren<LocalizedText>();
				if (Object.op_Implicit((Object)(object)componentInChildren))
				{
					((Behaviour)componentInChildren).enabled = false;
					Object.Destroy((Object)(object)componentInChildren);
				}
				nextPageButtonText = val.GetComponentInChildren<TextMeshProUGUI>();
				nextPageButton = val.GetComponent<Button>();
				((UnityEventBase)nextPageButton.onClick).RemoveAllListeners();
				ButtonClickedEvent onClick = nextPageButton.onClick;
				object obj = <>O.<0>__NextItemPage;
				if (obj == null)
				{
					UnityAction val2 = NextItemPage;
					<>O.<0>__NextItemPage = val2;
					obj = (object)val2;
				}
				((UnityEvent)onClick).AddListener((UnityAction)obj);
				val.SetActive(false);
			}
		}

		private static void UpdateNextPageButtonText(int totalPages)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Invalid comparison between Unknown and I4
			if (Object.op_Implicit((Object)(object)nextPageButtonText))
			{
				int num = currentModifiableItemPage + 1;
				((TMP_Text)nextPageButtonText).text = (((int)LocalizedText.CURRENT_LANGUAGE == 9) ? $"下一页({num}/{totalPages})" : $"Next Page ({num}/{totalPages})");
			}
		}
	}
	internal sealed class PhotonMasterClientCallbacks : IInRoomCallbacks
	{
		public void OnPlayerEnteredRoom(Player newPlayer)
		{
		}

		public void OnPlayerLeftRoom(Player otherPlayer)
		{
		}

		public void OnPlayerPropertiesUpdate(Player targetPlayer, Hashtable changedProps)
		{
		}

		public void OnRoomPropertiesUpdate(Hashtable propertiesThatChanged)
		{
		}

		public void OnMasterClientSwitched(Player newMasterClient)
		{
			if (CustomSettingsHandler.ShouldHandlePhotonCallbacks())
			{
				if (CustomSettingsHandler.IsWindowSessionActive)
				{
					CustomSettingsHandler.SetControlsInteractable(PhotonNetwork.IsMasterClient);
				}
				Character localCharacter = Character.localCharacter;
				if (PhotonNetwork.IsMasterClient && (Object)(object)localCharacter != (Object)null && !localCharacter.inAirport)
				{
					RunSettings.PushRunSettings((Player)null);
				}
			}
		}
	}
	[BepInPlugin("com.github.LengSword.CustomRunEx", "CustomRunEx", "0.2.2")]
	public class Plugin : BaseUnityPlugin
	{
		internal static bool isCustomToggleActive;

		private PhotonMasterClientCallbacks? photonCallbacks;

		public const string Id = "com.github.LengSword.CustomRunEx";

		internal static ManualLogSource Logger { get; private set; }

		public static string Name => "CustomRunEx";

		public static string Version => "0.2.2";

		private void Awake()
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Expected O, but got Unknown
			Logger = ((BaseUnityPlugin)this).Logger;
			Logger.LogInfo((object)("Plugin " + Name + " is loaded!"));
			PluginConfig.Initialize(((BaseUnityPlugin)this).Config, ((BaseUnityPlugin)this).Logger);
			CustomSettingsHandler.InitializeRuntimeConfigSnapshot();
			Harmony val = new Harmony("com.github.LengSword.CustomRunEx");
			val.PatchAll();
			photonCallbacks = new PhotonMasterClientCallbacks();
			PhotonNetwork.AddCallbackTarget((object)photonCallbacks);
			GlobalEvents.OnRunSettingsUpdated = (Action)Delegate.Combine(GlobalEvents.OnRunSettingsUpdated, new Action(OnRunSettingsUpdated));
		}

		private void OnDestroy()
		{
			GlobalEvents.OnRunSettingsUpdated = (Action)Delegate.Remove(GlobalEvents.OnRunSettingsUpdated, new Action(OnRunSettingsUpdated));
			if (photonCallbacks != null)
			{
				PhotonNetwork.RemoveCallbackTarget((object)photonCallbacks);
				photonCallbacks = null;
			}
		}

		private void Update()
		{
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			GUIManager instance = GUIManager.instance;
			if ((Object)(object)instance == (Object)null)
			{
				return;
			}
			BoardingPass boardingPass = instance.boardingPass;
			if ((Object)(object)boardingPass == (Object)null)
			{
				Logger.LogWarning((object)"BoardingPass is null. Cannot toggle Custom Run Window.");
				return;
			}
			CustomOptionsWindow customOptionsWindow = boardingPass.customOptionsWindow;
			if ((Object)(object)customOptionsWindow == (Object)null)
			{
				Logger.LogWarning((object)"CustomOptionsWindow is null. Cannot toggle Custom Run Window.");
				return;
			}
			Character localCharacter = Character.localCharacter;
			if ((Object)(object)localCharacter == (Object)null || (!localCharacter.inAirport && !RunSettings.IsCustomRun))
			{
				return;
			}
			if (CustomSettingsHandler.IsSessionEnabled && Input.GetKeyDown(PluginConfig.ShowCustomRunWindowKey.Value))
			{
				if (((MenuWindow)customOptionsWindow).isOpen)
				{
					((MenuWindow)customOptionsWindow).Close();
				}
				else
				{
					boardingPass.OpenCustom();
				}
			}
			if (((MenuWindow)customOptionsWindow).isOpen && !isCustomToggleActive)
			{
				isCustomToggleActive = true;
				CustomSettingsHandler.BeginWindowSession(PhotonNetwork.IsMasterClient);
			}
			else if (!((MenuWindow)customOptionsWindow).isOpen && isCustomToggleActive)
			{
				isCustomToggleActive = false;
				if (CustomSettingsHandler.IsSessionEnabled && PhotonNetwork.IsMasterClient && !localCharacter.inAirport)
				{
					RunSettings.PushRunSettings((Player)null);
				}
				CustomSettingsHandler.EndWindowSession();
			}
		}

		private static void OnRunSettingsUpdated()
		{
			CustomSettingsHandler.RefreshControlValues();
		}
	}
	public static class PluginConfig
	{
		internal static List<SETTINGTYPE> DisabledSettings = new List<SETTINGTYPE>(1) { (SETTINGTYPE)30000 };

		internal static readonly SpawnPool[] NaturePools;

		internal static ConfigEntry<bool> Enable { get; private set; } = null;

		internal static ConfigEntry<bool> ShowHiddenSettings { get; private set; } = null;

		internal static ConfigEntry<bool> ShowMoreNatureItems { get; private set; } = null;

		internal static ConfigEntry<bool> UseSelectedAscentInCustomRun { get; private set; } = null;

		internal static ConfigEntry<bool> AllowProgressionInCustomRun { get; private set; } = null;

		internal static ConfigEntry<KeyCode> ShowCustomRunWindowKey { get; private set; } = null;

		public static void Initialize(ConfigFile config, ManualLogSource logger)
		{
			Enable = config.Bind<bool>("General", "Enable", true, "Enable or disable the CustomRunEx plugin");
			ShowHiddenSettings = config.Bind<bool>("RunOptions", "ShowHiddenSettings", false, "Show settings that are hidden in the original Custom Run window");
			ShowMoreNatureItems = config.Bind<bool>("RunOptions", "ShowMoreNatureItems", false, "Show items from natural spawn pools in the Custom Run window");
			UseSelectedAscentInCustomRun = config.Bind<bool>("RunOptions", "UseSelectedAscentInCustomRun", false, "Use the selected Tenderfoot or ascent as the Custom Run starting preset and keep its level when the host starts. Settings remain editable.");
			AllowProgressionInCustomRun = config.Bind<bool>("RunOptions", "AllowProgressionInCustomRun", false, "Allow the local player to earn achievements, accumulate statistics, and unlock ascent levels in Custom Runs.");
			ShowCustomRunWindowKey = config.Bind<KeyCode>("Keybinds", "Show Custom Run Window Key", (KeyCode)293, "Key to show the Custom Run Window");
			logger.LogInfo((object)"Plugin Config Loaded.");
		}

		static PluginConfig()
		{
			SpawnPool[] array = new SpawnPool[11];
			RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/);
			NaturePools = (SpawnPool[])(object)array;
		}
	}
}
namespace CustomRunEx.Patches
{
	[HarmonyWrapSafe]
	[HarmonyPatch]
	internal static class AchievementManagerPatches
	{
		[HarmonyTargetMethods]
		private static IEnumerable<MethodBase> TargetMethods()
		{
			yield return AccessTools.Method(typeof(AchievementManager), "ThrowAchievement", (Type[])null, (Type[])null);
			yield return AccessTools.Method(typeof(AchievementManager), "TryCompleteAscent", (Type[])null, (Type[])null);
			yield return AccessTools.Method(typeof(AchievementManager), "SetSteamStatInternal", (Type[])null, (Type[])null);
			yield return AccessTools.Method(typeof(AchievementManager), "IncrementSteamStat", (Type[])null, (Type[])null);
		}

		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> BlockingTranspiler(IEnumerable<CodeInstruction> instructions)
		{
			MethodInfo blockingGetter = AccessTools.PropertyGetter(typeof(RunSettings), "blockingAchievements");
			MethodInfo filter = AccessTools.Method(typeof(AchievementManagerPatches), "ShouldBlockProgression", (Type[])null, (Type[])null);
			foreach (CodeInstruction instruction in instructions)
			{
				yield return instruction;
				if (CodeInstructionExtensions.Calls(instruction, blockingGetter))
				{
					yield return new CodeInstruction(OpCodes.Call, (object)filter);
				}
			}
		}

		private static bool ShouldBlockProgression(bool originallyBlocked)
		{
			if (originallyBlocked)
			{
				return !CustomSettingsHandler.ShouldAllowProgressionInCustomRun;
			}
			return false;
		}
	}
	[HarmonyWrapSafe]
	internal static class BoardingPassPatches
	{
		[HarmonyPatch(typeof(BoardingPass), "ToggleCustom")]
		[HarmonyPrefix]
		private static void ToggleCustomPrefix(out bool __state)
		{
			__state = RunSettings.IsCustomRun;
		}

		[HarmonyPatch(typeof(BoardingPass), "ToggleCustom")]
		[HarmonyPostfix]
		private static void ToggleCustomPostfix(BoardingPass __instance, bool __state)
		{
			if (!__state && RunSettings.IsCustomRun)
			{
				AscentPresetHandler.ApplySelectedPreset(__instance);
			}
		}

		[HarmonyPatch(typeof(BoardingPass), "IncrementAscent")]
		[HarmonyPostfix]
		private static void IncrementAscentPostfix(BoardingPass __instance)
		{
			AscentPresetHandler.ApplySelectedPreset(__instance);
		}

		[HarmonyPatch(typeof(BoardingPass), "DecrementAscent")]
		[HarmonyPostfix]
		private static void DecrementAscentPostfix(BoardingPass __instance)
		{
			AscentPresetHandler.ApplySelectedPreset(__instance);
		}

		[HarmonyPatch(typeof(BoardingPass), "UpdateAscent")]
		[HarmonyPostfix]
		private static void UpdateAscentPostfix(BoardingPass __instance)
		{
			if (AscentPresetHandler.CanUsePreservedAscent(__instance))
			{
				int num = Mathf.Min(8, Singleton<AchievementManager>.Instance.GetMaxAscent());
				((Selectable)__instance.incrementAscentButton).interactable = __instance.ascentIndex < num;
				((Selectable)__instance.decrementAscentButton).interactable = __instance.ascentIndex > -1;
				__instance.ascentTitle.text = __instance.ascentData.ascents[0].localizedTitle + " · " + __instance.ascentData.ascents[__instance.ascentIndex + 2].localizedTitle;
			}
		}

		[HarmonyPatch(typeof(BoardingPass), "StartGame")]
		[HarmonyPrefix]
		private static bool StartGamePrefix(BoardingPass __instance)
		{
			if (!AscentPresetHandler.CanUsePreservedAscent(__instance))
			{
				return true;
			}
			__instance.kiosk.StartGame(__instance.ascentIndex);
			return false;
		}
	}
	[HarmonyWrapSafe]
	internal sealed class CustomOptionsWindowPatches
	{
		[HarmonyPatch(typeof(CustomOptionsWindow), "OpenBoardingPass")]
		[HarmonyPrefix]
		private static bool CustomOptionsWindowOpenBoardingPassPatch()
		{
			if (!CustomSettingsHandler.IsSessionEnabled || !Plugin.isCustomToggleActive)
			{
				return true;
			}
			return false;
		}

		[HarmonyPatch(typeof(CustomOptionsWindow), "Initialize")]
		[HarmonyPostfix]
		private static void CustomOptionsWindowInitializePatch(CustomOptionsWindow __instance)
		{
			CustomSettingsHandler.InitializeCache(__instance);
		}

		[HarmonyPatch(typeof(CustomOptionItemToggle), "Init")]
		[HarmonyPostfix]
		private static void CustomOptionItemToggleInitPatch(CustomOptionItemToggle __instance)
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Invalid comparison between Unknown and I4
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Invalid comparison between Unknown and I4
			Item item = __instance.item;
			string text;
			switch (((Object)((Component)item).gameObject).name)
			{
			case "Mushroom Cluster Poison":
			case "Mushroom Lace Poison":
			case "Mushroom Normie Poison":
				text = (((int)LocalizedText.CURRENT_LANGUAGE == 9) ? "(有毒)" : " (Poisoned)");
				break;
			case "Mandrake_Hidden":
				text = (((int)LocalizedText.CURRENT_LANGUAGE == 9) ? "(曼德拉草)" : " (Mandrake)");
				break;
			default:
				text = string.Empty;
				break;
			}
			string text2 = text;
			if (text2.Length != 0)
			{
				__instance.text.autoSet = false;
				__instance.text.SetText(item.GetName() + text2);
				__instance.Refresh();
			}
		}
	}
	[HarmonyWrapSafe]
	internal sealed class NatureItemSpawnPatches
	{
		[HarmonyPatch(typeof(LootData), "GetRandomItem")]
		[HarmonyPrefix]
		private static bool LootDataGetRandomItemPatch(SpawnPool spawnPool, ref GameObject __result)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			if (!CustomSettingsHandler.ShouldFilterItemSpawns())
			{
				return true;
			}
			if (LootData.AllSpawnWeightData == null)
			{
				LootData.PopulateLootData();
			}
			Dictionary<SpawnPool, Dictionary<ushort, int>> allSpawnWeightData = LootData.AllSpawnWeightData;
			if (allSpawnWeightData == null || !allSpawnWeightData.TryGetValue(spawnPool, out var value))
			{
				return true;
			}
			List<KeyValuePair<ushort, int>> list = new List<KeyValuePair<ushort, int>>(value.Count);
			bool flag = false;
			Item val = default(Item);
			foreach (KeyValuePair<ushort, int> item in value)
			{
				if (ItemDatabase.TryGetItem(item.Key, ref val) && !val.IsValidToSpawn())
				{
					flag = true;
				}
				else
				{
					list.Add(item);
				}
			}
			if (!flag)
			{
				return true;
			}
			if (list.Count == 0)
			{
				__result = null;
				return false;
			}
			ushort key = Util.RandomSelection<KeyValuePair<ushort, int>>((IEnumerable<KeyValuePair<ushort, int>>)list, (Func<KeyValuePair<ushort, int>, int>)((KeyValuePair<ushort, int> entry) => entry.Value)).Key;
			Item val2 = default(Item);
			__result = (ItemDatabase.TryGetItem(key, ref val2) ? ((Component)val2).gameObject : null);
			return false;
		}

		[HarmonyPatch(typeof(SpawnList), "GetSpawns")]
		[HarmonyPrefix]
		private static bool SpawnListGetSpawnsPatch(SpawnList __instance, int count, bool canRepeat, ref List<GameObject> __result)
		{
			if (!CustomSettingsHandler.ShouldFilterItemSpawns())
			{
				return true;
			}
			List<SpawnEntry> list = new List<SpawnEntry>(__instance.items.Count);
			bool flag = false;
			foreach (SpawnEntry item in __instance.items)
			{
				if (IsDisabledItem(item.prefab))
				{
					flag = true;
				}
				else
				{
					list.Add(item);
				}
			}
			if (!flag)
			{
				return true;
			}
			List<SpawnEntry> list2 = new List<SpawnEntry>(list);
			List<GameObject> list3 = new List<GameObject>(count);
			for (int i = 0; i < count; i++)
			{
				if (list2.Count == 0)
				{
					list3.Add(null);
					continue;
				}
				SpawnEntry val = Util.RandomSelection<SpawnEntry>((IEnumerable<SpawnEntry>)list2, (Func<SpawnEntry, int>)((SpawnEntry entry) => entry.weight));
				list3.Add(val.prefab);
				if (!canRepeat)
				{
					if (list2.Count <= 1)
					{
						list2 = new List<SpawnEntry>(list);
					}
					list2.Remove(val);
				}
			}
			__result = list3;
			return false;
		}

		[HarmonyPatch(typeof(BerryBush), "SpawnItems")]
		[HarmonyPrefix]
		private static bool BerryBushSpawnItemsPatch(BerryBush __instance, ref List<PhotonView> __result)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			if (!CustomSettingsHandler.ShouldFilterItemSpawns() || (int)((Spawner)__instance).spawnMode != 0 || !IsDisabledItem(((Spawner)__instance).spawnedObjectPrefab))
			{
				return true;
			}
			__result = new List<PhotonView>();
			return false;
		}

		[HarmonyPatch(typeof(BerryVine), "SpawnItems")]
		[HarmonyPrefix]
		private static bool BerryVineSpawnItemsPatch(BerryVine __instance, ref List<PhotonView> __result)
		{
			return SkipSpawnListSpawnerWhenEmpty(((Spawner)__instance).spawns, ref __result);
		}

		[HarmonyPatch(typeof(GroundPlaceSpawner), "SpawnItems")]
		[HarmonyPrefix]
		private static bool GroundPlaceSpawnerSpawnItemsPatch(GroundPlaceSpawner __instance, ref List<PhotonView> __result)
		{
			return SkipSpawnListSpawnerWhenEmpty(((Spawner)__instance).spawns, ref __result);
		}

		[HarmonyPatch(typeof(Spawner), "GetObjectsToSpawn")]
		[HarmonyPostfix]
		private static void SpawnerGetObjectsToSpawnPatch(List<GameObject> __result)
		{
			if (!CustomSettingsHandler.ShouldFilterItemSpawns() || __result == null)
			{
				return;
			}
			for (int i = 0; i < __result.Count; i++)
			{
				if (IsDisabledItem(__result[i]))
				{
					__result[i] = null;
				}
			}
		}

		[HarmonyPatch(typeof(SingleItemSpawner), "TrySpawnItems")]
		[HarmonyPrefix]
		private static bool SingleItemSpawnerTrySpawnItemsPatch(SingleItemSpawner __instance, ref List<PhotonView> __result)
		{
			if (!CustomSettingsHandler.ShouldFilterItemSpawns() || !IsDisabledItem(__instance.prefab))
			{
				return true;
			}
			SpawnedItemTracker val = default(SpawnedItemTracker);
			if (SpawnerExtensions.HasSpawnTracking((ISpawner)(object)__instance, ref val) && val.HasSpawnHistory)
			{
				return true;
			}
			__result = new List<PhotonView>();
			return false;
		}

		private static bool SkipSpawnListSpawnerWhenEmpty(SpawnList spawnList, ref List<PhotonView> result)
		{
			if (!CustomSettingsHandler.ShouldFilterItemSpawns() || HasEnabledSpawn(spawnList))
			{
				return true;
			}
			result = new List<PhotonView>();
			return false;
		}

		private static bool HasEnabledSpawn(SpawnList spawnList)
		{
			if (!Object.op_Implicit((Object)(object)spawnList))
			{
				return false;
			}
			foreach (SpawnEntry item in spawnList.items)
			{
				if (Object.op_Implicit((Object)(object)item.prefab) && !IsDisabledItem(item.prefab))
				{
					return true;
				}
			}
			return false;
		}

		private static bool IsDisabledItem(GameObject prefab)
		{
			Item val = default(Item);
			if (Object.op_Implicit((Object)(object)prefab) && prefab.TryGetComponent<Item>(ref val))
			{
				return !val.IsValidToSpawn();
			}
			return false;
		}
	}
}
namespace System.Diagnostics.CodeAnalysis
{
	[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class ConstantExpectedAttribute : Attribute
	{
		public object? Min { get; set; }

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

		public string? UrlFormat { get; set; }

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

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

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

		public string[] Members { get; }

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

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

		public const string DateOnlyFormat = "DateOnlyFormat";

		public const string DateTimeFormat = "DateTimeFormat";

		public const string EnumFormat = "EnumFormat";

		public const string GuidFormat = "GuidFormat";

		public const string Json = "Json";

		public const string NumericFormat = "NumericFormat";

		public const string Regex = "Regex";

		public const string TimeOnlyFormat = "TimeOnlyFormat";

		public const string TimeSpanFormat = "TimeSpanFormat";

		public const string Uri = "Uri";

		public const string Xml = "Xml";

		public string Syntax { get; }

		public object?[] Arguments { get; }

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

		public StringSyntaxAttribute(string syntax, params object?[] arguments)
		{
			Syntax = syntax;
			Arguments = arguments;
		}
	}
	[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class UnscopedRefAttribute : Attribute
	{
	}
}
namespace System.Runtime.Versioning
{
	[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Module | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Interface | AttributeTargets.Delegate, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class RequiresPreviewFeaturesAttribute : Attribute
	{
		public string? Message { get; }

		public string? Url { get; set; }

		public RequiresPreviewFeaturesAttribute()
		{
		}

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

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

		public string MethodName { get; }

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

		public const string RequiredMembers = "RequiredMembers";

		public string FeatureName { get; }

		public bool IsOptional { get; set; }

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

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

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

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