Decompiled source of AllMapValuables v4.0.0

AllMapValuables.dll

Decompiled a month ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using Photon.Realtime;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: IgnoresAccessChecksTo("")]
[assembly: AssemblyCompany("REPOJP")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("zabuMod")]
[assembly: AssemblyTitle("zabuMod")]
[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.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace REPOJP.AllMapValuables
{
	[BepInPlugin("REPOJP.AllMapValuables", "AllMapValuables", "4.0.0")]
	public sealed class AllMapValuablesPlugin : BaseUnityPlugin
	{
		public const string PluginGuid = "REPOJP.AllMapValuables";

		public const string PluginName = "AllMapValuables";

		public const string PluginVersion = "4.0.0";

		internal static AllMapValuablesPlugin Instance;

		internal static ManualLogSource ModLogger;

		private Harmony harmony;

		private ConfigEntry<bool> enableMod;

		private ConfigEntry<bool> enableVerboseLog;

		private ConfigEntry<bool> fallbackToVanillaOnError;

		private ConfigEntry<bool> excludeCurrentMapFromExtraPool;

		private readonly Dictionary<string, ConfigEntry<int>> levelWeightConfigs = new Dictionary<string, ConfigEntry<int>>(StringComparer.OrdinalIgnoreCase);

		private void Awake()
		{
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Expected O, but got Unknown
			try
			{
				Instance = this;
				ModLogger = ((BaseUnityPlugin)this).Logger;
				((Component)this).transform.parent = null;
				((Object)((Component)this).gameObject).hideFlags = (HideFlags)61;
				Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
				enableMod = ((BaseUnityPlugin)this).Config.Bind<bool>("A General", "EnableMod", true, "Enable or disable this mod. このMODの有効無効");
				enableVerboseLog = ((BaseUnityPlugin)this).Config.Bind<bool>("A General", "EnableVerboseLog", false, "Enable verbose debug logging. 詳細デバッグログ有効");
				fallbackToVanillaOnError = ((BaseUnityPlugin)this).Config.Bind<bool>("A General", "FallbackToVanillaOnError", true, "Fall back to vanilla valuable generation when an error occurs. エラー時バニラ生成へ自動復帰");
				excludeCurrentMapFromExtraPool = ((BaseUnityPlugin)this).Config.Bind<bool>("A General", "ExcludeCurrentMapFromExtraPool", false, "Exclude the current level from the mixed valuable pool. 現在マップ由来の貴重品を混合候補から除外");
				harmony = new Harmony("REPOJP.AllMapValuables");
				harmony.PatchAll();
				WriteInfo("Loaded AllMapValuables v4.0.0");
			}
			catch (Exception ex)
			{
				if (((BaseUnityPlugin)this).Logger != null)
				{
					((BaseUnityPlugin)this).Logger.LogError((object)("Failure: Awake failed.\n" + ex));
				}
			}
		}

		private void OnDestroy()
		{
			try
			{
				if (harmony != null)
				{
					harmony.UnpatchSelf();
				}
			}
			catch (Exception ex)
			{
				WriteError("Failure: OnDestroy failed.\n" + ex);
			}
		}

		internal bool IsEnabled()
		{
			return enableMod != null && enableMod.Value;
		}

		internal bool IsVerboseLogEnabled()
		{
			return enableVerboseLog != null && enableVerboseLog.Value;
		}

		internal bool IsFallbackToVanillaOnErrorEnabled()
		{
			return fallbackToVanillaOnError != null && fallbackToVanillaOnError.Value;
		}

		internal bool IsExcludeCurrentMapFromExtraPoolEnabled()
		{
			return excludeCurrentMapFromExtraPool != null && excludeCurrentMapFromExtraPool.Value;
		}

		internal void EnsureLevelWeightConfigs()
		{
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Expected O, but got Unknown
			if ((Object)(object)RunManager.instance == (Object)null)
			{
				return;
			}
			List<Level> allowedSourceLevels = GetAllowedSourceLevels();
			foreach (Level item in allowedSourceLevels)
			{
				string levelName = GetLevelName(item);
				if (!string.IsNullOrWhiteSpace(levelName) && !levelWeightConfigs.ContainsKey(levelName))
				{
					levelWeightConfigs[levelName] = ((BaseUnityPlugin)this).Config.Bind<int>("B Level Valuable Weights", levelName, 1, new ConfigDescription("Spawn weight for valuables from this level. このマップ由来貴重品の生成重み", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 10), Array.Empty<object>()));
				}
			}
		}

		internal int GetLevelWeight(Level level)
		{
			EnsureLevelWeightConfigs();
			string levelName = GetLevelName(level);
			if (string.IsNullOrWhiteSpace(levelName))
			{
				return 1;
			}
			if (levelWeightConfigs.TryGetValue(levelName, out var value) && value != null)
			{
				return Mathf.Clamp(value.Value, 1, 10);
			}
			return 1;
		}

		internal List<Level> GetAllowedSourceLevels()
		{
			List<Level> list = new List<Level>();
			if ((Object)(object)RunManager.instance == (Object)null)
			{
				return list;
			}
			if (RunManager.instance.levels != null)
			{
				foreach (Level level in RunManager.instance.levels)
				{
					AddAllowedLevel(list, level);
				}
			}
			AddAllowedLevel(list, RunManager.instance.levelCurrent);
			return list;
		}

		internal void AddAllowedLevel(List<Level> levels, Level level)
		{
			if (levels == null || (Object)(object)level == (Object)null || !IsAllowedSourceLevel(level) || (IsExcludeCurrentMapFromExtraPoolEnabled() && (Object)(object)RunManager.instance != (Object)null && (Object)(object)RunManager.instance.levelCurrent == (Object)(object)level))
			{
				return;
			}
			for (int i = 0; i < levels.Count; i++)
			{
				if ((Object)(object)levels[i] == (Object)(object)level)
				{
					return;
				}
			}
			levels.Add(level);
		}

		internal static bool IsAllowedRuntimeLevel()
		{
			try
			{
				if ((Object)(object)RunManager.instance == (Object)null || (Object)(object)RunManager.instance.levelCurrent == (Object)null)
				{
					return false;
				}
				if (!SemiFunc.RunIsLevel())
				{
					return false;
				}
				if ((Object)(object)LevelGenerator.Instance == (Object)null || (Object)(object)LevelGenerator.Instance.Level == (Object)null)
				{
					return false;
				}
				return IsAllowedSourceLevel(LevelGenerator.Instance.Level);
			}
			catch
			{
				return false;
			}
		}

		internal static bool IsAllowedSourceLevel(Level level)
		{
			try
			{
				if ((Object)(object)level == (Object)null)
				{
					return false;
				}
				string levelName = GetLevelName(level);
				if (IsExcludedLevelName(levelName))
				{
					return false;
				}
				if (IsShopOrArenaLevel(level))
				{
					return false;
				}
				if (level.ValuablePresets == null || level.ValuablePresets.Count == 0)
				{
					return false;
				}
				return true;
			}
			catch
			{
				return false;
			}
		}

		internal static string GetLevelName(Level level)
		{
			if ((Object)(object)level == (Object)null)
			{
				return string.Empty;
			}
			return string.IsNullOrWhiteSpace(((Object)level).name) ? string.Empty : ((Object)level).name.Trim();
		}

		internal static bool IsShopOrArenaLevel(Level level)
		{
			if ((Object)(object)level == (Object)null)
			{
				return false;
			}
			if (InvokeSemiFuncLevelBool("IsLevelShop", level) || InvokeSemiFuncLevelBool("IsLevelArena", level))
			{
				return true;
			}
			if (IsLevelInRunManagerField(level, "levelShop") || IsLevelInRunManagerField(level, "levelArena"))
			{
				return true;
			}
			string text = NormalizeLevelName(GetLevelName(level));
			return text.IndexOf("Shop", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("Arena", StringComparison.OrdinalIgnoreCase) >= 0;
		}

		private static bool InvokeSemiFuncLevelBool(string methodName, Level level)
		{
			try
			{
				MethodInfo methodInfo = AccessTools.Method(typeof(SemiFunc), methodName, new Type[1] { typeof(Level) }, (Type[])null);
				if (methodInfo == null)
				{
					return false;
				}
				object obj = methodInfo.Invoke(null, new object[1] { level });
				if (obj is bool)
				{
					return (bool)obj;
				}
			}
			catch
			{
				return false;
			}
			return false;
		}

		private static bool IsLevelInRunManagerField(Level level, string fieldName)
		{
			try
			{
				if ((Object)(object)RunManager.instance == (Object)null || (Object)(object)level == (Object)null || string.IsNullOrWhiteSpace(fieldName))
				{
					return false;
				}
				FieldInfo fieldInfo = AccessTools.Field(typeof(RunManager), fieldName);
				if (fieldInfo == null)
				{
					return false;
				}
				object value = fieldInfo.GetValue(RunManager.instance);
				if (value == null)
				{
					return false;
				}
				Level val = (Level)((value is Level) ? value : null);
				if ((Object)(object)val != (Object)null)
				{
					return IsSameLevel(val, level);
				}
				if (!(value is IEnumerable enumerable))
				{
					return false;
				}
				foreach (object item in enumerable)
				{
					Level val2 = (Level)((item is Level) ? item : null);
					if ((Object)(object)val2 != (Object)null && IsSameLevel(val2, level))
					{
						return true;
					}
				}
			}
			catch
			{
				return false;
			}
			return false;
		}

		private static bool IsSameLevel(Level left, Level right)
		{
			if ((Object)(object)left == (Object)(object)right)
			{
				return true;
			}
			string levelName = GetLevelName(left);
			string levelName2 = GetLevelName(right);
			return !string.IsNullOrWhiteSpace(levelName) && !string.IsNullOrWhiteSpace(levelName2) && string.Equals(levelName, levelName2, StringComparison.OrdinalIgnoreCase);
		}

		private static string NormalizeLevelName(string levelName)
		{
			if (string.IsNullOrWhiteSpace(levelName))
			{
				return string.Empty;
			}
			string text = levelName.Trim();
			if (text.StartsWith("Level - ", StringComparison.OrdinalIgnoreCase))
			{
				text = text.Substring("Level - ".Length).Trim();
			}
			return text;
		}

		internal static bool IsExcludedLevelName(string levelName)
		{
			if (string.IsNullOrWhiteSpace(levelName))
			{
				return true;
			}
			string text = NormalizeLevelName(levelName);
			return string.Equals(text, "Splash Screen", StringComparison.OrdinalIgnoreCase) || string.Equals(text, "Main Menu", StringComparison.OrdinalIgnoreCase) || string.Equals(text, "Lobby Menu", StringComparison.OrdinalIgnoreCase) || string.Equals(text, "Lobby", StringComparison.OrdinalIgnoreCase) || string.Equals(text, "Tutorial", StringComparison.OrdinalIgnoreCase) || text.IndexOf("Shop", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("Arena", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("Recording", StringComparison.OrdinalIgnoreCase) >= 0;
		}

		internal static void WriteInfo(string message)
		{
			if (ModLogger != null)
			{
				ModLogger.LogInfo((object)message);
			}
		}

		internal static void WriteWarning(string message)
		{
			if (ModLogger != null)
			{
				ModLogger.LogWarning((object)message);
			}
		}

		internal static void WriteError(string message)
		{
			if (ModLogger != null)
			{
				ModLogger.LogError((object)message);
			}
		}
	}
	[HarmonyPatch(typeof(ValuableDirector), "SetupHost")]
	internal static class ValuableDirectorSetupHostPatch
	{
		private sealed class WeightedPrefabRef
		{
			public PrefabRef PrefabRef;

			public string ResourcePath;

			public int Weight;

			public string SourceLevelName;
		}

		private sealed class WeightedPoolSet
		{
			public readonly List<WeightedPrefabRef> TinyWeighted = new List<WeightedPrefabRef>();

			public readonly List<WeightedPrefabRef> SmallWeighted = new List<WeightedPrefabRef>();

			public readonly List<WeightedPrefabRef> MediumWeighted = new List<WeightedPrefabRef>();

			public readonly List<WeightedPrefabRef> BigWeighted = new List<WeightedPrefabRef>();

			public readonly List<WeightedPrefabRef> WideWeighted = new List<WeightedPrefabRef>();

			public readonly List<WeightedPrefabRef> TallWeighted = new List<WeightedPrefabRef>();

			public readonly List<WeightedPrefabRef> VeryTallWeighted = new List<WeightedPrefabRef>();

			public readonly Dictionary<string, WeightedPrefabRef> TinyUniqueMap = new Dictionary<string, WeightedPrefabRef>(StringComparer.OrdinalIgnoreCase);

			public readonly Dictionary<string, WeightedPrefabRef> SmallUniqueMap = new Dictionary<string, WeightedPrefabRef>(StringComparer.OrdinalIgnoreCase);

			public readonly Dictionary<string, WeightedPrefabRef> MediumUniqueMap = new Dictionary<string, WeightedPrefabRef>(StringComparer.OrdinalIgnoreCase);

			public readonly Dictionary<string, WeightedPrefabRef> BigUniqueMap = new Dictionary<string, WeightedPrefabRef>(StringComparer.OrdinalIgnoreCase);

			public readonly Dictionary<string, WeightedPrefabRef> WideUniqueMap = new Dictionary<string, WeightedPrefabRef>(StringComparer.OrdinalIgnoreCase);

			public readonly Dictionary<string, WeightedPrefabRef> TallUniqueMap = new Dictionary<string, WeightedPrefabRef>(StringComparer.OrdinalIgnoreCase);

			public readonly Dictionary<string, WeightedPrefabRef> VeryTallUniqueMap = new Dictionary<string, WeightedPrefabRef>(StringComparer.OrdinalIgnoreCase);

			public List<PrefabRef> TinyUnique = new List<PrefabRef>();

			public List<PrefabRef> SmallUnique = new List<PrefabRef>();

			public List<PrefabRef> MediumUnique = new List<PrefabRef>();

			public List<PrefabRef> BigUnique = new List<PrefabRef>();

			public List<PrefabRef> WideUnique = new List<PrefabRef>();

			public List<PrefabRef> TallUnique = new List<PrefabRef>();

			public List<PrefabRef> VeryTallUnique = new List<PrefabRef>();

			public bool IsCompletelyEmpty()
			{
				return TinyWeighted.Count == 0 && SmallWeighted.Count == 0 && MediumWeighted.Count == 0 && BigWeighted.Count == 0 && WideWeighted.Count == 0 && TallWeighted.Count == 0 && VeryTallWeighted.Count == 0;
			}
		}

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

			private object <>2__current;

			public ValuableDirector director;

			private bool <setupSuccess>5__1;

			private WeightedPoolSet <poolSet>5__2;

			private List<ValuableVolume> <allVolumes>5__3;

			private List<ValuableVolume> <tinyVolumes>5__4;

			private List<ValuableVolume> <smallVolumes>5__5;

			private List<ValuableVolume> <mediumVolumes>5__6;

			private List<ValuableVolume> <bigVolumes>5__7;

			private List<ValuableVolume> <wideVolumes>5__8;

			private List<ValuableVolume> <tallVolumes>5__9;

			private List<ValuableVolume> <veryTallVolumes>5__10;

			private int <totalMaxAmount>5__11;

			private int[] <maxAmounts>5__12;

			private string[] <paths>5__13;

			private int[] <chances>5__14;

			private List<ValuableVolume>[] <volumeLists>5__15;

			private List<WeightedPrefabRef>[] <weightedPools>5__16;

			private int[] <volumeIndex>5__17;

			private int <index>5__18;

			private int <selectedCategoryIndex>5__19;

			private ValuableVolume <targetVolume>5__20;

			private WeightedPrefabRef <selectedValuable>5__21;

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

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

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

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<poolSet>5__2 = null;
				<allVolumes>5__3 = null;
				<tinyVolumes>5__4 = null;
				<smallVolumes>5__5 = null;
				<mediumVolumes>5__6 = null;
				<bigVolumes>5__7 = null;
				<wideVolumes>5__8 = null;
				<tallVolumes>5__9 = null;
				<veryTallVolumes>5__10 = null;
				<maxAmounts>5__12 = null;
				<paths>5__13 = null;
				<chances>5__14 = null;
				<volumeLists>5__15 = null;
				<weightedPools>5__16 = null;
				<volumeIndex>5__17 = null;
				<targetVolume>5__20 = null;
				<selectedValuable>5__21 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0860: Unknown result type (might be due to invalid IL or missing references)
				//IL_086a: Expected O, but got Unknown
				//IL_08c8: Unknown result type (might be due to invalid IL or missing references)
				//IL_08d2: Expected O, but got Unknown
				//IL_0924: Unknown result type (might be due to invalid IL or missing references)
				//IL_092e: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<setupSuccess>5__1 = false;
					PrepareDirectorState(director);
					CalculateMaxAmounts(director);
					<poolSet>5__2 = BuildWeightedPoolSet();
					if (<poolSet>5__2.IsCompletelyEmpty())
					{
						AllMapValuablesPlugin.WriteWarning("Failure: Valuable pool is empty. No valuables will be spawned by AllMapValuables.");
						SetAllMaxAmounts(director, 0);
					}
					SetFieldValue(TinyValuablesField, director, <poolSet>5__2.TinyUnique);
					SetFieldValue(SmallValuablesField, director, <poolSet>5__2.SmallUnique);
					SetFieldValue(MediumValuablesField, director, <poolSet>5__2.MediumUnique);
					SetFieldValue(BigValuablesField, director, <poolSet>5__2.BigUnique);
					SetFieldValue(WideValuablesField, director, <poolSet>5__2.WideUnique);
					SetFieldValue(TallValuablesField, director, <poolSet>5__2.TallUnique);
					SetFieldValue(VeryTallValuablesField, director, <poolSet>5__2.VeryTallUnique);
					<allVolumes>5__3 = GetValuableVolumes();
					<tinyVolumes>5__4 = GetVolumesByType(<allVolumes>5__3, (Type)0);
					<smallVolumes>5__5 = GetVolumesByType(<allVolumes>5__3, (Type)1);
					<mediumVolumes>5__6 = GetVolumesByType(<allVolumes>5__3, (Type)2);
					<bigVolumes>5__7 = GetVolumesByType(<allVolumes>5__3, (Type)3);
					<wideVolumes>5__8 = GetVolumesByType(<allVolumes>5__3, (Type)4);
					<tallVolumes>5__9 = GetVolumesByType(<allVolumes>5__3, (Type)5);
					<veryTallVolumes>5__10 = GetVolumesByType(<allVolumes>5__3, (Type)6);
					ShuffleList(<tinyVolumes>5__4);
					ShuffleList(<smallVolumes>5__5);
					ShuffleList(<mediumVolumes>5__6);
					ShuffleList(<bigVolumes>5__7);
					ShuffleList(<wideVolumes>5__8);
					ShuffleList(<tallVolumes>5__9);
					ShuffleList(<veryTallVolumes>5__10);
					SetFieldValue(TinyVolumesField, director, <tinyVolumes>5__4);
					SetFieldValue(SmallVolumesField, director, <smallVolumes>5__5);
					SetFieldValue(MediumVolumesField, director, <mediumVolumes>5__6);
					SetFieldValue(BigVolumesField, director, <bigVolumes>5__7);
					SetFieldValue(WideVolumesField, director, <wideVolumes>5__8);
					SetFieldValue(TallVolumesField, director, <tallVolumes>5__9);
					SetFieldValue(VeryTallVolumesField, director, <veryTallVolumes>5__10);
					ApplyValuableDebugMode(director, <allVolumes>5__3, <tinyVolumes>5__4, <smallVolumes>5__5, <mediumVolumes>5__6, <bigVolumes>5__7, <wideVolumes>5__8, <tallVolumes>5__9, <veryTallVolumes>5__10, <poolSet>5__2);
					<totalMaxAmount>5__11 = Mathf.Max(0, GetFieldValue<int>(TotalMaxAmountField, director));
					<maxAmounts>5__12 = new int[7]
					{
						Mathf.Max(0, GetFieldValue<int>(TinyMaxAmountField, director)),
						Mathf.Max(0, GetFieldValue<int>(SmallMaxAmountField, director)),
						Mathf.Max(0, GetFieldValue<int>(MediumMaxAmountField, director)),
						Mathf.Max(0, GetFieldValue<int>(BigMaxAmountField, director)),
						Mathf.Max(0, GetFieldValue<int>(WideMaxAmountField, director)),
						Mathf.Max(0, GetFieldValue<int>(TallMaxAmountField, director)),
						Mathf.Max(0, GetFieldValue<int>(VeryTallMaxAmountField, director))
					};
					<paths>5__13 = new string[7]
					{
						GetFieldValue<string>(TinyPathField, director),
						GetFieldValue<string>(SmallPathField, director),
						GetFieldValue<string>(MediumPathField, director),
						GetFieldValue<string>(BigPathField, director),
						GetFieldValue<string>(WidePathField, director),
						GetFieldValue<string>(TallPathField, director),
						GetFieldValue<string>(VeryTallPathField, director)
					};
					<chances>5__14 = new int[7]
					{
						Mathf.Max(1, director.tinyChance),
						Mathf.Max(1, director.smallChance),
						Mathf.Max(1, director.mediumChance),
						Mathf.Max(1, director.bigChance),
						Mathf.Max(1, director.wideChance),
						Mathf.Max(1, director.tallChance),
						Mathf.Max(1, director.veryTallChance)
					};
					<volumeLists>5__15 = new List<ValuableVolume>[7] { <tinyVolumes>5__4, <smallVolumes>5__5, <mediumVolumes>5__6, <bigVolumes>5__7, <wideVolumes>5__8, <tallVolumes>5__9, <veryTallVolumes>5__10 };
					<weightedPools>5__16 = new List<WeightedPrefabRef>[7] { <poolSet>5__2.TinyWeighted, <poolSet>5__2.SmallWeighted, <poolSet>5__2.MediumWeighted, <poolSet>5__2.BigWeighted, <poolSet>5__2.WideWeighted, <poolSet>5__2.TallWeighted, <poolSet>5__2.VeryTallWeighted };
					<volumeIndex>5__17 = new int[7];
					if ((Object)(object)AllMapValuablesPlugin.Instance != (Object)null && AllMapValuablesPlugin.Instance.IsVerboseLogEnabled())
					{
						AllMapValuablesPlugin.WriteInfo($"Pool Summary | Tiny:{<poolSet>5__2.TinyWeighted.Count} Small:{<poolSet>5__2.SmallWeighted.Count} Medium:{<poolSet>5__2.MediumWeighted.Count} Big:{<poolSet>5__2.BigWeighted.Count} Wide:{<poolSet>5__2.WideWeighted.Count} Tall:{<poolSet>5__2.TallWeighted.Count} VeryTall:{<poolSet>5__2.VeryTallWeighted.Count}");
					}
					<index>5__18 = 0;
					goto IL_07f6;
				case 1:
					<>1__state = -1;
					<targetVolume>5__20 = null;
					<selectedValuable>5__21 = null;
					goto IL_07e4;
				case 2:
					<>1__state = -1;
					goto IL_087b;
				case 3:
					<>1__state = -1;
					goto IL_08e3;
				case 4:
					{
						<>1__state = -1;
						break;
					}
					IL_08e3:
					if (IsMultiplayerRoomActive() && GetFieldValue<int>(CosmeticWorldObjectSpawnPlayerReadyField, director) < PhotonNetwork.CurrentRoom.PlayerCount)
					{
						<>2__current = (object)new WaitForSeconds(0.1f);
						<>1__state = 3;
						return true;
					}
					director.VolumesAndSwitchSetup();
					break;
					IL_07f6:
					if (<index>5__18 < <totalMaxAmount>5__11)
					{
						<selectedCategoryIndex>5__19 = SelectCategoryIndex(<maxAmounts>5__12, <volumeIndex>5__17, <volumeLists>5__15, <weightedPools>5__16, <chances>5__14);
						if (<selectedCategoryIndex>5__19 != -1)
						{
							<targetVolume>5__20 = <volumeLists>5__15[<selectedCategoryIndex>5__19][<volumeIndex>5__17[<selectedCategoryIndex>5__19]];
							<selectedValuable>5__21 = PickWeightedPrefab(<weightedPools>5__16[<selectedCategoryIndex>5__19]);
							if (<selectedValuable>5__21 == null || <selectedValuable>5__21.PrefabRef == null)
							{
								<volumeIndex>5__17[<selectedCategoryIndex>5__19]++;
								goto IL_07e4;
							}
							InvokeSpawnValuable(director, <selectedValuable>5__21.PrefabRef, <targetVolume>5__20, <paths>5__13[<selectedCategoryIndex>5__19]);
							<volumeIndex>5__17[<selectedCategoryIndex>5__19]++;
							<>2__current = null;
							<>1__state = 1;
							return true;
						}
					}
					WriteSpawnShortageLog(director, <maxAmounts>5__12, <volumeIndex>5__17);
					RpcTargetAmount(director, "ValuablesTargetSetRPC", GetFieldValue<int>(ValuableTargetAmountField, director));
					IncrementIntField(ValuableSpawnPlayerReadyField, director);
					goto IL_087b;
					IL_087b:
					if (IsMultiplayerRoomActive() && GetFieldValue<int>(ValuableSpawnPlayerReadyField, director) < PhotonNetwork.CurrentRoom.PlayerCount)
					{
						<>2__current = (object)new WaitForSeconds(0.1f);
						<>1__state = 2;
						return true;
					}
					RunCosmeticWorldObjectSetup(director, <volumeIndex>5__17, <volumeLists>5__15);
					goto IL_08e3;
					IL_07e4:
					<index>5__18++;
					goto IL_07f6;
				}
				if (IsMultiplayerRoomActive() && GetFieldValue<int>(SwitchSetupPlayerReadyField, director) < PhotonNetwork.CurrentRoom.PlayerCount)
				{
					<>2__current = (object)new WaitForSeconds(0.1f);
					<>1__state = 4;
					return true;
				}
				SetFieldValue(SetupCompleteField, director, true);
				<setupSuccess>5__1 = true;
				if ((Object)(object)AllMapValuablesPlugin.Instance != (Object)null && AllMapValuablesPlugin.Instance.IsVerboseLogEnabled())
				{
					AllMapValuablesPlugin.WriteInfo("AllMapValuables setup completed.");
				}
				if (!<setupSuccess>5__1)
				{
					return false;
				}
				return false;
			}

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

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

		private static readonly MethodInfo SpawnValuableMethod = AccessTools.Method(typeof(ValuableDirector), "SpawnValuable", (Type[])null, (Type[])null);

		private static readonly MethodInfo SpawnCosmeticWorldObjectMethod = AccessTools.Method(typeof(ValuableDirector), "SpawnCosmeticWorldObject", (Type[])null, (Type[])null);

		private static readonly MethodInfo CosmeticWorldObjectLevelLoopsGetMethod = AccessTools.Method(typeof(ValuableDirector), "CosmeticWorldObjectLevelLoopsGet", (Type[])null, (Type[])null);

		private static readonly MethodInfo CosmeticWorldObjectLevelLoopsClampedGetMethod = AccessTools.Method(typeof(ValuableDirector), "CosmeticWorldObjectLevelLoopsClampedGet", (Type[])null, (Type[])null);

		private static readonly FieldInfo ValuableDebugField = AccessTools.Field(typeof(ValuableDirector), "valuableDebug");

		private static readonly FieldInfo SetupCompleteField = AccessTools.Field(typeof(ValuableDirector), "setupComplete");

		private static readonly FieldInfo ValuableSpawnPlayerReadyListField = AccessTools.Field(typeof(ValuableDirector), "valuableSpawnPlayerReadyList");

		private static readonly FieldInfo ValuableSpawnPlayerReadyField = AccessTools.Field(typeof(ValuableDirector), "valuableSpawnPlayerReady");

		private static readonly FieldInfo ValuableTargetAmountField = AccessTools.Field(typeof(ValuableDirector), "valuableTargetAmount");

		private static readonly FieldInfo SwitchSetupPlayerReadyListField = AccessTools.Field(typeof(ValuableDirector), "switchSetupPlayerReadyList");

		private static readonly FieldInfo SwitchSetupPlayerReadyField = AccessTools.Field(typeof(ValuableDirector), "switchSetupPlayerReady");

		private static readonly FieldInfo TotalMaxValueField = AccessTools.Field(typeof(ValuableDirector), "totalMaxValue");

		private static readonly FieldInfo TotalCurrentValueField = AccessTools.Field(typeof(ValuableDirector), "totalCurrentValue");

		private static readonly FieldInfo TotalMaxAmountField = AccessTools.Field(typeof(ValuableDirector), "totalMaxAmount");

		private static readonly FieldInfo TinyMaxAmountField = AccessTools.Field(typeof(ValuableDirector), "tinyMaxAmount");

		private static readonly FieldInfo SmallMaxAmountField = AccessTools.Field(typeof(ValuableDirector), "smallMaxAmount");

		private static readonly FieldInfo MediumMaxAmountField = AccessTools.Field(typeof(ValuableDirector), "mediumMaxAmount");

		private static readonly FieldInfo BigMaxAmountField = AccessTools.Field(typeof(ValuableDirector), "bigMaxAmount");

		private static readonly FieldInfo WideMaxAmountField = AccessTools.Field(typeof(ValuableDirector), "wideMaxAmount");

		private static readonly FieldInfo TallMaxAmountField = AccessTools.Field(typeof(ValuableDirector), "tallMaxAmount");

		private static readonly FieldInfo VeryTallMaxAmountField = AccessTools.Field(typeof(ValuableDirector), "veryTallMaxAmount");

		private static readonly FieldInfo TinyValuablesField = AccessTools.Field(typeof(ValuableDirector), "tinyValuables");

		private static readonly FieldInfo SmallValuablesField = AccessTools.Field(typeof(ValuableDirector), "smallValuables");

		private static readonly FieldInfo MediumValuablesField = AccessTools.Field(typeof(ValuableDirector), "mediumValuables");

		private static readonly FieldInfo BigValuablesField = AccessTools.Field(typeof(ValuableDirector), "bigValuables");

		private static readonly FieldInfo WideValuablesField = AccessTools.Field(typeof(ValuableDirector), "wideValuables");

		private static readonly FieldInfo TallValuablesField = AccessTools.Field(typeof(ValuableDirector), "tallValuables");

		private static readonly FieldInfo VeryTallValuablesField = AccessTools.Field(typeof(ValuableDirector), "veryTallValuables");

		private static readonly FieldInfo TinyVolumesField = AccessTools.Field(typeof(ValuableDirector), "tinyVolumes");

		private static readonly FieldInfo SmallVolumesField = AccessTools.Field(typeof(ValuableDirector), "smallVolumes");

		private static readonly FieldInfo MediumVolumesField = AccessTools.Field(typeof(ValuableDirector), "mediumVolumes");

		private static readonly FieldInfo BigVolumesField = AccessTools.Field(typeof(ValuableDirector), "bigVolumes");

		private static readonly FieldInfo WideVolumesField = AccessTools.Field(typeof(ValuableDirector), "wideVolumes");

		private static readonly FieldInfo TallVolumesField = AccessTools.Field(typeof(ValuableDirector), "tallVolumes");

		private static readonly FieldInfo VeryTallVolumesField = AccessTools.Field(typeof(ValuableDirector), "veryTallVolumes");

		private static readonly FieldInfo TinyPathField = AccessTools.Field(typeof(ValuableDirector), "tinyPath");

		private static readonly FieldInfo SmallPathField = AccessTools.Field(typeof(ValuableDirector), "smallPath");

		private static readonly FieldInfo MediumPathField = AccessTools.Field(typeof(ValuableDirector), "mediumPath");

		private static readonly FieldInfo BigPathField = AccessTools.Field(typeof(ValuableDirector), "bigPath");

		private static readonly FieldInfo WidePathField = AccessTools.Field(typeof(ValuableDirector), "widePath");

		private static readonly FieldInfo TallPathField = AccessTools.Field(typeof(ValuableDirector), "tallPath");

		private static readonly FieldInfo VeryTallPathField = AccessTools.Field(typeof(ValuableDirector), "veryTallPath");

		private static readonly FieldInfo CosmeticWorldObjectDebugField = AccessTools.Field(typeof(ValuableDirector), "cosmeticWorldObjectDebug");

		private static readonly FieldInfo CosmeticWorldObjectsSpawnCurveField = AccessTools.Field(typeof(ValuableDirector), "cosmeticWorldObjectsSpawnCurve");

		private static readonly FieldInfo CosmeticWorldObjectsLevelLoopField = AccessTools.Field(typeof(ValuableDirector), "cosmeticWorldObjectsLevelLoop");

		private static readonly FieldInfo CosmeticWorldObjectsLevelLoopsMaxField = AccessTools.Field(typeof(ValuableDirector), "cosmeticWorldObjectsLevelLoopsMax");

		private static readonly FieldInfo CosmeticWorldObjectSetupsField = AccessTools.Field(typeof(ValuableDirector), "cosmeticWorldObjectSetups");

		private static readonly FieldInfo CosmeticWorldObjectSpawnPlayerReadyListField = AccessTools.Field(typeof(ValuableDirector), "cosmeticWorldObjectSpawnPlayerReadyList");

		private static readonly FieldInfo CosmeticWorldObjectSpawnPlayerReadyField = AccessTools.Field(typeof(ValuableDirector), "cosmeticWorldObjectSpawnPlayerReady");

		private static readonly FieldInfo CosmeticWorldObjectTargetAmountField = AccessTools.Field(typeof(ValuableDirector), "cosmeticWorldObjectTargetAmount");

		private static readonly FieldInfo RunManagerCosmeticWorldObjectBadLuckCountField = AccessTools.Field(typeof(RunManager), "cosmeticWorldObjectBadLuckCount");

		private static bool Prefix(ValuableDirector __instance, ref IEnumerator __result)
		{
			if ((Object)(object)AllMapValuablesPlugin.Instance == (Object)null || !AllMapValuablesPlugin.Instance.IsEnabled())
			{
				return true;
			}
			if ((Object)(object)GameManager.instance != (Object)null && GameManager.instance.gameMode == 1 && !PhotonNetwork.IsMasterClient)
			{
				return true;
			}
			if (!AllMapValuablesPlugin.IsAllowedRuntimeLevel())
			{
				return true;
			}
			if (!HasRequiredMembers())
			{
				AllMapValuablesPlugin.WriteWarning("Failure: Required ValuableDirector members were not found. Falling back to vanilla generation.");
				return true;
			}
			try
			{
				AllMapValuablesPlugin.Instance.EnsureLevelWeightConfigs();
				__result = CustomSetupHost(__instance);
				return false;
			}
			catch (Exception ex)
			{
				AllMapValuablesPlugin.WriteError("Failure: Failed to start custom valuable generation.\n" + ex);
				return AllMapValuablesPlugin.Instance.IsFallbackToVanillaOnErrorEnabled();
			}
		}

		[IteratorStateMachine(typeof(<CustomSetupHost>d__52))]
		private static IEnumerator CustomSetupHost(ValuableDirector director)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <CustomSetupHost>d__52(0)
			{
				director = director
			};
		}

		private static bool HasRequiredMembers()
		{
			return SpawnValuableMethod != null && ValuableTargetAmountField != null && ValuableSpawnPlayerReadyField != null && SwitchSetupPlayerReadyField != null && TotalMaxAmountField != null && TinyValuablesField != null && SmallValuablesField != null && MediumValuablesField != null && BigValuablesField != null && WideValuablesField != null && TallValuablesField != null && VeryTallValuablesField != null;
		}

		private static void PrepareDirectorState(ValuableDirector director)
		{
			SetFieldValue(SetupCompleteField, director, false);
			SetFieldValue(ValuableTargetAmountField, director, 0);
			SetFieldValue(TotalCurrentValueField, director, 0f);
			SetFieldValue(ValuableSpawnPlayerReadyField, director, 0);
			SetFieldValue(SwitchSetupPlayerReadyField, director, 0);
			SetFieldValue(ValuableSpawnPlayerReadyListField, director, new List<Player>());
			SetFieldValue(SwitchSetupPlayerReadyListField, director, new List<Player>());
			SetFieldValue(CosmeticWorldObjectTargetAmountField, director, 0);
			SetFieldValue(CosmeticWorldObjectSpawnPlayerReadyField, director, 0);
			SetFieldValue(CosmeticWorldObjectSpawnPlayerReadyListField, director, new List<Player>());
		}

		private static void CalculateMaxAmounts(ValuableDirector director)
		{
			if (SemiFunc.RunGetDifficultyMultiplier2() > 0f && !SemiFunc.RunIsArena())
			{
				float num = SemiFunc.RunGetDifficultyMultiplier2();
				SetFieldValue(TotalMaxValueField, director, (float)Mathf.RoundToInt(director.totalMaxValueCurve2.Evaluate(num)));
				SetFieldValue(TinyMaxAmountField, director, Mathf.RoundToInt(director.tinyMaxAmountCurve2.Evaluate(num)));
				SetFieldValue(SmallMaxAmountField, director, Mathf.RoundToInt(director.smallMaxAmountCurve2.Evaluate(num)));
				SetFieldValue(MediumMaxAmountField, director, Mathf.RoundToInt(director.mediumMaxAmountCurve2.Evaluate(num)));
				SetFieldValue(BigMaxAmountField, director, Mathf.RoundToInt(director.bigMaxAmountCurve2.Evaluate(num)));
				SetFieldValue(WideMaxAmountField, director, Mathf.RoundToInt(director.wideMaxAmountCurve2.Evaluate(num)));
				SetFieldValue(TallMaxAmountField, director, Mathf.RoundToInt(director.tallMaxAmountCurve2.Evaluate(num)));
				SetFieldValue(VeryTallMaxAmountField, director, Mathf.RoundToInt(director.veryTallMaxAmountCurve2.Evaluate(num)));
			}
			else
			{
				float num2 = SemiFunc.RunGetDifficultyMultiplier1();
				SetFieldValue(TotalMaxValueField, director, (float)Mathf.RoundToInt(director.totalMaxValueCurve1.Evaluate(num2)));
				SetFieldValue(TinyMaxAmountField, director, Mathf.RoundToInt(director.tinyMaxAmountCurve1.Evaluate(num2)));
				SetFieldValue(SmallMaxAmountField, director, Mathf.RoundToInt(director.smallMaxAmountCurve1.Evaluate(num2)));
				SetFieldValue(MediumMaxAmountField, director, Mathf.RoundToInt(director.mediumMaxAmountCurve1.Evaluate(num2)));
				SetFieldValue(BigMaxAmountField, director, Mathf.RoundToInt(director.bigMaxAmountCurve1.Evaluate(num2)));
				SetFieldValue(WideMaxAmountField, director, Mathf.RoundToInt(director.wideMaxAmountCurve1.Evaluate(num2)));
				SetFieldValue(TallMaxAmountField, director, Mathf.RoundToInt(director.tallMaxAmountCurve1.Evaluate(num2)));
				SetFieldValue(VeryTallMaxAmountField, director, Mathf.RoundToInt(director.veryTallMaxAmountCurve1.Evaluate(num2)));
			}
		}

		private static void SetAllMaxAmounts(ValuableDirector director, int value)
		{
			SetFieldValue(TotalMaxAmountField, director, value);
			SetFieldValue(TinyMaxAmountField, director, value);
			SetFieldValue(SmallMaxAmountField, director, value);
			SetFieldValue(MediumMaxAmountField, director, value);
			SetFieldValue(BigMaxAmountField, director, value);
			SetFieldValue(WideMaxAmountField, director, value);
			SetFieldValue(TallMaxAmountField, director, value);
			SetFieldValue(VeryTallMaxAmountField, director, value);
		}

		private static WeightedPoolSet BuildWeightedPoolSet()
		{
			WeightedPoolSet weightedPoolSet = new WeightedPoolSet();
			if ((Object)(object)AllMapValuablesPlugin.Instance == (Object)null)
			{
				return weightedPoolSet;
			}
			List<Level> allowedSourceLevels = AllMapValuablesPlugin.Instance.GetAllowedSourceLevels();
			foreach (Level item in allowedSourceLevels)
			{
				if ((Object)(object)item == (Object)null || item.ValuablePresets == null || item.ValuablePresets.Count == 0)
				{
					continue;
				}
				string levelName = AllMapValuablesPlugin.GetLevelName(item);
				int levelWeight = AllMapValuablesPlugin.Instance.GetLevelWeight(item);
				foreach (LevelValuables valuablePreset in item.ValuablePresets)
				{
					if (!((Object)(object)valuablePreset == (Object)null))
					{
						AddWeightedPrefabs(weightedPoolSet.TinyWeighted, weightedPoolSet.TinyUniqueMap, valuablePreset.tiny, levelWeight, levelName);
						AddWeightedPrefabs(weightedPoolSet.SmallWeighted, weightedPoolSet.SmallUniqueMap, valuablePreset.small, levelWeight, levelName);
						AddWeightedPrefabs(weightedPoolSet.MediumWeighted, weightedPoolSet.MediumUniqueMap, valuablePreset.medium, levelWeight, levelName);
						AddWeightedPrefabs(weightedPoolSet.BigWeighted, weightedPoolSet.BigUniqueMap, valuablePreset.big, levelWeight, levelName);
						AddWeightedPrefabs(weightedPoolSet.WideWeighted, weightedPoolSet.WideUniqueMap, valuablePreset.wide, levelWeight, levelName);
						AddWeightedPrefabs(weightedPoolSet.TallWeighted, weightedPoolSet.TallUniqueMap, valuablePreset.tall, levelWeight, levelName);
						AddWeightedPrefabs(weightedPoolSet.VeryTallWeighted, weightedPoolSet.VeryTallUniqueMap, valuablePreset.veryTall, levelWeight, levelName);
					}
				}
			}
			weightedPoolSet.TinyUnique = GetUniquePrefabList(weightedPoolSet.TinyUniqueMap);
			weightedPoolSet.SmallUnique = GetUniquePrefabList(weightedPoolSet.SmallUniqueMap);
			weightedPoolSet.MediumUnique = GetUniquePrefabList(weightedPoolSet.MediumUniqueMap);
			weightedPoolSet.BigUnique = GetUniquePrefabList(weightedPoolSet.BigUniqueMap);
			weightedPoolSet.WideUnique = GetUniquePrefabList(weightedPoolSet.WideUniqueMap);
			weightedPoolSet.TallUnique = GetUniquePrefabList(weightedPoolSet.TallUniqueMap);
			weightedPoolSet.VeryTallUnique = GetUniquePrefabList(weightedPoolSet.VeryTallUniqueMap);
			return weightedPoolSet;
		}

		private static void AddWeightedPrefabs(List<WeightedPrefabRef> weightedList, Dictionary<string, WeightedPrefabRef> uniqueMap, List<PrefabRef> source, int levelWeight, string levelName)
		{
			if (weightedList == null || uniqueMap == null || source == null || source.Count == 0)
			{
				return;
			}
			foreach (PrefabRef item in source)
			{
				if (item == null || !item.IsValid())
				{
					continue;
				}
				string resourcePath = item.ResourcePath;
				if (!string.IsNullOrWhiteSpace(resourcePath))
				{
					if (uniqueMap.TryGetValue(resourcePath, out var value))
					{
						value.Weight += Mathf.Clamp(levelWeight, 1, 10);
						continue;
					}
					value = new WeightedPrefabRef();
					value.PrefabRef = item;
					value.ResourcePath = resourcePath;
					value.Weight = Mathf.Clamp(levelWeight, 1, 10);
					value.SourceLevelName = levelName;
					uniqueMap.Add(resourcePath, value);
					weightedList.Add(value);
				}
			}
		}

		private static List<PrefabRef> GetUniquePrefabList(Dictionary<string, WeightedPrefabRef> uniqueMap)
		{
			List<PrefabRef> list = new List<PrefabRef>();
			if (uniqueMap == null)
			{
				return list;
			}
			foreach (KeyValuePair<string, WeightedPrefabRef> item in uniqueMap)
			{
				if (item.Value != null && item.Value.PrefabRef != null)
				{
					list.Add(item.Value.PrefabRef);
				}
			}
			return list;
		}

		private static List<ValuableVolume> GetValuableVolumes()
		{
			ValuableVolume[] array = Object.FindObjectsOfType<ValuableVolume>(false);
			if (array == null || array.Length == 0)
			{
				return new List<ValuableVolume>();
			}
			return new List<ValuableVolume>(array);
		}

		private static List<ValuableVolume> GetVolumesByType(List<ValuableVolume> allVolumes, Type volumeType)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			List<ValuableVolume> list = new List<ValuableVolume>();
			if (allVolumes == null)
			{
				return list;
			}
			foreach (ValuableVolume allVolume in allVolumes)
			{
				if ((Object)(object)allVolume != (Object)null && allVolume.VolumeType == volumeType)
				{
					list.Add(allVolume);
				}
			}
			return list;
		}

		private static void ShuffleList<T>(List<T> list)
		{
			if (list != null && list.Count > 1)
			{
				for (int num = list.Count - 1; num > 0; num--)
				{
					int index = Random.Range(0, num + 1);
					T value = list[num];
					list[num] = list[index];
					list[index] = value;
				}
			}
		}

		private static void ApplyValuableDebugMode(ValuableDirector director, List<ValuableVolume> allVolumes, List<ValuableVolume> tinyVolumes, List<ValuableVolume> smallVolumes, List<ValuableVolume> mediumVolumes, List<ValuableVolume> bigVolumes, List<ValuableVolume> wideVolumes, List<ValuableVolume> tallVolumes, List<ValuableVolume> veryTallVolumes, WeightedPoolSet poolSet)
		{
			string fieldValueAsString = GetFieldValueAsString(ValuableDebugField, director);
			if (string.Equals(fieldValueAsString, "All", StringComparison.OrdinalIgnoreCase))
			{
				SetFieldValue(TotalMaxAmountField, director, allVolumes.Count);
				SetFieldValue(TotalMaxValueField, director, 99999f);
				SetFieldValue(TinyMaxAmountField, director, tinyVolumes.Count);
				SetFieldValue(SmallMaxAmountField, director, smallVolumes.Count);
				SetFieldValue(MediumMaxAmountField, director, mediumVolumes.Count);
				SetFieldValue(BigMaxAmountField, director, bigVolumes.Count);
				SetFieldValue(WideMaxAmountField, director, wideVolumes.Count);
				SetFieldValue(TallMaxAmountField, director, tallVolumes.Count);
				SetFieldValue(VeryTallMaxAmountField, director, veryTallVolumes.Count);
			}
			if (string.Equals(fieldValueAsString, "None", StringComparison.OrdinalIgnoreCase) || poolSet == null || poolSet.IsCompletelyEmpty())
			{
				SetAllMaxAmounts(director, 0);
			}
		}

		private static int SelectCategoryIndex(int[] maxAmounts, int[] volumeIndex, List<ValuableVolume>[] volumeLists, List<WeightedPrefabRef>[] weightedPools, int[] chances)
		{
			float num = -1f;
			int result = -1;
			for (int i = 0; i < volumeLists.Length; i++)
			{
				if (volumeIndex[i] < maxAmounts[i] && volumeLists[i] != null && volumeIndex[i] < volumeLists[i].Count && weightedPools[i] != null && weightedPools[i].Count != 0)
				{
					int num2 = Random.Range(0, Mathf.Max(1, chances[i]));
					if ((float)num2 > num)
					{
						num = num2;
						result = i;
					}
				}
			}
			return result;
		}

		private static WeightedPrefabRef PickWeightedPrefab(List<WeightedPrefabRef> weightedPool)
		{
			if (weightedPool == null || weightedPool.Count == 0)
			{
				return null;
			}
			int num = 0;
			foreach (WeightedPrefabRef item in weightedPool)
			{
				if (item != null && item.PrefabRef != null && item.Weight > 0)
				{
					num += item.Weight;
				}
			}
			if (num <= 0)
			{
				return null;
			}
			int num2 = Random.Range(0, num);
			int num3 = 0;
			foreach (WeightedPrefabRef item2 in weightedPool)
			{
				if (item2 != null && item2.PrefabRef != null && item2.Weight > 0)
				{
					num3 += item2.Weight;
					if (num2 < num3)
					{
						return item2;
					}
				}
			}
			return weightedPool[weightedPool.Count - 1];
		}

		private static void InvokeSpawnValuable(ValuableDirector director, PrefabRef prefabRef, ValuableVolume volume, string path)
		{
			SpawnValuableMethod.Invoke(director, new object[3] { prefabRef, volume, path });
		}

		private static void WriteSpawnShortageLog(ValuableDirector director, int[] maxAmounts, int[] volumeIndex)
		{
			if ((Object)(object)AllMapValuablesPlugin.Instance == (Object)null || !AllMapValuablesPlugin.Instance.IsVerboseLogEnabled())
			{
				return;
			}
			int fieldValue = GetFieldValue<int>(ValuableTargetAmountField, director);
			int fieldValue2 = GetFieldValue<int>(TotalMaxAmountField, director);
			if (fieldValue >= fieldValue2)
			{
				return;
			}
			string[] array = new string[7] { "Tiny", "Small", "Medium", "Big", "Wide", "Tall", "Very Tall" };
			for (int i = 0; i < array.Length; i++)
			{
				if (volumeIndex[i] < maxAmounts[i])
				{
					AllMapValuablesPlugin.WriteWarning("Could not spawn enough " + array[i] + " valuables.");
				}
			}
		}

		private static void RpcTargetAmount(ValuableDirector director, string rpcName, int targetAmount)
		{
			if (IsMultiplayerRoomActive())
			{
				PhotonView component = ((Component)director).GetComponent<PhotonView>();
				if (!((Object)(object)component == (Object)null))
				{
					component.RPC(rpcName, (RpcTarget)0, new object[1] { targetAmount });
				}
			}
		}

		private static void RunCosmeticWorldObjectSetup(ValuableDirector director, int[] volumeIndex, List<ValuableVolume>[] volumeLists)
		{
			if (CosmeticWorldObjectTargetAmountField == null || CosmeticWorldObjectSpawnPlayerReadyField == null)
			{
				return;
			}
			SetFieldValue(CosmeticWorldObjectTargetAmountField, director, 0);
			try
			{
				if (SpawnCosmeticWorldObjectMethod == null || CosmeticWorldObjectDebugField == null)
				{
					SetCosmeticWorldObjectTargetZero(director);
					return;
				}
				string fieldValueAsString = GetFieldValueAsString(CosmeticWorldObjectDebugField, director);
				if (string.Equals(fieldValueAsString, "Normal", StringComparison.OrdinalIgnoreCase) && SemiFunc.RunIsLevel())
				{
					RunNormalCosmeticWorldObjectSetup(director, volumeIndex, volumeLists);
				}
				else if (string.Equals(fieldValueAsString, "All", StringComparison.OrdinalIgnoreCase))
				{
					InvokeSpawnCosmeticWorldObjectByName(director, "Common", volumeIndex, volumeLists);
					InvokeSpawnCosmeticWorldObjectByName(director, "Uncommon", volumeIndex, volumeLists);
					InvokeSpawnCosmeticWorldObjectByName(director, "Rare", volumeIndex, volumeLists);
					InvokeSpawnCosmeticWorldObjectByName(director, "UltraRare", volumeIndex, volumeLists);
				}
				RpcTargetAmount(director, "CosmeticWorldObjectTargetSetRPC", GetFieldValue<int>(CosmeticWorldObjectTargetAmountField, director));
				IncrementIntField(CosmeticWorldObjectSpawnPlayerReadyField, director);
			}
			catch (Exception ex)
			{
				AllMapValuablesPlugin.WriteWarning("Failure: Cosmetic world object reflection setup failed. Cosmetic target is set to 0.\n" + ex);
				SetCosmeticWorldObjectTargetZero(director);
			}
		}

		private static void RunNormalCosmeticWorldObjectSetup(ValuableDirector director, int[] volumeIndex, List<ValuableVolume>[] volumeLists)
		{
			if (CosmeticWorldObjectSetupsField == null || CosmeticWorldObjectsSpawnCurveField == null)
			{
				return;
			}
			int num = InvokeIntMethod(CosmeticWorldObjectLevelLoopsGetMethod, director, 0);
			int num2 = InvokeIntMethod(CosmeticWorldObjectLevelLoopsClampedGetMethod, director, 0);
			int num3 = Mathf.Max(1, GetFieldValue<int>(CosmeticWorldObjectsLevelLoopField, director));
			AnimationCurve fieldValue = GetFieldValue<AnimationCurve>(CosmeticWorldObjectsSpawnCurveField, director);
			if (fieldValue == null)
			{
				return;
			}
			for (int i = 0; i <= num2; i++)
			{
				float num4;
				if (i < num)
				{
					num4 = 1f;
				}
				else
				{
					int num5 = (((Object)(object)RunManager.instance != (Object)null) ? RunManager.instance.levelsCompleted : 0);
					num4 = (float)(num5 % num3) / (float)num3;
				}
				int num6 = Mathf.RoundToInt(fieldValue.Evaluate(num4) * 100f);
				int runManagerBadLuckCount = GetRunManagerBadLuckCount();
				if (runManagerBadLuckCount > 0)
				{
					num6 += Mathf.RoundToInt((float)runManagerBadLuckCount * 20f);
				}
				if (Random.Range(0, 100) < num6)
				{
					object obj = PickCosmeticRarityByCurve(director, num4);
					if (obj != null)
					{
						InvokeSpawnCosmeticWorldObject(director, obj, volumeIndex, volumeLists);
					}
				}
			}
			if (GetFieldValue<int>(CosmeticWorldObjectTargetAmountField, director) <= 0)
			{
				SetRunManagerBadLuckCount(GetRunManagerBadLuckCount() + 1);
			}
		}

		private static object PickCosmeticRarityByCurve(ValuableDirector director, float curveTime)
		{
			IList fieldValue = GetFieldValue<IList>(CosmeticWorldObjectSetupsField, director);
			if (fieldValue == null || fieldValue.Count == 0)
			{
				return null;
			}
			object result = null;
			float num = -1f;
			foreach (object item in fieldValue)
			{
				if (item == null)
				{
					continue;
				}
				FieldInfo fieldInfo = AccessTools.Field(item.GetType(), "chanceCurve");
				FieldInfo fieldInfo2 = AccessTools.Field(item.GetType(), "rarity");
				if (fieldInfo == null || fieldInfo2 == null)
				{
					continue;
				}
				object? value = fieldInfo.GetValue(item);
				AnimationCurve val = (AnimationCurve)((value is AnimationCurve) ? value : null);
				if (val == null)
				{
					continue;
				}
				int num2 = Mathf.RoundToInt(val.Evaluate(curveTime) * 100f);
				if (num2 > 0)
				{
					int num3 = Random.Range(0, num2);
					if ((float)num3 > num)
					{
						num = num3;
						result = fieldInfo2.GetValue(item);
					}
				}
			}
			return result;
		}

		private static void InvokeSpawnCosmeticWorldObjectByName(ValuableDirector director, string rarityName, int[] volumeIndex, List<ValuableVolume>[] volumeLists)
		{
			object cosmeticRarityEnumValue = GetCosmeticRarityEnumValue(rarityName);
			if (cosmeticRarityEnumValue != null)
			{
				InvokeSpawnCosmeticWorldObject(director, cosmeticRarityEnumValue, volumeIndex, volumeLists);
			}
		}

		private static object GetCosmeticRarityEnumValue(string rarityName)
		{
			if (SpawnCosmeticWorldObjectMethod == null)
			{
				return null;
			}
			ParameterInfo[] parameters = SpawnCosmeticWorldObjectMethod.GetParameters();
			if (parameters == null || parameters.Length == 0 || parameters[0] == null || !parameters[0].ParameterType.IsEnum)
			{
				return null;
			}
			try
			{
				return Enum.Parse(parameters[0].ParameterType, rarityName);
			}
			catch
			{
				return null;
			}
		}

		private static void InvokeSpawnCosmeticWorldObject(ValuableDirector director, object rarityValue, int[] volumeIndex, List<ValuableVolume>[] volumeLists)
		{
			if (!(SpawnCosmeticWorldObjectMethod == null) && rarityValue != null)
			{
				SpawnCosmeticWorldObjectMethod.Invoke(director, new object[3] { rarityValue, volumeIndex, volumeLists });
			}
		}

		private static int InvokeIntMethod(MethodInfo methodInfo, object instance, int fallbackValue)
		{
			if (methodInfo == null || instance == null)
			{
				return fallbackValue;
			}
			if (!(methodInfo.Invoke(instance, Array.Empty<object>()) is int result))
			{
				return fallbackValue;
			}
			return result;
		}

		private static int GetRunManagerBadLuckCount()
		{
			if ((Object)(object)RunManager.instance == (Object)null || RunManagerCosmeticWorldObjectBadLuckCountField == null)
			{
				return 0;
			}
			if (!(RunManagerCosmeticWorldObjectBadLuckCountField.GetValue(RunManager.instance) is int result))
			{
				return 0;
			}
			return result;
		}

		private static void SetRunManagerBadLuckCount(int value)
		{
			if (!((Object)(object)RunManager.instance == (Object)null) && !(RunManagerCosmeticWorldObjectBadLuckCountField == null))
			{
				RunManagerCosmeticWorldObjectBadLuckCountField.SetValue(RunManager.instance, value);
			}
		}

		private static void SetCosmeticWorldObjectTargetZero(ValuableDirector director)
		{
			SetFieldValue(CosmeticWorldObjectTargetAmountField, director, 0);
			RpcTargetAmount(director, "CosmeticWorldObjectTargetSetRPC", 0);
			IncrementIntField(CosmeticWorldObjectSpawnPlayerReadyField, director);
		}

		private static bool IsMultiplayerRoomActive()
		{
			return (Object)(object)GameManager.instance != (Object)null && GameManager.instance.gameMode == 1 && PhotonNetwork.CurrentRoom != null;
		}

		private static void IncrementIntField(FieldInfo fieldInfo, object instance)
		{
			if (!(fieldInfo == null) && instance != null)
			{
				int fieldValue = GetFieldValue<int>(fieldInfo, instance);
				SetFieldValue(fieldInfo, instance, fieldValue + 1);
			}
		}

		private static string GetFieldValueAsString(FieldInfo fieldInfo, object instance)
		{
			if (fieldInfo == null || instance == null)
			{
				return string.Empty;
			}
			object value = fieldInfo.GetValue(instance);
			return (value == null) ? string.Empty : value.ToString();
		}

		private static T GetFieldValue<T>(FieldInfo fieldInfo, object instance)
		{
			if (fieldInfo == null || instance == null)
			{
				return default(T);
			}
			object value = fieldInfo.GetValue(instance);
			if (value == null)
			{
				return default(T);
			}
			return (T)value;
		}

		private static void SetFieldValue(FieldInfo fieldInfo, object instance, object value)
		{
			if (!(fieldInfo == null) && instance != null)
			{
				fieldInfo.SetValue(instance, value);
			}
		}
	}
}