Decompiled source of REPOLib v3.0.3

plugins/REPOLib.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
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 Photon.Pun;
using Photon.Realtime;
using REPOLib.Extensions;
using REPOLib.Modules;
using REPOLib.Objects;
using REPOLib.Objects.Sdk;
using REPOLib.Patches;
using TMPro;
using UnityEngine;
using UnityEngine.Audio;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("Zehs")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyCopyright("Copyright © 2025 Zehs")]
[assembly: AssemblyDescription("Library for adding content to R.E.P.O.")]
[assembly: AssemblyFileVersion("3.0.3.0")]
[assembly: AssemblyInformationalVersion("3.0.3+99c6abc788bb83af8f8dd98c7c5e1a7adba2b314")]
[assembly: AssemblyProduct("REPOLib")]
[assembly: AssemblyTitle("REPOLib")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/ZehsTeam/REPOLib")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("3.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

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

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

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace REPOLib
{
	public static class BundleLoader
	{
		private class LoadOperation
		{
			public enum State
			{
				LoadingBundle,
				LoadingContent
			}

			public string Path { get; }

			public DateTime StartTime { get; }

			public State CurrentState { get; set; }

			public bool LoadContents { get; }

			public Func<AssetBundle, IEnumerator>? OnBundleLoaded { get; }

			public AssetBundleCreateRequest BundleRequest { get; }

			public TimeSpan ElapsedTime => DateTime.Now - StartTime;

			public string FileName => System.IO.Path.GetFileNameWithoutExtension(Path);

			public LoadOperation(string path, Func<AssetBundle, IEnumerator>? onBundleLoaded = null, bool loadContents = true)
			{
				Path = path;
				StartTime = DateTime.Now;
				LoadContents = loadContents;
				OnBundleLoaded = onBundleLoaded;
				BundleRequest = AssetBundle.LoadFromFileAsync(path);
				base..ctor();
			}
		}

		[CompilerGenerated]
		private sealed class <>c__DisplayClass10_0
		{
			public Action<AssetBundle> onLoaded;

			public string path;
		}

		[StructLayout(LayoutKind.Auto)]
		[CompilerGenerated]
		private struct <>c__DisplayClass14_0
		{
			public LoadOperation operation;
		}

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

			private object <>2__current;

			public LoadOperation operation;

			private <>c__DisplayClass14_0 <>8__1;

			private AssetBundle <bundle>5__2;

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

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

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

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>8__1 = default(<>c__DisplayClass14_0);
				<bundle>5__2 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>8__1.operation = operation;
					<>2__current = <>8__1.operation.BundleRequest;
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					<bundle>5__2 = <>8__1.operation.BundleRequest.assetBundle;
					if ((Object)(object)<bundle>5__2 == (Object)null)
					{
						Logger.LogError("Failed to load bundle " + <>8__1.operation.FileName + "!");
						<FinishLoadOperation>g__Finish|14_0(ref <>8__1);
						return false;
					}
					if (<>8__1.operation.LoadContents)
					{
						<>2__current = LoadBundleContent(<>8__1.operation, <bundle>5__2);
						<>1__state = 2;
						return true;
					}
					goto IL_00f6;
				case 2:
					<>1__state = -1;
					goto IL_00f6;
				case 3:
					{
						<>1__state = -1;
						break;
					}
					IL_00f6:
					if (<>8__1.operation.OnBundleLoaded != null)
					{
						<>2__current = <>8__1.operation.OnBundleLoaded(<bundle>5__2);
						<>1__state = 3;
						return true;
					}
					break;
				}
				if (ConfigManager.ExtendedLogging.Value)
				{
					Logger.LogInfo($"Loaded bundle {<>8__1.operation.FileName} in {<>8__1.operation.ElapsedTime.TotalSeconds:N1}s");
				}
				<FinishLoadOperation>g__Finish|14_0(ref <>8__1);
				return false;
			}

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

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

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

			private object <>2__current;

			public MonoBehaviour behaviour;

			private float <lastUpdate>5__2;

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

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

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

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

			private bool MoveNext()
			{
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = null;
					<>1__state = 1;
					return true;
				case 1:
				{
					<>1__state = -1;
					AllBundlesLoaded = false;
					LoadOperation[] array = _operations.ToArray();
					foreach (LoadOperation operation in array)
					{
						behaviour.StartCoroutine(FinishLoadOperation(operation));
					}
					BundleLoaderLoadingText.Create();
					<lastUpdate>5__2 = Time.time;
					break;
				}
				case 2:
					<>1__state = -1;
					break;
				}
				while (_operations.Count > 0)
				{
					if (Time.time - <lastUpdate>5__2 > 1f)
					{
						<lastUpdate>5__2 = Time.time;
						string arg = ((_operations.Count == 1) ? "bundle" : "bundles");
						BundleLoaderLoadingText.SetText($"REPOLib: Waiting for {_operations.Count} {arg} to load...");
						if (!ConfigManager.ExtendedLogging.Value)
						{
							continue;
						}
						foreach (LoadOperation operation2 in _operations)
						{
							string text = $"Loading {operation2.FileName}: {operation2.CurrentState}";
							float? num = ((operation2.CurrentState != 0) ? null : new float?(((AsyncOperation)operation2.BundleRequest).progress));
							float? num2 = num;
							if (num2.HasValue)
							{
								text += $" {num2.Value:P0}";
							}
							Logger.LogDebug(text);
						}
					}
					<>2__current = null;
					<>1__state = 2;
					return true;
				}
				Logger.LogInfo("Finished loading bundles.");
				BundleLoaderLoadingText.Hide();
				AllBundlesLoaded = true;
				Utilities.SafeInvokeEvent(BundleLoader.OnAllBundlesLoaded);
				return false;
			}

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

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

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

			private object <>2__current;

			public LoadOperation operation;

			public AssetBundle bundle;

			private AssetBundleRequest <assetRequest>5__2;

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

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

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

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

			private bool MoveNext()
			{
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					operation.CurrentState = LoadOperation.State.LoadingContent;
					<assetRequest>5__2 = bundle.LoadAllAssetsAsync<ScriptableObject>();
					<>2__current = <assetRequest>5__2;
					<>1__state = 1;
					return true;
				case 1:
				{
					<>1__state = -1;
					Object[] allAssets = <assetRequest>5__2.allAssets;
					Mod[] array = allAssets.OfType<Mod>().ToArray();
					int num = array.Length;
					if (num <= 1)
					{
						if (num == 0)
						{
							Logger.LogError("Bundle " + operation.FileName + " contains no mods!");
							return false;
						}
						Mod mod = array[0];
						foreach (Content item in allAssets.OfType<Content>().OrderByTypeFirst<Content, LevelContent>())
						{
							try
							{
								item.Initialize(mod);
							}
							catch (Exception ex)
							{
								Logger.LogError($"Failed to load {item.Name} ({((object)item).GetType().Name}) from bundle {operation.FileName} ({mod.Identifier}): {ex}");
							}
						}
						return false;
					}
					Logger.LogError("Bundle " + operation.FileName + " contains more than one mod!");
					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 List<LoadOperation> _operations = new List<LoadOperation>();

		internal static bool AllBundlesLoaded { get; private set; }

		public static event Action? OnAllBundlesLoaded;

		internal static void LoadAllBundles(string root, string withExtension)
		{
			Logger.LogInfo("Loading all bundles with extension " + withExtension + " from root " + root, extended: true);
			string[] files = Directory.GetFiles(root, "*" + withExtension, SearchOption.AllDirectories);
			string[] array = files;
			foreach (string path in array)
			{
				LoadBundleAndContent(path);
			}
		}

		public static void LoadBundleAndContent(string path)
		{
			LoadBundle(path, (Func<AssetBundle, IEnumerator>?)null, loadContents: true);
		}

		public static void LoadBundle(string path, Action<AssetBundle> onLoaded, bool loadContents = false)
		{
			<>c__DisplayClass10_0 CS$<>8__locals0 = new <>c__DisplayClass10_0();
			CS$<>8__locals0.onLoaded = onLoaded;
			CS$<>8__locals0.path = path;
			LoadBundle(CS$<>8__locals0.path, (Func<AssetBundle, IEnumerator>?)OnLoaded, loadContents);
			[IteratorStateMachine(typeof(<>c__DisplayClass10_0.<<LoadBundle>g__OnLoaded|0>d))]
			IEnumerator OnLoaded(AssetBundle bundle)
			{
				//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
				return new <>c__DisplayClass10_0.<<LoadBundle>g__OnLoaded|0>d(0)
				{
					<>4__this = CS$<>8__locals0,
					bundle = bundle
				};
			}
		}

		public static void LoadBundle(string path, Func<AssetBundle, IEnumerator>? onLoaded = null, bool loadContents = false)
		{
			Logger.LogInfo("Loading bundle at " + path + "...");
			_operations.Add(new LoadOperation(path, onLoaded, loadContents));
		}

		internal static void FinishLoadOperations(MonoBehaviour behaviour)
		{
			behaviour.StartCoroutine(FinishLoadOperationsRoutine(behaviour));
		}

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

		[IteratorStateMachine(typeof(<FinishLoadOperation>d__14))]
		private static IEnumerator FinishLoadOperation(LoadOperation operation)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <FinishLoadOperation>d__14(0)
			{
				operation = operation
			};
		}

		[IteratorStateMachine(typeof(<LoadBundleContent>d__15))]
		private static IEnumerator LoadBundleContent(LoadOperation operation, AssetBundle bundle)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <LoadBundleContent>d__15(0)
			{
				operation = operation,
				bundle = bundle
			};
		}

		[Obsolete("Use LoadBundleAndContent instead")]
		public static void LoadBundle(string path, string relativePath)
		{
			LoadBundleAndContent(path);
		}

		[CompilerGenerated]
		internal static void <FinishLoadOperation>g__Finish|14_0(ref <>c__DisplayClass14_0 P_0)
		{
			_operations.Remove(P_0.operation);
		}
	}
	internal static class BundleLoaderLoadingText
	{
		private static TMP_Text? _text;

		public static void Create()
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = GameObject.Find("HUD Canvas");
			TMP_Text val2 = Object.FindObjectOfType<TMP_Text>();
			_text = Object.Instantiate<TMP_Text>(val2, val.transform);
			((Object)((Component)_text).gameObject).name = "REPOLibText";
			((Graphic)_text).color = Color.white;
			_text.fontStyle = (FontStyles)1;
			_text.alignment = (TextAlignmentOptions)514;
			RectTransform component = ((Component)_text).GetComponent<RectTransform>();
			component.anchoredPosition = Vector2.zero;
			component.anchorMin = Vector2.zero;
			component.anchorMax = Vector2.one;
			component.sizeDelta = Vector2.zero;
			((Component)_text).gameObject.SetActive(false);
			SetText("REPOLib is loading bundles... Hang tight!");
		}

		public static void Show()
		{
			VideoOverlay.Instance.Override(999f, 0.02f, 2f);
			TMP_Text? text = _text;
			if (text != null)
			{
				((Component)text).gameObject.SetActive(true);
			}
		}

		public static void Hide()
		{
			VideoOverlay.Instance.Override(0f, 0.02f, 2f);
			TMP_Text? text = _text;
			if (text != null)
			{
				((Component)text).gameObject.SetActive(false);
			}
		}

		public static void SetText(string value)
		{
			if (!((Object)(object)_text == (Object)null))
			{
				_text.text = value;
			}
		}
	}
	internal static class ConfigManager
	{
		public static ConfigFile ConfigFile { get; private set; }

		public static ConfigEntry<bool> ExtendedLogging { get; private set; }

		public static ConfigEntry<bool> DeveloperMode { get; private set; }

		public static ConfigEntry<bool> VanillaDeveloperMode { get; private set; }

		public static void Initialize(ConfigFile configFile)
		{
			ConfigFile = configFile;
			BindConfigs();
		}

		private static void BindConfigs()
		{
			ExtendedLogging = ConfigFile.Bind<bool>("General", "ExtendedLogging", false, "Enable extended logging.");
			DeveloperMode = ConfigFile.Bind<bool>("General", "DeveloperMode", false, "Enable developer mode chat commands for testing.");
			VanillaDeveloperMode = ConfigFile.Bind<bool>("General", "VanillaDeveloperMode", false, "Enable vanilla developer mode cheats and chat commands for testing.");
			VanillaDeveloperMode.SettingChanged += delegate
			{
				SteamManagerPatch.UpdateDeveloperMode();
			};
		}
	}
	internal static class Logger
	{
		public static ManualLogSource ManualLogSource { get; private set; }

		public static void Initialize(ManualLogSource manualLogSource)
		{
			ManualLogSource = manualLogSource;
		}

		public static void LogDebug(object data)
		{
			Log((LogLevel)32, data);
		}

		public static void LogInfo(object data, bool extended = false)
		{
			Log((LogLevel)16, data, extended);
		}

		public static void LogMessage(object data, bool extended = false)
		{
			Log((LogLevel)8, data, extended);
		}

		public static void LogWarning(object data, bool extended = false)
		{
			Log((LogLevel)4, data, extended);
		}

		public static void LogError(object data, bool extended = false)
		{
			Log((LogLevel)2, data, extended);
		}

		public static void LogFatal(object data, bool extended = false)
		{
			Log((LogLevel)1, data, extended);
		}

		public static void Log(LogLevel logLevel, object data, bool extended = false)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			if (!extended || IsExtendedLoggingEnabled())
			{
				ManualLogSource manualLogSource = ManualLogSource;
				if (manualLogSource != null)
				{
					manualLogSource.Log(logLevel, data);
				}
			}
		}

		public static bool IsExtendedLoggingEnabled()
		{
			return ConfigManager.ExtendedLogging?.Value ?? false;
		}
	}
	[BepInPlugin("REPOLib", "REPOLib", "3.0.3")]
	public class Plugin : BaseUnityPlugin
	{
		private readonly Harmony _harmony = new Harmony("REPOLib");

		public static Plugin Instance { get; private set; }

		private void Awake()
		{
			Instance = this;
			Logger.Initialize(Logger.CreateLogSource("REPOLib"));
			Logger.LogInfo("REPOLib has awoken!");
			_harmony.PatchAll(typeof(RunManagerPatch));
			_harmony.PatchAll(typeof(EnemyDirectorPatch));
			_harmony.PatchAll(typeof(StatsManagerPatch));
			_harmony.PatchAll(typeof(SemiFuncPatch));
			_harmony.PatchAll(typeof(AudioManagerPatch));
			_harmony.PatchAll(typeof(SteamManagerPatch));
			_harmony.PatchAll(typeof(PlayerControllerPatch));
			_harmony.PatchAll(typeof(DebugCommandHandlerPatch));
			_harmony.PatchAll(typeof(DefaultPoolPatch));
			_harmony.PatchAll(typeof(PrefabRefPatch));
			_harmony.PatchAll(typeof(SplashScreenPatch));
			ConfigManager.Initialize(((BaseUnityPlugin)this).Config);
			Upgrades.Initialize();
			BundleLoader.LoadAllBundles(Paths.PluginPath, ".repobundle");
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "REPOLib";

		public const string PLUGIN_NAME = "REPOLib";

		public const string PLUGIN_VERSION = "3.0.3";
	}
}
namespace REPOLib.Patches
{
	[HarmonyPatch(typeof(AudioManager))]
	internal static class AudioManagerPatch
	{
		[HarmonyPatch("Start")]
		[HarmonyPostfix]
		private static void StartPatch()
		{
			Utilities.FixAudioMixerGroupsOnPrefabs();
			LevelAmbiences.RegisterLevelAmbiences();
		}
	}
	[HarmonyPatch(typeof(DebugCommandHandler))]
	internal static class DebugCommandHandlerPatch
	{
		[HarmonyPatch("Start")]
		[HarmonyPrefix]
		private static void StartPatch()
		{
			Commands.RegisterCommands();
		}
	}
	[HarmonyPatch(typeof(DefaultPool))]
	internal static class DefaultPoolPatch
	{
		[HarmonyPatch("Instantiate")]
		[HarmonyPrefix]
		private static bool InstantiatePatch(string prefabId, Vector3 position, Quaternion rotation, ref GameObject __result)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			if (!NetworkPrefabs.TryGetNetworkPrefab(prefabId, out GameObject prefab))
			{
				return true;
			}
			bool activeSelf = prefab.activeSelf;
			if (activeSelf)
			{
				prefab.SetActive(false);
			}
			__result = Object.Instantiate<GameObject>(prefab, position, rotation);
			if (activeSelf)
			{
				prefab.SetActive(true);
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(EnemyDirector))]
	internal static class EnemyDirectorPatch
	{
		[HarmonyPatch("Awake")]
		[HarmonyPostfix]
		private static void AwakePatch()
		{
			Enemies.RegisterEnemies();
		}
	}
	[HarmonyPatch(typeof(PlayerController))]
	internal static class PlayerControllerPatch
	{
		[CompilerGenerated]
		private sealed class <LateStartTranspiler>d__0 : IEnumerable<CodeInstruction>, IEnumerable, IEnumerator<CodeInstruction>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private CodeInstruction <>2__current;

			private int <>l__initialThreadId;

			private IEnumerable<CodeInstruction> instructions;

			public IEnumerable<CodeInstruction> <>3__instructions;

			private bool <found>5__2;

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

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

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

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

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

			private bool MoveNext()
			{
				//IL_0168: Unknown result type (might be due to invalid IL or missing references)
				//IL_0172: Expected O, but got Unknown
				//IL_017b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0185: Expected O, but got Unknown
				try
				{
					switch (<>1__state)
					{
					default:
						return false;
					case 0:
					{
						<>1__state = -1;
						FieldInfo fieldInfo = AccessTools.Field(typeof(PlayerController), "playerAvatarScript");
						MethodInfo methodInfo = AccessTools.Method(typeof(SemiFunc), "PlayerGetSteamID", new Type[1] { typeof(PlayerAvatar) }, (Type[])null);
						MethodInfo methodInfo2 = AccessTools.Method(typeof(Upgrades), "InvokeStartActions", new Type[1] { typeof(string) }, (Type[])null);
						<found>5__2 = false;
						int num = 0;
						List<CodeInstruction> list = new List<CodeInstruction>();
						foreach (CodeInstruction instruction in instructions)
						{
							list.Add(instruction);
							if (num switch
							{
								0 => instruction.opcode == OpCodes.Ldloc_1, 
								1 => instruction.opcode == OpCodes.Ldfld && CodeInstructionExtensions.LoadsField(instruction, fieldInfo, false), 
								2 => instruction.opcode == OpCodes.Call && CodeInstructionExtensions.Calls(instruction, methodInfo), 
								3 => instruction.opcode == OpCodes.Stloc_2, 
								_ => false, 
							})
							{
								num++;
								if (num > 3)
								{
									<found>5__2 = true;
									num = 0;
									list.Add(new CodeInstruction(OpCodes.Ldloc_2, (object)null));
									list.Add(new CodeInstruction(OpCodes.Call, (object)methodInfo2));
								}
							}
							else
							{
								num = 0;
							}
						}
						<>7__wrap2 = list.GetEnumerator();
						<>1__state = -3;
						break;
					}
					case 1:
						<>1__state = -3;
						break;
					}
					if (<>7__wrap2.MoveNext())
					{
						CodeInstruction current2 = <>7__wrap2.Current;
						<>2__current = current2;
						<>1__state = 1;
						return true;
					}
					<>m__Finally1();
					<>7__wrap2 = default(List<CodeInstruction>.Enumerator);
					if (!<found>5__2)
					{
						Logger.LogWarning("Failed to patch PlayerController.LateStart!");
					}
					return false;
				}
				catch
				{
					//try-fault
					((IDisposable)this).Dispose();
					throw;
				}
			}

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

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

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

			[DebuggerHidden]
			IEnumerator<CodeInstruction> IEnumerable<CodeInstruction>.GetEnumerator()
			{
				<LateStartTranspiler>d__0 <LateStartTranspiler>d__;
				if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
				{
					<>1__state = 0;
					<LateStartTranspiler>d__ = this;
				}
				else
				{
					<LateStartTranspiler>d__ = new <LateStartTranspiler>d__0(0);
				}
				<LateStartTranspiler>d__.instructions = <>3__instructions;
				return <LateStartTranspiler>d__;
			}

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

		[IteratorStateMachine(typeof(<LateStartTranspiler>d__0))]
		[HarmonyPatch(/*Could not decode attribute arguments.*/)]
		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> LateStartTranspiler(IEnumerable<CodeInstruction> instructions)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <LateStartTranspiler>d__0(-2)
			{
				<>3__instructions = instructions
			};
		}
	}
	[HarmonyPatch(typeof(PrefabRef))]
	internal static class PrefabRefPatch
	{
		[HarmonyPatch(/*Could not decode attribute arguments.*/)]
		[HarmonyPrefix]
		private static bool PrefabPatch(PrefabRef __instance, ref GameObject __result)
		{
			if (NetworkPrefabs.TryGetNetworkPrefab(__instance.resourcePath, out GameObject prefab))
			{
				__result = prefab;
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(RunManager))]
	internal static class RunManagerPatch
	{
		private static bool _patchedAwake;

		[HarmonyPatch("Awake")]
		[HarmonyPostfix]
		[HarmonyPriority(0)]
		private static void AwakePatch(RunManager __instance)
		{
			if (!_patchedAwake)
			{
				_patchedAwake = true;
				NetworkingEvents.Initialize();
				ValuablePresets.Initialize();
				Levels.RegisterInitialLevels();
				Valuables.RegisterInitialValuables();
				BundleLoader.FinishLoadOperations((MonoBehaviour)(object)__instance);
			}
		}
	}
	[HarmonyPatch(typeof(SemiFunc))]
	internal static class SemiFuncPatch
	{
		[HarmonyPatch("DebugTester")]
		[HarmonyPrefix]
		private static bool DebugTesterPatch(ref bool __result)
		{
			if (ConfigManager.DeveloperMode.Value)
			{
				__result = true;
				return false;
			}
			return true;
		}

		[HarmonyPatch("EnemySpawn")]
		[HarmonyPrefix]
		private static bool EnemySpawnPatch(ref bool __result)
		{
			if (Enemies.SpawnNextEnemiesNotDespawned > 0)
			{
				Enemies.SpawnNextEnemiesNotDespawned--;
				__result = true;
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(SplashScreen))]
	internal static class SplashScreenPatch
	{
		private static bool _showedBundleLoaderLoadingText;

		[HarmonyPatch("StateWarning")]
		[HarmonyPostfix]
		private static void StateWarningPatch(SplashScreen __instance)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Invalid comparison between Unknown and I4
			if ((int)__instance.state == 3)
			{
				((Component)SplashScreenUI.instance.warningTransform).gameObject.SetActive(false);
			}
		}

		[HarmonyPatch("StateDone")]
		[HarmonyPrefix]
		private static bool StateDonePatch()
		{
			if (BundleLoader.AllBundlesLoaded)
			{
				return true;
			}
			if (_showedBundleLoaderLoadingText)
			{
				return false;
			}
			_showedBundleLoaderLoadingText = true;
			int childCount = ((Component)SplashScreenUI.instance).transform.childCount;
			for (int i = 1; i < childCount; i++)
			{
				Transform child = ((Component)SplashScreenUI.instance).transform.GetChild(i);
				((Component)child).gameObject.SetActive(false);
			}
			BundleLoaderLoadingText.Show();
			return false;
		}
	}
	[HarmonyPatch(typeof(StatsManager))]
	internal static class StatsManagerPatch
	{
		[HarmonyPatch("RunStartStats")]
		[HarmonyPostfix]
		private static void RunStartStatsPatch()
		{
			Items.RegisterItems();
			Upgrades.RegisterUpgrades();
		}
	}
	[HarmonyPatch(typeof(SteamManager))]
	internal static class SteamManagerPatch
	{
		[HarmonyPatch("Awake")]
		[HarmonyPostfix]
		public static void AwakePatch(SteamManager __instance)
		{
			UpdateDeveloperMode();
		}

		public static void UpdateDeveloperMode()
		{
			if (ConfigManager.VanillaDeveloperMode == null || (Object)(object)SteamManager.instance == (Object)null)
			{
				return;
			}
			bool value = ConfigManager.VanillaDeveloperMode.Value;
			if (SteamManager.instance.developerMode != value)
			{
				if (value)
				{
					Logger.LogInfo("Enabling vanilla developer mode.");
				}
				else
				{
					Logger.LogInfo("Disabling vanilla developer mode.");
				}
			}
			SteamManager.instance.developerMode = value;
		}
	}
}
namespace REPOLib.Objects
{
	internal class PrefabRefComparer : IEqualityComparer<PrefabRef>
	{
		public StringComparison ComparisonType { get; }

		public PrefabRefComparer(StringComparison comparisonType = StringComparison.OrdinalIgnoreCase)
		{
			ComparisonType = comparisonType;
		}

		public bool Equals(PrefabRef x, PrefabRef y)
		{
			if (x == y)
			{
				return true;
			}
			if (x == null || y == null)
			{
				return false;
			}
			if (string.Equals(x.PrefabName, y.PrefabName, ComparisonType))
			{
				return string.Equals(x.ResourcePath, y.ResourcePath, ComparisonType);
			}
			return false;
		}

		public int GetHashCode(PrefabRef obj)
		{
			if (obj == null)
			{
				return 0;
			}
			int num = 17;
			num = num * 23 + (obj.PrefabName?.GetHashCode(StringComparison.OrdinalIgnoreCase) ?? 0);
			return num * 23 + (obj.ResourcePath?.GetHashCode(StringComparison.OrdinalIgnoreCase) ?? 0);
		}
	}
	internal enum PrefabRefResult
	{
		Success,
		PrefabIdNullOrEmpty,
		PrefabNull,
		PrefabAlreadyRegistered,
		DifferentPrefabAlreadyRegistered
	}
	internal struct PrefabRefResponse
	{
		public PrefabRefResult Result { get; set; }

		public PrefabRef? PrefabRef { get; set; }

		public PrefabRefResponse(PrefabRefResult result, PrefabRef? prefabRef)
		{
			Result = result;
			PrefabRef = prefabRef;
		}
	}
	internal class UnityObjectNameComparer<T> : IEqualityComparer<T> where T : Object
	{
		public StringComparison ComparisonType { get; private set; }

		public UnityObjectNameComparer(StringComparison comparisonType = StringComparison.OrdinalIgnoreCase)
		{
			ComparisonType = comparisonType;
		}

		public bool Equals(T x, T y)
		{
			if ((Object)(object)x == (Object)(object)y)
			{
				return true;
			}
			if ((Object)(object)x == (Object)null || (Object)(object)y == (Object)null)
			{
				return false;
			}
			return ((Object)x).name.Equals(((Object)y).name, ComparisonType);
		}

		public int GetHashCode(T obj)
		{
			if (!((Object)(object)obj != (Object)null))
			{
				return 0;
			}
			return ((Object)obj).name.GetHashCode();
		}
	}
}
namespace REPOLib.Objects.Sdk
{
	public abstract class Content : ScriptableObject
	{
		public abstract string Name { get; }

		public abstract void Initialize(Mod mod);
	}
	[CreateAssetMenu(menuName = "REPOLib/Enemy", order = 3, fileName = "New Enemy")]
	public class EnemyContent : Content
	{
		[SerializeField]
		private EnemySetup? _setup;

		[SerializeField]
		private List<GameObject> _spawnObjects = new List<GameObject>();

		public EnemySetup? Setup => _setup;

		public List<GameObject> SpawnObjects => _spawnObjects;

		public override string Name
		{
			get
			{
				EnemySetup? setup = Setup;
				return ((setup != null) ? ((Object)setup).name : null) ?? string.Empty;
			}
		}

		public override void Initialize(Mod mod)
		{
			Enemies.RegisterEnemy(this);
		}
	}
	[CreateAssetMenu(menuName = "REPOLib/Item", order = 2, fileName = "New Item")]
	public class ItemContent : Content
	{
		[SerializeField]
		private ItemAttributes? _prefab;

		public ItemAttributes? Prefab => _prefab;

		public override string Name
		{
			get
			{
				ItemAttributes? prefab = Prefab;
				return ((prefab != null) ? ((Object)prefab).name : null) ?? string.Empty;
			}
		}

		public override void Initialize(Mod mod)
		{
			Items.RegisterItem(this);
		}
	}
	[CreateAssetMenu(menuName = "REPOLib/Level", order = 4, fileName = "New Level")]
	public class LevelContent : Content
	{
		[SerializeField]
		private Level? _level;

		[SerializeField]
		private GameObject? _connectObject;

		[SerializeField]
		private GameObject? _blockObject;

		[SerializeField]
		private List<GameObject> _startRooms = new List<GameObject>();

		[Space]
		[Header("Difficulty 1")]
		[SerializeField]
		private List<GameObject> _modulesNormal1 = new List<GameObject>();

		[SerializeField]
		private List<GameObject> _modulesPassage1 = new List<GameObject>();

		[SerializeField]
		private List<GameObject> _modulesDeadEnd1 = new List<GameObject>();

		[SerializeField]
		private List<GameObject> _modulesExtraction1 = new List<GameObject>();

		[Space]
		[Header("Difficulty 2")]
		[SerializeField]
		private List<GameObject> _modulesNormal2 = new List<GameObject>();

		[SerializeField]
		private List<GameObject> _modulesPassage2 = new List<GameObject>();

		[SerializeField]
		private List<GameObject> _modulesDeadEnd2 = new List<GameObject>();

		[SerializeField]
		private List<GameObject> _modulesExtraction2 = new List<GameObject>();

		[Space]
		[Header("Difficulty 3")]
		[SerializeField]
		private List<GameObject> _modulesNormal3 = new List<GameObject>();

		[SerializeField]
		private List<GameObject> _modulesPassage3 = new List<GameObject>();

		[SerializeField]
		private List<GameObject> _modulesDeadEnd3 = new List<GameObject>();

		[SerializeField]
		private List<GameObject> _modulesExtraction3 = new List<GameObject>();

		public Level? Level => _level;

		public override string Name
		{
			get
			{
				Level? level = Level;
				return ((level != null) ? ((Object)level).name : null) ?? string.Empty;
			}
		}

		public GameObject? ConnectObject => _connectObject;

		public GameObject? BlockObject => _blockObject;

		public List<GameObject> StartRooms => _startRooms;

		public List<GameObject> ModulesNormal1 => _modulesNormal1;

		public List<GameObject> ModulesPassage1 => _modulesPassage1;

		public List<GameObject> ModulesDeadEnd1 => _modulesDeadEnd1;

		public List<GameObject> ModulesExtraction1 => _modulesExtraction1;

		public List<GameObject> ModulesNormal2 => _modulesNormal2;

		public List<GameObject> ModulesPassage2 => _modulesPassage2;

		public List<GameObject> ModulesDeadEnd2 => _modulesDeadEnd2;

		public List<GameObject> ModulesExtraction2 => _modulesExtraction2;

		public List<GameObject> ModulesNormal3 => _modulesNormal3;

		public List<GameObject> ModulesPassage3 => _modulesPassage3;

		public List<GameObject> ModulesDeadEnd3 => _modulesDeadEnd3;

		public List<GameObject> ModulesExtraction3 => _modulesExtraction3;

		public override void Initialize(Mod mod)
		{
			Levels.RegisterLevel(this);
		}
	}
	[CreateAssetMenu(menuName = "REPOLib/Mod", order = 0, fileName = "New Mod")]
	public class Mod : ScriptableObject
	{
		[SerializeField]
		private string _name;

		[SerializeField]
		private string _author;

		[SerializeField]
		private string _version = "1.0.0";

		[SerializeField]
		private string _description;

		[SerializeField]
		private string _websiteUrl;

		[SerializeField]
		private string[] _dependencies = new string[1] { "Zehs-REPOLib-3.0.3" };

		[SerializeField]
		private Sprite? _icon;

		[SerializeField]
		private TextAsset? _readme;

		public string Name => _name;

		public string Author => _author;

		public string Version => _version;

		public string Description => _description;

		public string WebsiteUrl => _websiteUrl;

		public IReadOnlyList<string> Dependencies => _dependencies;

		public Sprite? Icon => _icon;

		public TextAsset? Readme => _readme;

		public string FullName => Author + "-" + Name;

		public string Identifier => Author + "-" + Name + "-" + Version;
	}
	[CreateAssetMenu(menuName = "REPOLib/Valuable", order = 1, fileName = "New Valuable")]
	public class ValuableContent : Content
	{
		[SerializeField]
		private ValuableObject? _prefab;

		[SerializeField]
		private string[] _valuablePresets = new string[1] { "Valuables - Generic" };

		public ValuableObject? Prefab => _prefab;

		public IReadOnlyList<string> ValuablePresets => _valuablePresets;

		public override string Name
		{
			get
			{
				ValuableObject? prefab = Prefab;
				return ((prefab != null) ? ((Object)prefab).name : null) ?? string.Empty;
			}
		}

		public override void Initialize(Mod mod)
		{
			Valuables.RegisterValuable(this);
		}
	}
}
namespace REPOLib.Modules
{
	public static class Commands
	{
		private static readonly List<ChatCommand> _commandsToRegister = new List<ChatCommand>();

		private static readonly List<ChatCommand> _commandsRegistered = new List<ChatCommand>();

		public static IReadOnlyList<ChatCommand> AllCommands => GetCommands();

		public static IReadOnlyList<ChatCommand> RegisteredCommands => _commandsRegistered;

		internal static void RegisterCommands()
		{
			if ((Object)(object)DebugCommandHandler.instance == (Object)null)
			{
				Logger.LogError("Failed to register commands. DebugCommandHandler instance is null.");
				return;
			}
			Logger.LogInfo("Adding commands.");
			_commandsRegistered.Clear();
			foreach (ChatCommand item in _commandsToRegister)
			{
				DebugCommandHandler.instance.Register(item);
				_commandsRegistered.Add(item);
			}
		}

		public static void RegisterCommand(ChatCommand chatCommand)
		{
			ChatCommand chatCommand2 = chatCommand;
			if (chatCommand2 == null)
			{
				throw new ArgumentException("Failed to register command. ChatCommand is null.");
			}
			if (chatCommand2.Execute == null)
			{
				Logger.LogError("Failed to register command \"" + chatCommand2.Name + "\". Execute method is null.");
			}
			else if (_commandsToRegister.Contains(chatCommand2))
			{
				Logger.LogError("Failed to register command \"" + chatCommand2.Name + "\". Command is already registered!");
			}
			else if (_commandsToRegister.Any((ChatCommand x) => x.Name == chatCommand2.Name))
			{
				Logger.LogError("Failed to register command \"" + chatCommand2.Name + "\". Command already exists with the same name.");
			}
			else
			{
				_commandsToRegister.Add(chatCommand2);
			}
		}

		private static IReadOnlyList<ChatCommand> GetCommands()
		{
			if ((Object)(object)DebugCommandHandler.instance == (Object)null)
			{
				return Array.Empty<ChatCommand>();
			}
			return DebugCommandHandler.instance._commands.Values.ToList();
		}
	}
	public static class Enemies
	{
		internal static int SpawnNextEnemiesNotDespawned = 0;

		private static readonly List<EnemySetup> _enemiesToRegister = new List<EnemySetup>();

		public static IReadOnlyList<EnemySetup> AllEnemies => EnemyDirector.instance?.GetEnemies() ?? new List<EnemySetup>();

		public static IReadOnlyList<EnemySetup> RegisteredEnemies => _enemiesToRegister;

		internal static void RegisterEnemies()
		{
			Logger.LogInfo("Adding enemies.");
			foreach (EnemySetup item in _enemiesToRegister)
			{
				RegisterEnemyWithGame(item);
			}
		}

		private static void RegisterEnemyWithGame(EnemySetup enemySetup)
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			if (!enemySetup.TryGetEnemyParent(out EnemyParent enemyParent))
			{
				Logger.LogError("Failed to register enemy \"" + ((Object)enemySetup).name + "\" to game. Could not find EnemyParent component.");
			}
			else if (EnemyDirector.instance.AddEnemy(enemySetup))
			{
				Logger.LogInfo($"Added enemy \"{enemyParent.enemyName}\" to difficulty {enemyParent.difficulty}", extended: true);
			}
		}

		public static void RegisterEnemy(EnemyContent? enemyContent)
		{
			if ((Object)(object)enemyContent == (Object)null)
			{
				Logger.LogError("Failed to register enemy. EnemyContent is null.");
				return;
			}
			EnemySetup enemySetup = enemyContent.Setup;
			List<GameObject> spawnObjects = enemyContent.SpawnObjects;
			if ((Object)(object)enemySetup == (Object)null)
			{
				Logger.LogError("Failed to register enemy. EnemySetup is null.");
				return;
			}
			if (spawnObjects == null || spawnObjects.Count == 0)
			{
				Logger.LogError("Failed to register enemy \"" + enemyContent.Name + "\". No spawn objects found.");
				return;
			}
			if (_enemiesToRegister.Contains(enemySetup))
			{
				Logger.LogError("Failed to register enemy \"" + enemyContent.Name + "\". Enemy is already registered!");
				return;
			}
			if (_enemiesToRegister.Any((EnemySetup x) => ((Object)x).name == ((Object)enemySetup).name))
			{
				Logger.LogError("Failed to register enemy \"" + enemyContent.Name + "\". Enemy already exists with the same name.");
				return;
			}
			List<PrefabRef> list = new List<PrefabRef>();
			foreach (GameObject item in spawnObjects)
			{
				if ((Object)(object)item == (Object)null)
				{
					Logger.LogWarning("Enemy \"" + enemyContent.Name + "\" has a null spawn object.");
					continue;
				}
				string prefabId = "Enemies/" + ((Object)item).name;
				PrefabRefResponse prefabRefResponse = NetworkPrefabs.RegisterNetworkPrefabInternal(prefabId, item);
				PrefabRef prefabRef = prefabRefResponse.PrefabRef;
				if (prefabRefResponse.Result == PrefabRefResult.DifferentPrefabAlreadyRegistered)
				{
					Logger.LogError("Failed to register enemy \"" + enemyContent.Name + "\" spawn object. A prefab is already registered with the same name.");
					continue;
				}
				if (prefabRefResponse.Result != 0 && prefabRefResponse.Result != PrefabRefResult.PrefabAlreadyRegistered)
				{
					Logger.LogError($"Failed to register enemy \"{enemyContent.Name}\" spawn object. (Reason: {prefabRefResponse.Result})");
					continue;
				}
				if (prefabRef == null)
				{
					Logger.LogError("Failed to register enemy \"" + enemyContent.Name + "\" spawn object. PrefabRef is null.");
					continue;
				}
				if (prefabRefResponse.Result == PrefabRefResult.Success)
				{
					Utilities.FixAudioMixerGroups(item);
				}
				list.Add(prefabRef);
			}
			if (list.Count == 0)
			{
				Logger.LogError("Failed to register enemy \"" + enemyContent.Name + "\". No valid spawn objects found.");
				return;
			}
			enemySetup.spawnObjects = list;
			_enemiesToRegister.Add(enemySetup);
		}

		public static List<EnemyParent>? SpawnEnemy(EnemySetup? enemySetup, Vector3 position, Quaternion rotation, bool spawnDespawned = false)
		{
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_025f: Unknown result type (might be due to invalid IL or missing references)
			//IL_019f: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)enemySetup == (Object)null)
			{
				Logger.LogError("Failed to spawn enemy. EnemySetup is null.");
				return null;
			}
			if (!enemySetup.TryGetEnemyParent(out EnemyParent enemyParent))
			{
				Logger.LogError("Failed to spawn enemy. EnemyParent is null.");
				return null;
			}
			if ((Object)(object)LevelGenerator.Instance == (Object)null)
			{
				Logger.LogError("Failed to spawn enemy \"" + enemyParent.enemyName + "\". EnemySetup instance is null.");
				return null;
			}
			if ((Object)(object)RunManager.instance == (Object)null)
			{
				Logger.LogError("Failed to spawn enemy \"" + enemyParent.enemyName + "\". RunManager instance is null.");
				return null;
			}
			if ((Object)(object)EnemyDirector.instance == (Object)null)
			{
				Logger.LogError("Failed to spawn enemy \"" + enemyParent.enemyName + "\". EnemyDirector instance is null.");
				return null;
			}
			RunManager.instance.EnemiesSpawnedRemoveStart();
			List<EnemyParent> list = new List<EnemyParent>();
			EnemyParent val2 = default(EnemyParent);
			foreach (PrefabRef spawnObject in enemySetup.spawnObjects)
			{
				GameObject prefab = spawnObject.Prefab;
				if ((Object)(object)prefab == (Object)null)
				{
					Logger.LogError("Failed to spawn enemy \"" + enemyParent.enemyName + "\" spawn object. GameObject is null.");
					continue;
				}
				GameObject val = NetworkPrefabs.SpawnNetworkPrefab(spawnObject, position, rotation, 0);
				if ((Object)(object)val == (Object)null)
				{
					Logger.LogError("Failed to spawn enemy \"" + enemyParent.enemyName + "\" spawn object \"" + ((Object)prefab).name + "\"");
				}
				else if (val.TryGetComponent<EnemyParent>(ref val2))
				{
					list.Add(val2);
					if (!spawnDespawned)
					{
						SpawnNextEnemiesNotDespawned++;
					}
					val2.SetupDone = true;
					Enemy componentInChildren = val.GetComponentInChildren<Enemy>();
					if ((Object)(object)componentInChildren != (Object)null)
					{
						componentInChildren.EnemyTeleported(position);
					}
					else
					{
						Logger.LogError("Enemy \"" + enemyParent.enemyName + "\" spawn object \"" + ((Object)prefab).name + "\" does not have an enemy component.");
					}
					val2.firstSpawnPointUsed = true;
					LevelGenerator instance = LevelGenerator.Instance;
					instance.EnemiesSpawnTarget++;
					EnemyDirector.instance.FirstSpawnPointAdd(val2);
				}
			}
			RunManager.instance.EnemiesSpawnedRemoveEnd();
			if (list.Count == 0)
			{
				Logger.LogInfo("Failed to spawn enemy \"" + enemyParent.enemyName + "\". No spawn objects where spawned.");
				return list;
			}
			Logger.LogInfo($"Spawned enemy \"{enemyParent.enemyName}\" at position {position}", extended: true);
			return list;
		}

		[Obsolete("This is no longer supported. Use AllEnemies or RegisteredEnemies instead.", true)]
		public static IReadOnlyList<EnemySetup> GetEnemies()
		{
			Logger.LogError("This method is deprecated! " + Utilities.GetStackTrace());
			return AllEnemies;
		}

		[Obsolete("This is no longer supported. Use AllEnemies or RegisteredEnemies instead.", true)]
		public static bool TryGetEnemyByName(string name, [NotNullWhen(true)] out EnemySetup? enemySetup)
		{
			Logger.LogError("This method is deprecated! " + Utilities.GetStackTrace());
			enemySetup = null;
			return false;
		}

		[Obsolete("This is no longer supported. Use AllEnemies or RegisteredEnemies instead.", true)]
		public static EnemySetup? GetEnemyByName(string name)
		{
			Logger.LogError("This method is deprecated! " + Utilities.GetStackTrace());
			return null;
		}

		[Obsolete("This is no longer supported. Use AllEnemies or RegisteredEnemies instead.", true)]
		public static bool TryGetEnemyThatContainsName(string name, [NotNullWhen(true)] out EnemySetup? enemySetup)
		{
			Logger.LogError("This method is deprecated! " + Utilities.GetStackTrace());
			enemySetup = null;
			return false;
		}

		[Obsolete("This is no longer supported. Use AllEnemies or RegisteredEnemies instead.", true)]
		public static EnemySetup? GetEnemyThatContainsName(string name)
		{
			Logger.LogError("This method is deprecated! " + Utilities.GetStackTrace());
			return null;
		}
	}
	public static class Items
	{
		private static readonly List<Item> _itemsToRegister = new List<Item>();

		private static readonly List<Item> _itemsRegistered = new List<Item>();

		private static bool _initialItemsRegistered;

		public static IReadOnlyList<Item> AllItems => StatsManager.instance?.GetItems() ?? new List<Item>();

		public static IReadOnlyList<Item> RegisteredItems => _itemsRegistered;

		internal static void RegisterItems()
		{
			Logger.LogInfo("Adding items.");
			foreach (Item item in _itemsToRegister)
			{
				RegisterItemWithGame(item);
			}
			_initialItemsRegistered = true;
		}

		private static void RegisterItemWithGame(Item item)
		{
			if (StatsManager.instance.AddItem(item))
			{
				if (!_itemsRegistered.Contains(item))
				{
					_itemsRegistered.Add(item);
				}
				Logger.LogInfo("Added item \"" + item.itemName + "\" to StatsManager.", extended: true);
			}
			else
			{
				Logger.LogWarning("Failed to add item \"" + item.itemName + "\" to StatsManager.", extended: true);
			}
		}

		public static PrefabRef? RegisterItem(ItemAttributes? itemAttributes)
		{
			if ((Object)(object)itemAttributes == (Object)null)
			{
				Logger.LogError("Failed to register item. ItemAttributes is null.");
				return null;
			}
			Item item = itemAttributes.item;
			if ((Object)(object)item == (Object)null)
			{
				Logger.LogError("Failed to register item. Item is null.");
				return null;
			}
			GameObject gameObject = ((Component)itemAttributes).gameObject;
			string prefabId = "Items/" + ((Object)gameObject).name;
			PrefabRefResponse prefabRefResponse = NetworkPrefabs.RegisterNetworkPrefabInternal(prefabId, gameObject);
			PrefabRef prefabRef = prefabRefResponse.PrefabRef;
			if (prefabRefResponse.Result == PrefabRefResult.PrefabAlreadyRegistered)
			{
				Logger.LogWarning("Failed to register item \"" + item.itemName + "\". Item is already registered!");
				return null;
			}
			if (prefabRefResponse.Result == PrefabRefResult.DifferentPrefabAlreadyRegistered)
			{
				Logger.LogError("Failed to register item \"" + item.itemName + "\". A item prefab is already registered with the same name.");
				return null;
			}
			if (prefabRefResponse.Result != 0)
			{
				Logger.LogError($"Failed to register item \"{((Object)gameObject).name}\". (Reason: {prefabRefResponse.Result})");
				return null;
			}
			if (prefabRef == null)
			{
				Logger.LogError("Failed to register item \"" + ((Object)gameObject).name + "\". PrefabRef is null.");
				return null;
			}
			item.prefab = prefabRef;
			Utilities.FixAudioMixerGroups(gameObject);
			_itemsToRegister.Add(item);
			if (_initialItemsRegistered)
			{
				RegisterItemWithGame(item);
			}
			return prefabRef;
		}

		public static PrefabRef? RegisterItem(ItemContent? itemContent)
		{
			if ((Object)(object)itemContent == (Object)null)
			{
				Logger.LogError("Failed to register item. ItemContent is null.");
				return null;
			}
			return RegisterItem(itemContent.Prefab);
		}

		public static GameObject? SpawnItem(Item? item, Vector3 position, Quaternion rotation)
		{
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)item == (Object)null)
			{
				Logger.LogError("Failed to spawn item. Item is null.");
				return null;
			}
			if (!item.prefab.IsValid())
			{
				Logger.LogError("Failed to spawn item \"" + item.itemName + "\". PrefabRef is not valid.");
				return null;
			}
			if (!SemiFunc.IsMasterClientOrSingleplayer())
			{
				Logger.LogError("Failed to spawn item \"" + item.itemName + "\". You are not the host.");
				return null;
			}
			GameObject val = NetworkPrefabs.SpawnNetworkPrefab(item.prefab, position, rotation, 0);
			if ((Object)(object)val == (Object)null)
			{
				Logger.LogError("Failed to spawn item \"" + item.itemName + "\". Spawned GameObject is null.");
				return null;
			}
			Logger.LogInfo($"Spawned item \"{item.itemName}\" at position {position}, rotation: {((Quaternion)(ref rotation)).eulerAngles}", extended: true);
			return val;
		}

		[Obsolete("This is no longer supported. Use AllItems or RegisteredItems instead.", true)]
		public static IReadOnlyList<Item> GetItems()
		{
			Logger.LogError("This method is deprecated! " + Utilities.GetStackTrace());
			return AllItems;
		}

		[Obsolete("This is no longer supported. Use AllItems or RegisteredItems instead.", true)]
		public static bool TryGetItemByName(string name, [NotNullWhen(true)] out Item? item)
		{
			Logger.LogError("This method is deprecated! " + Utilities.GetStackTrace());
			item = null;
			return false;
		}

		[Obsolete("This is no longer supported. Use AllItems or RegisteredItems instead.", true)]
		public static Item? GetItemByName(string name)
		{
			Logger.LogError("This method is deprecated! " + Utilities.GetStackTrace());
			return null;
		}

		[Obsolete("This is no longer supported. Use AllItems or RegisteredItems instead.", true)]
		public static bool TryGetItemThatContainsName(string name, [NotNullWhen(true)] out Item? item)
		{
			Logger.LogError("This method is deprecated! " + Utilities.GetStackTrace());
			item = null;
			return false;
		}

		[Obsolete("This is no longer supported. Use AllItems or RegisteredItems instead.", true)]
		public static Item? GetItemThatContainsName(string name)
		{
			Logger.LogError("This method is deprecated! " + Utilities.GetStackTrace());
			return null;
		}
	}
	internal static class LevelAmbiences
	{
		private static readonly List<LevelAmbience> _levelAmbiencesRegistered = new List<LevelAmbience>();

		private static readonly List<Level> _levelToProcess = new List<Level>();

		private static readonly List<Level> _levelsProcessed = new List<Level>();

		private static bool _initialLevelAmbiencesRegistered;

		public static IReadOnlyList<LevelAmbience> AllLevelAmbiences => AudioManager.instance?.levelAmbiences ?? new List<LevelAmbience>();

		public static IReadOnlyList<LevelAmbience> RegisteredLevelAmbiences => _levelAmbiencesRegistered;

		internal static void RegisterLevelAmbiences()
		{
			if (_initialLevelAmbiencesRegistered)
			{
				foreach (LevelAmbience item in _levelAmbiencesRegistered)
				{
					AddLevelAmbienceToAudioManager(item);
				}
				return;
			}
			Logger.LogInfo("Adding level ambiences.");
			foreach (Level item2 in _levelToProcess)
			{
				RegisterLevelAmbiencesWithGame(item2);
			}
			_initialLevelAmbiencesRegistered = true;
		}

		private static void AddLevelAmbienceToAudioManager(LevelAmbience levelAmbience)
		{
			if (!AllLevelAmbiences.Contains(levelAmbience))
			{
				AudioManager.instance.levelAmbiences.Add(levelAmbience);
				Logger.LogInfo("Added level ambience \"" + ((Object)levelAmbience).name + "\" to AudioManager.", extended: true);
			}
		}

		private static void RegisterLevelAmbiencesWithGame(Level level)
		{
			if (_levelsProcessed.Contains(level))
			{
				return;
			}
			for (int i = 0; i < level.AmbiencePresets.Count; i++)
			{
				LevelAmbience val = level.AmbiencePresets[i];
				if (!AudioManager.instance.levelAmbiences.Contains(val))
				{
					if (TryGetLevelAmbience(((Object)val).name, out LevelAmbience levelAmbience))
					{
						level.AmbiencePresets[i] = levelAmbience;
						Logger.LogInfo("Replaced existing level ambience \"" + ((Object)val).name + "\" in level \"" + ((Object)level).name + "\"", extended: true);
					}
					else
					{
						AddLevelAmbienceToAudioManager(val);
						_levelAmbiencesRegistered.Add(val);
						Logger.LogInfo("Registered level ambience \"" + ((Object)val).name + "\" from level \"" + ((Object)level).name + "\"", extended: true);
					}
				}
			}
			_levelsProcessed.Add(level);
		}

		public static void RegisterLevelAmbience(Level? level)
		{
			if ((Object)(object)level == (Object)null)
			{
				Logger.LogError("Failed to register level ambience for level. Level is null.");
				return;
			}
			if (_levelToProcess.Contains(level))
			{
				Logger.LogWarning("Failed to register level ambience for level \"" + ((Object)level).name + "\". Level has already been processed!");
				return;
			}
			_levelToProcess.Add(level);
			if (_initialLevelAmbiencesRegistered)
			{
				RegisterLevelAmbiencesWithGame(level);
			}
		}

		private static bool TryGetLevelAmbience(string name, [NotNullWhen(true)] out LevelAmbience? levelAmbience)
		{
			string name2 = name;
			levelAmbience = ((IEnumerable<LevelAmbience>)AllLevelAmbiences).FirstOrDefault((Func<LevelAmbience, bool>)((LevelAmbience x) => ((Object)x).name == name2));
			return (Object)(object)levelAmbience != (Object)null;
		}
	}
	public static class Levels
	{
		private enum ModuleType
		{
			StartRoom,
			Normal,
			Passage,
			DeadEnd,
			Extraction
		}

		private static readonly List<Level> _levelsToRegister = new List<Level>();

		private static readonly List<Level> _levelsRegistered = new List<Level>();

		private static bool _initialLevelsRegistered;

		public static IReadOnlyList<Level> AllLevels => RunManager.instance?.levels ?? new List<Level>();

		public static IReadOnlyList<Level> RegisteredLevels => _levelsRegistered;

		internal static void RegisterInitialLevels()
		{
			if (_initialLevelsRegistered)
			{
				return;
			}
			Logger.LogInfo("Adding levels.");
			foreach (Level item in _levelsToRegister)
			{
				RegisterLevelWithGame(item);
			}
			_initialLevelsRegistered = true;
		}

		private static void RegisterLevelWithGame(Level level)
		{
			if (!_levelsRegistered.Contains(level))
			{
				RegisterLevelValuablePresets(level);
				LevelAmbiences.RegisterLevelAmbience(level);
				RunManager.instance.levels.Add(level);
				Logger.LogInfo("Added level \"" + ((Object)level).name + "\"", extended: true);
				_levelsRegistered.Add(level);
			}
		}

		private static void RegisterLevelValuablePresets(Level level)
		{
			if (level.ValuablePresets.Count == 0)
			{
				Logger.LogWarning("Level \"" + ((Object)level).name + "\" does not have any valuable presets! Adding generic preset.");
				level.ValuablePresets.Add(ValuablePresets.GenericValuablePreset);
				return;
			}
			for (int i = 0; i < level.ValuablePresets.Count; i++)
			{
				LevelValuables val = level.ValuablePresets[i];
				if (!ValuablePresets.AllValuablePresets.Values.Contains(val))
				{
					if (ValuablePresets.AllValuablePresets.TryGetValue(((Object)val).name, out LevelValuables value))
					{
						level.ValuablePresets[i] = value;
						Logger.LogInfo("Replaced proxy valuable preset \"" + ((Object)val).name + "\" in level \"" + ((Object)level).name + "\"", extended: true);
					}
					else
					{
						ValuablePresets.RegisterValuablePreset(val);
						Logger.LogInfo("Registered valuable preset \"" + ((Object)val).name + "\" from level \"" + ((Object)level).name + "\"", extended: true);
					}
				}
			}
		}

		public static void RegisterLevel(LevelContent? levelContent)
		{
			if ((Object)(object)levelContent == (Object)null)
			{
				Logger.LogError("Failed to register level. LevelContent is null.");
				return;
			}
			Level level = levelContent.Level;
			if ((Object)(object)level == (Object)null)
			{
				Logger.LogError("Failed to register level. Level is null.");
				return;
			}
			if (_levelsToRegister.Contains(level))
			{
				Logger.LogWarning("Failed to register level \"" + ((Object)level).name + "\". Level is already registered!");
				return;
			}
			if (_levelsToRegister.Any((Level x) => ((Object)x).name.Equals(((Object)level).name, StringComparison.OrdinalIgnoreCase)))
			{
				Logger.LogError("Failed to register level \"" + ((Object)level).name + "\". Level already exists with the same name.");
				return;
			}
			GameObject connectObject = levelContent.ConnectObject;
			if ((Object)(object)connectObject != (Object)null)
			{
				RegisterLevelPrefab("Level/" + level.ResourcePath + "/Other/" + ((Object)connectObject).name, connectObject);
				level.ConnectObject = connectObject;
			}
			GameObject blockObject = levelContent.BlockObject;
			if ((Object)(object)blockObject != (Object)null)
			{
				RegisterLevelPrefab("Level/" + level.ResourcePath + "/Other/" + ((Object)blockObject).name, blockObject);
				level.BlockObject = blockObject;
			}
			level.StartRooms = RegisterLevelModules(level, ModuleType.StartRoom, levelContent.StartRooms);
			level.ModulesNormal1 = RegisterLevelModules(level, ModuleType.Normal, levelContent.ModulesNormal1);
			level.ModulesPassage1 = RegisterLevelModules(level, ModuleType.Passage, levelContent.ModulesPassage1);
			level.ModulesDeadEnd1 = RegisterLevelModules(level, ModuleType.DeadEnd, levelContent.ModulesDeadEnd1);
			level.ModulesExtraction1 = RegisterLevelModules(level, ModuleType.Extraction, levelContent.ModulesExtraction1);
			level.ModulesNormal2 = RegisterLevelModules(level, ModuleType.Normal, levelContent.ModulesNormal2);
			level.ModulesPassage2 = RegisterLevelModules(level, ModuleType.Passage, levelContent.ModulesPassage2);
			level.ModulesDeadEnd2 = RegisterLevelModules(level, ModuleType.DeadEnd, levelContent.ModulesDeadEnd2);
			level.ModulesExtraction2 = RegisterLevelModules(level, ModuleType.Extraction, levelContent.ModulesExtraction2);
			level.ModulesNormal3 = RegisterLevelModules(level, ModuleType.Normal, levelContent.ModulesNormal3);
			level.ModulesPassage3 = RegisterLevelModules(level, ModuleType.Passage, levelContent.ModulesPassage3);
			level.ModulesDeadEnd3 = RegisterLevelModules(level, ModuleType.DeadEnd, levelContent.ModulesDeadEnd3);
			level.ModulesExtraction3 = RegisterLevelModules(level, ModuleType.Extraction, levelContent.ModulesExtraction3);
			_levelsToRegister.Add(level);
			if (_initialLevelsRegistered)
			{
				RegisterLevelWithGame(level);
			}
		}

		private static List<PrefabRef> RegisterLevelModules(Level level, ModuleType moduleType, List<GameObject> modules)
		{
			List<PrefabRef> list = new List<PrefabRef>();
			foreach (GameObject module in modules)
			{
				string prefabId = $"Level/{((Object)level).name}/{moduleType}/{((Object)module).name}";
				PrefabRef val = RegisterLevelPrefab(prefabId, module);
				if (val != null)
				{
					list.Add(val);
				}
			}
			return list;
		}

		private static PrefabRef? RegisterLevelPrefab(string prefabId, GameObject prefab)
		{
			PrefabRefResponse prefabRefResponse = NetworkPrefabs.RegisterNetworkPrefabInternal(prefabId, prefab);
			if (prefabRefResponse.Result == PrefabRefResult.Success)
			{
				Utilities.FixAudioMixerGroups(prefab);
				return prefabRefResponse.PrefabRef;
			}
			if (prefabRefResponse.Result == PrefabRefResult.PrefabAlreadyRegistered)
			{
				return prefabRefResponse.PrefabRef;
			}
			if (prefabRefResponse.Result == PrefabRefResult.DifferentPrefabAlreadyRegistered)
			{
				Logger.LogError("Failed to register level network prefab \"" + prefabId + "\". A prefab is already registered with the same prefab ID.");
				return null;
			}
			Logger.LogError($"Failed to register level network prefab \"{prefabId}\". (Reason: {prefabRefResponse.Result})");
			return null;
		}

		[Obsolete("This is no longer supported. Use AllLevels or RegisteredLevels instead.", true)]
		public static IReadOnlyList<Level> GetLevels()
		{
			Logger.LogError("This method is deprecated! " + Utilities.GetStackTrace());
			return AllLevels;
		}

		[Obsolete("This is no longer supported. Use AllLevels or RegisteredLevels instead.", true)]
		public static bool TryGetLevelByName(string name, [NotNullWhen(true)] out Level? level)
		{
			Logger.LogError("This method is deprecated! " + Utilities.GetStackTrace());
			level = null;
			return false;
		}

		[Obsolete("This is no longer supported. Use AllLevels or RegisteredLevels instead.", true)]
		public static Level? GetLevelByName(string name)
		{
			Logger.LogError("This method is deprecated! " + Utilities.GetStackTrace());
			return null;
		}

		[Obsolete("This is no longer supported. Use AllLevels or RegisteredLevels instead.", true)]
		public static bool TryGetLevelThatContainsName(string name, [NotNullWhen(true)] out Level? level)
		{
			Logger.LogError("This method is deprecated! " + Utilities.GetStackTrace());
			level = null;
			return false;
		}

		[Obsolete("This is no longer supported. Use AllLevels or RegisteredLevels instead.", true)]
		public static Level? GetLevelThatContainsName(string name)
		{
			Logger.LogError("This method is deprecated! " + Utilities.GetStackTrace());
			return null;
		}
	}
	public static class NetworkingEvents
	{
		public static readonly byte[] ReservedEventCodes = new byte[3] { 0, 1, 2 };

		private static readonly List<NetworkedEvent> _customEvents = new List<NetworkedEvent>();

		public static readonly RaiseEventOptions RaiseAll = new RaiseEventOptions
		{
			Receivers = (ReceiverGroup)1
		};

		public static readonly RaiseEventOptions RaiseOthers = new RaiseEventOptions
		{
			Receivers = (ReceiverGroup)0
		};

		public static readonly RaiseEventOptions RaiseMasterClient = new RaiseEventOptions
		{
			Receivers = (ReceiverGroup)2
		};

		public static IReadOnlyList<NetworkedEvent> CustomEvents => _customEvents;

		internal static void Initialize()
		{
			PhotonNetwork.NetworkingClient.EventReceived += OnEvent;
			Application.quitting += delegate
			{
				PhotonNetwork.NetworkingClient.EventReceived -= OnEvent;
			};
		}

		internal static void AddCustomEvent(NetworkedEvent networkedEvent)
		{
			if (!_customEvents.Contains(networkedEvent))
			{
				_customEvents.Add(networkedEvent);
			}
		}

		private static void OnEvent(EventData photonEvent)
		{
			EventData photonEvent2 = photonEvent;
			_customEvents.FirstOrDefault((NetworkedEvent e) => e.EventCode == photonEvent2.Code)?.EventAction?.Invoke(photonEvent2);
		}

		internal static bool TryGetUniqueEventCode(out byte eventCode)
		{
			eventCode = 0;
			while (IsEventCodeTaken(eventCode) && eventCode < 200)
			{
				eventCode++;
			}
			if (eventCode > 200 || (eventCode == 200 && IsEventCodeTaken(eventCode)))
			{
				eventCode = 0;
				return false;
			}
			return true;
		}

		public static bool IsEventCodeTaken(byte eventCode)
		{
			if (ReservedEventCodes.Any((byte x) => x == eventCode))
			{
				return true;
			}
			if (_customEvents.Any((NetworkedEvent x) => x.EventCode == eventCode))
			{
				return true;
			}
			return false;
		}
	}
	public class NetworkedEvent
	{
		public string Name { get; private set; }

		public byte EventCode { get; private set; }

		public Action<EventData> EventAction { get; private set; }

		public NetworkedEvent(string name, Action<EventData> eventAction)
		{
			Name = name;
			EventAction = eventAction;
			if (NetworkingEvents.TryGetUniqueEventCode(out var eventCode))
			{
				EventCode = eventCode;
				NetworkingEvents.AddCustomEvent(this);
				Logger.LogInfo($"Registered NetworkedEvent \"{Name}\" with event code: {EventCode}", extended: true);
			}
			else
			{
				Logger.LogError("Failed to register NetworkedEvent \"" + Name + "\". Could not get unique event code.");
			}
		}

		public void RaiseEvent(object eventContent, RaiseEventOptions raiseEventOptions, SendOptions sendOptions)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			if (SemiFunc.IsMultiplayer())
			{
				PhotonNetwork.RaiseEvent(EventCode, eventContent, raiseEventOptions, sendOptions);
			}
			else if ((int)raiseEventOptions.Receivers != 0)
			{
				RaiseEventSingleplayer(eventContent);
			}
		}

		private void RaiseEventSingleplayer(object eventContent)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Expected O, but got Unknown
			if (!SemiFunc.IsMultiplayer())
			{
				EventData val = new EventData
				{
					Code = EventCode
				};
				val.Parameters[val.CustomDataKey] = eventContent;
				val.Parameters[val.SenderKey] = 1;
				EventAction?.Invoke(val);
			}
		}
	}
	public static class NetworkPrefabs
	{
		private static readonly Dictionary<string, GameObject> _prefabs = new Dictionary<string, GameObject>();

		private static readonly Dictionary<string, PrefabRef> _prefabRefs = new Dictionary<string, PrefabRef>();

		public static IReadOnlyDictionary<string, GameObject> Prefabs => _prefabs;

		public static IReadOnlyDictionary<string, PrefabRef> PrefabRefs => _prefabRefs;

		public static PrefabRef? RegisterNetworkPrefab(GameObject prefab)
		{
			return RegisterNetworkPrefab(((Object)prefab).name, prefab);
		}

		public static PrefabRef? RegisterNetworkPrefab(string prefabId, GameObject prefab)
		{
			PrefabRefResponse prefabRefResponse = RegisterNetworkPrefabInternal(prefabId, prefab);
			switch (prefabRefResponse.Result)
			{
			case PrefabRefResult.Success:
				return prefabRefResponse.PrefabRef;
			case PrefabRefResult.PrefabIdNullOrEmpty:
				Logger.LogError("Failed to register network prefab. PrefabId is null.");
				return null;
			case PrefabRefResult.PrefabNull:
				Logger.LogError("Failed to register network prefab. Prefab is null.");
				return null;
			case PrefabRefResult.PrefabAlreadyRegistered:
				Logger.LogWarning("Failed to register network prefab \"" + prefabId + "\". Prefab is already registered.");
				return prefabRefResponse.PrefabRef;
			case PrefabRefResult.DifferentPrefabAlreadyRegistered:
				Logger.LogError("Failed to register network prefab \"" + prefabId + "\". A prefab is already registered with the same ID. (GameObject: \"" + ((Object)prefabRefResponse.PrefabRef.Prefab).name + "\")");
				return null;
			default:
				return prefabRefResponse.PrefabRef;
			}
		}

		internal static PrefabRefResponse RegisterNetworkPrefabInternal(string prefabId, GameObject prefab)
		{
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Expected O, but got Unknown
			if (string.IsNullOrEmpty(prefabId))
			{
				return new PrefabRefResponse(PrefabRefResult.PrefabIdNullOrEmpty, null);
			}
			if ((Object)(object)prefab == (Object)null)
			{
				return new PrefabRefResponse(PrefabRefResult.PrefabNull, null);
			}
			PrefabRef networkPrefabRef = GetNetworkPrefabRef(prefabId);
			if (networkPrefabRef != null)
			{
				GameObject prefab2 = networkPrefabRef.Prefab;
				if ((Object)(object)prefab == (Object)(object)prefab2)
				{
					return new PrefabRefResponse(PrefabRefResult.PrefabAlreadyRegistered, networkPrefabRef);
				}
				return new PrefabRefResponse(PrefabRefResult.DifferentPrefabAlreadyRegistered, networkPrefabRef);
			}
			PrefabRef val = new PrefabRef
			{
				prefabName = ((Object)prefab).name,
				resourcePath = prefabId
			};
			_prefabs.Add(prefabId, prefab);
			_prefabRefs.Add(prefabId, val);
			return new PrefabRefResponse(PrefabRefResult.Success, val);
		}

		public static bool HasNetworkPrefab(string prefabId)
		{
			return _prefabs.ContainsKey(prefabId);
		}

		public static PrefabRef? GetNetworkPrefabRef(string prefabId)
		{
			return _prefabRefs.GetValueOrDefault(prefabId);
		}

		public static bool TryGetNetworkPrefabRef(string prefabId, [NotNullWhen(true)] out PrefabRef? prefabRef)
		{
			prefabRef = GetNetworkPrefabRef(prefabId);
			return prefabRef != null;
		}

		internal static bool TryGetNetworkPrefab(string prefabId, [NotNullWhen(true)] out GameObject? prefab)
		{
			prefab = _prefabs.GetValueOrDefault(prefabId);
			return (Object)(object)prefab != (Object)null;
		}

		public static GameObject? SpawnNetworkPrefab(PrefabRef prefabRef, Vector3 position, Quaternion rotation, byte group = 0, object[]? data = null)
		{
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			if (!prefabRef.IsValid())
			{
				Logger.LogError("Failed to spawn network prefab. PrefabRef is not valid.");
				return null;
			}
			if (!SemiFunc.IsMasterClientOrSingleplayer())
			{
				Logger.LogError("Failed to spawn network prefab \"" + prefabRef.PrefabName + "\". You are not the host.");
				return null;
			}
			if (SemiFunc.IsMultiplayer())
			{
				return PhotonNetwork.InstantiateRoomObject(prefabRef.ResourcePath, position, rotation, group, data);
			}
			return Object.Instantiate<GameObject>(prefabRef.Prefab, position, rotation);
		}
	}
	public static class Upgrades
	{
		private static readonly Dictionary<string, PlayerUpgrade> _playerUpgrades = new Dictionary<string, PlayerUpgrade>();

		private static NetworkedEvent? _upgradeEvent;

		public static IReadOnlyList<PlayerUpgrade> PlayerUpgrades => _playerUpgrades.Values.ToList();

		internal static void Initialize()
		{
			_upgradeEvent = new NetworkedEvent("REPOLib Upgrade", HandleUpgradeEvent);
		}

		internal static void RegisterUpgrades()
		{
			if ((Object)(object)StatsManager.instance == (Object)null)
			{
				Logger.LogError("Upgrades: Failed to register upgrades. StatsManager instance is null.");
				return;
			}
			foreach (KeyValuePair<string, PlayerUpgrade> playerUpgrade in _playerUpgrades)
			{
				string text = "playerUpgrade" + playerUpgrade.Key;
				Dictionary<string, int> playerDictionary = playerUpgrade.Value.PlayerDictionary;
				if (StatsManager.instance.dictionaryOfDictionaries.TryGetValue(text, out var value))
				{
					playerDictionary = value;
					Logger.LogInfo("Upgrades: Loaded upgrade \"" + text + "\" from StatsManager.", extended: true);
				}
				else
				{
					playerDictionary.Clear();
					StatsManager.instance.dictionaryOfDictionaries.Add(text, playerDictionary);
					Logger.LogInfo("Upgrades: Added upgrade \"" + text + "\" to StatsManager.", extended: true);
				}
			}
		}

		internal static void InvokeStartActions(string steamId)
		{
			PlayerAvatar val = SemiFunc.PlayerAvatarGetFromSteamID(steamId);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			string arg = SemiFunc.PlayerGetName(val);
			foreach (PlayerUpgrade playerUpgrade in PlayerUpgrades)
			{
				if (playerUpgrade.StartAction != null)
				{
					try
					{
						int level = playerUpgrade.GetLevel(steamId);
						playerUpgrade.StartAction(val, level);
						Logger.LogDebug($"Upgrades: Invoked start action for upgrade \"{playerUpgrade.UpgradeId}\" on player \"{arg}\" at level {level}");
					}
					catch (Exception arg2)
					{
						Logger.LogError($"Upgrades: Failed to invoke start action for upgrade \"{playerUpgrade.UpgradeId}\" on player \"{arg}\". {arg2}");
					}
				}
			}
		}

		internal static void RaiseUpgradeEvent(string upgradeId, string steamId, int level)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Expected O, but got Unknown
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected O, but got Unknown
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Expected O, but got Unknown
			//IL_0037: Expected O, but got Unknown
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			if (_upgradeEvent != null)
			{
				Hashtable val = new Hashtable();
				((Dictionary<object, object>)val).Add((object)"UpgradeId", (object)upgradeId);
				((Dictionary<object, object>)val).Add((object)"SteamId", (object)steamId);
				((Dictionary<object, object>)val).Add((object)"Level", (object)level);
				Hashtable eventContent = val;
				_upgradeEvent.RaiseEvent(eventContent, NetworkingEvents.RaiseOthers, SendOptions.SendReliable);
			}
		}

		private static void HandleUpgradeEvent(EventData eventData)
		{
			object customData = eventData.CustomData;
			Hashtable val = (Hashtable)((customData is Hashtable) ? customData : null);
			if (val != null)
			{
				string upgradeId = (string)val[(object)"UpgradeId"];
				string steamId = (string)val[(object)"SteamId"];
				int level = (int)val[(object)"Level"];
				if (TryGetUpgrade(upgradeId, out PlayerUpgrade playerUpgrade))
				{
					playerUpgrade.ApplyUpgrade(steamId, level);
				}
			}
		}

		public static PlayerUpgrade? RegisterUpgrade(string upgradeId, Item? item, Action<PlayerAvatar, int>? startAction, Action<PlayerAvatar, int>? upgradeAction)
		{
			if (_playerUpgrades.ContainsKey(upgradeId))
			{
				Logger.LogError("Failed to register upgrade \"" + upgradeId + "\". An upgrade with this UpgradeId has already been registered.");
				return null;
			}
			PlayerUpgrade playerUpgrade = new PlayerUpgrade(upgradeId, item, startAction, upgradeAction);
			_playerUpgrades.Add(upgradeId, playerUpgrade);
			return playerUpgrade;
		}

		public static PlayerUpgrade? GetUpgrade(string upgradeId)
		{
			if (_playerUpgrades.TryGetValue(upgradeId, out PlayerUpgrade value))
			{
				return value;
			}
			return null;
		}

		public static bool TryGetUpgrade(string upgradeId, [NotNullWhen(true)] out PlayerUpgrade? playerUpgrade)
		{
			playerUpgrade = GetUpgrade(upgradeId);
			return playerUpgrade != null;
		}
	}
	public class PlayerUpgrade
	{
		public readonly string UpgradeId;

		public readonly Item? Item;

		public Dictionary<string, int> PlayerDictionary = new Dictionary<string, int>();

		internal readonly Action<PlayerAvatar, int>? StartAction;

		private readonly Action<PlayerAvatar, int>? _upgradeAction;

		internal PlayerUpgrade(string upgradeId, Item? item, Action<PlayerAvatar, int>? startAction, Action<PlayerAvatar, int>? upgradeAction)
		{
			UpgradeId = upgradeId;
			Item = item;
			StartAction = startAction;
			_upgradeAction = upgradeAction;
		}

		public int GetLevel(PlayerAvatar playerAvatar)
		{
			if ((Object)(object)playerAvatar == (Object)null)
			{
				return 0;
			}
			return GetLevel(playerAvatar.steamID);
		}

		public int GetLevel(string steamId)
		{
			if (PlayerDictionary.TryGetValue(steamId, out var value))
			{
				return value;
			}
			return 0;
		}

		public int AddLevel(PlayerAvatar playerAvatar, int amount = 1)
		{
			if ((Object)(object)playerAvatar == (Object)null)
			{
				return 0;
			}
			return AddLevel(playerAvatar.steamID, amount);
		}

		public int AddLevel(string steamId, int amount = 1)
		{
			return ChangeLevelBy(steamId, amount);
		}

		public int RemoveLevel(PlayerAvatar playerAvatar, int amount = 1)
		{
			if ((Object)(object)playerAvatar == (Object)null)
			{
				return 0;
			}
			return RemoveLevel(playerAvatar.steamID, amount);
		}

		public int RemoveLevel(string steamId, int amount = 1)
		{
			return ChangeLevelBy(steamId, -amount);
		}

		public int SetLevel(PlayerAvatar playerAvatar, int level)
		{
			if ((Object)(object)playerAvatar == (Object)null)
			{
				return 0;
			}
			return SetLevel(playerAvatar.steamID, level);
		}

		public int SetLevel(string steamId, int level)
		{
			level = Mathf.Max(level, 0);
			PlayerDictionary[steamId] = level;
			ApplyUpgrade(steamId, level);
			Upgrades.RaiseUpgradeEvent(UpgradeId, steamId, level);
			return level;
		}

		private int ChangeLevelBy(string steamId, int amount)
		{
			int level = GetLevel(steamId);
			level += amount;
			return SetLevel(steamId, level);
		}

		internal void ApplyUpgrade(string steamId, int level)
		{
			PlayerDictionary[steamId] = level;
			if (_upgradeAction == null)
			{
				return;
			}
			PlayerAvatar val = SemiFunc.PlayerAvatarGetFromSteamID(steamId);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			string arg = SemiFunc.PlayerGetName(val);
			try
			{
				_upgradeAction(val, GetLevel(steamId));
				Logger.LogDebug($"PlayerUpgrade: Invoked upgrade action for upgrade \"{UpgradeId}\" on player \"{arg}\" at level {level}");
			}
			catch (Exception arg2)
			{
				Logger.LogError($"PlayerUpgrade: Failed to invoke upgrade action for upgrade \"{UpgradeId}\" on player \"{arg}\". {arg2}");
			}
		}
	}
	public class REPOLibItemUpgrade : MonoBehaviour
	{
		[SerializeField]
		private string _upgradeId;

		private ItemToggle _itemToggle;

		public string UpgradeId => _upgradeId;

		private void Start()
		{
			_itemToggle = ((Component)this).GetComponent<ItemToggle>();
		}

		public void Upgrade()
		{
			if ((Object)(object)_itemToggle == (Object)null)
			{
				Logger.LogError("REPOLibItemUpgrade: Failed to upgrade \"" + UpgradeId + "\". ItemToggle is null.");
				return;
			}
			int playerTogglePhotonID = _itemToggle.playerTogglePhotonID;
			PlayerAvatar val = SemiFunc.PlayerAvatarGetFromPhotonID(playerTogglePhotonID);
			if ((Object)(object)val == (Object)null)
			{
				Logger.LogError($"REPOLibItemUpgrade: Failed to upgrade \"{UpgradeId}\". Could not find PlayerAvatar from ItemToggle's playerTogglePhotonID {playerTogglePhotonID}.");
			}
			else if (val.isLocal)
			{
				if (!Upgrades.TryGetUpgrade(UpgradeId, out PlayerUpgrade playerUpgrade))
				{
					Logger.LogError("REPOLibItemUpgrade: Failed to upgrade \"" + UpgradeId + "\". Could not find PlayerUpgrade from UpgradeId.");
				}
				else
				{
					playerUpgrade.AddLevel(val);
				}
			}
		}
	}
	public static class Utilities
	{
		private static readonly List<GameObject> _prefabsToFix = new List<GameObject>();

		private static readonly List<GameObject> _fixedPrefabs = new List<GameObject>();

		internal static void FixAudioMixerGroupsOnPrefabs()
		{
			foreach (GameObject item in _prefabsToFix)
			{
				item.FixAudioMixerGroups();
				_fixedPrefabs.Add(item);
			}
			_prefabsToFix.Clear();
		}

		public static void FixAudioMixerGroups(GameObject prefab)
		{
			if (!((Object)(object)prefab == (Object)null) && !_prefabsToFix.Contains(prefab) && !_fixedPrefabs.Contains(prefab))
			{
				if ((Object)(object)AudioManager.instance == (Object)null)
				{
					_prefabsToFix.Add(prefab);
					return;
				}
				prefab.FixAudioMixerGroups();
				_fixedPrefabs.Add(prefab);
			}
		}

		internal static void SafeInvokeEvent(Action? action)
		{
			try
			{
				action?.Invoke();
			}
			catch (Exception arg)
			{
				Logger.LogError($"Exception occured while invoking event: {arg}");
			}
		}

		internal static string GetStackTrace()
		{
			StackTrace stackTrace = new StackTrace(1, fNeedFileInfo: true);
			return stackTrace.ToString();
		}
	}
	public static class ValuablePresets
	{
		private static readonly Dictionary<string, LevelValuables> _valuablePresets = new Dictionary<string, LevelValuables>();

		public const string GenericValuablePresetName = "Valuables - Generic";

		public static IReadOnlyDictionary<string, LevelValuables> AllValuablePresets => _valuablePresets;

		public static LevelValuables GenericValuablePreset => AllValuablePresets.GetValueOrDefault("Valuables - Generic");

		[Obsolete("Use GenericValuablePreset instead.", true)]
		public static LevelValuables GenericPreset => GenericValuablePreset;

		internal static void Initialize()
		{
			if ((Object)(object)RunManager.instance == (Object)null)
			{
				Logger.LogError("Failed to initialize ValuablePresets. RunManager instance is null.");
				return;
			}
			AddValuablePresets(RunManager.instance.levelArena.ValuablePresets);
			foreach (Level level in RunManager.instance.levels)
			{
				AddValuablePresets(level.ValuablePresets);
			}
			AddGenericValuablePresetToVanillaLevels();
		}

		private static void AddGenericValuablePresetToVanillaLevels()
		{
			LevelValuables genericValuablePreset = GenericValuablePreset;
			if ((Object)(object)genericValuablePreset == (Object)null)
			{
				Logger.LogError("Failed to add \"Valuables - Generic\" valuable preset to vanilla levels. Valuable preset is null.");
				return;
			}
			genericValuablePreset.tiny.Clear();
			genericValuablePreset.small.Clear();
			genericValuablePreset.medium.Clear();
			genericValuablePreset.big.Clear();
			genericValuablePreset.wide.Clear();
			genericValuablePreset.tall.Clear();
			genericValuablePreset.veryTall.Clear();
			foreach (Level level in RunManager.instance.levels)
			{
				if (level.ValuablePresets.Contains(genericValuablePreset))
				{
					Logger.LogInfo("Level \"" + ((Object)level).name + "\" already has the valuable preset \"" + ((Object)genericValuablePreset).name + "\"", extended: true);
				}
				else
				{
					level.ValuablePresets.Add(genericValuablePreset);
					Logger.LogInfo("Added valuable preset \"" + ((Object)genericValuablePreset).name + "\" to level \"" + ((Object)level).name + "\"", extended: true);
				}
			}
		}

		private static void AddValuablePresets(List<LevelValuables> valuablePresets)
		{
			foreach (LevelValuables valuablePreset in valuablePresets)
			{
				_valuablePresets.TryAdd(((Object)valuablePreset).name, valuablePreset);
			}
		}

		internal static void RegisterValuablePreset(LevelValuables valuablePreset)
		{
			RemoveMissingValuables(valuablePreset, valuablePreset.tiny);
			RemoveMissingValuables(valuablePreset, valuablePreset.small);
			RemoveMissingValuables(valuablePreset, valuablePreset.medium);
			RemoveMissingValuables(valuablePreset, valuablePreset.big);
			RemoveMissingValuables(valuablePreset, valuablePreset.wide);
			RemoveMissingValuables(valuablePreset, valuablePreset.tall);
			RemoveMissingValuables(valuablePreset, valuablePreset.veryTall);
			_valuablePresets.Add(((Object)valuablePreset).name, valuablePreset);
		}

		private static void RemoveMissingValuables(LevelValuables valuablePreset, List<PrefabRef> prefabRefs)
		{
			int count = prefabRefs.Count;
			for (int num = count - 1; num >= 0; num--)
			{
				PrefabRef val = prefabRefs[num];
				if (!val.IsValid() || (Object)(object)Resources.Load<GameObject>(val.ResourcePath) == (Object)null)
				{
					Logger.LogWarning($"Valuable preset \"{((Object)valuablePreset).name}\" has an invalid vanilla valuable PrefabRef at index {num} (PrefabName: \"{val.PrefabName}\", ResourcePath: \"{val.ResourcePath}\")");
					prefabRefs.RemoveAt(num);
				}
			}
		}
	}
	public static class Valuables
	{
		private static readonly Dictionary<PrefabRef, List<string>> _valuablesToRegister = new Dictionary<PrefabRef, List<string>>();

		private static readonly List<PrefabRef> _valuablesRegistered = new List<PrefabRef>();

		private static bool _initialValuablesRegistered;

		public static IReadOnlyList<PrefabRef> AllValuables
		{
			get
			{
				if ((Object)(object)RunManager.instance == (Object)null)
				{
					return Array.Empty<PrefabRef>();
				}
				return ValuablePresets.AllValuablePresets.Values.Select((LevelValuables levelValuables) => levelValuables.GetCombinedList()).SelectMany((List<PrefabRef> list) => list).Distinct()
					.ToList();
			}
		}

		public static IReadOnlyList<PrefabRef> RegisteredValuables => _valuablesRegistered;

		internal static void RegisterInitialValuables()
		{
			if (_initialValuablesRegistered)
			{
				return;
			}
			Logger.LogInfo("Adding valuables to valuable presets.");
			foreach (PrefabRef key in _valuablesToRegister.Keys)
			{
				RegisterValuableWithGame(key);
			}
			_valuablesToRegister.Clear();
			_initialValuablesRegistered = true;
		}

		private static void RegisterValuableWithGame(PrefabRef prefabRef)
		{
			if (_valuablesRegistered.Contains(prefabRef))
			{
				return;
			}
			List<string> list = _valuablesToRegister[prefabRef];
			if (!list.Any((string x) => ValuablePresets.AllValuablePresets.Keys.Any((string y) => x == y)))
			{
				Logger.LogWarning("Valuable \"" + prefabRef.PrefabName + "\" does not have any valid valuable preset names set. Adding generic valuable preset name.");
				list = new List<string>(1) { "Valuables - Generic" };
			}
			foreach (string item in list)
			{
				if (item == null || !ValuablePresets.AllValuablePresets.ContainsKey(item))
				{
					Logger.LogWarning("Failed to add valuable \"" + prefabRef.PrefabName + "\" to valuable preset \"" + item + "\". The valuable preset does not exist.");
				}
				else if (ValuablePresets.AllValuablePresets[item].AddValuable(prefabRef))
				{
					_valuablesRegistered.Add(prefabRef);
					Logger.LogDebug("Added valuable \"" + prefabRef.PrefabName + "\" to valuable preset \"" + item + "\"");
				}
				else
				{
					Logger.LogWarning("Failed to add valuable \"" + prefabRef.PrefabName + "\" to valuable preset \"" + item + "\"", extended: true);
				}
			}
		}

		public static PrefabRef? RegisterValuable(ValuableObject? valuableObject, List<string> presetNames)
		{
			if ((Object)(object)valuableObject == (Object)null)
			{
				Logger.LogError("Failed to register valuable. ValuableObject is null.");
				return null;
			}
			GameObject gameObject = ((Component)valuableObject).gameObject;
			string prefabId = "Valuables/" + ((Object)gameObject).name;
			if (presetNames == null || presetNames.Count == 0)
			{
				Logger.LogWarning("Valuable \"" + ((Object)gameObject).name + "\" does not have any valid valuable preset names set. Adding generic valuable preset name.", extended: true);
				presetNames = new List<string>(1) { "Valuables - Generic" };
			}
			PrefabRefResponse prefabRefResponse = NetworkPrefabs.RegisterNetworkPrefabInternal(prefabId, gameObject);
			PrefabRef prefabRef = prefabRefResponse.PrefabRef;
			if (prefabRefResponse.Result == PrefabRefResult.PrefabAlreadyRegistered)
			{
				Logger.LogWarning("Failed to register valuable \"" + ((Object)gameObject).name + "\". Valuable is already registered!");
				return null;
			}
			if (prefabRefResponse.Result == PrefabRefResult.DifferentPrefabAlreadyRegistered)
			{
				Logger.LogError("Failed to register valuable \"" + ((Object)gameObject).name + "\". A valuable prefab is already registered with the same name.");
				return null;
			}
			if (prefabRefResponse.Result != 0)
			{
				Logger.LogError($"Failed to register valuable \"{((Object)gameObject).name}\". (Reason: {prefabRefResponse.Result})");
				return null;
			}
			if (prefabRef == null)
			{
				Logger.LogError("Failed to register valuable \"" + ((Object)gameObject).name + "\". PrefabRef is null.");
				return null;
			}
			Utilities.FixAudioMixerGroups(gameObject);
			_valuablesToRegister.Add(prefabRef, presetNames);
			if (_initialValuablesRegistered)
			{
				RegisterValuableWithGame(prefabRef);
			}
			return prefabRef;
		}

		public static PrefabRef? RegisterValuable(ValuableObject? valuableObject)
		{
			return RegisterValuable(valuableObject, new List<string>());
		}

		public static PrefabRef? RegisterValuable(ValuableObject? valuableObject, List<LevelValuables> presets)
		{
			return RegisterValuable(valuableObject, presets.Select((LevelValuables preset) => ((Object)preset).name).ToList());
		}

		public static PrefabRef? RegisterValuable(ValuableContent? valuableContent)
		{
			if ((Object)(object)valuableContent == (Object)null)
			{
				Logger.LogError("Failed to register valuable. ValuableContent is null.");
				return null;
			}
			return RegisterValuable(valuableContent.Prefab, valuableContent.ValuablePresets.ToList());
		}

		public static PrefabRef? RegisterValuable(GameObject? prefab, List<string> presetNames)
		{
			if ((Object)(object)prefab == (Object)null)
			{
				Logger.LogError("Failed to register valuable. Prefab is null.");
				return null;
			}
			ValuableObject valuableObject = default(ValuableObject);
			if (!prefab.TryGetComponent<ValuableObject>(ref valuableObject))
			{
				Logger.LogError("Failed to register valuable \"" + ((Object)prefab).name + "\". Prefab does not have a ValuableObject component.");
				return null;
			}
			return RegisterValuable(valuableObject, presetNames);
		}

		public static PrefabRef? RegisterValuable(GameObject? prefab, List<LevelValuables> presets)
		{
			return RegisterValuable(prefab, presets.Select((LevelValuables preset) => ((Object)preset).name).ToList());
		}

		public static PrefabRef? RegisterValuable(GameObject? prefab)
		{
			return RegisterValuable(prefab, new List<string>());
		}

		public static GameObject? SpawnValuable(PrefabRef? prefabRef, Vector3 position, Quaternion rotation)
		{
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			if (prefabRef == null)
			{
				Logger.LogError("Failed to spawn valuable. PrefabRef is null.");
				return null;
			}
			if (!prefabRef.IsValid())
			{
				Logger.LogError("Failed to spawn valuable. PrefabRef is not valid.");
				return null;
			}
			if (!SemiFunc.IsMasterClientOrSingleplayer())
			{
				Logger.LogError("Failed to spawn valuable \"" + prefabRef.PrefabName + "\". You are not the host.");
				return null;
			}
			GameObject val = NetworkPrefabs.SpawnNetworkPrefab(prefabRef, position, rotation, 0);
			if ((Object)(object)val == (Object)null)
			{
				Logger.LogError("Failed to spawn valuable \"" + prefabRef.prefabName + "\". Spawned GameObject is null.");
				return null;
			}
			Logger.LogInfo($"Spawned valuable \"{prefabRef.prefabName}\" at position {position}, rotation: {((Quaternion)(ref rotation)).eulerAngles}", extended: true);
			return val;
		}

		[Obsolete("This is no longer supported. Use AllValuables or RegisteredValuables instead.", true)]
		public static IReadOnlyList<GameObject> GetValuables()
		{
			Logger.LogError("This method is deprecated! " + Utilities.GetStackTrace());
			return Array.Empty<GameObject>();
		}

		[Obsolete("This is no longer supported. Use AllValuables or RegisteredValuables instead.", true)]
		public static bool TryGetValuableByName(string name, [NotNullWhen(true)] out ValuableObject? prefabRef)
		{
			Logger.LogError("This method is deprecated! " + Utilities.GetStackTrace());
			prefabRef = null;
			return false;
		}

		[Obsolete("This is no longer supported. Use AllValuables or RegisteredValuables instead.", false)]
		public static ValuableObject? GetValuableByName(string name)
		{
			Logger.LogError("This method is deprecated! " + Utilities.GetStackTrace());
			return null;
		}

		[Obsolete("This is no longer supported. Use AllValuables or RegisteredValuables instead.", true)]
		public static bool TryGetValuableThatContainsName(string name, [NotNullWhen(true)] out ValuableObject? prefabRef)
		{
			Logger.LogError("This method is deprecated! " + Utilities.GetStackTrace());
			prefabRef = null;
			return false;
		}

		[Obsolete("This is no longer supported. Use AllValuables or RegisteredValuables instead.", true)]
		public static ValuableObject? GetValuableThatContainsName(string name)
		{
			Logger.LogError("This method is deprecated! " + Utilities.GetStackTrace());
			return null;
		}
	}
}
namespace REPOLib.Extensions
{
	internal static class AudioSourceExtensions
	{
		public static void FixAudioMixerGroup(this AudioSource audioSource)
		{
			audioSource.FixAudioMixerGroup(((Component)audioSource).gameObject);
		}

		public static void FixAudioMixerGroup(this AudioSource audioSource, GameObject rootObject)
		{
			if ((Object)(object)audioSource == (Object)null)
			{
				return;
			}
			string text = ((!((Object)(object)rootObject == (Object)(object)((Component)audioSource).gameObject)) ? (((Object)rootObject).name + "/" + ((Object)((Component)audioSource).gameObject).name) : ((Object)((Component)audioSource).gameObject).name);
			if ((Object)(object)AudioManager.instance == (Object)null)
			{
				Logger.LogWarning("Failed to fix AudioMixerGroup on GameObject \"" + text + "\". AudioManager instance is null.");
				return;
			}
			if ((Object)(object)audioSource.outputAudioMixerGroup == (Object)null)
			{
				Logger.LogWarning("Failed to fix AudioMixerGroup on GameObject \"" + text + "\". No AudioMixerGroup is assigned.");
				return;
			}
			AudioMixer val = (AudioMixer)(((Object)audioSource.outputAudioMixerGroup.audioMixer).name switch
			{
				"Master" => AudioManager.instance.MasterMixer, 
				"Music" => AudioManager.instance.MusicMasterGroup.audioMixer, 
				"Sound" => AudioManager.instance.SoundMasterGroup.audioMixer, 
				"Spectate" => AudioManager.instance.MicrophoneSpectateGroup.audioMixer, 
				_ => AudioManager.instance.SoundMasterGroup.audioMixer, 
			});
			AudioMixerGroup[] array = val.FindMatchingGroups(((Object)audioSource.outputAudioMixerGroup).name);
			AudioMixerGroup val2;
			if (array.Length >= 1)
			{
				val2 = array[0];
			}
			else
			{
				val = AudioManager.instance.SoundMasterGroup.audioMixer;
				val2 = val.FindMatchingGroups("Sound Effects")[0];
				Logger.LogWarning("Could not find matching AudioMixerGroup for GameObject \"" + text + "\". Using default AudioMixerGroup \"" + ((Object)val).name + "/" + ((Object)val2).name + "\"", extended: true);
			}
			audioSource.outputAudioMixerGroup = val2;
			Logger.LogDebug("Fixed AudioMixerGroup on GameObject \"" + text + "\". AudioMixerGroup \"" + ((Object)val).name + "/" + ((Object)val2).name + "\"");
		}
	}
	internal static class CollectionExtensions
	{
		public static IEnumerable<T> OrderByTypePriority<T>(this IEnumerable<T> source, Type[] types) where T : Content
		{
			Dictionary<Type, int> typesMap = new Dictionary<Type, int>();
			for (int i = 0; i < types.Length; i++)
			{
				typesMap[types[i]] = i;
			}
			int value;
			return source.OrderBy((T x) => typesMap.TryGetValue(((object)x).GetType(), out value) ? value : int.MaxValue);
		}

		public static IEnumerable<T> OrderByTypeFirst<T, TFirst>(this IEnumerable<T> source)
		{
			return source.OrderBy((T x) => (!(x is TFirst)) ? 1 : 0);
		}
	}
	internal static class EnemyDirectorExtensions
	{
		public static bool HasEnemy(this EnemyDirector enemyDirector, EnemySetup enemySetup)
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)enemySetup == (Object)null || enemySetup.spawnObjects.Count == 0)
			{
				return false;
			}
			if (!enemySetup.TryGetEnemyParent(out EnemyParent enemyParent))
			{
				return false;
			}
			if (!enemyDirector.TryGetList(enemyParent.difficulty, out List<EnemySetup> list))
			{
				return false;
			}
			return list.Contains(enemySetup);
		}

		internal static bool AddEnemy(this EnemyDirector enemyDirector, EnemySetup enemySetup)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)enemySetup == (Object)null)
			{
				return false;
			}
			if (!enemySetup.TryGetEnemyParent(out EnemyParent enemyParent))
			{
				return false;
			}
			if (!enemyDirector.TryGetList(enemyParent.difficulty, out List<EnemySetup> list))
			{
				return false;
			}
			if (list.Contains(enemySetup))
			{
				return false;
			}
			list.Add(enemySetup);
			return true;
		}

		public static bool TryGetList(this EnemyDirector enemyDirector, Difficulty difficultyType, [NotNullWhen(true)] out List<EnemySetup>? list)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected I4, but got Unknown
			list = (int)difficultyType switch
			{
				0 => enemyDirector.enemiesDifficulty1, 
				1 => enemyDirector.enemiesDifficulty2, 
				2 => enemyDirector.enemiesDifficulty3, 
				_ => null, 
			};
			return list != null;
		}

		public static List<EnemySetup> GetEnemies(this EnemyDirector enemyDirector)
		{
			List<EnemySetup> enemiesDifficulty = enemyDirector.enemiesDifficulty1;
			List<EnemySetup> enemiesDifficulty2 = enemyDirector.enemiesDifficulty2;
			List<EnemySetup> enemiesDifficulty3 = enemyDirector.enemiesDifficulty3;
			List<EnemySetup> list = new List<EnemySetup>(enemiesDifficulty.Count + enemiesDifficulty2.Count + enemiesDifficulty3.Count);
			list.AddRange(enemiesDifficulty);
			list.AddRange(enemiesDifficulty2);
			list.AddRange(enemiesDifficulty3);
			return list;
		}
	}
	internal static class EnemySetupExtensions
	{
		public static List<PrefabRef> GetDistinctSpawnObjects(this EnemySetup enemySetup)
		{
			return enemySetup.spawnObjects.Where((PrefabRef x) => x != null).Distinct(new PrefabRefComparer()).ToList();
		}

		public static EnemyParent? GetEnemyParent(this EnemySetup enemySetup)
		{
			EnemyParent result = default(EnemyParent);
			foreach (PrefabRef distinctSpawnObject in enemySetup.GetDistinctSpawnObjects())
			{
				if (distinctSpawnObject.Prefab.TryGetComponent<EnemyParent>(ref result))
				{
					return result;
				}
			}
			return null;
		}

		public static bool TryGetEnemyParent(this EnemySetup enemySetup, [NotNullWhen(true)] out EnemyParent? enemyParent)
		{
			enemyParent = enemySetup.GetEnemyParent();
			return (Object)(object)enemyParent != (Object)null;
		}
	}
	internal static class GameObjectExtensions
	{
		public static void FixAudioMixerGroups(this GameObject gameObject)
		{
			if ((Object)(object)gameObject == (Object)null)
			{
				return;
			}
			if ((Object)(object)AudioManager.instance == (Object)null)
			{
				Logger.LogWarning("Failed to fix audio mixer groups on GameObject \"" + ((Object)gameObject).name + "\". AudioManager instance is null.");
				return;
			}
			AudioSource[] componentsInChildren = gameObject.GetComponentsInChildren<AudioSource>();
			foreach (AudioSource audioSource in componentsInChildren)
			{
				audioSource.FixAudioMixerGroup(gameObject);
			}
		}
	}
	internal static class LevelValuablesExtensions
	{
		public static bool AddValuable(this LevelValuables levelValuables, PrefabRef prefabRef)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			GameObject prefab = prefabRef.Prefab;
			if ((O